arp.c (59fe2c14b4029930a239ecc380c3cfb365ef9284) arp.c (c72049e448b9e07af9fd73744ea51bd6c8b7f665)
1/*
2 * Copyright (c) 1984, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Sun Microsystems, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 21 unchanged lines hidden (view full) ---

30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
1/*
2 * Copyright (c) 1984, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Sun Microsystems, Inc.
7 *
8 * Redistribution and use in source and binary forms, with or without

--- 21 unchanged lines hidden (view full) ---

30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38static char copyright[] =
38static char const copyright[] =
39"@(#) Copyright (c) 1984, 1993\n\
40 The Regents of the University of California. All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
39"@(#) Copyright (c) 1984, 1993\n\
40 The Regents of the University of California. All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95";
44#if 0
45static char const sccsid[] = "@(#)from: arp.c 8.2 (Berkeley) 1/2/94";
46#endif
47static const char rcsid[] =
48 "$Id$";
45#endif /* not lint */
46
47/*
48 * arp - display, set, and delete arp table entries
49 */
50
51
52#include <sys/param.h>
53#include <sys/file.h>
54#include <sys/socket.h>
49#endif /* not lint */
50
51/*
52 * arp - display, set, and delete arp table entries
53 */
54
55
56#include <sys/param.h>
57#include <sys/file.h>
58#include <sys/socket.h>
59#include <sys/sockio.h>
55#include <sys/sysctl.h>
60#include <sys/sysctl.h>
61#include <sys/ioctl.h>
62#include <sys/time.h>
56
57#include <net/if.h>
63
64#include <net/if.h>
65#include <net/if_var.h>
58#include <net/if_dl.h>
59#include <net/if_types.h>
60#include <net/route.h>
61
62#include <netinet/in.h>
63#include <netinet/if_ether.h>
64
65#include <arpa/inet.h>
66
67#include <err.h>
68#include <errno.h>
69#include <netdb.h>
70#include <nlist.h>
71#include <paths.h>
72#include <stdio.h>
73#include <stdlib.h>
66#include <net/if_dl.h>
67#include <net/if_types.h>
68#include <net/route.h>
69
70#include <netinet/in.h>
71#include <netinet/if_ether.h>
72
73#include <arpa/inet.h>
74
75#include <err.h>
76#include <errno.h>
77#include <netdb.h>
78#include <nlist.h>
79#include <paths.h>
80#include <stdio.h>
81#include <stdlib.h>
74#include <string.h>
82#include <strings.h>
75#include <unistd.h>
76
83#include <unistd.h>
84
85void dump(u_long addr);
86int delete(char *host, char *info);
87void ether_print(u_char *cp);
88void usage(void);
89int set(int argc, char **argv);
90void get(char *host);
91int file(char *name);
92void getsocket(void);
93int my_ether_aton(char *a, u_char *n);
94int rtmsg(int cmd);
95int get_ether_addr(u_long ipaddr, u_char *hwaddr);
96
77static int pid;
78static int nflag;
79static int s = -1;
80
97static int pid;
98static int nflag;
99static int s = -1;
100
81int delete __P((char *, char *));
82void dump __P((u_long));
83int ether_aton __P((char *, u_char *));
84void ether_print __P((u_char *));
85int file __P((char *));
86void get __P((char *));
87void getsocket __P((void));
88int rtmsg __P((int));
89int set __P((int, char **));
90void usage __P((void));
91
92int
93main(argc, argv)
94 int argc;
95 char **argv;
96{
97 int ch;
98
99 pid = getpid();
101int
102main(argc, argv)
103 int argc;
104 char **argv;
105{
106 int ch;
107
108 pid = getpid();
100 while ((ch = getopt(argc, argv, "ands")) != EOF)
109 while ((ch = getopt(argc, argv, "andfsS")) != -1)
101 switch((char)ch) {
102 case 'a':
103 dump(0);
104 exit(0);
105 case 'd':
106 if (argc < 3 || argc > 4)
107 usage();
108 delete(argv[2], argv[3]);
109 exit(0);
110 case 'n':
111 nflag = 1;
112 continue;
110 switch((char)ch) {
111 case 'a':
112 dump(0);
113 exit(0);
114 case 'd':
115 if (argc < 3 || argc > 4)
116 usage();
117 delete(argv[2], argv[3]);
118 exit(0);
119 case 'n':
120 nflag = 1;
121 continue;
122 case 'S':
123 delete(argv[2], NULL);
124 /* FALL THROUGH */
113 case 's':
114 if (argc < 4 || argc > 7)
115 usage();
116 exit(set(argc-2, &argv[2]) ? 1 : 0);
125 case 's':
126 if (argc < 4 || argc > 7)
127 usage();
128 exit(set(argc-2, &argv[2]) ? 1 : 0);
129 case 'f' :
130 if (argc != 3)
131 usage();
132 return (file(argv[2]));
117 case '?':
118 default:
119 usage();
120 }
121 if (argc != 2)
122 usage();
123 get(argv[1]);
133 case '?':
134 default:
135 usage();
136 }
137 if (argc != 2)
138 usage();
139 get(argv[1]);
124 return (0);
140 exit(0);
125}
126
127/*
128 * Process a file to set standard arp entries
129 */
130int
141}
142
143/*
144 * Process a file to set standard arp entries
145 */
146int
131file(name)
132 char *name;
147file(char *name)
133{
134 FILE *fp;
135 int i, retval;
136 char line[100], arg[5][50], *args[5];
137
148{
149 FILE *fp;
150 int i, retval;
151 char line[100], arg[5][50], *args[5];
152
138 if ((fp = fopen(name, "r")) == NULL) {
139 fprintf(stderr, "arp: cannot open %s\n", name);
140 exit(1);
141 }
153 if ((fp = fopen(name, "r")) == NULL)
154 errx(1, "cannot open %s", name);
142 args[0] = &arg[0][0];
143 args[1] = &arg[1][0];
144 args[2] = &arg[2][0];
145 args[3] = &arg[3][0];
146 args[4] = &arg[4][0];
147 retval = 0;
148 while(fgets(line, 100, fp) != NULL) {
149 i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
150 arg[3], arg[4]);
151 if (i < 2) {
155 args[0] = &arg[0][0];
156 args[1] = &arg[1][0];
157 args[2] = &arg[2][0];
158 args[3] = &arg[3][0];
159 args[4] = &arg[4][0];
160 retval = 0;
161 while(fgets(line, 100, fp) != NULL) {
162 i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
163 arg[3], arg[4]);
164 if (i < 2) {
152 fprintf(stderr, "arp: bad line: %s\n", line);
165 warnx("bad line: %s", line);
153 retval = 1;
154 continue;
155 }
156 if (set(i, args))
157 retval = 1;
158 }
159 fclose(fp);
160 return (retval);
161}
162
163void
166 retval = 1;
167 continue;
168 }
169 if (set(i, args))
170 retval = 1;
171 }
172 fclose(fp);
173 return (retval);
174}
175
176void
164getsocket() {
177getsocket(void)
178{
165 if (s < 0) {
166 s = socket(PF_ROUTE, SOCK_RAW, 0);
179 if (s < 0) {
180 s = socket(PF_ROUTE, SOCK_RAW, 0);
167 if (s < 0) {
168 perror("arp: socket");
169 exit(1);
170 }
181 if (s < 0)
182 err(1, "socket");
171 }
172}
173
174struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
175struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
176struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
177int expire_time, flags, export_only, doing_proxy, found_entry;
178struct {
179 struct rt_msghdr m_rtm;
180 char m_space[512];
181} m_rtmsg;
182
183/*
183 }
184}
185
186struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
187struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
188struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
189int expire_time, flags, export_only, doing_proxy, found_entry;
190struct {
191 struct rt_msghdr m_rtm;
192 char m_space[512];
193} m_rtmsg;
194
195/*
184 * Set an individual arp entry
196 * Set an individual arp entry
185 */
186int
197 */
198int
187set(argc, argv)
188 int argc;
189 char **argv;
199set(int argc, char **argv)
190{
191 struct hostent *hp;
192 register struct sockaddr_inarp *sin = &sin_m;
193 register struct sockaddr_dl *sdl;
194 register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
195 u_char *ea;
196 char *host = argv[0], *eaddr = argv[1];
197
198 getsocket();
199 argc -= 2;
200 argv += 2;
201 sdl_m = blank_sdl;
202 sin_m = blank_sin;
203 sin->sin_addr.s_addr = inet_addr(host);
204 if (sin->sin_addr.s_addr == -1) {
205 if (!(hp = gethostbyname(host))) {
200{
201 struct hostent *hp;
202 register struct sockaddr_inarp *sin = &sin_m;
203 register struct sockaddr_dl *sdl;
204 register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
205 u_char *ea;
206 char *host = argv[0], *eaddr = argv[1];
207
208 getsocket();
209 argc -= 2;
210 argv += 2;
211 sdl_m = blank_sdl;
212 sin_m = blank_sin;
213 sin->sin_addr.s_addr = inet_addr(host);
214 if (sin->sin_addr.s_addr == -1) {
215 if (!(hp = gethostbyname(host))) {
206 fprintf(stderr, "arp: %s: ", host);
207 herror((char *)NULL);
216 warnx("%s: %s", host, hstrerror(h_errno));
208 return (1);
209 }
210 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
211 sizeof sin->sin_addr);
212 }
217 return (1);
218 }
219 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
220 sizeof sin->sin_addr);
221 }
213 ea = (u_char *)LLADDR(&sdl_m);
214 if (ether_aton(eaddr, ea) == 0)
215 sdl_m.sdl_alen = 6;
216 doing_proxy = flags = export_only = expire_time = 0;
217 while (argc-- > 0) {
218 if (strncmp(argv[0], "temp", 4) == 0) {
219 struct timeval time;
220 gettimeofday(&time, 0);
221 expire_time = time.tv_sec + 20 * 60;
222 }
223 else if (strncmp(argv[0], "pub", 3) == 0) {
224 flags |= RTF_ANNOUNCE;
225 doing_proxy = SIN_PROXY;
226 } else if (strncmp(argv[0], "trail", 5) == 0) {
227 printf("%s: Sending trailers is no longer supported\n",
228 host);
229 }
230 argv++;
231 }
222 doing_proxy = flags = export_only = expire_time = 0;
223 while (argc-- > 0) {
224 if (strncmp(argv[0], "temp", 4) == 0) {
225 struct timeval time;
226 gettimeofday(&time, 0);
227 expire_time = time.tv_sec + 20 * 60;
228 }
229 else if (strncmp(argv[0], "pub", 3) == 0) {
230 flags |= RTF_ANNOUNCE;
231 doing_proxy = SIN_PROXY;
232 } else if (strncmp(argv[0], "trail", 5) == 0) {
233 printf("%s: Sending trailers is no longer supported\n",
234 host);
235 }
236 argv++;
237 }
238 ea = (u_char *)LLADDR(&sdl_m);
239 if (doing_proxy && !strcmp(eaddr, "auto")) {
240 if (!get_ether_addr(sin->sin_addr.s_addr, ea)) {
241 return (1);
242 }
243 sdl_m.sdl_alen = 6;
244 } else {
245 if (my_ether_aton(eaddr, ea) == 0)
246 sdl_m.sdl_alen = 6;
247 }
232tryagain:
233 if (rtmsg(RTM_GET) < 0) {
248tryagain:
249 if (rtmsg(RTM_GET) < 0) {
234 perror(host);
250 warn("%s", host);
235 return (1);
236 }
237 sin = (struct sockaddr_inarp *)(rtm + 1);
238 sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
239 if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
240 if (sdl->sdl_family == AF_LINK &&
241 (rtm->rtm_flags & RTF_LLINFO) &&
242 !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {

--- 22 unchanged lines hidden (view full) ---

265 sdl_m.sdl_index = sdl->sdl_index;
266 return (rtmsg(RTM_ADD));
267}
268
269/*
270 * Display an individual arp entry
271 */
272void
251 return (1);
252 }
253 sin = (struct sockaddr_inarp *)(rtm + 1);
254 sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
255 if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
256 if (sdl->sdl_family == AF_LINK &&
257 (rtm->rtm_flags & RTF_LLINFO) &&
258 !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {

--- 22 unchanged lines hidden (view full) ---

281 sdl_m.sdl_index = sdl->sdl_index;
282 return (rtmsg(RTM_ADD));
283}
284
285/*
286 * Display an individual arp entry
287 */
288void
273get(host)
274 char *host;
289get(char *host)
275{
276 struct hostent *hp;
277 struct sockaddr_inarp *sin = &sin_m;
278
279 sin_m = blank_sin;
280 sin->sin_addr.s_addr = inet_addr(host);
281 if (sin->sin_addr.s_addr == -1) {
290{
291 struct hostent *hp;
292 struct sockaddr_inarp *sin = &sin_m;
293
294 sin_m = blank_sin;
295 sin->sin_addr.s_addr = inet_addr(host);
296 if (sin->sin_addr.s_addr == -1) {
282 if (!(hp = gethostbyname(host))) {
283 fprintf(stderr, "arp: %s: ", host);
284 herror((char *)NULL);
285 exit(1);
286 }
297 if (!(hp = gethostbyname(host)))
298 errx(1, "%s: %s", host, hstrerror(h_errno));
287 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
288 sizeof sin->sin_addr);
289 }
290 dump(sin->sin_addr.s_addr);
291 if (found_entry == 0) {
292 printf("%s (%s) -- no entry\n",
293 host, inet_ntoa(sin->sin_addr));
294 exit(1);
295 }
296}
297
298/*
299 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
300 sizeof sin->sin_addr);
301 }
302 dump(sin->sin_addr.s_addr);
303 if (found_entry == 0) {
304 printf("%s (%s) -- no entry\n",
305 host, inet_ntoa(sin->sin_addr));
306 exit(1);
307 }
308}
309
310/*
299 * Delete an arp entry
311 * Delete an arp entry
300 */
301int
312 */
313int
302delete(host, info)
303 char *host;
304 char *info;
314delete(char *host, char *info)
305{
306 struct hostent *hp;
307 register struct sockaddr_inarp *sin = &sin_m;
308 register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
309 struct sockaddr_dl *sdl;
310
311 if (info && strncmp(info, "pro", 3) )
312 export_only = 1;
313 getsocket();
314 sin_m = blank_sin;
315 sin->sin_addr.s_addr = inet_addr(host);
316 if (sin->sin_addr.s_addr == -1) {
317 if (!(hp = gethostbyname(host))) {
315{
316 struct hostent *hp;
317 register struct sockaddr_inarp *sin = &sin_m;
318 register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
319 struct sockaddr_dl *sdl;
320
321 if (info && strncmp(info, "pro", 3) )
322 export_only = 1;
323 getsocket();
324 sin_m = blank_sin;
325 sin->sin_addr.s_addr = inet_addr(host);
326 if (sin->sin_addr.s_addr == -1) {
327 if (!(hp = gethostbyname(host))) {
318 fprintf(stderr, "arp: %s: ", host);
319 herror((char *)NULL);
328 warnx("%s: %s", host, hstrerror(h_errno));
320 return (1);
321 }
322 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
323 sizeof sin->sin_addr);
324 }
325tryagain:
326 if (rtmsg(RTM_GET) < 0) {
329 return (1);
330 }
331 bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
332 sizeof sin->sin_addr);
333 }
334tryagain:
335 if (rtmsg(RTM_GET) < 0) {
327 perror(host);
336 warn("%s", host);
328 return (1);
329 }
330 sin = (struct sockaddr_inarp *)(rtm + 1);
331 sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
332 if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
333 if (sdl->sdl_family == AF_LINK &&
334 (rtm->rtm_flags & RTF_LLINFO) &&
335 !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {

--- 9 unchanged lines hidden (view full) ---

345 sin_m.sin_other = SIN_PROXY;
346 goto tryagain;
347 }
348delete:
349 if (sdl->sdl_family != AF_LINK) {
350 printf("cannot locate %s\n", host);
351 return (1);
352 }
337 return (1);
338 }
339 sin = (struct sockaddr_inarp *)(rtm + 1);
340 sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
341 if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
342 if (sdl->sdl_family == AF_LINK &&
343 (rtm->rtm_flags & RTF_LLINFO) &&
344 !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {

--- 9 unchanged lines hidden (view full) ---

354 sin_m.sin_other = SIN_PROXY;
355 goto tryagain;
356 }
357delete:
358 if (sdl->sdl_family != AF_LINK) {
359 printf("cannot locate %s\n", host);
360 return (1);
361 }
353 if (rtmsg(RTM_DELETE))
354 return (1);
355 printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
356 return (0);
362 if (rtmsg(RTM_DELETE) == 0) {
363 printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
364 return (0);
365 }
366 return (1);
357}
358
359/*
360 * Dump the entire arp table
361 */
362void
367}
368
369/*
370 * Dump the entire arp table
371 */
372void
363dump(addr)
364 u_long addr;
373dump(u_long addr)
365{
366 int mib[6];
367 size_t needed;
368 char *host, *lim, *buf, *next;
369 struct rt_msghdr *rtm;
370 struct sockaddr_inarp *sin;
371 struct sockaddr_dl *sdl;
372 extern int h_errno;
373 struct hostent *hp;
374
375 mib[0] = CTL_NET;
376 mib[1] = PF_ROUTE;
377 mib[2] = 0;
378 mib[3] = AF_INET;
379 mib[4] = NET_RT_FLAGS;
380 mib[5] = RTF_LLINFO;
381 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
374{
375 int mib[6];
376 size_t needed;
377 char *host, *lim, *buf, *next;
378 struct rt_msghdr *rtm;
379 struct sockaddr_inarp *sin;
380 struct sockaddr_dl *sdl;
381 extern int h_errno;
382 struct hostent *hp;
383
384 mib[0] = CTL_NET;
385 mib[1] = PF_ROUTE;
386 mib[2] = 0;
387 mib[3] = AF_INET;
388 mib[4] = NET_RT_FLAGS;
389 mib[5] = RTF_LLINFO;
390 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
382 err(1, "route-sysctl-estimate");
391 errx(1, "route-sysctl-estimate");
383 if ((buf = malloc(needed)) == NULL)
392 if ((buf = malloc(needed)) == NULL)
384 err(1, "malloc");
393 errx(1, "malloc");
385 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
394 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
386 err(1, "actual retrieval of routing table");
395 errx(1, "actual retrieval of routing table");
387 lim = buf + needed;
388 for (next = buf; next < lim; next += rtm->rtm_msglen) {
389 rtm = (struct rt_msghdr *)next;
390 sin = (struct sockaddr_inarp *)(rtm + 1);
391 sdl = (struct sockaddr_dl *)(sin + 1);
392 if (addr) {
393 if (addr != sin->sin_addr.s_addr)
394 continue;

--- 8 unchanged lines hidden (view full) ---

403 host = hp->h_name;
404 else {
405 host = "?";
406 if (h_errno == TRY_AGAIN)
407 nflag = 1;
408 }
409 printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
410 if (sdl->sdl_alen)
396 lim = buf + needed;
397 for (next = buf; next < lim; next += rtm->rtm_msglen) {
398 rtm = (struct rt_msghdr *)next;
399 sin = (struct sockaddr_inarp *)(rtm + 1);
400 sdl = (struct sockaddr_dl *)(sin + 1);
401 if (addr) {
402 if (addr != sin->sin_addr.s_addr)
403 continue;

--- 8 unchanged lines hidden (view full) ---

412 host = hp->h_name;
413 else {
414 host = "?";
415 if (h_errno == TRY_AGAIN)
416 nflag = 1;
417 }
418 printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
419 if (sdl->sdl_alen)
411 ether_print((u_char *)LLADDR(sdl));
420 ether_print(LLADDR(sdl));
412 else
413 printf("(incomplete)");
414 if (rtm->rtm_rmx.rmx_expire == 0)
415 printf(" permanent");
416 if (sin->sin_other & SIN_PROXY)
417 printf(" published (proxy only)");
418 if (rtm->rtm_addrs & RTA_NETMASK) {
419 sin = (struct sockaddr_inarp *)
420 (sdl->sdl_len + (char *)sdl);
421 if (sin->sin_addr.s_addr == 0xffffffff)
422 printf(" published");
423 if (sin->sin_len != 8)
424 printf("(wierd)");
425 }
426 printf("\n");
427 }
428}
429
430void
421 else
422 printf("(incomplete)");
423 if (rtm->rtm_rmx.rmx_expire == 0)
424 printf(" permanent");
425 if (sin->sin_other & SIN_PROXY)
426 printf(" published (proxy only)");
427 if (rtm->rtm_addrs & RTA_NETMASK) {
428 sin = (struct sockaddr_inarp *)
429 (sdl->sdl_len + (char *)sdl);
430 if (sin->sin_addr.s_addr == 0xffffffff)
431 printf(" published");
432 if (sin->sin_len != 8)
433 printf("(wierd)");
434 }
435 printf("\n");
436 }
437}
438
439void
431ether_print(cp)
432 u_char *cp;
440ether_print(u_char *cp)
433{
434 printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
435}
436
437int
441{
442 printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
443}
444
445int
438ether_aton(a, n)
439 char *a;
440 u_char *n;
446my_ether_aton(char *a, u_char *n)
441{
442 int i, o[6];
443
444 i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
445 &o[3], &o[4], &o[5]);
446 if (i != 6) {
447{
448 int i, o[6];
449
450 i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
451 &o[3], &o[4], &o[5]);
452 if (i != 6) {
447 fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
453 warnx("invalid Ethernet address '%s'", a);
448 return (1);
449 }
450 for (i=0; i<6; i++)
451 n[i] = o[i];
452 return (0);
453}
454
455void
454 return (1);
455 }
456 for (i=0; i<6; i++)
457 n[i] = o[i];
458 return (0);
459}
460
461void
456usage()
462usage(void)
457{
463{
458 printf("usage: arp hostname\n");
459 printf(" arp -a [kernel] [kernel_memory]\n");
460 printf(" arp -d hostname\n");
461 printf(" arp -s hostname ether_addr [temp] [pub]\n");
462 printf(" arp -f filename\n");
464 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
465 "usage: arp [-n] hostname",
466 " arp [-n] -a [kernel] [kernel_memory]",
467 " arp -d hostname",
468 " arp -s hostname ether_addr [temp] [pub]",
469 " arp -S hostname ether_addr [temp] [pub]",
470 " arp -f filename");
463 exit(1);
464}
465
466int
471 exit(1);
472}
473
474int
467rtmsg(cmd)
468 int cmd;
475rtmsg(int cmd)
469{
470 static int seq;
471 int rlen;
472 register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
473 register char *cp = m_rtmsg.m_space;
474 register int l;
475
476 errno = 0;
477 if (cmd == RTM_DELETE)
478 goto doit;
479 bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
480 rtm->rtm_flags = flags;
481 rtm->rtm_version = RTM_VERSION;
482
483 switch (cmd) {
484 default:
476{
477 static int seq;
478 int rlen;
479 register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
480 register char *cp = m_rtmsg.m_space;
481 register int l;
482
483 errno = 0;
484 if (cmd == RTM_DELETE)
485 goto doit;
486 bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
487 rtm->rtm_flags = flags;
488 rtm->rtm_version = RTM_VERSION;
489
490 switch (cmd) {
491 default:
485 fprintf(stderr, "arp: internal wrong cmd\n");
486 exit(1);
492 errx(1, "internal wrong cmd");
487 case RTM_ADD:
488 rtm->rtm_addrs |= RTA_GATEWAY;
489 rtm->rtm_rmx.rmx_expire = expire_time;
490 rtm->rtm_inits = RTV_EXPIRE;
491 rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
492 sin_m.sin_other = 0;
493 if (doing_proxy) {
494 if (export_only)

--- 17 unchanged lines hidden (view full) ---

512
513 rtm->rtm_msglen = cp - (char *)&m_rtmsg;
514doit:
515 l = rtm->rtm_msglen;
516 rtm->rtm_seq = ++seq;
517 rtm->rtm_type = cmd;
518 if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
519 if (errno != ESRCH || cmd != RTM_DELETE) {
493 case RTM_ADD:
494 rtm->rtm_addrs |= RTA_GATEWAY;
495 rtm->rtm_rmx.rmx_expire = expire_time;
496 rtm->rtm_inits = RTV_EXPIRE;
497 rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
498 sin_m.sin_other = 0;
499 if (doing_proxy) {
500 if (export_only)

--- 17 unchanged lines hidden (view full) ---

518
519 rtm->rtm_msglen = cp - (char *)&m_rtmsg;
520doit:
521 l = rtm->rtm_msglen;
522 rtm->rtm_seq = ++seq;
523 rtm->rtm_type = cmd;
524 if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
525 if (errno != ESRCH || cmd != RTM_DELETE) {
520 perror("writing to routing socket");
526 warn("writing to routing socket");
521 return (-1);
522 }
523 }
524 do {
525 l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
526 } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
527 if (l < 0)
527 return (-1);
528 }
529 }
530 do {
531 l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
532 } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
533 if (l < 0)
528 (void) fprintf(stderr, "arp: read from routing socket: %s\n",
529 strerror(errno));
534 warn("read from routing socket");
530 return (0);
531}
535 return (0);
536}
537
538/*
539 * get_ether_addr - get the hardware address of an interface on the
540 * the same subnet as ipaddr.
541 */
542#define MAX_IFS 32
543
544int
545get_ether_addr(u_long ipaddr, u_char *hwaddr)
546{
547 struct ifreq *ifr, *ifend, *ifp;
548 u_long ina, mask;
549 struct sockaddr_dl *dla;
550 struct ifreq ifreq;
551 struct ifconf ifc;
552 struct ifreq ifs[MAX_IFS];
553 int s;
554
555 s = socket(AF_INET, SOCK_DGRAM, 0);
556 if (s < 0)
557 err(1, "socket");
558
559 ifc.ifc_len = sizeof(ifs);
560 ifc.ifc_req = ifs;
561 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
562 warnx("ioctl(SIOCGIFCONF)");
563 close(s);
564 return 0;
565 }
566
567 /*
568 * Scan through looking for an interface with an Internet
569 * address on the same subnet as `ipaddr'.
570 */
571 ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
572 for (ifr = ifc.ifc_req; ifr < ifend; ) {
573 if (ifr->ifr_addr.sa_family == AF_INET) {
574 ina = ((struct sockaddr_in *)
575 &ifr->ifr_addr)->sin_addr.s_addr;
576 strncpy(ifreq.ifr_name, ifr->ifr_name,
577 sizeof(ifreq.ifr_name));
578 /*
579 * Check that the interface is up,
580 * and not point-to-point or loopback.
581 */
582 if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0)
583 continue;
584 if ((ifreq.ifr_flags &
585 (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|
586 IFF_LOOPBACK|IFF_NOARP))
587 != (IFF_UP|IFF_BROADCAST))
588 goto nextif;
589 /*
590 * Get its netmask and check that it's on
591 * the right subnet.
592 */
593 if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0)
594 continue;
595 mask = ((struct sockaddr_in *)
596 &ifreq.ifr_addr)->sin_addr.s_addr;
597 if ((ipaddr & mask) != (ina & mask))
598 goto nextif;
599 break;
600 }
601nextif:
602 ifr = (struct ifreq *)
603 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
604 }
605
606 if (ifr >= ifend) {
607 close(s);
608 return 0;
609 }
610
611 /*
612 * Now scan through again looking for a link-level address
613 * for this interface.
614 */
615 ifp = ifr;
616 for (ifr = ifc.ifc_req; ifr < ifend; ) {
617 if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0
618 && ifr->ifr_addr.sa_family == AF_LINK) {
619 /*
620 * Found the link-level address - copy it out
621 */
622 dla = (struct sockaddr_dl *) &ifr->ifr_addr;
623 memcpy(hwaddr, LLADDR(dla), dla->sdl_alen);
624 close (s);
625 printf("using interface %s for proxy with address ",
626 ifp->ifr_name);
627 ether_print(hwaddr);
628 printf("\n");
629 return dla->sdl_alen;
630 }
631 ifr = (struct ifreq *)
632 ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len);
633 }
634 return 0;
635}