Date created: Thursday, May 24, 2012 8:51:45 PM. Last modified: Sunday, December 10, 2017 2:29:41 PM
Etherate Notes
C code snippets:
Printing binary of ints and shorts
Encoding VLAN ID, DEI bit and PCP value
Low level access to network devices
sockaddr_ll - Phy config
htons/htonl/htonll convertions
struct ethhdr
Printing MAC addresses
Opening raw sockets
Promiscuous mode
// Printing binary of ints and shorts const int SHIFT = 8 * sizeof( unsigned ) - 1; // const int SHIFT = 15; // This would be used for a short const unsigned MASK = 1 << SHIFT; int myInt = 4096; for ( int i = 1; i <= SHIFT + 1; i++ ) { cout << ( TCI & MASK ? '1' : '0' ); myInt <<= 1; if ( i % 8 == 0 ) cout << ' '; } cout << endl; // This prints: 00000000 00000000 11111111 11111111
// Encoding VLAN ID, DEI bit and PCP value directly on to the wire // Assume DEI is 0 for now... short PCP = 5 short vlanID = 1111 short vlanIDtemp; short TPI = 0; short TCI = 0; short *p = &TPI; short *c = &TCI; TPI = htons(0x8100); memcpy((void*)(txBuffer+offset), p, 2); offset+=2; cout << "PCP: " << PCP << endl; cout << "vlanID: " << vlanID << endl; TCI = (PCP & 0x07) << 5; // 00000101 gets shifted up to 10100000 vlanID = vlanID >> 8; // 00000100 01010111 gets shifted down to 00000100 TCI = TCI | (vlanID & 0x0f); // OR 10100000 and 00000100 to give 10100100 vlanID = vlanIDtemp; // Bring back the original vlan ID 00000100 01010111 vlanID = vlanID << 8; // Shift up to 01010111 00000000 TCI = TCI | (vlanID & 0xffff); // OR 01010111 00000000 with 00000000 10100100 cout << "TCI: " << TCI << endl; // Gives the result 01010111 10100100 for ( int i = 1; i <= SHIFT + 1; i++ ) { // Print it out in binary cout << ( TCI & MASK ? '1' : '0' ); TCI <<= 1; if ( i % 8 == 0 ) cout << ' '; } cout << endl; /* Final output on the CLI is; * PCP: 5 * vlanID: 1111 * 01010111 10100100 * * Gets dumped on to the wire in reverse bytes order (but not reverse bit order!) as * * 10100100 01010111 * * Which breaks down into * 101|0 |0100 01010111 * PCP|DEI|VLAN ID */
/* netdevice - Low level access to Linux network devices. #include <sys/ioctl.h> #include <net/if.h> */ struct ifreq { char ifr_name[IFNAMSIZ]; // Interface name union { struct sockaddrifr_addr; struct sockaddrifr_dstaddr; struct sockaddrifr_broadaddr; struct sockaddrifr_netmask; struct sockaddrifr_hwaddr; short ifr_flags; int ifr_ifindex; int ifr_metric; int ifr_mtu; struct ifmapifr_map; char ifr_slave[IFNAMSIZ]; char ifr_newname[IFNAMSIZ]; char * ifr_data; }; }; struct ifconf { int ifc_len; // size of buffer union { char * ifc_buf; // buffer address struct ifreq *ifc_req; // array of structures }; };
/* The sockaddr_ll is a device independent physical layer address. #include <sys/socket.h> #define MAX_IFS 64 #include <linux/if_packet.h> #include <linux/if_ether.h> #include <linux/if_arp.h> */ struct sockaddr_ll { unsigned short sll_family; // Always AF_PACKET unsigned short sll_protocol; // Physical layer protocol int sll_ifindex; // Interface number unsigned short sll_hatype; // Header type unsigned char sll_pkttype; // Packet type unsigned char sll_halen; // Length of address unsigned char sll_addr[8]; // Physical layer address }; */ /* * sll_family = PF_PACKET = RAW packet communication * sll_protocol = No protocol above the Ethernet layer is actually used * sll_ifindex = Index of the network device * sll_hatype = ARP hardware identifier is ethernet * sll_pkttype = Target is another host * sll_halen = Layer 2 address length * sll_addr[] = Destination MAC Address */
#include <netinet/in.h> // Host-to-Network-short htons() // Host-to-Network-long htonl() // Network-to-Host-short ntohs() // Network-to-Host-long ntohl() #include <byteswap.h> unsigned long long htonll(unsigned long long val) { if (__BYTE_ORDER == __BIG_ENDIAN) return (val); else return __bswap_64(val); } unsigned long long ntohll(unsigned long long val) { if (__BYTE_ORDER == __BIG_ENDIAN) return (val); else return __bswap_64(val); }
struct ethhdr { unsigned char h_dest[ETH_ALEN]; // destination eth addr unsigned char h_source[ETH_ALEN]; // source ether addr __be16 h_proto; // packet type ID field } __attribute__((packed));
printf("Ethernet %02x:%02x:%02x:%02x:%02x:%02x\n", destMAC[0],destMAC[1],destMAC[2],destMAC[3],destMAC[4], destMAC[5]);
// Opening raw sockets TEST_INTERFACE.SOCKET_FD = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); /* A socket must be opened with three arguments; * Communication Domain = AF_PACKET * Type/Communication Semantics = SOCK_RAW * Protocol = ETH_P_ALL == 0x0003, which is 'everything', from if_ether.h */
// Promiscuous mode, this came fromt eh following URL // http://www.linuxjournal.com/article/4659?page=0,1 printf("Entering promiscuous mode\n"); strncpy(ethreq.ifr_name,TEST_INTERFACE.IF_NAME,IFNAMSIZ); if (ioctl(TEST_INTERFACE.SOCKET_FD,SIOCGIFFLAGS,ðreq) == -1) { printf("Error getting socket flags, entering promiscuous mode failed!\n"); perror("ioctl() "); close(TEST_INTERFACE.SOCKET_FD); return EX_SOFTWARE; } ethreq.ifr_flags|=IFF_PROMISC; if (ioctl(TEST_INTERFACE.SOCKET_FD,SIOCSIFFLAGS,ðreq) == -1) { printf("Error setting socket flags, entering promiscuous mode failed!\n"); perror("ioctl() "); close(TEST_INTERFACE.SOCKET_FD); return EX_SOFTWARE; }
Previous page: Etherate Features
Next page: EtherateMT Notes