diff --git a/src/lan-play.c b/src/lan-play.c index c6cd699..1e34a6d 100644 --- a/src/lan-play.c +++ b/src/lan-play.c @@ -7,9 +7,9 @@ struct lan_play real_lan_play; uint8_t SEND_BUFFER[BUFFER_SIZE]; void lan_play_pcap_handler(uv_pcap_t *handle, const struct pcap_pkthdr *pkt_header, const u_char *packet, const uint8_t *mac); -int init_pcap(struct lan_play *lan_play) +int init_pcap(struct lan_play *lan_play, char *netif) { - int ret = uv_pcap_init(lan_play->loop, &lan_play->pcap, lan_play_pcap_handler); + int ret = uv_pcap_init(lan_play->loop, &lan_play->pcap, lan_play_pcap_handler, netif); if (ret != 0) { RETURN_ERR(lan_play, "failed at uv_pcap_init"); }; @@ -75,7 +75,7 @@ int lan_play_init(struct lan_play *lan_play) SHA1Final(lan_play->key, &hashctx); } - ret = init_pcap(lan_play); + ret = init_pcap(lan_play, options.netif); if (ret != 0) return ret; CPY_IPV4(ip, str2ip(SERVER_IP)); diff --git a/src/lan-play.h b/src/lan-play.h index ad007d2..2188e6e 100644 --- a/src/lan-play.h +++ b/src/lan-play.h @@ -93,6 +93,7 @@ struct cli_options { bool list_if; char *netif_ipaddr; + char *netif; char *netif_netmask; char *relay_server_addr; diff --git a/src/main.c b/src/main.c index d153759..e244291 100644 --- a/src/main.c +++ b/src/main.c @@ -64,6 +64,7 @@ int parse_arguments(int argc, char **argv) options.fake_internet = false; options.list_if = false; + options.netif = NULL; options.netif_ipaddr = NULL; options.netif_netmask = NULL; @@ -88,10 +89,10 @@ int parse_arguments(int argc, char **argv) options.help = 1; } else if (!strcmp(arg, "--version")) { options.version = 1; - // } else if (!strcmp(arg, "--netif-ipaddr")) { - // CHECK_PARAM(); - // options.netif_ipaddr = argv[i + 1]; - // i++; + } else if (!strcmp(arg, "--netif")) { + CHECK_PARAM(); + options.netif = strdup(argv[i + 1]); + i++; // } else if (!strcmp(arg, "--netif-netmask")) { // CHECK_PARAM(); // options.netif_netmask = argv[i + 1]; @@ -205,7 +206,7 @@ void print_help(const char *name) " [--version]\n" " [--broadcast]\n" " [--fake-internet]\n" - // " [--netif-ipaddr ] default: 10.13.37.1\n" + " [--netif ] default: all\n" // " [--netif-netmask ] default: 255.255.0.0\n" " [--relay-server-addr ]\n" " [--username ]\n" @@ -307,7 +308,11 @@ int old_main() RT_ASSERT(uv_signal_start(&signal_int, lan_play_signal_cb, SIGINT) == 0); signal_int.data = lan_play; - printf("Opening interfaces\n"); + if (options.netif == NULL) { + printf("Interface not specified, opening all interfaces\n"); + } else { + printf("Opening single interface\n"); + } RT_ASSERT(lan_play_init(lan_play) == 0); ret = uv_run(lan_play->loop, UV_RUN_DEFAULT); diff --git a/src/pcaploop.cpp b/src/pcaploop.cpp index b13afc3..93bd462 100644 --- a/src/pcaploop.cpp +++ b/src/pcaploop.cpp @@ -112,12 +112,11 @@ int uv_pcap_sendpacket(uv_pcap_t *handle, const u_char *data, int size) return 0; } -int uv_pcap_init(uv_loop_t *loop, uv_pcap_t *handle, uv_pcap_cb cb) +int uv_pcap_init(uv_loop_t *loop, uv_pcap_t *handle, uv_pcap_cb cb, char *netif) { handle->cb = cb; handle->inner = new uv_pcap_inner; auto inner = handle->inner; - pcap_if_t *alldevs; char err_buf[PCAP_ERRBUF_SIZE]; if (pcap_findalldevs(&alldevs, err_buf)) { @@ -126,19 +125,73 @@ int uv_pcap_init(uv_loop_t *loop, uv_pcap_t *handle, uv_pcap_cb cb) } int i = 0; pcap_if_t *d; + for (d = alldevs; d; d = d->next) { i++; + if (netif != NULL) { + int netif_index = atoi(netif); + if (i == netif_index) { + netif = strdup(d->name); + } + } } if (i == 0) { fprintf(stderr, "Error pcap_findalldevs 0 item\n"); exit(1); } - inner->interfaces = new uv_pcap_interf_t[i]; i = 0; for (d = alldevs; d; d = d->next) { pcap_t *dev; int ret; + if (netif != NULL) { + if (!strcmp(d->name, netif)) { + printf("found interface: %s\n", d->name); + // found requested interface + dev = pcap_open_live(d->name, 65535, 1, 500, err_buf); + if (!dev) { + LLOG(LLOG_DEBUG, "open %s fail", d->name); + goto fail_single; + } + + auto datalink = pcap_datalink(dev); + if (datalink != DLT_EN10MB) { + LLOG(LLOG_DEBUG, "open specified interface: %s fail: datalink(%d)", d->name, datalink); + goto fail_single; + } + + uint8_t mac[6]; + if (get_mac_address(d, dev, mac) != 0) { + LLOG(LLOG_DEBUG, "open specified interface: %s fail: get mac", d->name); + goto fail_single; + } + if (memcmp(EmptyMac, mac, 6) == 0) { + LLOG(LLOG_DEBUG, "open specified interface: %s fail: get all zero mac", d->name); + goto fail_single; + } + + set_filter(dev, mac); + + if (set_immediate_mode(dev) == -1) { + LLOG(LLOG_DEBUG, "open specified interface: %s fail: set_immediate_mode %s", d->name, strerror(errno)); + goto fail_single; + } + + ret = uv_pcap_interf_init(loop, &inner->interfaces[i], uv_pcap_callback, dev, mac); + if (ret) { + LLOG(LLOG_DEBUG, "open specified interface: %s fail: pcap init", d->name); + goto fail_single; + } + inner->interfaces[i].data = handle; + i++; + LLOG(LLOG_DEBUG, "open specified interface: %s ok", d->name); + break; + } + continue; + fail_single: + pcap_close(dev); + break; + } dev = pcap_open_live(d->name, 65535, 1, 500, err_buf); if (!dev) { diff --git a/src/pcaploop.h b/src/pcaploop.h index e1aa52f..d54109a 100644 --- a/src/pcaploop.h +++ b/src/pcaploop.h @@ -19,7 +19,7 @@ struct uv_pcap_s { void *data; }; -int uv_pcap_init(uv_loop_t *loop, uv_pcap_t *handle, uv_pcap_cb cb); +int uv_pcap_init(uv_loop_t *loop, uv_pcap_t *handle, uv_pcap_cb cb, char *netif); void uv_pcap_close(uv_pcap_t *handle); int uv_pcap_sendpacket(uv_pcap_t *handle, const u_char *data, int size);