+ if(pfd.revents) {
+ ret = read(fd, buf, sizeof(buf));
+ if(ret < 0) {
+ fprintf(stderr, "mctap: read: %s\n", strerror(errno));
+ exit(1);
+ }
+ for(i = 0; i < ret; i++) {
+ printf("%02x ", (unsigned char)buf[i]);
+ if(i % 20 == 19)
+ putchar(10);
+ }
+ putchar(10);
+ }
+ }
+}
+
+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(!quit) {
+ 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) {
+ syslog(LOG_ERR, "mctap: poll: %s", strerror(errno));
+ exit(1);
+ }
+ continue;
+ }
+ if(pfds[0].revents) {
+ ret = read(sock, buf, sizeof(buf));
+ if(ret < 0) {
+ if((errno != EINTR) && (errno != EAGAIN)) {
+ syslog(LOG_ERR, "mctap: mcast packet: %s", strerror(errno));
+ exit(1);
+ }
+ } else {
+ if(sizeof(buf) - ret < sizeof(pi)) {
+ /* Drop */
+ } else if((ret < 12) || !memcmp(macaddr, buf + 6, 6)) {
+ /* Drop looped back */
+ } else {
+ memmove(buf + sizeof(pi), buf, ret);
+ pi.flags = 0;
+ pi.proto = 0;
+ memcpy(buf, &pi, sizeof(pi));
+ write(tap, buf, sizeof(pi) + ret);
+ }
+ }
+ }
+ if(pfds[1].revents) {
+ ret = read(tap, buf, sizeof(buf));
+ if(ret < 0) {
+ if((errno != EINTR) && (errno != EAGAIN)) {
+ syslog(LOG_ERR, "mctap: mcast packet: %s", 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);
+ if(ioctl(fd, SIOCGIFHWADDR, &rb))
+ return(-1);
+ memcpy(macaddr, rb.ifr_hwaddr.sa_data, 6);
+ return(fd);
+}
+
+static void sighand(int sig)
+{
+ switch(sig) {
+ case SIGINT:
+ case SIGTERM:
+ quit = 1;
+ break;
+ case SIGHUP:
+ break;