From: Philipp Tölke Date: Wed, 26 Jan 2011 13:15:22 +0000 (+0000) Subject: Documented, cleaned and indented gnunet-helper-vpn X-Git-Tag: initial-import-from-subversion-38251~19240 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=62c64f683cce5f7521a9a49e6a1055b22da82091;p=oweals%2Fgnunet.git Documented, cleaned and indented gnunet-helper-vpn --- diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c index 1cee01c71..00eb15c6a 100644 --- a/src/vpn/gnunet-helper-vpn.c +++ b/src/vpn/gnunet-helper-vpn.c @@ -47,7 +47,7 @@ /** * This is in linux/include/net/ipv6.h, but not always exported... */ -struct in6_ifreq +struct in6_ifreq { struct in6_addr ifr6_addr; uint32_t ifr6_prefixlen; @@ -55,50 +55,52 @@ struct in6_ifreq }; #endif - /** * Creates a tun-interface called dev; * @param dev is asumed to point to a char[IFNAMSIZ] * if *dev == '\\0', uses the name supplied by the kernel * @return the fd to the tun or -1 on error */ -static int -init_tun (char *dev) +static int +init_tun (char *dev) { struct ifreq ifr; int fd; - if (NULL == dev) + if (NULL == dev) { errno = EINVAL; return -1; } - if (-1 == (fd = open("/dev/net/tun", O_RDWR))) + if (-1 == (fd = open ("/dev/net/tun", O_RDWR))) + { + fprintf (stderr, + "Error opening `%s': %s\n", "/dev/net/tun", strerror (errno)); + return -1; + } + + if (fd >= FD_SETSIZE) { - fprintf (stderr, - "Error opening `%s': %s\n", - "/dev/net/tun", - strerror(errno)); + fprintf (stderr, "Filedescriptor to large: %d", fd); return -1; } - memset(&ifr, 0, sizeof(ifr)); + memset (&ifr, 0, sizeof (ifr)); ifr.ifr_flags = IFF_TUN; if ('\0' == *dev) - strncpy(ifr.ifr_name, dev, IFNAMSIZ); + strncpy (ifr.ifr_name, dev, IFNAMSIZ); - if (-1 == ioctl(fd, TUNSETIFF, (void *) &ifr)) + if (-1 == ioctl (fd, TUNSETIFF, (void *) &ifr)) { - fprintf (stderr, - "Error with ioctl on `%s': %s\n", - "/dev/net/tun", - strerror(errno)); + fprintf (stderr, + "Error with ioctl on `%s': %s\n", + "/dev/net/tun", strerror (errno)); close (fd); return -1; } - strcpy(dev, ifr.ifr_name); + strcpy (dev, ifr.ifr_name); return fd; } @@ -111,10 +113,8 @@ init_tun (char *dev) * @param prefix_len the length of the network-prefix */ static void -set_address6 (const char *dev, - const char *address, - unsigned long prefix_len) -{ +set_address6 (const char *dev, const char *address, unsigned long prefix_len) +{ struct ifreq ifr; struct in6_ifreq ifr6; struct sockaddr_in6 sa6; @@ -122,70 +122,73 @@ set_address6 (const char *dev, if (-1 == (fd = socket (PF_INET6, SOCK_DGRAM, 0))) { - fprintf (stderr, - "Error creating socket: %s\n", - strerror (errno)); + fprintf (stderr, "Error creating socket: %s\n", strerror (errno)); exit (1); } memset (&sa6, 0, sizeof (struct sockaddr_in6)); sa6.sin6_family = AF_INET6; + /* + * parse the new address + */ if (1 != inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr)) { - fprintf (stderr, + fprintf (stderr, "Failed to parse address `%s': %s\n", - address, - strerror (errno)); + address, strerror (errno)); exit (1); } + memcpy (&ifr6.ifr6_addr, &sa6.sin6_addr, sizeof (struct in6_addr)); + - memcpy (&ifr6.ifr6_addr, - &sa6.sin6_addr, - sizeof (struct in6_addr)); + /* + * Get the index of the if + */ strncpy (ifr.ifr_name, dev, IFNAMSIZ); if (-1 == ioctl (fd, SIOGIFINDEX, &ifr)) { - fprintf (stderr, - "ioctl failed at %d: %s\n", - __LINE__, - strerror (errno)); + fprintf (stderr, + "ioctl failed at %d: %s\n", __LINE__, strerror (errno)); exit (1); } - ifr6.ifr6_ifindex = ifr.ifr_ifindex; + ifr6.ifr6_prefixlen = prefix_len; + + /* + * Set the address + */ if (-1 == ioctl (fd, SIOCSIFADDR, &ifr6)) { - fprintf (stderr, - "ioctl failed at line %d: %s\n", - __LINE__, - strerror (errno)); + fprintf (stderr, + "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); exit (1); } + /* + * Get the flags + */ if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) { - fprintf (stderr, - "ioctl failed at line %d: %s\n", - __LINE__, - strerror (errno)); + fprintf (stderr, + "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); exit (1); } + + /* + * Add the UP and RUNNING flags + */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) { - fprintf (stderr, - "ioctl failed at line %d: %s\n", - __LINE__, - strerror (errno)); + fprintf (stderr, + "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); exit (1); } if (0 != close (fd)) { - fprintf (stderr, - "close failed: %s\n", - strerror (errno)); + fprintf (stderr, "close failed: %s\n", strerror (errno)); exit (1); } } @@ -211,6 +214,9 @@ set_address4 (char *dev, char *address, char *mask) addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr (address); + /* + * Parse the address + */ int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr); if (r < 0) { @@ -227,6 +233,9 @@ set_address4 (char *dev, char *address, char *mask) strncpy (ifr.ifr_name, dev, IFNAMSIZ); + /* + * Set the address + */ if (ioctl (fd, SIOCSIFADDR, &ifr) != 0) { perror ("SIOCSIFADDR"); @@ -234,6 +243,9 @@ set_address4 (char *dev, char *address, char *mask) return; } + /* + * Parse the netmask + */ addr = (struct sockaddr_in *) &(ifr.ifr_netmask); r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr); if (r < 0) @@ -242,6 +254,9 @@ set_address4 (char *dev, char *address, char *mask) exit (1); } + /* + * Set the netmask + */ if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0) { perror ("SIOCSIFNETMASK"); @@ -249,156 +264,211 @@ set_address4 (char *dev, char *address, char *mask) return; } - (void) ioctl (fd, SIOCGIFFLAGS, &ifr); + /* + * Get the flags + */ + if (-1 == ioctl (fd, SIOCGIFFLAGS, &ifr)) + { + fprintf (stderr, + "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); + exit (1); + } + + /* + * Add the UP and RUNNING flags + */ ifr.ifr_flags |= IFF_UP | IFF_RUNNING; - (void) ioctl (fd, SIOCSIFFLAGS, &ifr); - close (fd); + if (-1 == ioctl (fd, SIOCSIFFLAGS, &ifr)) + { + fprintf (stderr, + "ioctl failed at line %d: %s\n", __LINE__, strerror (errno)); + exit (1); + } + + if (0 != close (fd)) + { + fprintf (stderr, "close failed: %s\n", strerror (errno)); + exit (1); + } } static void run (int fd_tun) { - unsigned char buf[MAX_SIZE]; + /* + * The buffer filled by reading from fd_tun + */ + unsigned char buftun[MAX_SIZE]; + ssize_t buftun_size = 0; + unsigned char *buftun_read; + + /* + * The buffer filled by reading from stdin + */ + unsigned char bufin[MAX_SIZE]; + ssize_t bufin_size = 0; + unsigned char *bufin_write; + fd_set fds_w; fd_set fds_r; + int rea = 1; int wri = 1; - int write_fd_possible = 0; - int write_stdout_possible = 0; - ssize_t tin; -outer: + while ((1 == rea) || (1 == wri)) { FD_ZERO (&fds_w); FD_ZERO (&fds_r); - if (rea) + /* + * We are supposed to read and the buffer is empty + * -> select on read from tun + */ + if (rea && (0 == buftun_size)) { FD_SET (fd_tun, &fds_r); - if (!write_stdout_possible) - FD_SET (1, &fds_w); } - if (wri) + /* + * We are supposed to read and the buffer is not empty + * -> select on write to stdout + */ + if (rea && (0 != buftun_size)) + { + FD_SET (1, &fds_w); + } + + /* + * We are supposed to write and the buffer is empty + * -> select on read from stdin + */ + if (wri && (0 == bufin_size)) { FD_SET (0, &fds_r); - if (!write_fd_possible) - FD_SET (fd_tun, &fds_w); + } + + /* + * We are supposed to write and the buffer is not empty + * -> select on write to tun + */ + if (wri && (0 != bufin_size)) + { + FD_SET (fd_tun, &fds_w); } int r = select (fd_tun + 1, &fds_r, &fds_w, NULL, NULL); - /* FIXME: if error... */ - if (r > 0) + if (-1 == r) { - if (FD_ISSET (fd_tun, &fds_w)) - write_fd_possible = 1; - if (FD_ISSET (1, &fds_w)) - write_stdout_possible = 1; + fprintf (stderr, "select failed: %s\n", strerror (errno)); + exit (1); + } - if (FD_ISSET (0, &fds_r) && write_fd_possible) + if (r > 0) + { + if (FD_ISSET (fd_tun, &fds_r)) { - write_fd_possible = 0; - struct GNUNET_MessageHeader *pkt = ( struct GNUNET_MessageHeader *) buf; - tin = read (0, buf, sizeof (struct GNUNET_MessageHeader)); - if (tin <= 0) + buftun_size = + read (fd_tun, buftun + sizeof (struct GNUNET_MessageHeader), + MAX_SIZE - sizeof (struct GNUNET_MessageHeader)) + + sizeof (struct GNUNET_MessageHeader); + if (-1 == buftun_size) { fprintf (stderr, "read-error: %s\n", strerror (errno)); - shutdown (fd_tun, SHUT_WR); - shutdown (0, SHUT_RD); - wri = 0; - goto outer; + shutdown (fd_tun, SHUT_RD); + shutdown (1, SHUT_WR); + rea = 0; + buftun_size = 0; } - if (pkt->type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER)) - abort (); - while (tin < ntohs (pkt->size)) + else if (0 == buftun_size) { - ssize_t t = read (0, buf + tin, ntohs (pkt->size) - tin); - if (t <= 0) - { - fprintf (stderr, "read-error: %s\n", strerror (errno)); - shutdown (fd_tun, SHUT_WR); - shutdown (0, SHUT_RD); - wri = 0; - goto outer; - } - tin += t; + fprintf (stderr, "eof on tun\n"); + shutdown (fd_tun, SHUT_RD); + shutdown (1, SHUT_WR); + rea = 0; + buftun_size = 0; } - tin = 0; - while (tin < - ntohs (pkt->size) - - sizeof (struct GNUNET_MessageHeader)) + else { - ssize_t t = write (fd_tun, &pkt[1], - ntohs (pkt->size) - - sizeof (struct GNUNET_MessageHeader) - tin); - if (t <= 0) - { - fprintf (stderr, "write-error 3: %s\n", - strerror (errno)); - shutdown (fd_tun, SHUT_WR); - shutdown (0, SHUT_RD); - wri = 0; - goto outer; - } - tin += t; + buftun_read = buftun; + struct GNUNET_MessageHeader *hdr = + (struct GNUNET_MessageHeader *) buftun; + hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + hdr->size = htons (buftun_size); } } - else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r)) + else if (FD_ISSET (1, &fds_w)) { - write_stdout_possible = 0; - tin = read (fd_tun, buf, MAX_SIZE); - if (tin <= 0) + ssize_t written = write (1, buftun_read, buftun_size); + if (-1 == written) { - fprintf (stderr, "read-error: %s\n", strerror (errno)); + fprintf (stderr, "write-error to stdout: %s\n", + strerror (errno)); shutdown (fd_tun, SHUT_RD); shutdown (1, SHUT_WR); rea = 0; - goto outer; + buftun_size = 0; + } + buftun_size -= written; + buftun_read += written; + } + + if (FD_ISSET (0, &fds_r)) + { + bufin_size = read (0, bufin, MAX_SIZE); + if (-1 == bufin_size) + { + fprintf (stderr, "read-error: %s\n", strerror (errno)); + shutdown (0, SHUT_RD); + shutdown (fd_tun, SHUT_WR); + wri = 0; + bufin_size = 0; } - struct GNUNET_MessageHeader hdr = {.size = - htons (r + sizeof (struct GNUNET_MessageHeader)),.type = - htons (GNUNET_MESSAGE_TYPE_VPN_HELPER) - }; - tin = 0; - while (tin < sizeof (struct GNUNET_MessageHeader)) + else if (0 == bufin_size) { - ssize_t t = - write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - tin); - if (t < 0) - { - fprintf (stderr, "write-error 2: %s\n", - strerror (errno)); - shutdown (fd_tun, SHUT_RD); - shutdown (1, SHUT_WR); - rea = 0; - goto outer; - } - tin += t; + fprintf (stderr, "eof on stdin\n"); + shutdown (0, SHUT_RD); + shutdown (fd_tun, SHUT_WR); + wri = 0; + bufin_size = 0; } - while (tin < ntohs (hdr.size)) + else { - size_t t = write (1, buf, ntohs (hdr.size) - tin); - if (t < 0) + struct GNUNET_MessageHeader *hdr = + (struct GNUNET_MessageHeader *) bufin; + if ((bufin_size < sizeof (struct GNUNET_MessageHeader)) + || (ntohs (hdr->type) != GNUNET_MESSAGE_TYPE_VPN_HELPER) + || (ntohs (hdr->size) != bufin_size)) { - fprintf (stderr, "write-error 1: %s, written %d/%d\n", - strerror (errno), r, ntohs (hdr.size)); - shutdown (fd_tun, SHUT_RD); - shutdown (1, SHUT_WR); - rea = 0; - goto outer; + fprintf (stderr, "protocol violation!\n"); + exit (1); } - tin += t; + bufin_write = bufin + sizeof (struct GNUNET_MessageHeader); + bufin_size -= sizeof (struct GNUNET_MessageHeader); + } + } + else if (FD_ISSET (fd_tun, &fds_w)) + { + ssize_t written = write (fd_tun, bufin_write, bufin_size); + if (-1 == written) + { + fprintf (stderr, "write-error to tun: %s\n", + strerror (errno)); + shutdown (0, SHUT_RD); + shutdown (fd_tun, SHUT_WR); + wri = 0; + bufin_size = 0; } + bufin_size -= written; + bufin_write += written; } } } } -int -main (int argc, - char** argv) +int +main (int argc, char **argv) { char dev[IFNAMSIZ]; int fd_tun; @@ -406,8 +476,7 @@ main (int argc, memset (dev, 0, IFNAMSIZ); if (-1 == (fd_tun = init_tun (dev))) { - fprintf (stderr, - "Fatal: could not initialize tun-interface\n"); + fprintf (stderr, "Fatal: could not initialize tun-interface\n"); return 1; } @@ -428,9 +497,7 @@ main (int argc, uid_t uid = getuid (); if (0 != setresuid (uid, uid, uid)) - fprintf (stderr, - "Failed to setresuid: %s\n", - strerror (errno)); + fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno)); run (fd_tun); close (fd_tun); return 0;