Saturday, September 03, 2005

Nice Coding practice for byte packing

I am trying to write a code to using SOCK_RAW using PACKET protocol family PF_PACKET.
My intention to find out healthiness of Target with minimum overhead. Instead of trying to call connect i want to use ICMP protocols like ping. While doing that i thought why cant I do event ARP. Then started looking for some sample code for ARP.

I found Blacky Room at fdin. He got simple codes for lower level Ethernet Protocols. Ofcourse the site is in Japanese language. But can access code samples.

One good thing i liked at these code samples is the way packing of bytes is done before calling send. In the following function , buffer is a character array. And eth and arp are just pointers.
Iinitially these pointers are just addressed to respective positions. Then as members are filled buffer is ready.

Normally i do other way around. First i update structures and then assign to each byte of buffer like buf[0] = arp->arp_hrd.

But this method essentially eliminates second copy and more secure.


int send_arprequest(int sock, struct dev *dev, struct addr *src, struct addr *dst)
{
struct sockaddr_ll sll;
struct ether_header *eth;
struct ether_arp *arp;
char buf[sizeof(struct ether_header) + sizeof(struct ether_arp)];

memset(&sll, 0, sizeof(sll));
sll.sll_family = PF_PACKET;
sll.sll_ifindex = dev->index;
sll.sll_halen = ETH_ALEN;
memcpy(&sll.sll_addr, dst->mac, ETH_ALEN);

memset(buf, 0, sizeof(buf));
eth = (struct ether_header *)buf;
arp = (struct ether_arp *)((char *)eth + sizeof(struct ether_header));

/* arp header */
arp->arp_hrd = htons(ARPHRD_ETHER);
arp->arp_pro = htons(ETH_P_IP);
arp->arp_hln = ETH_ALEN;
arp->arp_pln = IP_LEN;
arp->arp_op = htons(ARPOP_REQUEST);
memcpy(arp->arp_sha, src->mac, ETH_ALEN);
memcpy(arp->arp_spa, &(src->ip), IP_LEN);
memset(arp->arp_tha, 0, ETH_ALEN);
memcpy(arp->arp_tpa, &(dst->ip), IP_LEN);

/* ether_header */
memcpy(eth->ether_shost, src->mac, ETH_ALEN);
memcpy(eth->ether_dhost, dst->mac, ETH_ALEN);
eth->ether_type = htons(ETH_P_ARP);

/* send to arp request packet */
return sendto(sock, buf, sizeof(buf), 0, (struct sockaddr *)&sll, sizeof(sll));
}

No comments: