Exemple #1
0
	int
main(int argc, char **argv)
{
	int c;
	int tunfd, maxfd;
	int ret;
	fd_set rset, wset;
	FILE *inslip;
	const char *siodev = NULL;
	const char *host = NULL;
	const char *port = NULL;
	const char *prog;
	int baudrate = -2;
	int tap = 0;
	slipfd = 0;

	prog = argv[0];
	setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */

	while((c = getopt(argc, argv, "B:D:Lhs:t:v::d::a:p:T")) != -1) {
		switch(c) {
			case 'B':
				baudrate = atoi(optarg);
				break;

			case 'L':
				timestamp=1;
				break;

			case 's':
				if(strncmp("/dev/", optarg, 5) == 0) {
					siodev = optarg + 5;
				} else {
					siodev = optarg;
				}
				break;

			case 't':
				if(strncmp("/dev/", optarg, 5) == 0) {
					strncpy(tundev, optarg + 5, sizeof(tundev));
				} else {
					strncpy(tundev, optarg, sizeof(tundev));
				}
				break;

			case 'a':
				host = optarg;
				break;

			case 'p':
				port = optarg;
				break;

			case 'd':
				basedelay = 10;
				if (optarg) basedelay = atoi(optarg);
				break;

			case 'v':
				verbose = 2;
				if (optarg) verbose = atoi(optarg);
				break;

			case 'T':
				tap = 1;
				break;

			case '?':
			case 'h':
			default:
				fprintf(stderr,"usage:  %s [options] ipaddress\n", prog);
				fprintf(stderr,"example: tunslip6 -L -v2 -s ttyUSB1 aaaa::1/64\n");
				fprintf(stderr,"Options are:\n");
				fprintf(stderr," -B baudrate    9600,19200,38400,57600,115200 (default)\n");
				fprintf(stderr," -L             Log output format (adds time stamps)\n");
				fprintf(stderr," -s siodev      Serial device (default /dev/ttyUSB0)\n");
				fprintf(stderr," -T             Make tap interface (default is tun interface)\n");
				//fprintf(stderr," -t tundev      Name of interface (default tap0 or tun0)\n");
				fprintf(stderr," -t tundev      Name of interface\n");
				fprintf(stderr," -v[level]      Verbosity level\n");
				fprintf(stderr,"    -v0         No messages\n");
				fprintf(stderr,"    -v1         Encapsulated SLIP debug messages (default)\n");
				fprintf(stderr,"    -v2         Printable strings after they are received\n");
				fprintf(stderr,"    -v3         Printable strings and SLIP packet notifications\n");
				fprintf(stderr,"    -v4         All printable characters as they are received\n");
				fprintf(stderr,"    -v5         All SLIP packets in hex\n");
				fprintf(stderr,"    -v          Equivalent to -v3\n");
				fprintf(stderr," -d[basedelay]  Minimum delay between outgoing SLIP packets.\n");
				fprintf(stderr,"                Actual delay is basedelay*(#6LowPAN fragments) milliseconds.\n");
				fprintf(stderr,"                -d is equivalent to -d10.\n");
				fprintf(stderr," -a serveraddr  \n");
				fprintf(stderr," -p serverport  \n");
				exit(1);
				break;
		}
	}
	argc -= (optind - 1);
	argv += (optind - 1);

	if(argc != 2 && argc != 3) {
		err(1, "usage: %s [-B baudrate] [-L] [-s siodev] [-t tundev] [-T] [-v verbosity] [-d delay] [-a serveraddress] [-p serverport] ipaddress", prog);
	}
	ipaddr = argv[1];

	switch(baudrate) {
		case -2:
			break;			/* Use default. */
		case 9600:
			b_rate = B9600;
			break;
		case 19200:
			b_rate = B19200;
			break;
		case 38400:
			b_rate = B38400;
			break;
		case 57600:
			b_rate = B57600;
			break;
		case 115200:
			b_rate = B115200;
			break;
		default:
			err(1, "unknown baudrate %d", baudrate);
			break;
	}

#if 0
	if(*tundev == '\0') {
		/* Use default. */
		if(tap) {
			strcpy(tundev, "tap0");
		} else {
			strcpy(tundev, "tun0");
		}
	}
#endif
	if(host != NULL) {
		struct addrinfo hints, *servinfo, *p;
		int rv;
		char s[INET6_ADDRSTRLEN];

		if(port == NULL) {
			port = "60001";
		}

		memset(&hints, 0, sizeof hints);
		hints.ai_family = AF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;

		if((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
			err(1, "getaddrinfo: %s", gai_strerror(rv));
		}

		/* loop through all the results and connect to the first we can */
		for(p = servinfo; p != NULL; p = p->ai_next) {
			if((slipfd = socket(p->ai_family, p->ai_socktype,
							p->ai_protocol)) == -1) {
				perror("client: socket");
				continue;
			}

			if(connect(slipfd, p->ai_addr, p->ai_addrlen) == -1) {
				close(slipfd);
				perror("client: connect");
				continue;
			}
			break;
		}

		if(p == NULL) {
			err(1, "can't connect to ``%s:%s''", host, port);
		}

		fcntl(slipfd, F_SETFL, O_NONBLOCK);

		inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
				s, sizeof(s));
		fprintf(stderr, "slip connected to ``%s:%s''\n", s, port);

		/* all done with this structure */
		freeaddrinfo(servinfo);

	} else {
		if(siodev != NULL) {
			slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);
			if(slipfd == -1) {
				err(1, "can't open siodev ``/dev/%s''", siodev);
			}
		} else {
			static const char *siodevs[] = {
				"ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
			};
			int i;
			for(i = 0; i < 3; i++) {
				siodev = siodevs[i];
				slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);
				if(slipfd != -1) {
					break;
				}
			}
			if(slipfd == -1) {
				err(1, "can't open siodev");
			}
		}
		if (timestamp) stamptime();
		fprintf(stderr, "********SLIP started on ``/dev/%s''\n", siodev);
		stty_telos(slipfd);
	}
	slip_send(slipfd, SLIP_END);
	inslip = fdopen(slipfd, "r");
	if(inslip == NULL) err(1, "main: fdopen");

	tunfd = tun_alloc(tundev, tap);
	if(tunfd == -1) err(1, "main: open");
	if (timestamp) stamptime();
	fprintf(stderr, "opened %s device ``/dev/%s''\n",
			tap ? "tap" : "tun", tundev);

	atexit(cleanup);
	signal(SIGHUP, sigcleanup);
	signal(SIGTERM, sigcleanup);
	signal(SIGINT, sigcleanup);
	signal(SIGALRM, sigalarm);
	ifconf(tundev, ipaddr);

	while(1) {
		maxfd = 0;
		FD_ZERO(&rset);
		FD_ZERO(&wset);

		/* do not send IPA all the time... - add get MAC later... */
		/*     if(got_sigalarm) { */
		/*       /\* Send "?IPA". *\/ */
		/*       slip_send(slipfd, '?'); */
		/*       slip_send(slipfd, 'I'); */
		/*       slip_send(slipfd, 'P'); */
		/*       slip_send(slipfd, 'A'); */
		/*       slip_send(slipfd, SLIP_END); */
		/*       got_sigalarm = 0; */
		/*     } */

		if(!slip_empty()) {		/* Anything to flush? */
			FD_SET(slipfd, &wset);
		}

		FD_SET(slipfd, &rset);	/* Read from slip ASAP! */
		if(slipfd > maxfd) maxfd = slipfd;

		/* We only have one packet at a time queued for slip output. */
		if(slip_empty()) {
			FD_SET(tunfd, &rset);
			if(tunfd > maxfd) maxfd = tunfd;
		}

		ret = select(maxfd + 1, &rset, &wset, NULL, NULL);
		if(ret == -1 && errno != EINTR) {
			err(1, "select");
		} else if(ret > 0) {
			if(FD_ISSET(slipfd, &rset)) {
				serial_to_tun(inslip, tunfd);
			}

			if(FD_ISSET(slipfd, &wset)) {
				slip_flushbuf(slipfd);
				sigalarm_reset();
			}

			/* Optional delay between outgoing packets */
			/* Base delay times number of 6lowpan fragments to be sent */
			if(delaymsec) {
				struct timeval tv;
				int dmsec;
				gettimeofday(&tv, NULL) ;
				dmsec=(tv.tv_sec-delaystartsec)*1000+tv.tv_usec/1000-delaystartmsec;
				if(dmsec<0) delaymsec=0;
				if(dmsec>delaymsec) delaymsec=0;
			}

			if(delaymsec==0) {
				//int size;

				if(slip_empty() && FD_ISSET(tunfd, &rset)) {
					//size = tun_to_serial(tunfd, slipfd);
					tun_to_serial(tunfd, slipfd);
					slip_flushbuf(slipfd);
					sigalarm_reset();

					if(basedelay) {
						struct timeval tv;
						gettimeofday(&tv, NULL) ;
						//         delaymsec=basedelay*(1+(size/120));//multiply by # of 6lowpan packets?
						delaymsec=basedelay;
						delaystartsec =tv.tv_sec;
						delaystartmsec=tv.tv_usec/1000;
					}
				}
			}
		}
	}
}
Exemple #2
0
int
main(int argc, char **argv)
{
  int c;
  int tunfd, slipfd, maxfd;
  int ret;
  fd_set rset, wset;
  FILE *inslip;
  const char *siodev = NULL;
  int baudrate = -2;
  request_mac = 1;
  setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */

  while((c = getopt(argc, argv, "B:D:hs:t:")) != -1) {
    switch (c) {
    case 'B':
      baudrate = atoi(optarg);
      break;

    case 's':
      if(strncmp("/dev/", optarg, 5) == 0) {
	siodev = optarg + 5;
      } else {
	siodev = optarg;
      }
      break;

    case 't':
      if(strncmp("/dev/", optarg, 5) == 0) {
	strcpy(tundev, optarg + 5);
      } else {
	strcpy(tundev, optarg);
      }
      break;

    case '?':
    case 'h':
    default:
      errx(1, USAGE_STRING);
      break;
    }
  }
  argc -= (optind - 1);
  argv += (optind - 1);

  if(argc != 3 && argc != 4) {
    errx(1, USAGE_STRING);
  }
  ipaddr = argv[1];
  netmask = argv[2];
  circuit_addr = inet_addr(ipaddr);
  netaddr = inet_addr(ipaddr) & inet_addr(netmask);

  switch(baudrate) {
  case -2:
    break;			/* Use default. */
  case 9600:
    b_rate = B9600;
    break;
  case 19200:
    b_rate = B19200;
    break;
  case 38400:
    b_rate = B38400;
    break;
  case 57600:
    b_rate = B57600;
    break;
  case 115200:
    b_rate = B115200;
    break;
  default:
    err(1, "unknown baudrate %d", baudrate);
    break;
  }


  if(siodev != NULL) {
      slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);
      if(slipfd == -1) {
	err(1, "can't open siodev ``/dev/%s''", siodev);
      }
  } else {
    static const char *siodevs[] = {
      "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
    };
    int i;
    for(i = 0; i < 3; i++) {
      siodev = siodevs[i];
      slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);
      if (slipfd != -1)
	break;
    }
    if(slipfd == -1) {
      err(1, "can't open siodev");
    }
  }
  fprintf(stderr, "slip started on ``/dev/%s''\n", siodev);
  stty_telos(slipfd);
  slip_send(slipfd, SLIP_END);
  inslip = fdopen(slipfd, "r");
  if(inslip == NULL) err(1, "main: fdopen");

  tunfd = tun_alloc(tundev);
  printf("opening: %s", tundev);
  if(tunfd == -1) err(1, "main: open");
  fprintf(stderr, "opened device ``/dev/%s''\n", tundev);

  atexit(cleanup);
  signal(SIGHUP, sigcleanup);
  signal(SIGTERM, sigcleanup);
  signal(SIGINT, sigcleanup);
  signal(SIGALRM, sigalarm);
  ifconf(tundev, ipaddr, netmask);

  while(1) {
    maxfd = 0;
    FD_ZERO(&rset);
    FD_ZERO(&wset);

    /* request mac address from gateway node for autoconfiguration of
       ethernet interface tap0 */
    if (request_mac) {
      slip_send(slipfd, '?');
      slip_send(slipfd, 'M');
      slip_send(slipfd, SLIP_END);
      request_mac = 0;
    }

    if(got_sigalarm) {
      /* Send "?IPA". */
      slip_send(slipfd, '?');
      slip_send(slipfd, 'I');
      slip_send(slipfd, 'P');
      slip_send(slipfd, 'A');
      slip_send(slipfd, SLIP_END);
      got_sigalarm = 0;
    }

    if(!slip_empty()) {		/* Anything to flush? */
      FD_SET(slipfd, &wset);
    }

    FD_SET(slipfd, &rset);	/* Read from slip ASAP! */
    if(slipfd > maxfd) maxfd = slipfd;

    /* We only have one packet at a time queued for slip output. */
    if(slip_empty()) {
      FD_SET(tunfd, &rset);
      if(tunfd > maxfd) maxfd = tunfd;
    }

    ret = select(maxfd + 1, &rset, &wset, NULL, NULL);
    if(ret == -1 && errno != EINTR) {
      err(1, "select");
    } else if(ret > 0) {
      if(FD_ISSET(slipfd, &rset)) {
        serial_to_tun(inslip, tunfd);
      }

      if(FD_ISSET(slipfd, &wset)) {
	slip_flushbuf(slipfd);
	sigalarm_reset();
      }

      if(slip_empty() && FD_ISSET(tunfd, &rset)) {
        tun_to_serial(tunfd, slipfd);
	slip_flushbuf(slipfd);
	sigalarm_reset();
      }
    }
  }
}
Exemple #3
0
int main(int argc, char **argv)
{
	int c;
	int tunfd, slipfd, maxfd;
	int ret;
	fd_set rset, wset;

	unsigned short dst_port = DST_PORT + 1;

	ip_id = getpid() * time(NULL);

	setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */

	while ((c = getopt(argc, argv, "n:t:")) != -1) {
		switch (c) {
		case 'n':
			dst_port = DST_PORT + atoi(optarg);
			break;
		case 't':
			if (strncmp("/dev/", optarg, 5) == 0) {
				strcpy(tundev, optarg + 5);
			} else {
				strcpy(tundev, optarg);
			}
			break;

		case '?':
		case 'h':
		default:
			err(1,USAGE_STRING);
			break;
		}
	}
	argc -= (optind - 1);
	argv += (optind - 1);

	if (argc != 1) {
		err(1, USAGE_STRING);
	}
	ipaddr = "172.16.0.0";
	netmask = "255.255.0.0";
	circuit_addr = inet_addr(ipaddr);
	netaddr = inet_addr(ipaddr) & inet_addr(netmask);

	slipfd = devopen(dst_port);
	if (slipfd == -1) {
		err(1, "can't open port %u", dst_port);
	}

	fprintf(stderr, "slip sending to port %u\n", dst_port);
	stty_telos(slipfd);
	slip_send(slipfd, SLIP_END);

	tunfd = tun_alloc(tundev);
	if (tunfd == -1)
		err(1, "main: open");
	fprintf(stderr, "opened device ``/dev/%s''\n", tundev);

	atexit(cleanup);
	signal(SIGHUP, sigcleanup);
	signal(SIGTERM, sigcleanup);
	signal(SIGINT, sigcleanup);
	signal(SIGALRM, sigalarm);
	ifconf(tundev, ipaddr, netmask);

	while (1) {
		maxfd = 0;
		FD_ZERO(&rset);
		FD_ZERO(&wset);

		if (got_sigalarm) {
			/* Send "?IPA". */
			slip_send(slipfd, '?');
			slip_send(slipfd, 'I');
			slip_send(slipfd, 'P');
			slip_send(slipfd, 'A');
			slip_send(slipfd, SLIP_END);
			got_sigalarm = 0;
		}

		if (!slip_empty()) { /* Anything to flush? */
			FD_SET(slipfd, &wset);
		}

		FD_SET(slipfd, &rset); /* Read from slip ASAP! */
		if (slipfd > maxfd)
			maxfd = slipfd;

		/* We only have one packet at a time queued for slip output. */
		if (slip_empty()) {
			FD_SET(tunfd, &rset);
			if (tunfd > maxfd)
				maxfd = tunfd;
			if (dhsock != -1) {
				FD_SET(dhsock, &rset);
				if (dhsock > maxfd)
					maxfd = dhsock;
			}
		}

		ret = select(maxfd + 1, &rset, &wset, NULL, NULL);
		if (ret == -1 && errno != EINTR) {
			err(1, "select");
		} else if (ret > 0) {
			if (FD_ISSET(slipfd, &rset)) {
				serial_to_tun(slipfd, tunfd);
			}

			if (FD_ISSET(slipfd, &wset)) {
				slip_flushbuf(slipfd);
				sigalarm_reset();
			}

			if (slip_empty() && FD_ISSET(tunfd, &rset)) {
				tun_to_serial(tunfd, slipfd);
				slip_flushbuf(slipfd);
				sigalarm_reset();
			}

			if (dhsock != -1 && slip_empty() && FD_ISSET(dhsock, &rset)) {
				relay_dhcp_to_client(slipfd); ///  ####  ////
				slip_flushbuf(slipfd);
			}
		}
	}
}
Exemple #4
0
int
main(int argc, char **argv)
{
    int c;
    int tunfd, slipfd, maxfd;
    int ret;
    fd_set rset, wset;
    FILE *inslip;
    const char *siodev = NULL;
    const char *dhcp_server = NULL;
    u_int16_t myport = BOOTPS, dhport = BOOTPS;
    int baudrate = -2;

    ip_id = getpid() * time(NULL);

    setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */

    while ((c = getopt(argc, argv, "B:D:hs:t:")) != -1) {
        switch (c) {
            case 'B':
                baudrate = atoi(optarg);
                break;

            case 'D':
                dhcp_server = optarg;
                break;

            case 's':
                if (strncmp("/dev/", optarg, 5) == 0) {
                    siodev = optarg + 5;
                }
                else {
                    siodev = optarg;
                }

                break;

            case 't':
                if (strncmp("/dev/", optarg, 5) == 0) {
                    strcpy(tundev, optarg + 5);
                }
                else {
                    strcpy(tundev, optarg);
                }

                break;

            case '?':
            case 'h':
            default:
                err(1, "usage: tunslip [-B baudrate] [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]");
                break;
        }
    }

    argc -= (optind - 1);
    argv += (optind - 1);

    if (argc != 3 && argc != 4) {
        err(1, "usage: tunslip [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]");
    }

    ipaddr = argv[1];
    netmask = argv[2];
    circuit_addr = inet_addr(ipaddr);
    netaddr = inet_addr(ipaddr) & inet_addr(netmask);

    switch (baudrate) {
        case -2:
            break;			/* Use default. */

        case 9600:
            b_rate = B9600;
            break;

        case 19200:
            b_rate = B19200;
            break;

        case 38400:
            b_rate = B38400;
            break;

        case 57600:
            b_rate = B57600;
            break;

        case 115200:
            b_rate = B115200;
            break;

        default:
            err(1, "unknown baudrate %d", baudrate);
            break;
    }

    /*
     * Set up DHCP relay agent socket and find the address of this relay
     * agent.
     */
    if (argc == 4) {
        dhcp_server = argv[3];
    }

    if (dhcp_server != NULL) {
        struct sockaddr_in myaddr;
        socklen_t len;
        in_addr_t a;

        if (strchr(dhcp_server, ':') != NULL) {
            dhport = atoi(strchr(dhcp_server, ':') + 1);
            myport = dhport + 1;
            *strchr(dhcp_server, ':') = '\0';
        }

        a = inet_addr(dhcp_server);

        if (a == -1) {
            err(1, "illegal dhcp-server address");
        }

#ifndef linux
        dhaddr.sin_len = sizeof(dhaddr);
#endif
        dhaddr.sin_family = AF_INET;
        dhaddr.sin_port = htons(dhport);
        dhaddr.sin_addr.s_addr = a;

        dhsock = socket(AF_INET, SOCK_DGRAM, 0);

        if (dhsock < 0) {
            err(1, "socket");
        }

        memset(&myaddr, 0x0, sizeof(myaddr));
#ifndef linux
        myaddr.sin_len = sizeof(myaddr);
#endif
        myaddr.sin_family = AF_INET;
        myaddr.sin_addr.s_addr = INADDR_ANY;
        myaddr.sin_port = htons(myport);

        if (bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
            err(1, "bind dhcp-relay");
        }

        if (connect(dhsock, (struct sockaddr *)&dhaddr, sizeof(dhaddr)) < 0) {
            err(1, "connect to dhcp-server");
        }

        len = sizeof(myaddr);

        if (getsockname(dhsock, (struct sockaddr *)&myaddr, &len) < 0) {
            err(1, "getsockname dhsock");
        }

        giaddr = myaddr.sin_addr.s_addr;

        /*
         * Don't want connected socket.
         */
        close(dhsock);
        dhsock = socket(AF_INET, SOCK_DGRAM, 0);

        if (dhsock < 0) {
            err(1, "socket");
        }

        myaddr.sin_family = AF_INET;
        myaddr.sin_addr.s_addr = INADDR_ANY;
        myaddr.sin_port = htons(myport);

        if (bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
            err(1, "bind dhcp-relay");
        }

        fprintf(stderr, "DHCP server at %s:%d\n", dhcp_server, dhport);
    }

    if (siodev != NULL) {
        slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);

        if (slipfd == -1) {
            err(1, "can't open siodev ``/dev/%s''", siodev);
        }
    }
    else {
        static const char *siodevs[] = {
            "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
        };
        int i;

        for (i = 0; i < 3; i++) {
            siodev = siodevs[i];
            slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);

            if (slipfd != -1) {
                break;
            }
        }

        if (slipfd == -1) {
            err(1, "can't open siodev");
        }
    }

    fprintf(stderr, "slip started on ``/dev/%s''\n", siodev);
    stty_telos(slipfd);
    slip_send(slipfd, SLIP_END);
    inslip = fdopen(slipfd, "r");

    if (inslip == NULL) {
        err(1, "main: fdopen");
    }

    tunfd = tun_alloc(tundev);

    if (tunfd == -1) {
        err(1, "main: open");
    }

    fprintf(stderr, "opened device ``/dev/%s''\n", tundev);

    atexit(cleanup);
    signal(SIGHUP, sigcleanup);
    signal(SIGTERM, sigcleanup);
    signal(SIGINT, sigcleanup);
    signal(SIGALRM, sigalarm);
    ifconf(tundev, ipaddr, netmask);

    while (1) {
        maxfd = 0;
        FD_ZERO(&rset);
        FD_ZERO(&wset);

        if (got_sigalarm) {
            /* Send "?IPA". */
            slip_send(slipfd, '?');
            slip_send(slipfd, 'I');
            slip_send(slipfd, 'P');
            slip_send(slipfd, 'A');
            slip_send(slipfd, SLIP_END);
            got_sigalarm = 0;
        }

        if (!slip_empty()) {		/* Anything to flush? */
            FD_SET(slipfd, &wset);
        }

        FD_SET(slipfd, &rset);	/* Read from slip ASAP! */

        if (slipfd > maxfd) {
            maxfd = slipfd;
        }

        /* We only have one packet at a time queued for slip output. */
        if (slip_empty()) {
            FD_SET(tunfd, &rset);

            if (tunfd > maxfd) {
                maxfd = tunfd;
            }

            if (dhsock != -1) {
                FD_SET(dhsock, &rset);

                if (dhsock > maxfd) {
                    maxfd = dhsock;
                }
            }
        }

        ret = select(maxfd + 1, &rset, &wset, NULL, NULL);

        if (ret == -1 && errno != EINTR) {
            err(1, "select");
        }
        else if (ret > 0) {
            if (FD_ISSET(slipfd, &rset)) {
                serial_to_tun(inslip, tunfd);
            }

            if (FD_ISSET(slipfd, &wset)) {
                slip_flushbuf(slipfd);
                sigalarm_reset();
            }

            if (slip_empty() && FD_ISSET(tunfd, &rset)) {
                tun_to_serial(tunfd, slipfd);
                slip_flushbuf(slipfd);
                sigalarm_reset();
            }

            if (dhsock != -1 && slip_empty() && FD_ISSET(dhsock, &rset)) {
                relay_dhcp_to_client(slipfd);
                slip_flushbuf(slipfd);
            }
        }
    }
}