+static void bridge(int sock, int tap, struct sockaddr *dst, socklen_t dstlen)
+{
+ char buf[65536];
+ int ret;
+ struct pollfd pfds[2];
+ struct tun_pi pi;
+
+ fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
+ fcntl(tap, F_SETFL, fcntl(tap, F_GETFL) | O_NONBLOCK);
+ while(1) {
+ pfds[0].fd = sock;
+ pfds[0].events = POLLIN;
+ pfds[1].fd = tap;
+ pfds[1].events = POLLIN;
+ ret = poll(pfds, 2, -1);
+ if(ret < 0) {
+ if(errno != EINTR) {
+ fprintf(stderr, "mctap: poll: %s\n", strerror(errno));
+ exit(1);
+ }
+ continue;
+ }
+ if(pfds[0].revents) {
+ ret = read(sock, buf, sizeof(buf));
+ if(ret < 0) {
+ if((errno != EINTR) && (errno != EAGAIN)) {
+ fprintf(stderr, "mctap: mcast packet: %s\n", strerror(errno));
+ exit(1);
+ }
+ } else {
+ if(sizeof(buf) - ret < sizeof(pi)) {
+ /* Drop */
+ } else {
+ memmove(buf + sizeof(pi), buf, ret);
+ pi.flags = 0;
+ pi.proto = 0;
+ memcpy(buf, &pi, sizeof(pi));
+ write(tap, buf, ret);
+ }
+ }
+ }
+ if(pfds[1].revents) {
+ ret = read(tap, buf, sizeof(buf));
+ if(ret < 0) {
+ if((errno != EINTR) && (errno != EAGAIN)) {
+ fprintf(stderr, "mctap: mcast packet: %s\n", strerror(errno));
+ exit(1);
+ }
+ } else {
+ if(ret < sizeof(pi)) {
+ /* Drop */
+ } else {
+ memcpy(&pi, buf, sizeof(pi));
+ if(pi.flags & TUN_PKT_STRIP) {
+ /* Drop */
+ } else {
+ sendto(sock, buf + sizeof(pi), ret - sizeof(pi), 0, dst, dstlen);
+ }
+ }
+ }
+ }
+ }
+}
+
+static int maketap(char *name)
+{
+ int fd;
+ struct ifreq rb;
+
+ if((fd = open("/dev/net/tun", O_RDWR)) < 0)
+ return(-1);
+ memset(&rb, 0, sizeof(rb));
+ rb.ifr_flags = IFF_TAP;
+ strncpy(rb.ifr_name, name, IFNAMSIZ);
+ if(ioctl(fd, TUNSETIFF, &rb))
+ return(-1);
+ return(fd);
+}
+