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