int main(int argc, char *argv[]) { int sfd, cfd; ssize_t numRead; char buf[BUF_SIZE]; sfd = unixBind(SV_SOCK_PATH, SOCK_STREAM); if (sfd == -1) errExit("unixBind"); if (listen(sfd, 5) == -1) errExit("listen"); for (;;) { /* Handle client connections iteratively */ cfd = accept(sfd, NULL, NULL); if (cfd == -1) errExit("accept"); /* Transfer data from connected socket to stdout until EOF */ while ((numRead = read(cfd, buf, BUF_SIZE)) > 0) if (write(STDOUT_FILENO, buf, numRead) != numRead) fatal("partial/failed write"); if (numRead == -1) errExit("read"); if (close(cfd) == -1) errMsg("close"); } }
int main(int argc, char *argv[]) { struct msghdr msgh; struct iovec iov; int data, lfd, sfd, fd, opt; ssize_t nr; Boolean useDatagramSocket; union { struct cmsghdr cmh; char control[CMSG_SPACE(sizeof(int))]; /* Space large enough to hold an 'int' */ } control_un; struct cmsghdr *cmhp; /* Parse command-line arguments */ useDatagramSocket = FALSE; while ((opt = getopt(argc, argv, "d")) != -1) { switch (opt) { case 'd': useDatagramSocket = TRUE; break; default: usageErr("%s [-d]\n" " -d use datagram socket\n", argv[0]); } } /* Create socket bound to well-known address */ if (remove(SOCK_PATH) == -1 && errno != ENOENT) errExit("remove-%s", SOCK_PATH); if (useDatagramSocket) { fprintf(stderr, "Receiving via datagram socket\n"); sfd = unixBind(SOCK_PATH, SOCK_DGRAM); if (sfd == -1) errExit("unixBind"); } else { fprintf(stderr, "Receiving via stream socket\n"); lfd = unixListen(SOCK_PATH, 5); if (lfd == -1) errExit("unixListen"); sfd = accept(lfd, NULL, 0); if (sfd == -1) errExit("accept"); } /* Set 'control_un' to describe ancillary data that we want to receive */ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(int)); control_un.cmh.cmsg_level = SOL_SOCKET; control_un.cmh.cmsg_type = SCM_RIGHTS; /* Set 'msgh' fields to describe 'control_un' */ msgh.msg_control = control_un.control; msgh.msg_controllen = sizeof(control_un.control); /* Set fields of 'msgh' to point to buffer used to receive (real) data read by recvmsg() */ msgh.msg_iov = &iov; msgh.msg_iovlen = 1; iov.iov_base = &data; iov.iov_len = sizeof(int); msgh.msg_name = NULL; /* We don't need address of peer */ msgh.msg_namelen = 0; /* Receive real plus ancillary data */ nr = recvmsg(sfd, &msgh, 0); if (nr == -1) errExit("recvmsg"); fprintf(stderr, "recvmsg() returned %ld\n", (long) nr); if (nr > 0) fprintf(stderr, "Received data = %d\n", data); /* Get the received file descriptor (which is typically a different file descriptor number than was used in the sending process) */ cmhp = CMSG_FIRSTHDR(&msgh); if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(int))) fatal("bad cmsg header / message length"); if (cmhp->cmsg_level != SOL_SOCKET) fatal("cmsg_level != SOL_SOCKET"); if (cmhp->cmsg_type != SCM_RIGHTS) fatal("cmsg_type != SCM_RIGHTS"); fd = *((int *) CMSG_DATA(cmhp)); fprintf(stderr, "Received fd=%d\n", fd); /* Having obtained the file descriptor, read the file's contents and print them on standard output */ for (;;) { char buf[BUF_SIZE]; ssize_t numRead; numRead = read(fd, buf, BUF_SIZE); if (numRead == -1) errExit("read"); if (numRead == 0) break; write(STDOUT_FILENO, buf, numRead); } exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { struct msghdr msgh; struct iovec iov; struct ucred *ucredp, ucred; int data, lfd, sfd, optval, opt; ssize_t nr; Boolean useDatagramSocket; union { struct cmsghdr cmh; char control[CMSG_SPACE(sizeof(struct ucred))]; /* Space large enough to hold a ucred structure */ } control_un; struct cmsghdr *cmhp; socklen_t len; /* Parse command-line arguments */ useDatagramSocket = FALSE; while ((opt = getopt(argc, argv, "d")) != -1) { switch (opt) { case 'd': useDatagramSocket = TRUE; break; default: usageErr("%s [-d]\n" " -d use datagram socket\n", argv[0]); } } /* Create socket bound to well-known address */ if (remove(SOCK_PATH) == -1 && errno != ENOENT) errExit("remove-%s", SOCK_PATH); if (useDatagramSocket) { printf("Receiving via datagram socket\n"); sfd = unixBind(SOCK_PATH, SOCK_DGRAM); if (sfd == -1) errExit("unixBind"); } else { printf("Receiving via stream socket\n"); lfd = unixListen(SOCK_PATH, 5); if (lfd == -1) errExit("unixListen"); sfd = accept(lfd, NULL, 0); if (sfd == -1) errExit("accept"); } /* We must set the SO_PASSCRED socket option in order to receive credentials */ optval = 1; if (setsockopt(sfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) == -1) errExit("setsockopt"); /* Set 'control_un' to describe ancillary data that we want to receive */ control_un.cmh.cmsg_len = CMSG_LEN(sizeof(struct ucred)); control_un.cmh.cmsg_level = SOL_SOCKET; control_un.cmh.cmsg_type = SCM_CREDENTIALS; /* Set 'msgh' fields to describe 'control_un' */ msgh.msg_control = control_un.control; msgh.msg_controllen = sizeof(control_un.control); /* Set fields of 'msgh' to point to buffer used to receive (real) data read by recvmsg() */ msgh.msg_iov = &iov; msgh.msg_iovlen = 1; iov.iov_base = &data; iov.iov_len = sizeof(int); msgh.msg_name = NULL; /* We don't need address of peer */ msgh.msg_namelen = 0; /* Receive real plus ancillary data */ nr = recvmsg(sfd, &msgh, 0); if (nr == -1) errExit("recvmsg"); printf("recvmsg() returned %ld\n", (long) nr); if (nr > 0) printf("Received data = %d\n", data); /* Extract credentials information from received ancillary data */ cmhp = CMSG_FIRSTHDR(&msgh); if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(struct ucred))) fatal("bad cmsg header / message length"); if (cmhp->cmsg_level != SOL_SOCKET) fatal("cmsg_level != SOL_SOCKET"); if (cmhp->cmsg_type != SCM_CREDENTIALS) fatal("cmsg_type != SCM_CREDENTIALS"); ucredp = (struct ucred *) CMSG_DATA(cmhp); printf("Received credentials pid=%ld, uid=%ld, gid=%ld\n", (long) ucredp->pid, (long) ucredp->uid, (long) ucredp->gid); /* The Linux-specific, read-only SO_PEERCRED socket option returns credential information about the peer, as described in socket(7) */ len = sizeof(struct ucred); if (getsockopt(sfd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) errExit("getsockopt"); printf("Credentials from SO_PEERCRED: pid=%ld, euid=%ld, egid=%ld\n", (long) ucred.pid, (long) ucred.uid, (long) ucred.gid); exit(EXIT_SUCCESS); }