int main(int argc, char **argv) { struct sockaddr_ll from; socklen_t fromlen = sizeof(from); char *device = "eth0", *ps; uint8_t *buf, *p; int n, i, err=0; unsigned int len; struct sk_buff *skb; conf.ifindex=-1; conf.debug = 0; if(jelopt(argv, 'h', "help", NULL, &err)) { printf("econsole [DEV] [CONSOLE] [DESTMAC] [(scan|debug)]\n"); exit(0); } argc = jelopt_final(argv, &err); if(err) { printf("Syntax error in arguments.\n"); exit(2); } while(--argc > 0) { if(strcmp(argv[argc], "scan")==0) { printf("Scanning for econsoles\n"); conf.scan = 1; continue; } if(strcmp(argv[argc], "debug")==0) { printf("Debug mode\n"); conf.debug++; continue; } if( (strlen(argv[argc]) < 3) && isdigit(*argv[argc])) { conf.console = atoi(argv[argc]); continue; } if(strchr(argv[argc], ':' )) { unsigned int a; ps = argv[argc]; for(i=0;i<6;i++) { sscanf(ps, "%x", &a); conf.dest.sll_addr[i] = a; ps = strchr(ps, ':'); if(!ps) break; ps++; } conf.ucast = 1; continue; } else { device = argv[argc]; } } conf.devsocket = devsocket(); while(set_flag(device, (IFF_UP | IFF_RUNNING))) { printf("Waiting for interface to be available\n"); sleep(1); } if(device) { conf.ifindex = if_nametoindex(device); if(!conf.ifindex) { fprintf(stderr, "no such device %s\n", device); exit(1); } } conf.s = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_EGETTY)); if(conf.s == -1) { fprintf(stderr, "socket(): %s\n", strerror(errno)); exit(1); } if(conf.ifindex >= 0) { struct sockaddr_ll addr; memset(&addr, 0, sizeof(addr)); addr.sll_family = AF_PACKET; addr.sll_protocol = htons(ETH_P_EGETTY); addr.sll_ifindex = conf.ifindex; if(bind(conf.s, (const struct sockaddr *)&addr, sizeof(addr))) { fprintf(stderr, "bind failed: %s\n", strerror(errno)); exit(1); } } if(!conf.scan) { terminal_settings(); signals_init(); winch_handler(0); fprintf(stderr, "Use CTRL-] to close connection.\n"); } skb = alloc_skb(1500); if(conf.scan) console_scan(conf.s, conf.ifindex, skb); while(1) { struct pollfd fds[2]; fds[0].fd = 0; fds[0].events = POLLIN; fds[0].revents = 0; fds[1].fd = conf.s; fds[1].events = POLLIN; fds[1].revents = 0; n = poll(fds, 2, -1); if(n == 0) { printf("timeout\n"); continue; } if(fds[0].revents & POLLIN) { skb_reset(skb); skb_reserve(skb, 4); buf = skb_put(skb, 0); n = read(0, buf, skb_tailroom(skb)); if(n == -1) { fprintf(stderr, "read() failed\n"); exit(1); } if(n == 0) { fprintf(stderr, "read() EOF\n"); exit(0); } buf[n] = 0; if(conf.debug) printf("read %d bytes from stdin\n", n); if(conf.debug > 1) printf("buf[0] == %d\n", buf[0]); if(n==1 && buf[0] == 0x1d) { console_hup(conf.s, conf.ifindex); tcsetattr(0, TCSANOW, &conf.term); exit(0); } skb_put(skb, n); if(!conf.scan) console_put(conf.s, conf.ifindex, skb); } if(fds[1].revents) { skb_reset(skb); buf = skb_put(skb, 0); n = recvfrom(conf.s, buf, skb_tailroom(skb), 0, (struct sockaddr *)&from, &fromlen); if(n == -1) { fprintf(stderr, "recvfrom() failed. ifconfig up?\n"); continue; } skb_put(skb, n); if(conf.ucast) if(memcmp(conf.dest.sll_addr, from.sll_addr, 6)) continue; if(ntohs(from.sll_protocol) == ETH_P_EGETTY) { if(conf.debug) printf("Received EGETTY\n"); p = skb->data; if(*p == EGETTY_HELLO) { if(conf.scan) { p++; printf("Console: %d ", *p); for(i=0;i<6;i++) printf("%02x%s", from.sll_addr[i], i==5?"":":"); printf("\n"); } continue; } if(*p == EGETTY_OUT || *p == EGETTY_KMSG) { p++; if(*p++ != conf.console) continue; len = *p++ << 8; len += *p; skb_trim(skb, len); skb_pull(skb, 4); if(!conf.scan) write(1, skb->data, skb->len); } continue; } } } exit(0); }
int http_recv(sk_t *sk) { AN(skb_rdsz(sk->recvbuf)); if (!has_rnrn_termination(sk->recvbuf)) { wsd_errno = WSD_EINPUT; return (-1); } int rv; chunk_t tok; memset(&tok, 0, sizeof(chunk_t)); rv = http_header_tok(&sk->recvbuf->data[sk->recvbuf->rdpos], &tok); if (0 > rv) { if (LOG_VVERBOSE <= wsd_cfg->verbose) { printf("\t%s: errno=%d\n", __func__, errno); } goto error; } http_req_t hreq; memset(&hreq, 0, sizeof(http_req_t)); /* Parse status line, see whether or not it's a request ... */ if (0 > parse_request_line(&tok, &hreq)) { if (LOG_VVERBOSE <= wsd_cfg->verbose) { printf("\t%s: errno=%d\n", __func__, errno); } if (0 == skb_put_str(sk->sendbuf, HTTP_400)) { sk->close_on_write = 1; } goto error; } /* ... validate request line ... */ if (!is_valid_req_line(&hreq)) { if (0 == skb_put_str(sk->sendbuf, HTTP_400)) { sk->close_on_write = 1; } goto error; } /* ... tokenise and parse header fields ... */ while (0 < http_header_tok(NULL, &tok)) { if (0 > parse_header_field(&tok, &hreq)) { if (LOG_VVERBOSE <= wsd_cfg->verbose) { printf("\t%s: errno=%d\n", __func__, errno); } if (0 == skb_put_str(sk->sendbuf, HTTP_400)) { sk->close_on_write = 1; } goto error; } } /* ... and finally, validate HTTP protocol fields. */ if (!is_valid_host_header_field(&hreq)) { if (LOG_VVERBOSE <= wsd_cfg->verbose) { printf("\t%s: invalid host header field\n", __func__); } /* * Implementing as MUST; see RFC7230, section 5.4 and * RFC6455, section 4.1 */ if (0 == skb_put_str(sk->sendbuf, HTTP_400)) { sk->close_on_write = 1; } goto error; } if (!is_valid_upgrade_header_field(&hreq)) { if (LOG_VVERBOSE <= wsd_cfg->verbose) { printf("\t%s: invalid upgrade header field\n", __func__); } if (0 == skb_put_str(sk->sendbuf, HTTP_400)) { sk->close_on_write = 1; } goto error; } if (!is_valid_connection_header_field(&hreq)) { if (LOG_VVERBOSE <= wsd_cfg->verbose) { printf("\t%s: invalid connection header field\n", __func__); } if (0 == skb_put_str(sk->sendbuf, HTTP_400)) { sk->close_on_write = 1; } goto error; } skb_reset(sk->recvbuf); return sk->proto->decode_handshake(sk, &hreq); error: skb_reset(sk->recvbuf); wsd_errno = WSD_EBADREQ; if (sk->close_on_write) { turn_off_events(sk, EPOLLIN); if (!(sk->events & EPOLLOUT)) { turn_on_events(sk, EPOLLOUT); } } return (-1); }