[ Team LiB ] |
17.8 ARP Cache OperationsOn some systems, the ARP cache is also manipulated with the ioctl function. Systems that use routing sockets (Chapter 18) usually use routing sockets instead of ioctl to access the ARP cache. These requests use an arpreq structure, shown in Figure 17.12 and defined by including the <net/if_arp.h> header. Figure 17.12 arpreq structure used with ioctl requests for ARP cache.<net/if_arp.h> struct arpreq { struct sockaddr arp_pa; /* protocol address */ struct sockaddr arp_ha; /* hardware address */ int arp_flags; /* flags */ }; #define ATF_INUSE 0x01 /* entry in use */ #define ATF_COM 0x02 /* completed entry (hardware addr valid) */ #define ATF_PERM 0x04 /* permanent entry */ #define ATF_PUBL 0x08 /* published entry (respond for other host) */ The third argument to ioctl must point to one of these structures. The following three requests are supported:
Only the superuser can add or delete an entry. These three requests are normally issued by the arp program.
Notice that there is no way with ioctl to list all the entries in the ARP cache. On many systems, the arp command, when invoked with the -a flag (list all entries in the ARP cache), reads the kernel's memory (/dev/kmem) to obtain the current contents of the ARP cache. We will see an easier (and better) way to do this using sysctl, which only works on some systems (Section 18.4). Example: Print Hardware Addresses of HostWe now use our get_ifi_info function to return all of a host's IP addresses, followed by an ioctl of SIOCGARP for each IP address to obtain and print the hardware addresses. We show our program in Figure 17.13. Get List of Addresses and Loop Through Each One12 We call get_ifi_info to obtain the host's IP addresses and then loop through each address. Print IP Address13 We print the IP address using sock_ntop. We asked get_ifi_info to only return IPv4 addresses, since ARP is not used with IPv6. Issue ioctl and Check for Error14–19 We fill in the arp_pa structure as an IPv4 socket address structure containing the IPv4 address. ioctl is called, and if it returns an error (e.g., because the address supplied isn't on an interface that supports ARP), we print the error and loop to the next address. Print Hardware Address20–22 The hardware address returned from the ioctl is printed. Figure 17.13 Print a host's hardware addresses.ioctl/prmac.c 1 #include "unpifi.h" 2 #include <net/if_arp.h> 3 int 4 main(int argc, char **argv) 5 { 6 int sockfd; 7 struct ifi_info *ifi; 8 unsigned char *ptr; 9 struct arpreq arpreq; 10 struct sockaddr_in *sin; 11 sockfd = Socket(AF_INET, SOCK_DGRAM, 0); 12 for (ifi = get_ifi_info(AF_INET, 0); ifi != NULL; ifi = ifi->ifi_next) { 13 printf("%s: ", Sock_ntop(ifi->ifi_addr, sizeof(struct sockaddr_in))); 14 sin = (struct sockaddr_in *) &arpreq.arp_pa; 15 memcpy(sin, ifi->ifi_addr, sizeof(struct sockaddr_in)); 16 if (ioctl(sockfd, SIOCGARP, &arpreq) < 0) { 17 err_ret("ioctl SIOCGARP"); 18 continue; 19 } 20 ptr = &arpreq.arp_ha.sa_data[0]; 21 printf("%x:%x:%x:%x:%x:%x\n", *ptr, *(ptr + 1), 22 *(ptr + 2), *(ptr + 3), *(ptr + 4), *(ptr + 5)); 23 } 24 exit(0); 25 } Running this program on our hpux host gives
hpux % prmac
192.6.38.100: 0:60:b0:c2:68:9b
192.168.1.1: 0:60:b0:b2:28:2b
127.0.0.1: ioctl SIOCGARP: Invalid argument
|
[ Team LiB ] |