Adjusted Contiki download page content to the fact that there are now two disk images...
[contiki-2.x.git] / tools / wpcapslip / wpcapslip.c
blobeb465ac081fc431dc605643254b284049d4c7504
1 /*
2 * Copyright (c) 2007, Swedish Institute of Computer Science.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * This file is part of the Contiki operating system.
31 * Author: Oliver Schmidt <ol.sc@web.de>
33 * $Id: wpcapslip.c,v 1.3 2008/06/19 07:52:28 adamdunkels Exp $
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #ifdef __CYGWIN__
41 #include <alloca.h>
42 #else /* __CYGWIN__ */
43 #include <malloc.h>
44 #endif /* __CYGWIN__ */
45 #include <signal.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <stdarg.h>
49 #include <string.h>
50 #include <time.h>
51 #include <sys/types.h>
52 #include <sys/select.h>
54 #include <unistd.h>
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <signal.h>
58 #include <termios.h>
59 #include <sys/ioctl.h>
61 #include <err.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
66 #define PROGRESS(x)
68 void wpcap_start(char *ethifaddr, char *netaddr, char *netmask, int logging);
70 void wpcap_send(void *buf, int len);
72 uint16_t wpcap_poll(char **buf);
74 #include "net/tcpdump.h"
75 static int should_print = 0;
77 #define IP_HLEN 20
79 /*---------------------------------------------------------------------------*/
80 static void
81 print_packet(uint8_t *packet, int len)
83 char buf[2000];
84 if(should_print) {
85 tcpdump_format(packet, len, buf, sizeof(buf));
86 printf("%s\n", buf);
89 /*---------------------------------------------------------------------------*/
90 void cleanup(void);
91 /*---------------------------------------------------------------------------*/
92 void
93 sigcleanup(int signo)
95 fprintf(stderr, "signal %d\n", signo);
96 exit(0); /* exit(0) will call cleanup() */
98 /*---------------------------------------------------------------------------*/
99 #define SLIP_END 0300
100 #define SLIP_ESC 0333
101 #define SLIP_ESC_END 0334
102 #define SLIP_ESC_ESC 0335
104 struct ip {
105 u_int8_t ip_vhl; /* version and header length */
106 #define IP_V4 0x40
107 #define IP_V 0xf0
108 #define IP_HL 0x0f
109 u_int8_t ip_tos; /* type of service */
110 u_int16_t ip_len; /* total length */
111 u_int16_t ip_id; /* identification */
112 u_int16_t ip_off; /* fragment offset field */
113 #define IP_RF 0x8000 /* reserved fragment flag */
114 #define IP_DF 0x4000 /* dont fragment flag */
115 #define IP_MF 0x2000 /* more fragments flag */
116 #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
117 u_int8_t ip_ttl; /* time to live */
118 u_int8_t ip_p; /* protocol */
119 u_int16_t ip_sum; /* checksum */
120 u_int32_t ip_src, ip_dst; /* source and dest address */
121 u_int16_t uh_sport; /* source port */
122 u_int16_t uh_dport; /* destination port */
123 u_int16_t uh_ulen; /* udp length */
124 u_int16_t uh_sum; /* udp checksum */
127 static int ip_id, last_id;
130 ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2)));
133 ssystem(const char *fmt, ...)
135 char cmd[128];
136 va_list ap;
137 va_start(ap, fmt);
138 vsnprintf(cmd, sizeof(cmd), fmt, ap);
139 va_end(ap);
140 printf("%s\n", cmd);
141 fflush(stdout);
142 return system(cmd);
146 is_sensible_string(const unsigned char *s, int len)
148 int i;
149 for(i = 1; i < len; i++) {
150 if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') {
151 continue;
152 } else if(s[i] < ' ' || '~' < s[i]) {
153 return 0;
156 return 1;
160 u_int16_t
161 ip4sum(u_int16_t sum, const void *_p, u_int16_t len)
163 u_int16_t t;
164 const u_int8_t *p = _p;
165 const u_int8_t *end = p + len;
167 while(p < (end-1)) {
168 t = (p[0] << 8) + p[1];
169 sum += t;
170 if (sum < t) sum++;
171 p += 2;
173 if(p < end) {
174 t = (p[0] << 8) + 0;
175 sum += t;
176 if (sum < t) sum++;
178 return sum;
181 static uint16_t
182 chksum(const void *p, uint16_t len)
184 uint16_t sum = ip4sum(0, p, len);
185 return (sum == 0) ? 0xffff : htons(sum);
189 check_ip(const struct ip *ip, unsigned ip_len)
191 u_int16_t sum, ip_hl;
193 /* Check IP version and length. */
194 if((ip->ip_vhl & IP_V) != IP_V4) {
195 return -1;
198 if(ntohs(ip->ip_len) > ip_len) {
199 return -2;
202 if(ntohs(ip->ip_len) < ip_len) {
203 return -3;
206 /* Check IP header. */
207 ip_hl = 4*(ip->ip_vhl & IP_HL);
208 sum = ip4sum(0, ip, ip_hl);
209 if(sum != 0xffff && sum != 0x0) {
210 return -4;
213 if(ip->ip_p == 6 || ip->ip_p == 17) { /* Check TCP or UDP header. */
214 u_int16_t tcp_len = ip_len - ip_hl;
216 /* Sum pseudoheader. */
217 sum = ip->ip_p + tcp_len; /* proto and len, no carry */
218 sum = ip4sum(sum, &ip->ip_src, 8); /* src and dst */
220 /* Sum TCP/UDP header and data. */
221 sum = ip4sum(sum, (u_int8_t*)ip + ip_hl, tcp_len);
223 /* Failed checksum test? */
224 if(sum != 0xffff && sum != 0x0) {
225 if(ip->ip_p == 6) { /* TCP == 6 */
226 return -5;
227 } else { /* UDP */
228 /* Deal with disabled UDP checksums. */
229 if(ip->uh_sum != 0) {
230 return -6;
234 } else if (ip->ip_p == 1) { /* ICMP */
235 u_int16_t icmp_len = ip_len - ip_hl;
237 sum = ip4sum(0, (u_int8_t*)ip + ip_hl, icmp_len);
238 if(sum != 0xffff && sum != 0x0) {
239 return -7;
242 return 0;
246 * Read from serial, when we have a packet write it to tun. No output
247 * buffering, input buffered by stdio.
249 void
250 serial_to_wpcap(FILE *inslip)
252 static union {
253 unsigned char inbuf[2000];
254 struct ip iphdr;
255 } uip;
256 static int inbufptr = 0;
258 int ret;
259 unsigned char c;
261 #ifdef linux
262 ret = fread(&c, 1, 1, inslip);
263 if(ret == -1 || ret == 0) err(1, "serial_to_tun: read");
264 goto after_fread;
265 #endif
267 read_more:
268 if(inbufptr >= sizeof(uip.inbuf)) {
269 inbufptr = 0;
271 ret = fread(&c, 1, 1, inslip);
272 #ifdef linux
273 after_fread:
274 #endif
275 if(ret == -1) {
276 err(1, "serial_to_tun: read");
278 if(ret == 0) {
279 clearerr(inslip);
280 return;
281 fprintf(stderr, "serial_to_tun: EOF\n");
282 exit(1);
284 /* fprintf(stderr, ".");*/
285 switch(c) {
286 case SLIP_END:
287 if(inbufptr > 0) {
289 * Sanity checks.
291 #define DEBUG_LINE_MARKER '\r'
292 int ecode;
293 ecode = check_ip(&uip.iphdr, inbufptr);
294 if(ecode < 0 && inbufptr == 8 && strncmp(uip.inbuf, "=IPA", 4) == 0) {
295 static struct in_addr ipa;
297 inbufptr = 0;
298 if(memcmp(&ipa, &uip.inbuf[4], sizeof(ipa)) == 0) {
299 break;
302 /* New address. */
303 if(ipa.s_addr != 0) {
304 #if 0
305 #ifdef linux
306 ssystem("route delete -net %s netmask %s dev %s",
307 inet_ntoa(ipa), "255.255.255.255", tundev);
308 #else
309 ssystem("route delete -net %s -netmask %s -interface %s",
310 inet_ntoa(ipa), "255.255.255.255", tundev);
311 #endif
312 #endif /* 0 */
315 memcpy(&ipa, &uip.inbuf[4], sizeof(ipa));
316 if(ipa.s_addr != 0) {
317 #if 0
318 #ifdef linux
319 ssystem("route add -net %s netmask %s dev %s",
320 inet_ntoa(ipa), "255.255.255.255", tundev);
321 #else
322 ssystem("route add -net %s -netmask %s -interface %s",
323 inet_ntoa(ipa), "255.255.255.255", tundev);
324 #endif
325 #endif /* 0 */
327 break;
328 } else if(ecode < 0) {
330 * If sensible ASCII string, print it as debug info!
332 /* printf("----------------------------------\n");*/
333 if(uip.inbuf[0] == DEBUG_LINE_MARKER) {
334 fwrite(uip.inbuf + 1, inbufptr - 1, 1, stderr);
335 } else if(is_sensible_string(uip.inbuf, inbufptr)) {
336 fwrite(uip.inbuf, inbufptr, 1, stderr);
337 } else {
338 fprintf(stderr,
339 "serial_to_tun: drop packet len=%d ecode=%d\n",
340 inbufptr, ecode);
342 inbufptr = 0;
343 break;
345 PROGRESS("s");
347 #if 0
348 if(dhsock != -1) {
349 struct ip *ip = (void *)uip.inbuf;
350 if(ip->ip_p == 17 && ip->ip_dst == 0xffffffff /* UDP and broadcast */
351 && ip->uh_sport == ntohs(BOOTPC) && ip->uh_dport == ntohs(BOOTPS)) {
352 relay_dhcp_to_server(ip, inbufptr);
353 inbufptr = 0;
356 #endif /* 0 */
357 /* if(write(outfd, uip.inbuf, inbufptr) != inbufptr) {
358 err(1, "serial_to_tun: write");
360 /* printf("Sending to wpcap\n");*/
361 print_packet(uip.inbuf, inbufptr);
362 wpcap_send(uip.inbuf, inbufptr);
363 /* printf("After sending to wpcap\n");*/
364 inbufptr = 0;
366 break;
368 case SLIP_ESC:
369 if(fread(&c, 1, 1, inslip) != 1) {
370 clearerr(inslip);
371 /* Put ESC back and give up! */
372 ungetc(SLIP_ESC, inslip);
373 return;
376 switch(c) {
377 case SLIP_ESC_END:
378 c = SLIP_END;
379 break;
380 case SLIP_ESC_ESC:
381 c = SLIP_ESC;
382 break;
384 /* FALLTHROUGH */
385 default:
386 uip.inbuf[inbufptr++] = c;
387 break;
390 goto read_more;
392 /*---------------------------------------------------------------------------*/
393 unsigned char slip_buf[2000];
394 int slip_end, slip_begin;
395 /*---------------------------------------------------------------------------*/
396 void
397 slip_send(int fd, unsigned char c)
399 if(slip_end >= sizeof(slip_buf)) {
400 err(1, "slip_send overflow");
402 slip_buf[slip_end] = c;
403 slip_end++;
405 /*---------------------------------------------------------------------------*/
407 slip_empty()
409 return slip_end == 0;
411 /*---------------------------------------------------------------------------*/
412 void
413 slip_flushbuf(int fd)
415 int n;
417 if (slip_empty())
418 return;
420 n = write(fd, slip_buf + slip_begin, (slip_end - slip_begin));
422 if(n == -1 && errno != EAGAIN) {
423 err(1, "slip_flushbuf write failed");
424 } else if(n == -1) {
425 PROGRESS("Q"); /* Outqueueis full! */
426 } else {
427 slip_begin += n;
428 if(slip_begin == slip_end) {
429 slip_begin = slip_end = 0;
433 /*---------------------------------------------------------------------------*/
434 void
435 write_to_serial(int outfd, void *inbuf, int len)
437 u_int8_t *p = inbuf;
438 int i, ecode;
439 struct ip *iphdr = inbuf;
442 * Sanity checks.
444 ecode = check_ip(inbuf, len);
445 if(ecode < 0) {
446 fprintf(stderr, "write_to_serial: drop packet %d\n", ecode);
447 return;
450 if(iphdr->ip_id == 0 && iphdr->ip_off & IP_DF) {
451 uint16_t nid = htons(ip_id++);
452 iphdr->ip_id = nid;
453 nid = ~nid; /* negate */
454 iphdr->ip_sum += nid; /* add */
455 if(iphdr->ip_sum < nid) { /* 1-complement overflow? */
456 iphdr->ip_sum++;
458 ecode = check_ip(inbuf, len);
459 if(ecode < 0) {
460 fprintf(stderr, "write_to_serial: drop packet %d\n", ecode);
461 return;
466 iphdr->ip_ttl = htons(htons(iphdr->ip_ttl) + 1);
467 if(iphdr->ip_ttl == 0) {
468 fprintf(stderr, "Packet with ttl %d dropped\n", iphdr->ip_ttl);
469 return;
471 iphdr->ip_sum = 0;
472 iphdr->ip_sum = ~chksum(iphdr, 4 * (iphdr->ip_vhl & IP_HL));
473 ecode = check_ip(inbuf, len);
474 if(ecode < 0) {
475 fprintf(stderr, "write_to_serial: drop packet %d\n", ecode);
476 return;
479 /* It would be ``nice'' to send a SLIP_END here but it's not
480 * really necessary.
482 /* slip_send(outfd, SLIP_END); */
484 for(i = 0; i < len; i++) {
485 switch(p[i]) {
486 case SLIP_END:
487 slip_send(outfd, SLIP_ESC);
488 slip_send(outfd, SLIP_ESC_END);
489 break;
490 case SLIP_ESC:
491 slip_send(outfd, SLIP_ESC);
492 slip_send(outfd, SLIP_ESC_ESC);
493 break;
494 default:
495 slip_send(outfd, p[i]);
496 break;
500 slip_send(outfd, SLIP_END);
501 /* printf("slip end\n");*/
502 PROGRESS("t");
504 /*---------------------------------------------------------------------------*/
506 * Read from tun, write to slip.
508 #if 0
509 void
510 tun_to_serial(int infd, int outfd)
512 static union {
513 unsigned char inbuf[2000];
514 struct ip iphdr;
515 } uip;
516 int size;
518 if((size = read(infd, uip.inbuf, 2000)) == -1) {
519 err(1, "tun_to_serial: read");
522 write_to_serial(outfd, uip.inbuf, size);
524 #endif /* 0 */
525 /*---------------------------------------------------------------------------*/
526 #ifndef BAUDRATE
527 #define BAUDRATE B115200
528 #endif
529 speed_t b_rate = BAUDRATE;
531 void
532 cfmakeraw(t)
533 struct termios *t;
536 t->c_iflag &= ~(IMAXBEL|IXOFF|INPCK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IGNPAR);
537 t->c_iflag |= IGNBRK;
538 t->c_oflag &= ~OPOST;
539 t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|NOFLSH|TOSTOP);
540 t->c_cflag &= ~(CSIZE|PARENB);
541 t->c_cflag |= CS8|CREAD;
542 t->c_cc[VMIN] = 1;
543 t->c_cc[VTIME] = 0;
546 void
547 stty_telos(int fd)
549 struct termios options;
550 speed_t speed = b_rate;
552 /* if(fcntl(fd, F_SETFL, 0) < 0) {
553 perror("could not set fcntl");
554 exit(-1);
557 if(tcgetattr(fd, &options) < 0) {
558 perror("could not get options");
559 exit(-1);
562 cfsetispeed(&options, speed);
563 cfsetospeed(&options, speed);
564 /* Enable the receiver and set local mode */
565 options.c_cflag |= (CLOCAL | CREAD);
566 /* Mask the character size bits and turn off (odd) parity */
567 options.c_cflag &= ~(CSIZE|PARENB|PARODD);
568 /* Select 8 data bits */
569 options.c_cflag |= CS8;
571 /* Raw input */
572 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
573 /* Raw output */
574 options.c_oflag &= ~OPOST;
576 if (tcsetattr(fd, TCSANOW, &options) < 0) {
577 perror("could not set options");
578 exit(-1);
581 #if 0
582 struct termios tty;
583 speed_t speed = b_rate;
584 int i;
586 if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush");
588 if(tcgetattr(fd, &tty) == -1) err(1, "tcgetattr");
590 cfmakeraw(&tty);
592 /* Nonblocking read. */
593 tty.c_cc[VTIME] = 0;
594 tty.c_cc[VMIN] = 0;
595 tty.c_cflag &= ~CRTSCTS;
596 tty.c_cflag &= ~HUPCL;
597 tty.c_cflag &= ~CLOCAL;
599 cfsetispeed(&tty, speed);
600 cfsetospeed(&tty, speed);
602 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr");
604 #if 1
605 /* Nonblocking read and write. */
606 /* if(fcntl(fd, F_SETFL, O_NONBLOCK) == -1) err(1, "fcntl"); */
608 tty.c_cflag |= CLOCAL;
609 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) err(1, "tcsetattr");
611 i = TIOCM_DTR;
612 if(ioctl(fd, TIOCMBIS, &i) == -1) err(1, "ioctl");
613 #endif
615 usleep(10*1000); /* Wait for hardware 10ms. */
617 /* Flush input and output buffers. */
618 if(tcflush(fd, TCIOFLUSH) == -1) err(1, "tcflush");
619 #endif /* 0 */
621 /*---------------------------------------------------------------------------*/
623 devopen(const char *dev, int flags)
625 char t[32];
626 strcpy(t, "/dev/");
627 strcat(t, dev);
628 return open(t, flags);
630 /*---------------------------------------------------------------------------*/
631 /*const char *ipaddr;*/
632 /*const char *netmask;*/
633 static int got_sigalarm;
634 void
635 sigalarm(int signo)
637 got_sigalarm = 1;
638 return;
640 /*---------------------------------------------------------------------------*/
641 void
642 sigalarm_reset()
644 #ifdef linux
645 #define TIMEOUT (997*1000)
646 #else
647 #define TIMEOUT (2451*1000)
648 #endif
649 ualarm(TIMEOUT, TIMEOUT);
650 got_sigalarm = 0;
652 /*---------------------------------------------------------------------------*/
654 main(int argc, char **argv)
656 int c;
657 int slipfd, maxfd;
658 int ret;
659 fd_set rset, wset;
660 FILE *inslip;
661 const char *siodev = NULL;
662 const char *dhcp_server = NULL;
663 /* u_int16_t myport = BOOTPS, dhport = BOOTPS;*/
664 int baudrate = -2;
665 char buf[4000];
666 int logging = 0;
668 ip_id = getpid() * time(NULL);
670 setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */
672 while((c = getopt(argc, argv, "B:D:hls:t:T")) != -1) {
673 switch (c) {
674 case 'B':
675 baudrate = atoi(optarg);
676 break;
678 case 'D':
679 dhcp_server = optarg;
680 break;
682 case 's':
683 if(strncmp("/dev/", optarg, 5) == 0) {
684 siodev = optarg + 5;
685 } else {
686 siodev = optarg;
688 break;
690 #if 0
691 case 't':
692 if(strncmp("/dev/", optarg, 5) == 0) {
693 strcpy(tundev, optarg + 5);
694 } else {
695 strcpy(tundev, optarg);
697 break;
698 #endif /* 0 */
700 case 'T':
701 should_print = 1;
702 break;
704 case 'l':
705 logging = 1;
706 break;
708 case '?':
709 case 'h':
710 default:
711 err(1, "usage: wpcapslip [-B baudrate] [-s siodev] [-D dhcp-server] [-T] ipaddress netmask [dhcp-server]");
712 break;
715 argc -= (optind - 1);
716 argv += (optind - 1);
718 if(argc != 4) {
719 err(1, "usage: wpcapslip [-s siodev] [-D dhcp-server] [-T] <IP address of local Ethernet card> <IP address of SLIP network> <netmask of SLIP network>");
721 /* ipaddr = argv[1];
722 netmask = argv[2];*/
723 wpcap_start(argv[1], argv[2], argv[3], logging);
724 /* netaddr = inet_addr(ipaddr) & inet_addr(netmask);*/
726 switch(baudrate) {
727 case -2:
728 break; /* Use default. */
729 case 9600:
730 b_rate = B9600;
731 break;
732 case 19200:
733 b_rate = B19200;
734 break;
735 case 38400:
736 b_rate = B38400;
737 break;
738 case 57600:
739 b_rate = B57600;
740 break;
741 case 115200:
742 b_rate = B115200;
743 break;
744 default:
745 err(1, "unknown baudrate %d", baudrate);
746 break;
750 * Set up DHCP relay agent socket and find the address of this relay
751 * agent.
753 #if 0
754 if(argc == 4) {
755 dhcp_server = argv[3];
757 if(dhcp_server != NULL) {
758 struct sockaddr_in myaddr;
759 socklen_t len;
760 in_addr_t a;
762 if(strchr(dhcp_server, ':') != NULL) {
763 dhport = atoi(strchr(dhcp_server, ':') + 1);
764 myport = dhport + 1;
765 *strchr(dhcp_server, ':') = '\0';
767 a = inet_addr(dhcp_server);
768 if(a == -1) {
769 err(1, "illegal dhcp-server address");
771 #ifndef linux
772 dhaddr.sin_len = sizeof(dhaddr);
773 #endif
774 dhaddr.sin_family = AF_INET;
775 dhaddr.sin_port = htons(dhport);
776 dhaddr.sin_addr.s_addr = a;
778 dhsock = socket(AF_INET, SOCK_DGRAM, 0);
779 if(dhsock < 0) {
780 err (1, "socket");
782 memset(&myaddr, 0x0, sizeof(myaddr));
783 #ifndef linux
784 myaddr.sin_len = sizeof(myaddr);
785 #endif
786 myaddr.sin_family = AF_INET;
787 myaddr.sin_addr.s_addr = INADDR_ANY;
788 myaddr.sin_port = htons(myport);
789 if(bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
790 err(1, "bind dhcp-relay");
793 if(connect(dhsock, (struct sockaddr *)&dhaddr, sizeof(dhaddr)) < 0) {
794 err(1, "connect to dhcp-server");
797 len = sizeof(myaddr);
798 if(getsockname(dhsock, (struct sockaddr *)&myaddr, &len) < 0) {
799 err(1, "getsockname dhsock");
802 giaddr = myaddr.sin_addr.s_addr;
805 * Don't want connected socket.
807 close(dhsock);
808 dhsock = socket(AF_INET, SOCK_DGRAM, 0);
809 if(dhsock < 0) {
810 err (1, "socket");
812 myaddr.sin_family = AF_INET;
813 myaddr.sin_addr.s_addr = INADDR_ANY;
814 myaddr.sin_port = htons(myport);
815 if(bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
816 err(1, "bind dhcp-relay");
818 fprintf(stderr, "DHCP server at %s:%d\n", dhcp_server, dhport);
820 #endif /* 0 */
822 if(siodev != NULL) {
823 slipfd = devopen(siodev, O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC );
824 if(slipfd == -1) {
825 err(1, "can't open siodev ``/dev/%s''", siodev);
827 } else {
828 static const char *siodevs[] = {
829 "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
831 int i;
832 for(i = 0; i < 3; i++) {
833 siodev = siodevs[i];
834 slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);
835 if(slipfd != -1) {
836 break;
839 if(slipfd == -1) {
840 err(1, "can't open siodev");
843 fprintf(stderr, "slip started on ``/dev/%s''\n", siodev);
844 stty_telos(slipfd);
845 slip_send(slipfd, SLIP_END);
846 inslip = fdopen(slipfd, "r");
847 if(inslip == NULL) {
848 err(1, "main: fdopen");
851 /* tunfd = tun_alloc(tundev);
852 if(tunfd == -1) err(1, "main: open");
853 fprintf(stderr, "opened device ``/dev/%s''\n", tundev);*/
855 atexit(cleanup);
856 signal(SIGHUP, sigcleanup);
857 signal(SIGTERM, sigcleanup);
858 signal(SIGINT, sigcleanup);
859 signal(SIGALRM, sigalarm);
860 /* ifconf(tundev, ipaddr, netmask);*/
862 while(1) {
863 maxfd = 0;
864 FD_ZERO(&rset);
865 FD_ZERO(&wset);
867 if(got_sigalarm) {
868 /* Send "?IPA". */
869 slip_send(slipfd, '?');
870 slip_send(slipfd, 'I');
871 slip_send(slipfd, 'P');
872 slip_send(slipfd, 'A');
873 slip_send(slipfd, SLIP_END);
874 got_sigalarm = 0;
877 if(!slip_empty()) { /* Anything to flush? */
878 FD_SET(slipfd, &wset);
881 FD_SET(slipfd, &rset); /* Read from slip ASAP! */
882 if(slipfd > maxfd) {
883 maxfd = slipfd;
886 /* We only have one packet at a time queued for slip output. */
887 if(slip_empty()) {
888 /* FD_SET(tunfd, &rset);
889 if(tunfd > maxfd) maxfd = tunfd;
890 if(dhsock != -1) {
891 FD_SET(dhsock, &rset);
892 if(dhsock > maxfd) maxfd = dhsock;
897 if(slip_empty()) {
898 char *pbuf = buf;
900 ret = wpcap_poll(&pbuf);
901 if(ret > 0) {
902 struct ip *iphdr = (struct ip *)pbuf;
903 if(iphdr->ip_id != last_id) {
904 last_id = iphdr->ip_id;
905 /* printf("------ wpcap_poll ret %d\n", ret);*/
906 print_packet(pbuf, ret);
907 write_to_serial(slipfd, pbuf, ret);
908 slip_flushbuf(slipfd);
909 sigalarm_reset();
912 /* } else {
913 printf("!slip_empty\n");*/
916 struct timeval tv;
917 tv.tv_sec = 0;
918 tv.tv_usec = 10;
919 ret = select(maxfd + 1, &rset, &wset, NULL, &tv);
921 if(ret == -1 && errno != EINTR) {
922 err(1, "select");
923 } else if(ret > 0) {
924 if(FD_ISSET(slipfd, &rset)) {
925 /* printf("serial_to_wpcap\n");*/
926 /*serial_to_tun(inslip, tunfd);*/
927 serial_to_wpcap(inslip);
928 /* printf("End of serial_to_wpcap\n");*/
931 if(FD_ISSET(slipfd, &wset)) {
932 /* printf("slip_flushbuf\n");*/
933 slip_flushbuf(slipfd);
934 sigalarm_reset();
937 /* if(slip_empty() && FD_ISSET(tunfd, &rset)) {
938 tun_to_serial(tunfd, slipfd);
939 slip_flushbuf(slipfd);
940 sigalarm_reset();
943 #if 0
944 if(dhsock != -1 && slip_empty() && FD_ISSET(dhsock, &rset)) {
945 relay_dhcp_to_client(slipfd);
946 slip_flushbuf(slipfd);
948 #endif /* 0 */
952 /*---------------------------------------------------------------------------*/