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