10 #if defined(NMRPFLASH_WINDOWS)
12 #define NMRPFLASH_ALIAS_PREFIX "net"
15 #if defined(NMRPFLASH_LINUX)
16 #include <linux/if_packet.h>
17 #elif defined (NMRPFLASH_OSX)
18 #include <net/if_dl.h>
23 #define MIN(a, b) ((a) < (b) ? (a) : (b))
30 #ifndef NMRPFLASH_WINDOWS
31 struct timeval timeout;
40 static int x_pcap_findalldevs(pcap_if_t **devs)
42 char errbuf[PCAP_ERRBUF_SIZE];
43 if (pcap_findalldevs(devs, errbuf) != 0) {
44 fprintf(stderr, "%s.\n", errbuf);
51 #ifndef NMRPFLASH_WINDOWS
52 static bool get_hwaddr(uint8_t *hwaddr, const char *intf)
54 struct ifaddrs *ifas, *ifa;
58 if (getifaddrs(&ifas) != 0) {
65 for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
66 if (!strcmp(ifa->ifa_name, intf)) {
67 #ifdef NMRPFLASH_LINUX
68 if (ifa->ifa_addr->sa_family != AF_PACKET) {
71 src = ((struct sockaddr_ll*)ifa->ifa_addr)->sll_addr;
73 if (ifa->ifa_addr->sa_family != AF_LINK) {
76 src = LLADDR((struct sockaddr_dl*)ifa->ifa_addr);
78 memcpy(hwaddr, src, 6);
89 static void win_perror2(const char *msg, int err)
91 fprintf(stderr, "%s: error %d\n", msg, err);
94 static bool get_hwaddr(uint8_t *hwaddr, const char *intf)
96 PIP_ADAPTER_INFO adapters, adapter;
101 if ((ret = GetAdaptersInfo(NULL, &bufLen)) != ERROR_BUFFER_OVERFLOW) {
102 win_perror2("GetAdaptersInfo", ret);
106 adapters = malloc(bufLen);
112 if ((ret = GetAdaptersInfo(adapters, &bufLen) == NO_ERROR)) {
113 for (adapter = adapters; adapter; adapter = adapter->Next) {
114 if (adapter->Type != MIB_IF_TYPE_ETHERNET) {
118 #ifndef NMRPFLASH_WINDOWS
119 if (!strcmp(intf, adapter->AdapterName))
121 /* Interface names from WinPcap are "\Device\NPF_{GUID}", while
122 * AdapterName from GetAdaptersInfo is just "{GUID}".*/
123 if (strstr(intf, adapter->AdapterName))
126 if (adapter->AddressLength == 6) {
127 for (i = 0; i != 6; ++i) {
128 hwaddr[i] = adapter->Address[i];
137 win_perror2("GetAdaptersInfo", ret);
144 static const char *intf_alias_to_wpcap(const char *intf)
146 static char buf[128];
147 pcap_if_t *devs, *dev;
148 unsigned i = 0, dev_num = 0;
150 if (intf[0] == '\\') {
152 } else if (sscanf(intf, NMRPFLASH_ALIAS_PREFIX "%u", &dev_num) != 1) {
153 fprintf(stderr, "Invalid interface alias.\n");
157 if (x_pcap_findalldevs(&devs) != 0) {
161 for (dev = devs; dev; dev = dev->next) {
163 printf(NMRPFLASH_ALIAS_PREFIX "%u: %s\n", i, dev->name);
164 strncpy(buf, dev->name, sizeof(buf) - 1);
165 buf[sizeof(buf) - 1] = '\0';
170 pcap_freealldevs(devs);
173 fprintf(stderr, "Interface alias not found.\n");
180 static const char *intf_get_pretty_name(const char *intf)
182 static char buf[512];
188 guid = strstr(intf, "NPF_{");
195 snprintf(buf, sizeof(buf),
196 "System\\CurrentControlSet\\Control\\Network\\"
197 "{4D36E972-E325-11CE-BFC1-08002BE10318}\\"
198 "%s\\Connection", guid);
199 err = RegOpenKeyExA(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &hkey);
200 if (err != ERROR_SUCCESS) {
201 win_perror2("RegOpenKeyExA", err);
206 err = RegQueryValueExA(hkey, "Name", NULL, NULL, (LPBYTE)buf, &len);
207 if (err == ERROR_SUCCESS) {
210 win_perror2("RegQueryValueExA", err);
220 inline uint8_t *ethsock_get_hwaddr(struct ethsock *sock)
225 struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
227 char buf[PCAP_ERRBUF_SIZE];
228 struct bpf_program fp;
229 struct ethsock *sock;
232 sock = malloc(sizeof(struct ethsock));
238 #ifdef NMRPFLASH_WINDOWS
239 intf = intf_alias_to_wpcap(intf);
247 sock->pcap = pcap_open_live(intf, BUFSIZ, 1, 1, buf);
249 fprintf(stderr, "%s.\n", buf);
254 fprintf(stderr, "Warning: %s.\n", buf);
257 if (pcap_datalink(sock->pcap) != DLT_EN10MB) {
258 fprintf(stderr, "%s is not an ethernet interface.\n",
263 if (!get_hwaddr(sock->hwaddr, intf)) {
264 fprintf(stderr, "Failed to get MAC address of interface.\n");
268 #ifndef NMRPFLASH_WINDOWS
269 sock->fd = pcap_get_selectable_fd(sock->pcap);
270 if (sock->fd == -1) {
271 fprintf(stderr, "No selectable file descriptor available.\n");
275 sock->handle = pcap_getevent(sock->pcap);
277 fprintf(stderr, "No event handle available.\n");
282 snprintf(buf, sizeof(buf), "ether proto %04x", protocol);
283 err = pcap_compile(sock->pcap, &fp, buf, 0, 0);
285 pcap_perror(sock->pcap, "pcap_compile");
289 if ((err = pcap_setfilter(sock->pcap, &fp))) {
290 pcap_perror(sock->pcap, "pcap_setfilter");
297 pcap_close(sock->pcap);
303 ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len)
305 struct pcap_pkthdr* hdr;
306 const u_char *capbuf;
308 #ifndef NMRPFLASH_WINDOWS
314 #ifndef NMRPFLASH_WINDOWS
315 if (sock->timeout.tv_sec || sock->timeout.tv_usec) {
317 FD_SET(sock->fd, &fds);
319 status = select(sock->fd + 1, &fds, NULL, NULL, &sock->timeout);
323 } else if (status == 0) {
329 ret = WaitForSingleObject(sock->handle, sock->timeout);
330 if (ret == WAIT_TIMEOUT) {
332 } else if (ret != WAIT_OBJECT_0) {
333 fprintf(stderr, "WaitForSingleObject: returned %d\n", (int)ret);
339 status = pcap_next_ex(sock->pcap, &hdr, &capbuf);
342 memcpy(buf, capbuf, MIN(len, hdr->caplen));
347 pcap_perror(sock->pcap, "pcap_next_ex");
350 fprintf(stderr, "pcap_next_ex: returned %d.\n", status);
355 int ethsock_send(struct ethsock *sock, void *buf, size_t len)
357 #ifdef NMRPFLASH_WINDOWS
358 if (pcap_sendpacket(sock->pcap, buf, len) == 0) {
361 pcap_perror(sock->pcap, "pcap_sendpacket");
365 if (pcap_inject(sock->pcap, buf, len) == len) {
368 pcap_perror(sock->pcap, "pcap_inject");
374 int ethsock_close(struct ethsock *sock)
376 pcap_close(sock->pcap);
381 int ethsock_set_timeout(struct ethsock *sock, unsigned msec)
383 #ifndef NMRPFLASH_WINDOWS
384 sock->timeout.tv_sec = msec / 1000;
385 sock->timeout.tv_usec = (msec % 1000) * 1000;
387 sock->timeout = msec;
392 static bool is_ethernet(const char *intf)
395 char errbuf[PCAP_ERRBUF_SIZE];
398 if ((pcap = pcap_create(intf, errbuf))) {
399 if (pcap_activate(pcap) == 0) {
400 ret = (pcap_datalink(pcap) == DLT_EN10MB);
408 int ethsock_list_all(void)
410 pcap_if_t *devs, *dev;
413 unsigned dev_num = 0;
414 #ifdef NMRPFLASH_WINDOWS
418 if (x_pcap_findalldevs(&devs) != 0) {
422 memset(hwaddr, 0, 6);
424 for (dev = devs; dev; dev = dev->next) {
425 if (!is_ethernet(dev->name)) {
427 printf("%s (not an ethernet device)\n",
433 if (!get_hwaddr(hwaddr, dev->name)) {
435 printf("%s (failed to get hardware address)\n",
441 #ifndef NMRPFLASH_WINDOWS
442 printf("%s", dev->name);
444 printf(NMRPFLASH_ALIAS_PREFIX "%u", dev_num);
447 for (addr = dev->addresses; addr; addr = addr->next) {
448 if (addr->addr->sa_family == AF_INET) {
450 inet_ntoa(((struct sockaddr_in*)addr->addr)->sin_addr));
459 printf(" %02x:%02x:%02x:%02x:%02x:%02x", hwaddr[0], hwaddr[1],
460 hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
462 #ifdef NMRPFLASH_WINDOWS
464 printf(" %s", dev->name);
467 pretty = intf_get_pretty_name(dev->name);
469 printf(" (%s)", pretty);
470 } else if (dev->description) {
471 printf(" (%s)", dev->description);
480 printf("No suitable network interfaces found.\n");