1 /*
2  *  libnet
3  *  arp.c - Utility routines for doing ARP resolution.
4  *
5  */
6 
7 #if (HAVE_CONFIG_H)
8 #include "../include/config.h"
9 #endif
10 #include "../include/libnet.h"
11 
12 #if (RAW_IS_COOKED)
13 #include <net/if_arp.h>
14 
15 int
libnet_query_arp(u_long ip,char * hwaddr,char * ebuf)16 libnet_query_arp(u_long ip, char *hwaddr, char *ebuf)
17 {
18     int fd;
19     struct arpreq arpreq;
20     struct sockaddr_in *query;
21     struct sockaddr *result;
22 
23     if ((fd=socket(PF_INET, SOCK_DGRAM, 0))==-1)
24     {
25         sprintf( ebuf, "socket: %s", strerror(errno));
26         return -1;
27     }
28 
29     memset(&arpreq, 0, sizeof arpreq);
30 
31     query=(struct sockaddr_in *)&arpreq.arp_pa;
32     result=(struct sockaddr *)&arpreq.arp_ha;
33 
34     query->sin_family=AF_INET;
35     query->sin_addr.s_addr=ip;
36     result->sa_family=AF_UNSPEC;
37 
38     if (ioctl(fd, SIOCGARP, (caddr_t)&arpreq)==-1)
39     {
40         sprintf( ebuf, "ioctl: %s", strerror(errno));
41         close(fd);
42         return -1;
43     }
44     memcpy(hwaddr, (void *)arpreq.arp_ha.sa_data, 6);
45 
46     close(fd);
47     return 0;
48 }
49 
50 /* Taken from get_mac.c */
51 
52 int
send_arp_request(u_long ip,u_char * device,char * ebuf)53 send_arp_request(u_long ip, u_char *device, char *ebuf)
54 {
55     u_char *buf;
56     char errbuf[1024];
57     struct link_int *linkent;
58     struct ether_addr *dev_hwaddr;
59     u_long local_ip;
60     u_char *enet_dst="\xff\xff\xff\xff\xff\xff";
61     int n;
62 
63     if ((linkent=libnet_open_link_interface(device,errbuf))==NULL)
64     {
65         sprintf (ebuf,"libnet_open_link_interface: %s",errbuf);
66         return -1;
67     }
68 
69     if (libnet_init_packet(ARP_H + ETH_H, &buf) == -1)
70     {
71         sprintf (ebuf,"libnet_init_packet memory failure");
72         return -1;
73     }
74 
75     if ((dev_hwaddr = libnet_get_hwaddr(linkent, device, errbuf))==NULL)
76     {
77         sprintf(ebuf, "libnet_get_hwaddr: %s\n", errbuf);
78         return (-1);
79     }
80 
81     local_ip = htonl(libnet_get_ipaddr(linkent, device, errbuf));
82     if (!local_ip)
83     {
84         sprintf(ebuf, "libnet_get_ipaddr: %s\n", errbuf);
85         return (-1);
86     }
87 
88     libnet_build_ethernet(
89             enet_dst,               /* broadcast ethernet address */
90             dev_hwaddr->ether_addr_octet,    /* source ethernet address */
91             ETHERTYPE_ARP,          /* this frame holds an ARP packet */
92             NULL,                   /* payload */
93             0,                      /* payload size */
94             buf);                   /* packet header memory */
95 
96     libnet_build_arp(
97             ARPHRD_ETHER,           /* hardware address type */
98             ETHERTYPE_IP,           /* protocol address type */
99             ETHER_ADDR_LEN,         /* hardware address length */
100             4,                      /* protocol address length */
101             ARPOP_REQUEST,          /* packet type - ARP request */
102             dev_hwaddr->ether_addr_octet, /* source (local) ethernet address */
103             (u_char *)&local_ip,    /* source (local) IP address */
104             enet_dst,               /* target's ethernet address (broadcast) */
105             (u_char *)&ip,          /* target's IP address */
106             NULL,                   /* payload */
107             0,                      /* payload size */
108             buf + ETH_H);           /* packet header memory */
109 
110     n = libnet_write_link_layer(linkent, device, buf, ARP_H + ETH_H);
111     if (n == -1)
112     {
113         sprintf(ebuf, "libnet_write_link_layer failed\n");
114         return (-1);
115     }
116     libnet_close_link_interface(linkent);
117     libnet_destroy_packet(&buf);
118     return 0;
119 }
120 
121 int
libnet_active_query_arp(u_long ip,char * hwaddr,u_char * device,char * ebuf)122 libnet_active_query_arp(u_long ip, char *hwaddr, u_char *device, char *ebuf)
123 {
124     int tries=3;
125 
126     while (tries--)
127     {
128         if (libnet_query_arp(ip,hwaddr,ebuf)!=-1)
129             return 0;
130 
131         send_arp_request(ip,device,ebuf);
132 
133         sleep(1);
134     }
135     return -1;
136 }
137 
138 #endif /* RAW_IS_COOKED */
139 
140 /* EOF */
141