1 /*
2 * $Id: get_mac.c,v 1.1.1.1 1999/05/18 15:33:44 dugsong Exp $
3 *
4 * libnet
5 * get_mac.c - get the MAC address of a remote host
6 *
7 * Copyright (c) 1998, 1999 Mike D. Schiffman <mike@infonexus.com>
8 * route|daemon9 <route@infonexus.com>
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34 #if (HAVE_CONFIG_H)
35 #include "../../include/config.h"
36 #endif
37 #include <libnet.h>
38 #include <pcap.h>
39
40 #define IP_UCHAR_COMP(x, y) \
41 (x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3])
42
43
44 u_char enet_dst[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
45
46 int libnet_do_arp(struct link_int *, u_char *, struct ether_addr *, u_long);
47
48 int
main(int argc,char * argv[])49 main(int argc, char *argv[])
50 {
51 int i, c;
52 char errbuf[256];
53 char *device = NULL;
54 struct link_int *l;
55 struct ether_addr e;
56 u_long ip;
57
58 while ((c = getopt(argc, argv, "i:")) != EOF)
59 {
60 switch (c)
61 {
62 case 'i':
63 device = optarg;
64 break;
65 default:
66 exit(EXIT_FAILURE);
67 }
68 }
69
70 if (!device)
71 {
72 fprintf(stderr, "Specify a device\n");
73 exit(EXIT_FAILURE);
74 }
75 if (argc > optind)
76 {
77 if ((ip = libnet_name_resolve(argv[optind], 1)) == -1)
78 {
79 fprintf(stderr, "Cannot resolve IP address\n");
80 exit(EXIT_FAILURE);
81 }
82 }
83 else
84 {
85 fprintf(stderr, "IP address to ARP for?\n");
86 exit(EXIT_FAILURE);
87 }
88
89 l = libnet_open_link_interface(device, errbuf);
90 if (!l)
91 {
92 fprintf(stderr, "libnet_open_link_interface: %s\n", errbuf);
93 exit(EXIT_FAILURE);
94 }
95
96 c = libnet_do_arp(l, device, &e, ip);
97 if (c != -1)
98 {
99 for (i = 0; i < 6; i++)
100 {
101 printf("%x", e.ether_addr_octet[i]);
102 if (i != 5)
103 {
104 printf(":");
105 }
106 }
107 printf("\n");
108 }
109 return (c == -1 ? EXIT_FAILURE : EXIT_SUCCESS);
110 }
111
112
113 int
libnet_do_arp(struct link_int * l,u_char * device,struct ether_addr * e,u_long ip)114 libnet_do_arp(struct link_int *l, u_char *device, struct ether_addr *e,
115 u_long ip)
116 {
117 int n, i;
118 u_char *buf, errbuf[256], *packet, *ip_p;
119 struct libnet_ethernet_hdr *p;
120 struct libnet_arp_hdr *a;
121 u_long local_ip;
122 pcap_t *pd;
123 struct pcap_pkthdr pc_hdr;
124
125 /*
126 * Initialize a packet.
127 */
128 if (libnet_init_packet(ARP_H + ETH_H, &buf) == -1)
129 {
130 perror("libnet_init_packet memory:");
131 exit(EXIT_FAILURE);
132 }
133
134 /*
135 * Get the ethernet address of the device.
136 */
137 e = libnet_get_hwaddr(l, device, errbuf);
138 if (e == NULL)
139 {
140 fprintf(stderr, "libnet_get_hwaddr: %s\n", errbuf);
141 return (-1);
142 }
143
144 /*
145 * Get the IP address of the device.
146 */
147 local_ip = htonl(libnet_get_ipaddr(l, device, errbuf));
148 if (!local_ip)
149 {
150 fprintf(stderr, "libnet_get_ipaddr: %s\n", errbuf);
151 return (-1);
152 }
153
154 /*
155 * Open the pcap device.
156 */
157 pd = pcap_open_live(device, ARP_H + ETH_H, 1, 500, errbuf);
158 if (pd == NULL)
159 {
160 fprintf(stderr, "pcap_open_live: %s\n", errbuf);
161 return (-1);
162 }
163
164 /*
165 * Ethernet header
166 */
167 libnet_build_ethernet(
168 enet_dst, /* broadcast ethernet address */
169 e->ether_addr_octet, /* source ethernet address */
170 ETHERTYPE_ARP, /* this frame holds an ARP packet */
171 NULL, /* payload */
172 0, /* payload size */
173 buf); /* packet header memory */
174
175 /*
176 * ARP header
177 */
178 libnet_build_arp(
179 ARPHRD_ETHER, /* hardware address type */
180 ETHERTYPE_IP, /* protocol address type */
181 ETHER_ADDR_LEN, /* hardware address length */
182 4, /* protocol address length */
183 ARPOP_REQUEST, /* packet type - ARP request */
184 e->ether_addr_octet, /* source (local) ethernet address */
185 (u_char *)&local_ip, /* source (local) IP address */
186 enet_dst, /* target's ethernet address (broadcast) */
187 (u_char *)&ip, /* target's IP address */
188 NULL, /* payload */
189 0, /* payload size */
190 buf + ETH_H); /* packet header memory */
191
192 n = libnet_write_link_layer(l, device, buf, ARP_H + ETH_H);
193 if (n == -1)
194 {
195 fprintf(stderr, "libnet_write_link_layer choked\n");
196 return (-1);
197 }
198 printf("Sent a %d byte ARP request looking for the MAC of %s.\n",
199 n, host_lookup(ip, 0));
200 printf("Waiting for a response...\n");
201
202 for (;(packet = ((u_char *)pcap_next(pd, &pc_hdr)));)
203 {
204 p = (struct libnet_ethernet_hdr *)(packet);
205 if (ntohs(p->ether_type) == ETHERTYPE_ARP)
206 {
207 a = (struct libnet_arp_hdr *)(packet + ETH_H);
208 if (ntohs(a->ar_op) == ARPOP_REPLY)
209 {
210 ip_p = (u_char *)&ip;
211 if (IP_UCHAR_COMP(a->ar_spa, ip_p))
212 {
213 printf("Target hardware address: ");
214 for (i = 0; i < 6; i++)
215 {
216 printf("%x", a->ar_sha[i]);
217 if (i != 5)
218 {
219 printf(":");
220 }
221 }
222 printf("\n");
223 }
224 }
225 }
226 }
227
228 libnet_destroy_packet(&buf);
229 return (n);
230 }
231
232 /* EOF */
233
234