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
77long slip_received = 0;
81#define PROGRESS(s) do { } while(0)
85#define SLIP_ESC_END 0334
86#define SLIP_ESC_ESC 0335
90get_in_addr(
struct sockaddr *sa)
92 if(sa->sa_family == AF_INET) {
93 return &(((
struct sockaddr_in *)sa)->sin_addr);
95 return &(((
struct sockaddr_in6 *)sa)->sin6_addr);
99connect_to_server(
const char *host,
const char *port)
102 struct addrinfo hints, *servinfo, *p;
103 char s[INET6_ADDRSTRLEN];
106 memset(&hints, 0,
sizeof hints);
107 hints.ai_family = AF_UNSPEC;
108 hints.ai_socktype = SOCK_STREAM;
110 if((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
111 err(EXIT_FAILURE,
"getaddrinfo: %s", gai_strerror(rv));
116 for(p = servinfo; p != NULL; p = p->ai_next) {
117 if((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
118 perror(
"client: socket");
122 if(connect(fd, p->ai_addr, p->ai_addrlen) == -1) {
124 perror(
"client: connect");
131 err(EXIT_FAILURE,
"can't connect to ``%s:%s''", host, port);
135 fcntl(fd, F_SETFL, O_NONBLOCK);
137 inet_ntop(p->ai_family, get_in_addr((
struct sockaddr *)p->ai_addr),
141 freeaddrinfo(servinfo);
146is_sensible_string(
const unsigned char *s,
int len)
149 for(i = 1; i < len; i++) {
150 if(s[i] == 0 || s[i] ==
'\r' || s[i] ==
'\n' || s[i] ==
'\t') {
152 }
else if(s[i] <
' ' ||
'~' < s[i]) {
160slip_packet_input(
unsigned char *data,
int len)
163 if(slip_config_verbose > 0) {
164 printf(
"Packet input over SLIP: %d\n", len);
166 NETSTACK_MAC.
input();
174serial_input(FILE *inslip)
176 static unsigned char inbuf[2048];
177 static int inbufptr = 0;
182 ret = fread(&c, 1, 1, inslip);
183 if(ret == -1 || ret == 0) {
184 err(EXIT_FAILURE,
"serial_input: read");
190 if(inbufptr >=
sizeof(inbuf)) {
191 fprintf(stderr,
"*** dropping large %d byte packet\n", inbufptr);
194 ret = fread(&c, 1, 1, inslip);
199 err(EXIT_FAILURE,
"serial_input: read");
209 if(inbuf[0] ==
'!') {
210 command_context = CMD_CONTEXT_RADIO;
211 cmd_input(inbuf, inbufptr);
212 }
else if(inbuf[0] ==
'?') {
213#define DEBUG_LINE_MARKER '\r'
214 }
else if(inbuf[0] == DEBUG_LINE_MARKER) {
215 fwrite(inbuf + 1, inbufptr - 1, 1, stdout);
216 }
else if(is_sensible_string(inbuf, inbufptr)) {
217 if(slip_config_verbose == 1) {
218 fwrite(inbuf, inbufptr, 1, stdout);
221 if(slip_config_verbose > 2) {
222 printf(
"Packet from SLIP of length %d - write TUN\n", inbufptr);
223 if(slip_config_verbose > 4) {
224#if WIRESHARK_IMPORT_FORMAT
226 for(i = 0; i < inbufptr; i++) {
227 printf(
" %02x", inbuf[i]);
231 for(i = 0; i < inbufptr; i++) {
232 printf(
"%02x", inbuf[i]);
244 slip_packet_input(inbuf, inbufptr);
251 if(fread(&c, 1, 1, inslip) != 1) {
254 ungetc(SLIP_ESC, inslip);
268 inbuf[inbufptr++] = c;
272 if(slip_config_verbose == 4) {
273 if(c == 0 || c ==
'\r' || c ==
'\n' || c ==
'\t' || (c >=
' ' && c <=
'~')) {
274 fwrite(&c, 1, 1, stdout);
276 }
else if(slip_config_verbose >= 2) {
277 if(c ==
'\n' && is_sensible_string(inbuf, inbufptr)) {
278 fwrite(inbuf, inbufptr, 1, stdout);
287unsigned char slip_buf[2048];
288int slip_end, slip_begin, slip_packet_end, slip_packet_count;
289static struct timer send_delay_timer;
291static clock_time_t send_delay = SEND_DELAY;
294slip_send(
int fd,
unsigned char c)
296 if(slip_end >=
sizeof(slip_buf)) {
297 err(EXIT_FAILURE,
"slip_send overflow");
299 slip_buf[slip_end] = c;
305 if(slip_packet_end == 0) {
306 slip_packet_end = slip_end;
314 return slip_packet_end == 0;
326 n = write(fd, slip_buf + slip_begin, slip_packet_end - slip_begin);
328 if(n == -1 && errno != EAGAIN) {
329 err(EXIT_FAILURE,
"slip_flushbuf write failed");
334 if(slip_begin == slip_packet_end) {
336 if(slip_end > slip_packet_end) {
337 memmove(slip_buf, slip_buf + slip_packet_end,
338 slip_end - slip_packet_end);
340 slip_end -= slip_packet_end;
341 slip_begin = slip_packet_end = 0;
344 for(n = 1; n < slip_end; n++) {
345 if(slip_buf[n] == SLIP_END) {
346 slip_packet_end = n + 1;
352 timer_set(&send_delay_timer, send_delay);
360write_to_serial(
int outfd,
const uint8_t *inbuf,
int len)
362 const uint8_t *p = inbuf;
365 if(slip_config_verbose > 2) {
366 printf(
"Packet from TUN of length %d - write SLIP\n", len);
367 if(slip_config_verbose > 4) {
368#if WIRESHARK_IMPORT_FORMAT
370 for(i = 0; i < len; i++) {
371 printf(
" %02x", p[i]);
375 for(i = 0; i < len; i++) {
376 printf(
"%02x", p[i]);
394 for(i = 0; i < len; i++) {
397 slip_send(outfd, SLIP_ESC);
398 slip_send(outfd, SLIP_ESC_END);
401 slip_send(outfd, SLIP_ESC);
402 slip_send(outfd, SLIP_ESC_ESC);
405 slip_send(outfd, p[i]);
409 slip_send(outfd, SLIP_END);
415write_to_slip(
const uint8_t *buf,
int len)
418 write_to_serial(slipfd, buf, len);
426 speed_t speed = slip_config_b_rate;
429 if(tcflush(fd, TCIOFLUSH) == -1) {
430 err(EXIT_FAILURE,
"tcflush");
433 if(tcgetattr(fd, &tty) == -1) {
442 if(slip_config_flowcontrol) {
443 tty.c_cflag |= CRTSCTS;
445 tty.c_cflag &= ~CRTSCTS;
447 tty.c_cflag &= ~HUPCL;
448 tty.c_cflag &= ~CLOCAL;
450 cfsetispeed(&tty, speed);
451 cfsetospeed(&tty, speed);
453 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) {
454 err(EXIT_FAILURE,
"tcsetattr");
461 tty.c_cflag |= CLOCAL;
462 if(tcsetattr(fd, TCSAFLUSH, &tty) == -1) {
463 err(EXIT_FAILURE,
"tcsetattr");
467 if(ioctl(fd, TIOCMBIS, &i) == -1) {
468 err(EXIT_FAILURE,
"ioctl");
475 if(tcflush(fd, TCIOFLUSH) == -1) {
476 err(EXIT_FAILURE,
"tcflush");
481set_fd(fd_set *rset, fd_set *wset)
484 if(!slip_empty() && (send_delay == 0 ||
timer_expired(&send_delay_timer))) {
485 FD_SET(slipfd, wset);
488 FD_SET(slipfd, rset);
493handle_fd(fd_set *rset, fd_set *wset)
495 if(FD_ISSET(slipfd, rset)) {
496 serial_input(inslip);
499 if(FD_ISSET(slipfd, wset)) {
500 slip_flushbuf(slipfd);
504static const struct select_callback slip_callback = { set_fd, handle_fd };
509 setvbuf(stdout, NULL, _IOLBF, 0);
511 if(slip_config_host != NULL) {
512 if(slip_config_port == NULL) {
513 slip_config_port =
"60001";
515 slipfd = connect_to_server(slip_config_host, slip_config_port);
517 err(EXIT_FAILURE,
"can't connect to ``%s:%s''", slip_config_host,
520 }
else if(slip_config_siodev != NULL) {
521 if(strcmp(slip_config_siodev,
"null") == 0) {
525 slipfd = open(slip_config_siodev, O_RDWR | O_NONBLOCK);
527 err(EXIT_FAILURE,
"can't open siodev ``%s''", slip_config_siodev);
530 static const char *siodevs[] = {
531 "/dev/ttyUSB0",
"/dev/cuaU0",
"/dev/ucom0"
533 for(
int i = 0; i < 3; i++) {
534 slip_config_siodev = siodevs[i];
535 slipfd = open(slip_config_siodev, O_RDWR | O_NONBLOCK);
541 err(EXIT_FAILURE,
"can't open siodev");
545 select_set_callback(slipfd, &slip_callback);
547 if(slip_config_host != NULL) {
548 fprintf(stderr,
"********SLIP opened to ``%s:%s''\n", slip_config_host,
551 fprintf(stderr,
"********SLIP started on ``/dev/%s''\n", slip_config_siodev);
556 slip_send(slipfd, SLIP_END);
557 inslip = fdopen(slipfd,
"r");
559 err(EXIT_FAILURE,
"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.