1 #include <sys/socket.h>
13 #define MIN(a, b) ((a) < (b) ? (a) : (b))
19 struct timeval timeout;
24 static bool ethsock_fill_hwaddr(struct ethsock *sock, const char *interface)
26 struct ifaddrs *ifas, *ifa;
30 if (getifaddrs(&ifas) != 0) {
37 for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
38 if (!strcmp(ifa->ifa_name, interface)) {
40 if (ifa->ifa_addr->sa_family != AF_PACKET) {
43 src = ((struct sockaddr_ll*)ifa->ifa_addr)->sll_addr;
45 if (ifa->ifa_addr->sa_family != AF_LINK) {
48 src = LLADDR((struct sockaddr_dl*)ifa->ifa_addr);
50 memcpy(sock->hwaddr, src, 6);
57 fprintf(stderr, "Failed to get MAC address of interface %s.\n", interface);
64 inline uint8_t *ethsock_get_hwaddr(struct ethsock *sock)
69 struct ethsock *ethsock_create(const char *interface, uint16_t protocol)
71 char buf[PCAP_ERRBUF_SIZE];
72 struct bpf_program fp;
76 sock = malloc(sizeof(struct ethsock));
82 if (!ethsock_fill_hwaddr(sock, interface)) {
88 sock->pcap = pcap_open_live(interface, BUFSIZ, 1, 1, buf);
90 fprintf(stderr, "%s\n", buf);
95 fprintf(stderr, "Warning: %s.\n", buf);
98 if (pcap_datalink(sock->pcap) != DLT_EN10MB) {
99 fprintf(stderr, "Interface %s not supported.\n", interface);
103 sock->fd = pcap_get_selectable_fd(sock->pcap);
104 if (sock->fd == -1) {
105 fprintf(stderr, "No selectable file descriptor available.\n");
109 snprintf(buf, sizeof(buf), "ether proto %04x", protocol);
110 err = pcap_compile(sock->pcap, &fp, buf, 0, PCAP_NETMASK_UNKNOWN);
112 pcap_perror(sock->pcap, "pcap_compile");
116 if ((err = pcap_setfilter(sock->pcap, &fp))) {
117 pcap_perror(sock->pcap, "pcap_setfilter");
124 pcap_close(sock->pcap);
130 ssize_t ethsock_recv(struct ethsock *sock, void *buf, size_t len)
132 struct pcap_pkthdr* hdr;
133 const u_char *capbuf;
137 if (sock->timeout.tv_sec || sock->timeout.tv_usec) {
139 FD_SET(sock->fd, &fds);
141 status = select(sock->fd + 1, &fds, NULL, NULL, &sock->timeout);
145 } else if (status == 0) {
150 status = pcap_next_ex(sock->pcap, &hdr, &capbuf);
153 memcpy(buf, capbuf, MIN(len, hdr->caplen));
158 pcap_perror(sock->pcap, "pcap_next_ex");
161 fprintf(stderr, "pcap_next_ex: returned %d.\n", status);
166 int ethsock_send(struct ethsock *sock, void *buf, size_t len)
168 #if defined(_WIN32) || defined(_WIN64)
169 if (pcap_sendpacket(sock->pcap, buf, len) == 0) {
172 pcap_perror(sock->pcap, "pcap_sendpacket");
176 if (pcap_inject(sock->pcap, buf, len) == len) {
179 pcap_perror(sock->pcap, "pcap_inject");
185 int ethsock_close(struct ethsock *sock)
187 pcap_close(sock->pcap);
192 int ethsock_set_timeout(struct ethsock *sock, unsigned msec)
194 sock->timeout.tv_sec = msec / 1000;
195 sock->timeout.tv_usec = (msec % 1000) * 1000;