10 #if defined(NMRPFLASH_WINDOWS)
14 #include <sys/socket.h>
16 #if defined(NMRPFLASH_LINUX)
17 #include <linux/if_packet.h>
18 #elif defined (NMRPFLASH_OSX)
19 #include <net/if_dl.h>
24 #define MIN(a, b) ((a) < (b) ? (a) : (b))
30 #ifndef NMRPFLASH_WINDOWS
31 struct timeval timeout;
40 #ifndef NMRPFLASH_WINDOWS
41 static bool get_hwaddr(uint8_t *hwaddr, const char *intf)
43 struct ifaddrs *ifas, *ifa;
47 if (getifaddrs(&ifas) != 0) {
54 for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
55 if (!strcmp(ifa->ifa_name, intf)) {
56 #ifdef NMRPFLASH_LINUX
57 if (ifa->ifa_addr->sa_family != AF_PACKET) {
60 src = ((struct sockaddr_ll*)ifa->ifa_addr)->sll_addr;
62 if (ifa->ifa_addr->sa_family != AF_LINK) {
65 src = LLADDR((struct sockaddr_dl*)ifa->ifa_addr);
67 memcpy(hwaddr, src, 6);
77 static bool get_hwaddr(uint8_t *hwaddr, const char *intf)
79 PIP_ADAPTER_INFO adapters, adapter;
84 if ((ret = GetAdaptersInfo(NULL, &bufLen)) != ERROR_BUFFER_OVERFLOW) {
85 fprintf(stderr, "GetAdaptersInfo: error %d.\n", (int)ret);
89 adapters = malloc(bufLen);
95 if ((ret = GetAdaptersInfo(adapters, &bufLen) == NO_ERROR)) {
96 for (adapter = adapters; adapter; adapter = adapter->Next) {
97 if (adapter->Type != MIB_IF_TYPE_ETHERNET) {
101 if (!strcmp(adapter->AdapterName, intf)) {
102 if (adapter->AddressLength == 6) {
103 for (i = 0; i != 6; ++i) {
104 hwaddr[i] = adapter->Address[i];
113 fprintf(stderr, "GetAdaptersInfo: error %d.\n", (int)ret);
122 inline uint8_t *ethsock_get_hwaddr(struct ethsock *sock)
127 struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
129 char buf[PCAP_ERRBUF_SIZE];
130 struct bpf_program fp;
131 struct ethsock *sock;
134 sock = malloc(sizeof(struct ethsock));
142 sock->pcap = pcap_open_live(intf, BUFSIZ, 1, 1, buf);
144 fprintf(stderr, "%s.\n", buf);
149 fprintf(stderr, "Warning: %s.\n", buf);
152 if (pcap_datalink(sock->pcap) != DLT_EN10MB) {
153 fprintf(stderr, "%s is not an ethernet interface.\n",
158 if (!get_hwaddr(sock->hwaddr, intf)) {
159 fprintf(stderr, "Failed to get MAC address of interface.\n");
163 #ifndef NMRPFLASH_WINDOWS
164 sock->fd = pcap_get_selectable_fd(sock->pcap);
165 if (sock->fd == -1) {
166 fprintf(stderr, "No selectable file descriptor available.\n");
170 sock->handle = pcap_getevent(sock->pcap);
172 fprintf(stderr, "No event handle available.\n");
177 snprintf(buf, sizeof(buf), "ether proto %04x", protocol);
178 err = pcap_compile(sock->pcap, &fp, buf, 0, 0);
180 pcap_perror(sock->pcap, "pcap_compile");
184 if ((err = pcap_setfilter(sock->pcap, &fp))) {
185 pcap_perror(sock->pcap, "pcap_setfilter");
192 pcap_close(sock->pcap);
198 ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len)
200 struct pcap_pkthdr* hdr;
201 const u_char *capbuf;
203 #ifndef NMRPFLASH_WINDOWS
209 #ifndef NMRPFLASH_WINDOWS
210 if (sock->timeout.tv_sec || sock->timeout.tv_usec) {
212 FD_SET(sock->fd, &fds);
214 status = select(sock->fd + 1, &fds, NULL, NULL, &sock->timeout);
218 } else if (status == 0) {
224 ret = WaitForSingleObject(sock->handle, sock->timeout);
225 if (ret == WAIT_TIMEOUT) {
227 } else if (ret != WAIT_OBJECT_0) {
228 fprintf(stderr, "WaitForSingleObject: returned %d\n", (int)ret);
234 status = pcap_next_ex(sock->pcap, &hdr, &capbuf);
237 memcpy(buf, capbuf, MIN(len, hdr->caplen));
242 pcap_perror(sock->pcap, "pcap_next_ex");
245 fprintf(stderr, "pcap_next_ex: returned %d.\n", status);
250 int ethsock_send(struct ethsock *sock, void *buf, size_t len)
252 #ifdef NMRPFLASH_WINDOWS
253 if (pcap_sendpacket(sock->pcap, buf, len) == 0) {
256 pcap_perror(sock->pcap, "pcap_sendpacket");
260 if (pcap_inject(sock->pcap, buf, len) == len) {
263 pcap_perror(sock->pcap, "pcap_inject");
269 int ethsock_close(struct ethsock *sock)
271 pcap_close(sock->pcap);
276 int ethsock_set_timeout(struct ethsock *sock, unsigned msec)
278 #ifndef NMRPFLASH_WINDOWS
279 sock->timeout.tv_sec = msec / 1000;
280 sock->timeout.tv_usec = (msec % 1000) * 1000;
282 sock->timeout = msec;
287 static bool is_ethernet(const char *intf)
290 char errbuf[PCAP_ERRBUF_SIZE];
293 if ((pcap = pcap_create(intf, errbuf))) {
294 if (pcap_activate(pcap) == 0) {
295 ret = (pcap_datalink(pcap) == DLT_EN10MB);
303 int ethsock_list_all(void)
305 pcap_if_t *devs, *dev;
307 char errbuf[PCAP_ERRBUF_SIZE];
309 if (pcap_findalldevs(&devs, errbuf) != 0) {
310 fprintf(stderr, "%s.\n", errbuf);
314 memset(hwaddr, 0, 6);
316 for (dev = devs; dev; dev = dev->next) {
317 if (dev->flags & PCAP_IF_LOOPBACK) {
321 if (!is_ethernet(dev->name)) {
325 if (!get_hwaddr(hwaddr, dev->name)) {
329 printf("%s %02x:%02x:%02x:%02x:%02x:%02x", dev->name, hwaddr[0],
330 hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
332 if (dev->description) {
333 printf(" (%s)\n", dev->description);