/* Ethernet packet generator */ /* Written by Vladimir Zapolsky */ /* mail to avz101c@motolola.com */ /* July 28, 2007 */ #define ETH_FRAME_LEN 1514 #define ETH_HEADER_LEN (2 * ETH_ALEN) #include #include #include #include #include #include #include #include #include #include #include typedef struct _Packets { unsigned int dst[ETH_ALEN]; unsigned int src[ETH_ALEN]; unsigned char hdr[ETH_HEADER_LEN]; unsigned char payload; char ifname[5]; int fll; int cnt; int rnd; int len; } Packets; Packets packets; const char* program; void dump_packets() { printf("Interface name: %s\n", packets.ifname); if (packets.fll) { printf("Fillall\n"); } else { printf("Source MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", packets.src[0], packets.src[1], packets.src[2], packets.src[3], packets.src[4], packets.src[5]); printf("Destination MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", packets.dst[0], packets.dst[1], packets.dst[2], packets.dst[3], packets.dst[4], packets.dst[5]); } printf("Count: %d\n", packets.cnt); printf("Length: %d\n", packets.len); if (packets.rnd) { printf("Payload: random\n"); } else { printf("Payload: %02X\n", packets.payload); } } void src_mac(const int sd, int* index) { struct ifreq ifr; int i; strcpy(ifr.ifr_name, packets.ifname); if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) { perror("Cannot get ifindex of the interface"); exit(1); } *index = ifr.ifr_ifindex; if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1 ) { perror("Cannot get source MAC "); exit(1); } for (i = 0; i < 6; i++) { packets.src[i] = ifr.ifr_hwaddr.sa_data[i]; } } void print_usage() { printf("Usage: %s [options]\n", program); printf(" -h --help Display the usage information.\n"); printf(" -p --payload (0x[0-9A-F]{2}|rand) Set payload.\n"); printf(" -i --interface eth[0-9] Set interface.\n"); printf(" -c --count num Set number of packets to send.\n"); printf(" -f --fillall Set packet header similar to payload.\n"); printf(" -d --dest XX:XX:XX:XX:XX Set destination MAC address.\n"); printf(" -l --length num Set whole length of a packet ( min 60, max 1514 )\n"); printf(" Default payload is 0x00, interface is eth0, count of packets is 1, length is 1514.\n"); printf(" Default destination MAC address is 00:00:00:00:00:00.\n"); exit(1); } void print_error(char* str) { printf("%s\n", str); exit(1); } int main (int argc, char* argv[]) { int sd = 0; int rd = 0; program = argv[0]; int opt; unsigned char buffer[ETH_FRAME_LEN]; int i; struct sockaddr_ll saddr; /* int status;*/ const char* const short_opt = "hp:i:c:fd:l:"; const struct option long_opt[] = { { "help", 0, NULL, 'h' }, { "payload", 1, NULL, 'p' }, { "interface", 1, NULL, 'i' }, { "count", 1, NULL, 'c' }, { "fillall", 0, NULL, 'f' }, { "dest", 1, NULL, 'd' }, { "length", 1, NULL, 'l' } }; for (i = 0; i < ETH_ALEN; i++) { packets.dst[i] = 0x00; packets.src[i] = 0x00; } packets.len = ETH_FRAME_LEN; packets.rnd = 0; packets.cnt = 1; packets.payload = 0x00; packets.fll = 0; strcpy(packets.ifname, "eth0"); do { opt = getopt_long(argc, argv, short_opt, long_opt, NULL); switch (opt) { case 'h': print_usage(); case 'p': if (strlen(optarg) != 4) { print_error("Invalid payload"); } else if (!strcmp("rand", optarg)) { packets.rnd = 1; } else if (!strncmp("0x", optarg, 2)) { packets.payload = strtol(optarg, (char**)NULL, 16); } else { print_error("Invalid payload"); } break; case 'i': if (strlen(optarg) > 4 || strncmp("eth", optarg, 3)) { print_error("Invalid interface name"); } strcpy(packets.ifname, optarg); break; case 'c': packets.cnt = strtol(optarg, (char**)NULL, 10); if (packets.cnt <= 0) { print_error("Invalid count"); } break; case 'f': packets.fll = 1; break; case 'd': if (strlen(optarg) != 17) { print_error("Invalid destination MAC address"); } else { for (i = 0; i < 5; i++) { if (optarg[3*i+2] != ':') { print_error("Invalid destination MAC address"); } } if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", &packets.dst[0], &packets.dst[1], &packets.dst[2], &packets.dst[3], &packets.dst[4], &packets.dst[5]) != ETH_ALEN) { print_error("Invalid destination MAC address"); } } break; case 'l': packets.len = strtol(optarg, (char**)NULL, 10); if (packets.len > ETH_FRAME_LEN || packets.len < 60) { print_error("Invalid length"); } break; default: break; } } while (opt != -1); /* Body */ if (packets.rnd) { rd = open("/dev/urandom", O_RDONLY); if (rd == -1) { printf("Cannot open /dev/urandom, packets are filled with zeroes\n"); packets.rnd = 0; } } sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sd == -1) { perror("Cannot open socket "); exit(1); } saddr.sll_family = PF_PACKET; saddr.sll_protocol = htons(ETH_P_IP); src_mac(sd, &saddr.sll_ifindex); saddr.sll_hatype = ARPHRD_ETHER; saddr.sll_pkttype = PACKET_OTHERHOST; saddr.sll_halen = ETH_ALEN; /* saddr.sll_addr[i] = packets.dst[i];*/ dump_packets(); /* Generate payload */ for (i = 0; i < ETH_ALEN; i++) { packets.hdr[i] = (unsigned char)packets.dst[i]; packets.hdr[i + ETH_ALEN] = (unsigned char)packets.src[i]; } if (!packets.rnd) { memset((void*)buffer, packets.payload, packets.len); } if (!packets.fll) { memcpy((void*)buffer, (void*)packets.hdr, ETH_HEADER_LEN); } while(packets.cnt > 0) { if (packets.rnd) { if (packets.fll) { read(rd, buffer, packets.len); } else { read(rd, &buffer[ETH_HEADER_LEN], packets.len - ETH_HEADER_LEN); } } if (sendto(sd, buffer, packets.len, 0, (struct sockaddr*)&saddr, sizeof(saddr)) != packets.len) { print_error("Cannot send a packet"); perror(""); } packets.cnt--; } printf("Done.\n"); if (rd > 0) { close(rd); } close(sd); return(0); }