diff options
author | Brian Somers <brian@FreeBSD.org> | 1998-05-02 21:57:50 +0000 |
---|---|---|
committer | Brian Somers <brian@FreeBSD.org> | 1998-05-02 21:57:50 +0000 |
commit | 96c9bb21aa57081809d2c59a47106f95b5d22d9d (patch) | |
tree | 5e0db87fe7fc7730adfe7cebaac652a56d0deca4 /usr.sbin/ppp/bundle.c | |
parent | b1ac9332fd8c9e933c5ff4aa09d1a6091d76af15 (diff) | |
download | src-test2-96c9bb21aa57081809d2c59a47106f95b5d22d9d.tar.gz src-test2-96c9bb21aa57081809d2c59a47106f95b5d22d9d.zip |
Notes
Diffstat (limited to 'usr.sbin/ppp/bundle.c')
-rw-r--r-- | usr.sbin/ppp/bundle.c | 201 |
1 files changed, 99 insertions, 102 deletions
diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index e10556f0ec2d..0b5a48e073c0 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bundle.c,v 1.1.2.67 1998/05/01 19:22:09 brian Exp $ + * $Id: bundle.c,v 1.1.2.68 1998/05/01 19:23:55 brian Exp $ */ #include <sys/types.h> @@ -45,6 +45,7 @@ #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> +#include <sys/uio.h> #include <termios.h> #include <unistd.h> @@ -81,6 +82,10 @@ #include "datalink.h" #include "ip.h" +#define SCATTER_SEGMENTS 4 /* version, datalink, name, physical */ +#define SOCKET_OVERHEAD 100 /* additional buffer space for large */ + /* {recv,send}msg() calls */ + static const char *PhaseNames[] = { "Dead", "Establish", "Authenticate", "Network", "Terminate" }; @@ -1087,43 +1092,68 @@ bundle_GetLabel(struct bundle *bundle) } void -bundle_ReceiveDatalink(struct bundle *bundle, int fd) +bundle_ReceiveDatalink(struct bundle *bundle, int s, struct sockaddr_un *sun) { + char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)]; + struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf; + struct msghdr msg; + struct iovec iov[SCATTER_SEGMENTS]; struct datalink *dl, *ndl; - u_char *buf; - int get, got, vlen; - - /* - * We expect: - * .---------.---------.--------------. - * | ver len | Version | datalink len | - * `---------'---------'--------------' - * We then pass the rest of the stream to datalink. - */ + int niov, link_fd, expect, f; log_Printf(LogPHASE, "Receiving datalink\n"); - vlen = strlen(Version); - get = sizeof(int) * 2 + vlen; - buf = (u_char *)malloc(get); - got = fullread(fd, buf, get); - if (got != get) { - log_Printf(LogWARN, "Cannot receive datalink header" - " (got %d bytes, not %d)\n", got, get); - close(fd); - free(buf); + /* Create our scatter/gather array */ + niov = 1; + iov[0].iov_len = strlen(Version) + 1; + iov[0].iov_base = (char *)malloc(iov[0].iov_len); + if (datalink2iov(NULL, iov, &niov, sizeof iov / sizeof *iov) == -1) + return; + + for (f = expect = 0; f < niov; f++) + expect += iov[f].iov_len; + + /* Set up our message */ + cmsg->cmsg_len = sizeof cmsgbuf; + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + memset(&msg, '\0', sizeof msg); + msg.msg_name = (caddr_t)sun; + msg.msg_namelen = sizeof *sun; + msg.msg_iov = iov; + msg.msg_iovlen = niov; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof cmsgbuf; + + log_Printf(LogDEBUG, "Expecting %d scatter/gather bytes\n", expect); + f = expect + 100; + setsockopt(s, SOL_SOCKET, SO_RCVBUF, &f, sizeof f); + if ((f = recvmsg(s, &msg, MSG_WAITALL)) != expect) { + if (f == -1) + log_Printf(LogERROR, "Failed recvmsg: %s\n", strerror(errno)); + else + log_Printf(LogERROR, "Failed recvmsg: Got %d, not %d\n", f, expect); + while (niov--) + free(iov[niov].iov_base); return; } - if (*(int *)buf != vlen || *(int *)(buf + sizeof(int) + vlen) != sizeof *dl || - memcmp(buf + sizeof(int), Version, vlen)) { - log_Printf(LogWARN, "Cannot receive datalink, incorrect version\n"); - close(fd); - free(buf); + + /* We've successfully received an open file descriptor through our socket */ + link_fd = *(int *)CMSG_DATA(cmsg); + + if (strncmp(Version, iov[0].iov_base, iov[0].iov_len)) { + log_Printf(LogWARN, "Cannot receive datalink, incorrect version" + " (\"%.*s\", not \"%s\")\n", (int)iov[0].iov_len, + iov[0].iov_base, Version); + close(link_fd); + while (niov--) + free(iov[niov].iov_base); return; } - free(buf); - ndl = datalink_FromBinary(bundle, fd); + niov = 1; + ndl = iov2datalink(bundle, iov, &niov, sizeof iov / sizeof *iov, link_fd); if (ndl) { /* Make sure the name is unique ! */ do { @@ -1140,24 +1170,22 @@ bundle_ReceiveDatalink(struct bundle *bundle, int fd) log_Printf(LogPHASE, "%s: Created in %s state\n", ndl->name, datalink_State(ndl)); datalink_AuthOk(ndl); - } + } else + close(link_fd); + + free(iov[0].iov_base); } void -bundle_SendDatalink(struct datalink *dl, int ppp_fd) +bundle_SendDatalink(struct datalink *dl, int s, struct sockaddr_un *sun) { - int len, link_fd, err, nfd, flags; + char cmsgbuf[sizeof(struct cmsghdr) + sizeof(int)]; /* pass ppp_fd */ + struct cmsghdr *cmsg = (struct cmsghdr *)cmsgbuf; + struct msghdr msg; + struct iovec iov[SCATTER_SEGMENTS]; + int niov, link_fd, f, expect; struct datalink **pdl; struct bundle *bundle = dl->bundle; - char procname[100]; - - /* - * We send: - * .---------.---------.--------------. - * | ver len | Version | datalink len | - * `---------'---------'--------------' - * We then pass the rest of the stream to datalink. - */ log_Printf(LogPHASE, "Transmitting datalink %s\n", dl->name); @@ -1169,70 +1197,39 @@ bundle_SendDatalink(struct datalink *dl, int ppp_fd) break; } - /* Write our bit of the data */ - err = 0; - len = strlen(Version); - if (write(ppp_fd, &len, sizeof len) != sizeof len) - err++; - if (write(ppp_fd, Version, len) != len) - err++; - len = sizeof(struct datalink); - if (write(ppp_fd, &len, sizeof len) != sizeof len) - err++; - - if (err) { - log_Printf(LogERROR, "Failed sending version\n"); - close(ppp_fd); - ppp_fd = -1; - } + /* Build our scatter/gather array */ + iov[0].iov_len = strlen(Version) + 1; + iov[0].iov_base = strdup(Version); + niov = 1; - link_fd = datalink_ToBinary(dl, ppp_fd); + link_fd = datalink2iov(dl, iov, &niov, sizeof iov / sizeof *iov); if (link_fd != -1) { - switch (fork()) { - case 0: - timer_TermService(); - - ppp_fd = fcntl(ppp_fd, F_DUPFD, 3); - link_fd = fcntl(link_fd, F_DUPFD, 3); - nfd = dup2(open(_PATH_DEVNULL, O_WRONLY), STDERR_FILENO); - fcntl(3, F_SETFD, 1); /* Set close-on-exec flag */ - - setsid(); - setuid(geteuid()); - - flags = fcntl(ppp_fd, F_GETFL, 0); - fcntl(ppp_fd, F_SETFL, flags & ~O_NONBLOCK); - flags = fcntl(link_fd, F_GETFL, 0); - fcntl(link_fd, F_SETFL, flags & ~O_NONBLOCK); - - switch (fork()) { - case 0: - dup2(ppp_fd, STDIN_FILENO); - dup2(link_fd, STDOUT_FILENO); - snprintf(procname, sizeof procname, "%s -> %s", - dl->name, *dl->physical->name.base ? - dl->physical->name.base : "network"); - execl(CATPROG, procname, NULL); - log_Printf(LogERROR, "exec: %s: %s\n", CATPROG, strerror(errno)); - break; - case -1: - break; - default: - dup2(link_fd, STDIN_FILENO); - dup2(ppp_fd, STDOUT_FILENO); - snprintf(procname, sizeof procname, "%s <- %s", - dl->name, *dl->physical->name.base ? - dl->physical->name.base : "network"); - execl(CATPROG, procname, NULL); - log_Printf(LogERROR, "exec: %s: %s\n", CATPROG, strerror(errno)); - break; - } - exit(1); - break; - case -1: - log_Printf(LogERROR, "fork: %s\n", strerror(errno)); - break; - } + cmsg->cmsg_len = sizeof cmsgbuf; + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = link_fd; + + memset(&msg, '\0', sizeof msg); + msg.msg_name = (caddr_t)sun; + msg.msg_namelen = sizeof *sun; + msg.msg_iov = iov; + msg.msg_iovlen = niov; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof cmsgbuf; + + for (f = expect = 0; f < niov; f++) + expect += iov[f].iov_len; + + log_Printf(LogDEBUG, "Sending %d bytes in scatter/gather array\n", expect); + + f = expect + SOCKET_OVERHEAD; + setsockopt(s, SOL_SOCKET, SO_SNDBUF, &f, sizeof f); + if (sendmsg(s, &msg, 0) == -1) + log_Printf(LogERROR, "Failed sendmsg: %s\n", strerror(errno)); + close(link_fd); } + + while (niov--) + free(iov[niov].iov_base); } |