33#define WIRESHARK_IMPORT_FORMAT 1
48#include <sys/socket.h>
49#include <netinet/in.h>
59extern int slip_config_verbose;
60extern int slip_config_flowcontrol;
61extern const char *slip_config_siodev;
62extern const char *slip_config_host;
63extern const char *slip_config_port;
64extern uint16_t slip_config_basedelay;
65extern speed_t slip_config_b_rate;
67#ifdef SLIP_DEV_CONF_SEND_DELAY
68#define SEND_DELAY SLIP_DEV_CONF_SEND_DELAY
73int devopen(
const char *dev,
int flags);
79long slip_received = 0;
83#define PROGRESS(s) do { } while(0)
87#define SLIP_ESC_END 0334
88#define SLIP_ESC_ESC 0335
92get_in_addr(
struct sockaddr *sa)
94 if(sa->sa_family == AF_INET) {
95 return &(((
struct sockaddr_in *)sa)->sin_addr);
97 return &(((
struct sockaddr_in6 *)sa)->sin6_addr);
101connect_to_server(
const char *host,
const char *port)
104 struct addrinfo hints, *servinfo, *p;
105 char s[INET6_ADDRSTRLEN];
108 memset(&hints, 0,
sizeof hints);
109 hints.ai_family = AF_UNSPEC;
110 hints.ai_socktype = SOCK_STREAM;
112 if((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
113 err(1,
"getaddrinfo: %s", gai_strerror(rv));
118 for(p = servinfo; p != NULL; p = p->ai_next) {
119 if((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
120 perror(
"client: socket");
124 if(connect(fd, p->ai_addr, p->ai_addrlen) == -1) {
126 perror(
"client: connect");
133 err(1,
"can't connect to ``%s:%s''", host, port);
137 fcntl(fd, F_SETFL, O_NONBLOCK);
139 inet_ntop(p->ai_family, get_in_addr((
struct sockaddr *)p->ai_addr),
143 freeaddrinfo(servinfo);
148is_sensible_string(
const unsigned char *s,
int len)
151 for(i = 1; i < len; i++) {
152 if(s[i] == 0 || s[i] ==
'\r' || s[i] ==
'\n' || s[i] ==
'\t') {
154 }
else if(s[i] <
' ' ||
'~' < s[i]) {
162slip_packet_input(
unsigned char *data,
int len)
165 if(slip_config_verbose > 0) {
166 printf(
"Packet input over SLIP: %d\n", len);
168 NETSTACK_MAC.
input();
176serial_input(FILE *inslip)
178 static unsigned char inbuf[2048];
179 static int inbufptr = 0;
184 ret = fread(&c, 1, 1, inslip);
185 if(ret == -1 || ret == 0) {
186 err(1,
"serial_input: read");
192 if(inbufptr >=
sizeof(inbuf)) {
193 fprintf(stderr,
"*** dropping large %d byte packet\n", inbufptr);
196 ret = fread(&c, 1, 1, inslip);
201 err(1,
"serial_input: read");
211 if(inbuf[0] ==
'!') {
212 command_context = CMD_CONTEXT_RADIO;
213 cmd_input(inbuf, inbufptr);
214 }
else if(inbuf[0] ==
'?') {
215#define DEBUG_LINE_MARKER '\r'
216 }
else if(inbuf[0] == DEBUG_LINE_MARKER) {
217 fwrite(inbuf + 1, inbufptr - 1, 1, stdout);
218 }
else if(is_sensible_string(inbuf, inbufptr)) {
219 if(slip_config_verbose == 1) {
220 fwrite(inbuf, inbufptr, 1, stdout);
223 if(slip_config_verbose > 2) {
224 printf(
"Packet from SLIP of length %d - write TUN\n", inbufptr);
225 if(slip_config_verbose > 4) {
226#if WIRESHARK_IMPORT_FORMAT
228 for(i = 0; i < inbufptr; i++) {
229 printf(
" %02x", inbuf[i]);
233 for(i = 0; i < inbufptr; i++) {
234 printf(
"%02x", inbuf[i]);
246 slip_packet_input(inbuf, inbufptr);
253 if(fread(&c, 1, 1, inslip) != 1) {
256 ungetc(SLIP_ESC, inslip);
270 inbuf[inbufptr++] = c;
274 if(slip_config_verbose == 4) {
275 if(c == 0 || c ==
'\r' || c ==
'\n' || c ==
'\t' || (c >=
' ' && c <=
'~')) {
276 fwrite(&c, 1, 1, stdout);
278 }
else if(slip_config_verbose >= 2) {
279 if(c ==
'\n' && is_sensible_string(inbuf, inbufptr)) {
280 fwrite(inbuf, inbufptr, 1, stdout);
289unsigned char slip_buf[2048];
290int slip_end, slip_begin, slip_packet_end, slip_packet_count;
291static struct timer send_delay_timer;
293static clock_time_t send_delay = SEND_DELAY;
296slip_send(
int fd,
unsigned char c)
298 if(slip_end >=
sizeof(slip_buf)) {
299 err(1,
"slip_send overflow");
301 slip_buf[slip_end] = c;
307 if(slip_packet_end == 0) {
308 slip_packet_end = slip_end;
316 return slip_packet_end == 0;
328 n = write(fd, slip_buf + slip_begin, slip_packet_end - slip_begin);
330 if(n == -1 && errno != EAGAIN) {
331 err(1,
"slip_flushbuf write failed");
336 if(slip_begin == slip_packet_end) {
338 if(slip_end > slip_packet_end) {
339 memmove(slip_buf, slip_buf + slip_packet_end,
340 slip_end - slip_packet_end);
342 slip_end -= slip_packet_end;
343 slip_begin = slip_packet_end = 0;
346 for(n = 1; n < slip_end; n++) {
347 if(slip_buf[n] == SLIP_END) {
348 slip_packet_end = n + 1;
354 timer_set(&send_delay_timer, send_delay);
362write_to_serial(
int outfd,
const uint8_t *inbuf,
int len)
364 const uint8_t *p = inbuf;
367 if(slip_config_verbose > 2) {
368 printf(
"Packet from TUN of length %d - write SLIP\n", len);
369 if(slip_config_verbose > 4) {
370#if WIRESHARK_IMPORT_FORMAT
372 for(i = 0; i < len; i++) {
373 printf(
" %02x", p[i]);
377 for(i = 0; i < len; i++) {
378 printf(
"%02x", p[i]);
396 for(i = 0; i < len; i++) {
399 slip_send(outfd, SLIP_ESC);
400 slip_send(outfd, SLIP_ESC_END);
403 slip_send(outfd, SLIP_ESC);
404 slip_send(outfd, SLIP_ESC_ESC);
407 slip_send(outfd, p[i]);
411 slip_send(outfd, SLIP_END);
417write_to_slip(
const uint8_t *buf,
int len)
420 write_to_serial(slipfd, buf, len);
428 speed_t speed = slip_config_b_rate;
431 if(tcflush(fd, TCIOFLUSH) == -1) {
435 if(tcgetattr(fd, &tty) == -1) {
444 if(slip_config_flowcontrol) {
445 tty.c_cflag |= CRTSCTS;
447 tty.c_cflag &= ~CRTSCTS;
449 tty.c_cflag &= ~HUPCL;
450 tty.c_cflag &= ~CLOCAL;
452 cfsetispeed(&tty, speed);
453 cfsetospeed(&tty, speed);
455 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) {
463 tty.c_cflag |= CLOCAL;
464 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) {
469 if(ioctl(fd, TIOCMBIS, &i) == -1) {
477 if(tcflush(fd, TCIOFLUSH) == -1) {
483set_fd(fd_set *rset, fd_set *wset)
486 if(!slip_empty() && (send_delay == 0 ||
timer_expired(&send_delay_timer))) {
487 FD_SET(slipfd, wset);
490 FD_SET(slipfd, rset);
495handle_fd(fd_set *rset, fd_set *wset)
497 if(FD_ISSET(slipfd, rset)) {
498 serial_input(inslip);
501 if(FD_ISSET(slipfd, wset)) {
502 slip_flushbuf(slipfd);
506static const struct select_callback slip_callback = { set_fd, handle_fd };
511 setvbuf(stdout, NULL, _IOLBF, 0);
513 if(slip_config_host != NULL) {
514 if(slip_config_port == NULL) {
515 slip_config_port =
"60001";
517 slipfd = connect_to_server(slip_config_host, slip_config_port);
519 err(1,
"can't connect to ``%s:%s''", slip_config_host, slip_config_port);
521 }
else if(slip_config_siodev != NULL) {
522 if(strcmp(slip_config_siodev,
"null") == 0) {
526 slipfd = devopen(slip_config_siodev, O_RDWR | O_NONBLOCK);
528 err(1,
"can't open siodev ``/dev/%s''", slip_config_siodev);
531 static const char *siodevs[] = {
532 "ttyUSB0",
"cuaU0",
"ucom0"
535 for(i = 0; i < 3; i++) {
536 slip_config_siodev = siodevs[i];
537 slipfd = devopen(slip_config_siodev, O_RDWR | O_NONBLOCK);
543 err(1,
"can't open siodev");
547 select_set_callback(slipfd, &slip_callback);
549 if(slip_config_host != NULL) {
550 fprintf(stderr,
"********SLIP opened to ``%s:%s''\n", slip_config_host,
553 fprintf(stderr,
"********SLIP started on ``/dev/%s''\n", slip_config_siodev);
558 slip_send(slipfd, SLIP_END);
559 inslip = fdopen(slipfd,
"r");
561 err(1,
"slip_init: fdopen");
Sets up some commands for the border router.
int packetbuf_copyfrom(const void *from, uint16_t len)
Copy from external data into the packetbuf.
void timer_set(struct timer *t, clock_time_t interval)
Set a timer.
bool timer_expired(struct timer *t)
Check if a timer has expired.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.
void(* input)(void)
Callback for getting notified of incoming packet.