#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if_arp.h> #include <netinet/in.h> #include <linux/sockios.h> #include <net/if.h> #include <sys/types.h> unsigned char hex2dec(unsigned char hex) { hex = toupper(hex); hex -= (hex - 48 > 9) ? 55 : 48; return hex; } int hexstr_to_int(char *hex) { int i, j; union { int l; unsigned char ch[4]; } num; j = 0; for (i = 0; i < 8; i += 2) num.ch[j++] = hex2dec(hex[i]) * 16 + hex2dec(hex[i + 1]); return htonl(num.l); } char *get_gateway_str(void) { FILE *fp; char *rt_file = "/proc/net/route"; char str[256]; char dst[9]; char *dst_bgn; static char gw_str[9]; char *gw_bgn; fp = fopen(rt_file, "r"); if (fp == NULL) { printf("Cannot open file: %s\n", rt_file); perror("fopen()"); exit(EXIT_FAILURE); } while (fgets(str, 255, fp) != NULL) { dst_bgn = strchr(str, '\11') + 1; memcpy(dst, dst_bgn, 8); dst[8] = '\0'; if (strcmp(dst, "00000000") == 0) { gw_bgn = dst_bgn + 8 + 1; memcpy(gw_str, gw_bgn, 8); } } fclose(fp); return gw_str; } static char *get_gateway_iface(void) { FILE *fp; char *rt_file = "/proc/net/route"; char str[256]; char dst[9]; char *dst_bgn; static char iface_str[9]; fp = fopen(rt_file, "r"); if (fp == NULL) { printf("Cannot open file: %s\n", rt_file); perror("fopen()"); exit(EXIT_FAILURE); } while (fgets(str, 255, fp) != NULL) { dst_bgn = strchr(str, '\11') + 1; memcpy(dst, dst_bgn, 8); dst[8] = '\0'; if (strcmp(dst, "00000000") == 0) { memcpy(iface_str, str, dst_bgn - str - 1); iface_str[dst_bgn - str - 1] = '\0'; } } fclose(fp); return iface_str; } void show_header(unsigned char header[14]) { int i; for (i = 0; i < 14; i++) { if (i > 0) printf(" "); printf("%02X", header[i] & 0x00FF); } printf("\n"); } static unsigned char *get_mac_arpcache(char *ip_str, char *iface) { int s; struct arpreq areq; struct sockaddr_in *sin; struct in_addr ipaddr; /* static unsigned char *mac_bin = (unsigned char *) areq.arp_ha.sa_data; */ static unsigned char *mac_bin; mac_bin = (unsigned char *)areq.arp_ha.sa_data; /* Get an internet domain socket. */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { perror("socket"); exit(1); } /* Make the ARP request. */ memset(&areq, 0, sizeof(areq)); sin = (struct sockaddr_in *)&areq.arp_pa; sin->sin_family = AF_INET; if (inet_aton(ip_str, &ipaddr) == 0) { fprintf(stderr, "-- Error: invalid IP address %s.\n", ip_str); exit(1); } sin->sin_addr = ipaddr; sin = (struct sockaddr_in *)&areq.arp_ha; sin->sin_family = ARPHRD_ETHER; strncpy(areq.arp_dev, iface, 15); if (ioctl(s, SIOCGARP, (caddr_t) & areq) == -1) { perror("-- Error: unable to make ARP request, error"); exit(1); } return mac_bin; } int get_dev_mac(char *dev, unsigned char mac[6]) { int i; int status; int sock; struct ifreq ifr; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock == -1) { perror("socket() ERROR"); return -1; } strcpy(ifr.ifr_name, dev); status = ioctl(sock, SIOCGIFHWADDR, (char *)&ifr); if (status == -1) { perror("ioctl(SIOCGIFHWADDR) ERROR"); return -1; } memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); close(sock); return 0; } static unsigned char *create_eth_header(void) { int i; char *ip; char *iface; unsigned char gw_mac[6]; unsigned char eth_mac[6]; static unsigned char eth_header[14]; /* Findout gateway IP address */ ip = (char *)inet_ntoa(hexstr_to_int(get_gateway_str())); /* Findout gateway interface name */ iface = get_gateway_iface(); /* Read gateway mac address from arp cache */ memcpy(gw_mac, get_mac_arpcache(ip, iface), 6); /* Findout local eth mac addrsss */ get_dev_mac(iface, eth_mac); for (i = 0; i < 6; i++) { eth_header[i] = gw_mac[i]; eth_header[i + 6] = eth_mac[i]; } eth_header[12] = 8; eth_header[13] = 0; return eth_header; } int main() { show_header(create_eth_header()); return 0; }