/* writes an 802.15.4 packet to slip-radio */ void write_to_slip(const uint8_t * buf, int len) { if(slipfd > 0) { write_to_serial(slipfd, buf, len); } }
/* * Read from tun, write to slip. */ void tun_to_serial(int infd, int outfd) { static union { unsigned char inbuf[2000]; struct ip iphdr; } uip; int size; if ((size = read(infd, uip.inbuf, 2000)) == -1) err(1, "tun_to_serial: read"); write_to_serial(outfd, uip.inbuf, size); }
/* * Read from tun, write to slip. */ int tun_to_serial(int infd, int outfd) { struct { unsigned char inbuf[2000]; } uip; int size; if((size = read(infd, uip.inbuf, 2000)) == -1) err(1, "tun_to_serial: read"); write_to_serial(outfd, uip.inbuf, size); return size; }
int main(int argc, char **argv) { int c; int slipfd, maxfd; int ret; fd_set rset, wset; FILE *inslip; char siodev[10] = ""; int baudrate = -2; char buf[4000]; prog = argv[0]; setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */ memset(&osVersionInfo,0,sizeof(OSVERSIONINFO)); osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osVersionInfo); while((c = getopt(argc, argv, "B:D:L:hs:c:ra:p:vtb:")) != -1) { switch (c) { case 'B': baudrate = atoi(optarg); break; case 'L': if(strncmp("0", optarg, 1) == 0) { timestamp = 0; } else { timestamp = atoi(optarg); if (timestamp==0) timestamp=1; } break; case 's': if(strncmp("/dev/", optarg, 5) == 0) { strncpy(siodev,optarg + 5,sizeof(siodev)-1); } else if(strncmp("COM", optarg, 3) == 0) { int portnum; portnum = atoi(optarg+3); if(portnum == 0){ err(1,"port number is invalid"); } sprintf(siodev,"ttyS%d",portnum-1); } else { strncpy(siodev,optarg,sizeof(siodev)-1); } break; case 'c': channel = atoi(optarg); set_channel = 1; break; case 'r': sniffer_mode = 1; break; case 'a': if(autoconf == true){ print_help(); } local_ipaddr = optarg; if (!validIPAddr(local_ipaddr, 0)){ if (timestamp) stamptime(); fprintf(stderr, "Invalid IPv6 address: %s", local_ipaddr); exit(1); } break; case 'p': if(local_ipaddr !=NULL){ print_help(); } autoconf = true; ipprefix = optarg; if (!validIPAddr(ipprefix, 0)){ if (timestamp) stamptime(); fprintf(stderr, "Invalid IPv6 prefix: %s", ipprefix); exit(1); } break; case 'v': verbose = true; break; case 't': tun = true; break; case 'b': br_prefix = optarg; send_prefix = true; send_mac = false; tun = true; if (!validIPAddr(br_prefix, 64)){ if (timestamp) stamptime(); fprintf(stderr, "Invalid IPv6 64-bit prefix: %s", br_prefix); exit(1); } strtok(br_prefix,"/"); // Remove prefix length if it is present. break; case '?': case 'h': default: print_help(); break; } } argc -= (optind - 1); argv += (optind - 1); if(argc != 2 || *siodev == '\0') { print_help(); } if(autoconf == true && br_prefix != NULL){ if (timestamp) stamptime(); fprintf(stderr, "-p and -b options cannot be used together.\r\n"); print_help(); } sscanf(argv[1],"%2X-%2X-%2X-%2X-%2X-%2X", (int *)&adapter_eth_addr.addr[0],(int *)&adapter_eth_addr.addr[1], (int *)&adapter_eth_addr.addr[2],(int *)&adapter_eth_addr.addr[3], (int *)&adapter_eth_addr.addr[4],(int *)&adapter_eth_addr.addr[5]); if_name = wpcap_start(&adapter_eth_addr, verbose); if(local_ipaddr!=NULL){ addAddress(if_name, local_ipaddr); } 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; case 230400: b_rate = B230400; break; case 460800: b_rate = B460800; break; case 921600: b_rate = B921600; break; default: err(1, "unknown baudrate %d", baudrate); break; } slipfd = devopen(siodev, O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC ); if(slipfd == -1) { err(1, "can't open siodev ``/dev/%s''", siodev); } if (timestamp) stamptime(); fprintf(stderr, "wpcapslip6 started on ``/dev/%s''\n", siodev); stty_telos(slipfd); slip_send(SLIP_END); inslip = fdopen(slipfd, "r"); if(inslip == NULL) err(1, "main: fdopen"); atexit(cleanup); signal(SIGHUP, sigcleanup); signal(SIGTERM, sigcleanup); signal(SIGINT, sigcleanup); signal(SIGALRM, sigalarm); /* Request mac address from gateway. It may be useful for setting the best IPv6 address of the local interface. */ while(1) { maxfd = 0; FD_ZERO(&rset); FD_ZERO(&wset); send_commands(); if(!slip_empty()) { /* Anything to flush? */ FD_SET(slipfd, &wset); } FD_SET(slipfd, &rset); /* Read from slip ASAP! */ if(slipfd > maxfd) maxfd = slipfd; #ifdef WITH_STDIN FD_SET(STDIN_FILENO, &rset); /* Read from stdin too. */ if(STDIN_FILENO > maxfd) maxfd = STDIN_FILENO; /* This would not be necessary, since we know STDIN_FILENO is 0. */ #endif if(slip_empty()) { char *pbuf = buf; ret = wpcap_poll(pbuf); if( ret > 0 ){ struct uip_eth_hdr * eth_hdr = (struct uip_eth_hdr *)pbuf; if(eth_hdr->type == htons(UIP_ETHTYPE_IPV6)){ // We forward only IPv6 packet. if(tun){ // Cut away ethernet header. pbuf += sizeof(struct uip_eth_hdr); ret -= sizeof(struct uip_eth_hdr); } write_to_serial(pbuf, ret); /*print_packet(pbuf, ret);*/ slip_flushbuf(slipfd); } } } { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 10; ret = select(maxfd + 1, &rset, &wset, NULL, &tv); } if(ret == -1 && errno != EINTR && errno != EAGAIN) { err(1, "select"); } else if(ret > 0) { if(FD_ISSET(slipfd, &rset)) { /* printf("serial_to_wpcap\n"); */ serial_to_wpcap(inslip); /* printf("End of serial_to_wpcap\n");*/ } if(FD_ISSET(slipfd, &wset)) { slip_flushbuf(slipfd); } #ifdef WITH_STDIN if(FD_ISSET(STDIN_FILENO, &rset)) { char inbuf; if(fread(&inbuf,1,1,stdin)){ if(inbuf=='q'){ exit(0); } } } #endif } } }
void relay_dhcp_to_client(int slipfd) { struct dhcp_msg inm; struct { struct ip ip; struct dhcp_light_msg m; } pkt; int n, optlen, ip_len, udp_len; u_int8_t *p, *t, *end; u_int16_t sum; u_int8_t op, msg_type = 0; struct in_addr yiaddr; memset(&inm.options, 0x0, sizeof(inm.options)); n = recv(dhsock, &inm, sizeof(inm), 0x0/*flags*/); if (inm.op != BOOTREPLY) { return; } memcpy(&yiaddr, inm.yiaddr, sizeof(inm.yiaddr)); memcpy(&pkt.m, &inm, DHCP_BASE_LEN); pkt.m.hops++; memset(pkt.m.giaddr, 0x0, sizeof(pkt.m.giaddr)); /* * Copy options we would like to send to client. */ memcpy(pkt.m.options, inm.options, 4); /* Magic cookie */ end = &inm.op + n; p = inm.options + 4; /* Magic cookie */ t = pkt.m.options + 4; /* Magic cookie */ while (p < end) { op = p[0]; switch (op) { case DHCP_OPTION_END: goto done; case DHCP_OPTION_MSG_TYPE: msg_type = p[2]; case DHCP_OPTION_SUBNET_MASK: case DHCP_OPTION_ROUTER: case DHCP_OPTION_LEASE_TIME: case DHCP_OPTION_SERVER_ID: /* Copy these options */ memcpy(t, p, p[1] + 2); t += p[1] + 2; p += p[1] + 2; break; case DHCP_OPTION_DNS_SERVER: /* Only copy first server */ *t++ = p[0]; *t++ = 4; memcpy(t, p + 2, 4); t += 4; p += p[1] + 2; break; default: /* Ignore these options */ /* printf("option type %d len %d\n", op, p[1]); */ p += p[1] + 2; continue; } } done: if (op == DHCP_OPTION_END) { *t++ = op; //*p++; } optlen = t - pkt.m.options; ip_len = 20 + 8 + DHCP_BASE_LEN + optlen; udp_len = 8 + DHCP_BASE_LEN + optlen; pkt.ip.ip_vhl = 0x45; /* IPv4 and hdrlen=5*4 */ pkt.ip.ip_tos = 0; pkt.ip.ip_len = htons(ip_len); pkt.ip.ip_id = htons(ip_id++); pkt.ip.ip_off = 0; pkt.ip.ip_ttl = 64; pkt.ip.ip_p = 17; /* proto UDP */ pkt.ip.ip_sum = 0; pkt.ip.ip_src = giaddr; if (inm.flags & htons(BOOTP_BROADCAST)) /* check bcast bit */ pkt.ip.ip_dst = 0xffffffff; /* 255.255.255.255 */ else pkt.ip.ip_dst = yiaddr.s_addr; pkt.ip.uh_sport = htons(BOOTPS); pkt.ip.uh_dport = htons(BOOTPC); pkt.ip.uh_ulen = htons(udp_len); pkt.ip.uh_sum = 0; pkt.ip.ip_sum = ~htons(ip4sum(0, &pkt.ip, 20)); sum = 17 + udp_len; sum = ip4sum(sum, &pkt.ip.ip_src, 8); sum = ip4sum(sum, &pkt.ip.uh_sport, udp_len); if (sum != 0xffff) pkt.ip.uh_sum = ~htons(sum); else pkt.ip.uh_sum = 0xffff; write_to_serial(slipfd, &pkt, ip_len); if (msg_type == DHCPACK) { printf("DHCPACK %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x IP %s\n", pkt.m.chaddr[0], pkt.m.chaddr[1], pkt.m.chaddr[2], pkt.m.chaddr[3], pkt.m.chaddr[4], pkt.m.chaddr[5], pkt.m.chaddr[6], pkt.m.chaddr[7], inet_ntoa(yiaddr)); /* ssystem("arp -s %s auto pub only", inet_ntoa(yiaddr)); */ } }
/* writes an 802.15.4 packet to slip-radio */ void write_to_slip(const uint8_t *buf, int len) { /* printf("Packet to SLIP: %d\n", len); */ write_to_serial(slipfd, buf, len); }