/** This tool can be used to send packets with custom (ie, bad) Ethernet * Frame Checksum. * * This requires the 'Low-level Ethernet debugging features.' patch series, * which supports e100, e1000, and e1000e drivers. Support for igb and * hopefully ixgbe will be added soon. * * To compile: gcc -Wall nofcs.c -o nofcs * * Usage: * Send 10 packets out eth0 with bad FCS: * ./nofcs -i eth0 -dm 00:11:22:33:44:55 * * To receive the packets, you could use a version of ethtool that supports * the feature strings logic posted by Michal Miroslaw and enable 'rx-all' * and optionally: 'rx-fcs'. * * The patch for ethtool is posted here: * http://patchwork.ozlabs.org/patch/96374/ * * This code was written by Ben Greear * and is hereby released into the public domain with no restrictions. * February 17, 2012. * */ #include #include #include #include #include #include #include #include #include #include static char* dev = NULL; static int count = 10; static int bytes = 128; // not counting fcs static unsigned int fcs = 0xdeadbeef; static char* dst_mac = NULL; static void print_usage() { printf("usage: -i [dev-name] -b [byte-count] -c [packet-count] -f [fcs] -dm [dest-mac]\n" "Example: nofcs -i eth0 -b 128 -c 10 -dm 00:11:22:33:44:55 -f 0xdeadbeef\n\n"); } int createPacketSocket(const char* dev_name, int ether_type) { int s = socket(PF_PACKET, SOCK_RAW, htons(ether_type)); int r; //retval struct sockaddr_ll myaddr; if (s < 0) { perror("socket(PF_PACKET)"); exit(1); } memset(&myaddr, '\0', sizeof(myaddr)); myaddr.sll_family = AF_PACKET; myaddr.sll_protocol = htons(ether_type); myaddr.sll_ifindex = if_nametoindex(dev_name); if (myaddr.sll_ifindex == 0) { perror("if_nametoindex"); exit(1); } r = bind(s, (struct sockaddr*)(&myaddr), sizeof(myaddr)); if (r < 0) { perror("bind"); exit(1); } return s; } static int toMacString(unsigned char* rslt_mac, const char* raw_mac) { /* Turn HEX into bytes. First, gather all the useful HEX */ char tmp[12]; /* More than 12 is useless, at least right now */ char c; int j = 0; /* tmp's index. */ int i; char tmp_bt[3]; for (i = 0; i= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F'))) { tmp[j] = c; if (j == 11) { break; /* done */ } j++; } else { if ((c == ':') || (c == ' ') || (c == '.')) { /* Ok, valid divider */ } else { printf("ERROR: Invalid characters found in the MAC input string: %s index: %i character: %c\n", raw_mac, i, c); exit(1); } } } if (j != 11) { printf("ERROR: Not enough HEX values in the input string.\n"); exit(1); } for (i = 0; i<6; i++) { tmp_bt[0] = tmp[i*2]; tmp_bt[1] = tmp[i*2 +1]; tmp_bt[2] = 0; rslt_mac[i] = (char)(strtol(tmp_bt, NULL, 16) & 0xFF); /* base 16 (HEX) */ } return 0; }//toMacString int main(int argc, char **argv) { int i; int s; unsigned char* buf; unsigned int opt = 1; dev = strdup("eth0"); dst_mac = strdup("00:11:22:33:44:55"); for (i = 1; i> 24) & 0xff; buf[bytes + 1] = (fcs >> 16) & 0xff; buf[bytes + 2] = (fcs >> 8) & 0xff; buf[bytes + 3] = fcs & 0xff; for (i = 0; i