int _open_serial_connection(char *name, char *baudrate_arg) { unsigned baudrate = 0; if (_parse_baudrate(baudrate_arg, &baudrate) == -1) { fprintf(stderr, "Invalid baudrate specified: %s\n", baudrate_arg); return 1; } int serial_fd = open(name, O_RDWR | O_NOCTTY | O_SYNC); if (serial_fd < 0) { fprintf(stderr, "Error opening serial device %s\n", name); return -1; } set_serial_attribs(serial_fd, baudrate, 0); set_blocking(serial_fd, 1); return serial_fd; }
int main(int argc, char *argv[]) { char inbuf[MTU]; unsigned baudrate = BAUDRATE_DEFAULT; serial_t serial = {0}; if (argc < 3) { usage(); return 1; } if (argc >= 4 && _parse_baudrate(argv[3], &baudrate) == -1) { fprintf(stderr, "Invalid baudrate specified: %s\n", argv[3]); return 1; } char ifname[IFNAMSIZ]; strncpy(ifname, argv[1], IFNAMSIZ); int tap_fd = tun_alloc(ifname, IFF_TAP | IFF_NO_PI); if (tap_fd < 0) { return 1; } int serial_fd = open(argv[2], O_RDWR | O_NOCTTY | O_SYNC); if (serial_fd < 0) { fprintf(stderr, "Error opening serial device %s\n", argv[2]); return 1; } set_serial_attribs(serial_fd, baudrate, 0); set_blocking(serial_fd, 1); fd_set readfds; int max_fd = (serial_fd > tap_fd) ? serial_fd : tap_fd; fprintf(stderr, "----> ethos: sending hello.\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO); fprintf(stderr, "----> ethos: activating serial pass through.\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO); while(1) { int activity; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); FD_SET(tap_fd, &readfds); FD_SET(serial_fd, &readfds); activity = select( max_fd + 1 , &readfds , NULL , NULL , NULL); if ((activity < 0) && (errno != EINTR)) { perror("select error"); } if (FD_ISSET(serial_fd, &readfds)) { ssize_t n = read(serial_fd, inbuf, sizeof(inbuf)); if (n > 0) { char *ptr = inbuf; while (n--) { size_t res = _serial_handle_byte(&serial, *ptr++); if (res) { switch (serial.frametype) { case LINE_FRAME_TYPE_DATA: checked_write(tap_fd, serial.frame, serial.framebytes); break; case LINE_FRAME_TYPE_TEXT: checked_write(STDOUT_FILENO, serial.frame, serial.framebytes); break; case LINE_FRAME_TYPE_HELLO: case LINE_FRAME_TYPE_HELLO_REPLY: if (serial.framebytes == 6) { memcpy(serial.remote_l2_addr, serial.frame, 6); if (serial.frametype == LINE_FRAME_TYPE_HELLO) { fprintf(stderr, "----> ethos: hello received\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO_REPLY); } else { fprintf(stderr, "----> ethos: hello reply received\n"); } _clear_neighbor_cache(ifname); } break; } memset(&serial, '\0', sizeof(serial)); } } } else { fprintf(stderr, "lost serial connection.\n"); exit(1); } } if (FD_ISSET(tap_fd, &readfds)) { ssize_t res = read(tap_fd, inbuf, sizeof(inbuf)); if (res <= 0) { fprintf(stderr, "error reading from tap device. res=%zi\n", res); continue; } char delim = LINE_FRAME_DELIMITER; checked_write(serial_fd, &delim, 1); _write_escaped(serial_fd, inbuf, res); checked_write(serial_fd, &delim, 1); } if (FD_ISSET(STDIN_FILENO, &readfds)) { ssize_t res = read(STDIN_FILENO, inbuf, sizeof(inbuf)); if (res <= 0) { fprintf(stderr, "error reading from stdio. res=%zi\n", res); continue; } if (res) { char delim = LINE_FRAME_DELIMITER; char head[] = { LINE_FRAME_DELIMITER, LINE_ESC_CHAR, (LINE_FRAME_TYPE_TEXT ^ 0x20) }; checked_write(serial_fd, head, sizeof(head)); _write_escaped(serial_fd, inbuf, res); checked_write(serial_fd, &delim, 1); } } } return 0; }