9 #if defined(_WIN32) || defined(_WIN64)
10 #define NMRPFLASH_WINDOWS
11 #elif defined(__linux__)
12 #define NMRPFLASH_LINUX
13 #elif defined(__APPLE__) && defined(__MACH__)
15 #elif defined(__unix__)
16 #define NMRPFLASH_UNIX
17 #warning "nmrp-flash is not fully supported on your operating system"
20 #if defined(NMRPFLASH_WINDOWS)
24 #include <sys/socket.h>
26 #if defined(NMRPFLASH_LINUX)
27 #include <linux/if_packet.h>
28 #elif defined (NMRPFLASH_OSX)
29 #include <net/if_dl.h>
34 #define MIN(a, b) ((a) < (b) ? (a) : (b))
40 struct timeval timeout;
45 #ifndef NMRPFLASH_WINDOWS
46 static bool get_hwaddr(uint8_t *hwaddr, const char *intf)
48 struct ifaddrs *ifas, *ifa;
52 if (getifaddrs(&ifas) != 0) {
59 for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
60 if (!strcmp(ifa->ifa_name, intf)) {
61 #ifdef NMRPFLASH_LINUX
62 if (ifa->ifa_addr->sa_family != AF_PACKET) {
65 src = ((struct sockaddr_ll*)ifa->ifa_addr)->sll_addr;
67 if (ifa->ifa_addr->sa_family != AF_LINK) {
70 src = LLADDR((struct sockaddr_dl*)ifa->ifa_addr);
72 memcpy(hwaddr, src, 6);
82 static bool get_hwaddr(uint8_t *hwaddr, const char *intf)
84 PIP_ADAPTER_INFO adapters, adapter;
89 if ((ret = GetAdaptersInfo(NULL, &bufLen)) != ERROR_BUFFER_OVERFLOW) {
90 fprintf(stderr, "GetAdaptersInfo: error %d.\n", ret);
94 adapters = malloc(bufLen);
100 if ((ret = GetAdaptersInfo(adapters, bufLen) == NO_ERROR)) {
101 for (adapter = adapters; adapter; adapter = adapter->Next) {
102 if (adapter->Type != MIB_IF_TYPE_ETHERNET) {
106 if (!strcmp(adapter->AdapterName, intf)) {
107 if (adapter->AddressLength == 6) {
108 for (i = 0; i != 6; ++i) {
109 hwaddr[i] = adapter->Address[i];
118 fprintf(stderr, "GetAdaptersInfo: error %d.\n", ret);
127 inline uint8_t *ethsock_get_hwaddr(struct ethsock *sock)
132 struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
134 char buf[PCAP_ERRBUF_SIZE];
135 struct bpf_program fp;
136 struct ethsock *sock;
139 sock = malloc(sizeof(struct ethsock));
147 sock->pcap = pcap_open_live(intf, BUFSIZ, 1, 1, buf);
149 fprintf(stderr, "%s.\n", buf);
154 fprintf(stderr, "Warning: %s.\n", buf);
157 if (pcap_datalink(sock->pcap) != DLT_EN10MB) {
158 fprintf(stderr, "%s is not an ethernet interface.\n",
163 if (!get_hwaddr(sock->hwaddr, intf)) {
164 fprintf(stderr, "Failed to get MAC address of interface.\n");
168 sock->fd = pcap_get_selectable_fd(sock->pcap);
169 if (sock->fd == -1) {
170 fprintf(stderr, "No selectable file descriptor available.\n");
174 snprintf(buf, sizeof(buf), "ether proto %04x", protocol);
175 err = pcap_compile(sock->pcap, &fp, buf, 0, PCAP_NETMASK_UNKNOWN);
177 pcap_perror(sock->pcap, "pcap_compile");
181 if ((err = pcap_setfilter(sock->pcap, &fp))) {
182 pcap_perror(sock->pcap, "pcap_setfilter");
189 pcap_close(sock->pcap);
195 ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len)
197 struct pcap_pkthdr* hdr;
198 const u_char *capbuf;
202 if (sock->timeout.tv_sec || sock->timeout.tv_usec) {
204 FD_SET(sock->fd, &fds);
206 status = select(sock->fd + 1, &fds, NULL, NULL, &sock->timeout);
210 } else if (status == 0) {
215 status = pcap_next_ex(sock->pcap, &hdr, &capbuf);
218 memcpy(buf, capbuf, MIN(len, hdr->caplen));
223 pcap_perror(sock->pcap, "pcap_next_ex");
226 fprintf(stderr, "pcap_next_ex: returned %d.\n", status);
231 int ethsock_send(struct ethsock *sock, void *buf, size_t len)
233 #ifdef NMRPFLASH_WINDOWS
234 if (pcap_sendpacket(sock->pcap, buf, len) == 0) {
237 pcap_perror(sock->pcap, "pcap_sendpacket");
241 if (pcap_inject(sock->pcap, buf, len) == len) {
244 pcap_perror(sock->pcap, "pcap_inject");
250 int ethsock_close(struct ethsock *sock)
252 pcap_close(sock->pcap);
257 int ethsock_set_timeout(struct ethsock *sock, unsigned msec)
259 sock->timeout.tv_sec = msec / 1000;
260 sock->timeout.tv_usec = (msec % 1000) * 1000;
264 static bool is_ethernet(const char *intf)
267 char errbuf[PCAP_ERRBUF_SIZE];
270 if ((pcap = pcap_create(intf, errbuf))) {
271 if (pcap_activate(pcap) == 0) {
272 ret = (pcap_datalink(pcap) == DLT_EN10MB);
280 int ethsock_list_all(void)
282 pcap_if_t *devs, *dev;
284 char errbuf[PCAP_ERRBUF_SIZE];
286 if (pcap_findalldevs(&devs, errbuf) != 0) {
287 fprintf(stderr, "%s.\n", errbuf);
291 memset(hwaddr, 0, 6);
293 for (dev = devs; dev; dev = dev->next) {
294 if (dev->flags & PCAP_IF_LOOPBACK) {
298 if (!is_ethernet(dev->name)) {
302 if (!get_hwaddr(hwaddr, dev->name)) {
306 printf("%s %02x:%02x:%02x:%02x:%02x:%02x", dev->name, hwaddr[0],
307 hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
309 if (dev->description) {
310 printf(" (%s)\n", dev->description);