DF-3533 / kshold.c
/* kshold.c -- create a ksocket node via generic NGM_MKPEER on our own * control socket, then HOLD the socket open so the graph stays alive. * Naming/binding done externally via ngbmsg (fresh sockets). */ #include <sys/types.h> #include <sys/socket.h> #include <netgraph/ng_message.h> #include <netgraph/socket/ng_socket.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <stddef.h> #include <err.h> #include <errno.h> int main(int argc, char **argv) { static char mbuf[512]; struct ng_mesg *msg = (struct ng_mesg *)mbuf; struct sockaddr_ng dst; struct iovec iov[2]; struct msghdr mhdr; struct ngm_mkpeer mk; int s = socket(AF_NETGRAPH, SOCK_DGRAM, NG_CONTROL); if (s < 0) err(1, "socket"); memset(&mk, 0, sizeof(mk)); strcpy(mk.type, argc > 3 ? argv[3] : "ksocket"); strcpy(mk.ourhook, "k0"); strcpy(mk.peerhook, argc > 1 ? argv[1] : "inet/dgram/udp"); memset(msg, 0, sizeof(*msg) + sizeof(mk)); msg->header.version = NG_VERSION; msg->header.typecookie = 851672668; /* NGM_GENERIC_COOKIE */ msg->header.cmd = 2; /* NGM_MKPEER */ msg->header.arglen = sizeof(mk); memcpy(msg->data, &mk, sizeof(mk)); memset(&dst, 0, sizeof(dst)); dst.sg_len = offsetof(struct sockaddr_ng, sg_data) + 1; dst.sg_family = AF_NETGRAPH; dst.sg_data[0] = 0; iov[0].iov_base = (caddr_t)&msg->header; iov[0].iov_len = sizeof(struct ng_msghdr); iov[1].iov_base = (caddr_t)msg->data; iov[1].iov_len = sizeof(mk); memset(&mhdr, 0, sizeof(mhdr)); mhdr.msg_name = (caddr_t)&dst; mhdr.msg_namelen = dst.sg_len; mhdr.msg_iov = iov; mhdr.msg_iovlen = 2; if (sendmsg(s, &mhdr, 0) < 0) err(1, "mkpeer sendmsg"); { struct timeval tv0 = {1, 0}; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv0, sizeof(tv0)); read(s, mbuf, sizeof(mbuf)); } /* NGM_NAME the peer (relative path k0) -- ksocket node */ { struct ngm_name nm; memset(&nm, 0, sizeof(nm)); strcpy(nm.name, argc > 4 ? argv[4] : "ks0"); memset(msg, 0, sizeof(*msg) + sizeof(nm)); msg->header.version = NG_VERSION; msg->header.typecookie = 851672668; msg->header.cmd = 4; /* NGM_NAME */ msg->header.arglen = sizeof(nm); memcpy(msg->data, &nm, sizeof(nm)); iov[1].iov_base = (caddr_t)msg->data; iov[1].iov_len = sizeof(nm); memset(&dst, 0, sizeof(dst)); dst.sg_len = offsetof(struct sockaddr_ng, sg_data) + strlen("k0") + 1; dst.sg_family = AF_NETGRAPH; strcpy(dst.sg_data, "k0"); mhdr.msg_name = (caddr_t)&dst; mhdr.msg_namelen = dst.sg_len; if (sendmsg(s, &mhdr, 0) < 0) warn("name sendmsg (%s)", strerror(errno)); read(s, mbuf, sizeof(mbuf)); } printf("mkpeer+name sent, holding %ds (pid %d)\n", argc > 2 ? atoi(argv[2]) : 600, getpid()); fflush(stdout); sleep(argc > 2 ? atoi(argv[2]) : 600); return 0; } |