/* Copyright Coraid, Inc. 2006. All rights reserved. */ /* Modified the original with BSD license by Lluis Batlle */ #include #include #include #include #include #include #include #include /* for the glibc version number */ #if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1 #include #include /* the L2 protocols */ #else #include #include #include /* The L2 protocols */ #endif #include #include #include #include #include #include "main.h" #include "eth_linux.h" enum { ETH_PROTO = 0xCACA }; static int fd; static char srcaddr[6]; static int debug = 0; static void dump(unsigned char *buf, int len) { int i; for(i=0; i < len; ++i) { printf("%x ", (int) buf[i]); } putchar('\n'); } // return the index of device 'name' static int getindx(int s, char *name) { struct ifreq xx; int n; strncpy(xx.ifr_name, name, sizeof(xx.ifr_name)); xx.ifr_name[sizeof(xx.ifr_name)-1] = 0; n = ioctl(s, SIOCGIFINDEX, &xx); if (n == -1) return -1; return xx.ifr_ifindex; } // get us a raw connection to an interface int eth_open(char *eth) { int i, n; struct sockaddr_ll sa; struct ifreq xx; memset(&sa, 0, sizeof sa); fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_PROTO)); if (fd == -1) { perror("got bad socket"); return -1; } i = getindx(fd, eth); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(ETH_PROTO); sa.sll_ifindex = i; n = bind(fd, (struct sockaddr *)&sa, sizeof sa); if (n == -1) { perror("bind funky"); return -1; } strncpy(xx.ifr_name, eth, sizeof(xx.ifr_name)); xx.ifr_name[sizeof(xx.ifr_name)-1] = 0; n = ioctl(fd, SIOCGIFHWADDR, &xx); if (n == -1) { perror("Can't get hw addr"); return -1; } memmove(srcaddr, xx.ifr_hwaddr.sa_data, 6); return fd; } int eth_recv(char *buf, int len, char *partner_mac) { struct sockaddr_ll sa; int sa_len = sizeof(sa); int res; dump_line("eth_recv\n"); res = recvfrom(fd, buf, len, 0, (struct sockaddr *) &sa, &sa_len); if (debug) { printf("read %d bytes\r\n", res); dump(buf, res); } /* Assume sa_len will be ok */ if (partner_mac) memcpy(partner_mac, sa.sll_addr, sa.sll_halen); return res; } int eth_send(char *dev, char *mac, void *p, int len) { struct sockaddr_ll sa; int i; dump_line("eth_send\n"); i = getindx(fd, dev); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(ETH_PROTO); sa.sll_ifindex = i; sa.sll_halen = 6; memcpy(sa.sll_addr, mac, 6); if (debug) { printf("sending %d bytes\r\n", len); dump(p, len); } if (len > 1500) len = 1500; return sendto(fd, p, len, 0, (struct sockaddr*) &sa, sizeof(sa)); }