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); } } } }
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); } } } }