]>
git.saurik.com Git - apple/network_cmds.git/blob - arp.tproj/arp.c
4e932b4931599ad89a2ce59e7722ad6ef6f2028b
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1984, 1993
26 * The Regents of the University of California. All rights reserved.
28 * This code is derived from software contributed to Berkeley by
29 * Sun Microsystems, Inc.
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 static char copyright
[] =
62 "@(#) Copyright (c) 1984, 1993\n\
63 The Regents of the University of California. All rights reserved.\n";
67 static char sccsid
[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95";
71 * arp - display, set, and delete arp table entries
75 #include <sys/param.h>
77 #include <sys/socket.h>
78 #include <sys/sysctl.h>
81 #include <net/if_dl.h>
82 #include <net/if_types.h>
83 #include <net/route.h>
85 #include <netinet/in.h>
86 #include <netinet/if_ether.h>
88 #include <arpa/inet.h>
104 int delete __P((char *, char *));
105 void dump
__P((u_long
));
106 int ether_aton
__P((char *, u_char
*));
107 void ether_print
__P((u_char
*));
108 int file
__P((char *));
109 void get
__P((char *));
110 void getsocket
__P((void));
111 int rtmsg
__P((int));
112 int set
__P((int, char **));
113 void usage
__P((void));
123 while ((ch
= getopt(argc
, argv
, "ands")) != EOF
)
129 if (argc
< 3 || argc
> 4)
131 delete(argv
[2], argv
[3]);
137 if (argc
< 4 || argc
> 7)
139 exit(set(argc
-2, &argv
[2]) ? 1 : 0);
151 * Process a file to set standard arp entries
159 char line
[100], arg
[5][50], *args
[5];
161 if ((fp
= fopen(name
, "r")) == NULL
) {
162 fprintf(stderr
, "arp: cannot open %s\n", name
);
165 args
[0] = &arg
[0][0];
166 args
[1] = &arg
[1][0];
167 args
[2] = &arg
[2][0];
168 args
[3] = &arg
[3][0];
169 args
[4] = &arg
[4][0];
171 while(fgets(line
, 100, fp
) != NULL
) {
172 i
= sscanf(line
, "%s %s %s %s %s", arg
[0], arg
[1], arg
[2],
175 fprintf(stderr
, "arp: bad line: %s\n", line
);
189 s
= socket(PF_ROUTE
, SOCK_RAW
, 0);
191 perror("arp: socket");
197 struct sockaddr_in so_mask
= {8, 0, 0, { 0xffffffff}};
198 struct sockaddr_inarp blank_sin
= {sizeof(blank_sin
), AF_INET
}, sin_m
;
199 struct sockaddr_dl blank_sdl
= {sizeof(blank_sdl
), AF_LINK
}, sdl_m
;
200 int expire_time
, flags
, export_only
, doing_proxy
, found_entry
;
202 struct rt_msghdr m_rtm
;
207 * Set an individual arp entry
215 register struct sockaddr_inarp
*sin
= &sin_m
;
216 register struct sockaddr_dl
*sdl
;
217 register struct rt_msghdr
*rtm
= &(m_rtmsg
.m_rtm
);
219 char *host
= argv
[0], *eaddr
= argv
[1];
226 sin
->sin_addr
.s_addr
= inet_addr(host
);
227 if (sin
->sin_addr
.s_addr
== -1) {
228 if (!(hp
= gethostbyname(host
))) {
229 fprintf(stderr
, "arp: %s: ", host
);
230 herror((char *)NULL
);
233 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
234 sizeof sin
->sin_addr
);
236 ea
= (u_char
*)LLADDR(&sdl_m
);
237 if (ether_aton(eaddr
, ea
) == 0)
239 doing_proxy
= flags
= export_only
= expire_time
= 0;
241 if (strncmp(argv
[0], "temp", 4) == 0) {
243 gettimeofday(&time
, 0);
244 expire_time
= time
.tv_sec
+ 20 * 60;
246 else if (strncmp(argv
[0], "pub", 3) == 0) {
247 flags
|= RTF_ANNOUNCE
;
248 doing_proxy
= SIN_PROXY
;
249 } else if (strncmp(argv
[0], "trail", 5) == 0) {
250 printf("%s: Sending trailers is no longer supported\n",
256 if (rtmsg(RTM_GET
) < 0) {
260 sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
261 sdl
= (struct sockaddr_dl
*)(sin
->sin_len
+ (char *)sin
);
262 if (sin
->sin_addr
.s_addr
== sin_m
.sin_addr
.s_addr
) {
263 if (sdl
->sdl_family
== AF_LINK
&&
264 (rtm
->rtm_flags
& RTF_LLINFO
) &&
265 !(rtm
->rtm_flags
& RTF_GATEWAY
)) switch (sdl
->sdl_type
) {
266 case IFT_ETHER
: case IFT_FDDI
: case IFT_ISO88023
:
267 case IFT_ISO88024
: case IFT_ISO88025
:
270 if (doing_proxy
== 0) {
271 printf("set: can only proxy for %s\n", host
);
274 if (sin_m
.sin_other
& SIN_PROXY
) {
275 printf("set: proxy entry exists for non 802 device\n");
278 sin_m
.sin_other
= SIN_PROXY
;
283 if (sdl
->sdl_family
!= AF_LINK
) {
284 printf("cannot intuit interface index and type for %s\n", host
);
287 sdl_m
.sdl_type
= sdl
->sdl_type
;
288 sdl_m
.sdl_index
= sdl
->sdl_index
;
289 return (rtmsg(RTM_ADD
));
293 * Display an individual arp entry
300 struct sockaddr_inarp
*sin
= &sin_m
;
303 sin
->sin_addr
.s_addr
= inet_addr(host
);
304 if (sin
->sin_addr
.s_addr
== -1) {
305 if (!(hp
= gethostbyname(host
))) {
306 fprintf(stderr
, "arp: %s: ", host
);
307 herror((char *)NULL
);
310 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
311 sizeof sin
->sin_addr
);
313 dump(sin
->sin_addr
.s_addr
);
314 if (found_entry
== 0) {
315 printf("%s (%s) -- no entry\n",
316 host
, inet_ntoa(sin
->sin_addr
));
322 * Delete an arp entry
330 register struct sockaddr_inarp
*sin
= &sin_m
;
331 register struct rt_msghdr
*rtm
= &m_rtmsg
.m_rtm
;
332 struct sockaddr_dl
*sdl
;
334 if (info
&& strncmp(info
, "pro", 3) )
338 sin
->sin_addr
.s_addr
= inet_addr(host
);
339 if (sin
->sin_addr
.s_addr
== -1) {
340 if (!(hp
= gethostbyname(host
))) {
341 fprintf(stderr
, "arp: %s: ", host
);
342 herror((char *)NULL
);
345 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
346 sizeof sin
->sin_addr
);
349 if (rtmsg(RTM_GET
) < 0) {
353 sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
354 sdl
= (struct sockaddr_dl
*)(sin
->sin_len
+ (char *)sin
);
355 if (sin
->sin_addr
.s_addr
== sin_m
.sin_addr
.s_addr
) {
356 if (sdl
->sdl_family
== AF_LINK
&&
357 (rtm
->rtm_flags
& RTF_LLINFO
) &&
358 !(rtm
->rtm_flags
& RTF_GATEWAY
)) switch (sdl
->sdl_type
) {
359 case IFT_ETHER
: case IFT_FDDI
: case IFT_ISO88023
:
360 case IFT_ISO88024
: case IFT_ISO88025
:
364 if (sin_m
.sin_other
& SIN_PROXY
) {
365 fprintf(stderr
, "delete: can't locate %s\n",host
);
368 sin_m
.sin_other
= SIN_PROXY
;
372 if (sdl
->sdl_family
!= AF_LINK
) {
373 printf("cannot locate %s\n", host
);
376 if (rtmsg(RTM_DELETE
))
378 printf("%s (%s) deleted\n", host
, inet_ntoa(sin
->sin_addr
));
383 * Dump the entire arp table
391 char *host
, *lim
, *buf
, *next
;
392 struct rt_msghdr
*rtm
;
393 struct sockaddr_inarp
*sin
;
394 struct sockaddr_dl
*sdl
;
402 mib
[4] = NET_RT_FLAGS
;
404 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
405 err(1, "route-sysctl-estimate");
406 if ((buf
= malloc(needed
)) == NULL
)
408 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
409 err(1, "actual retrieval of routing table");
411 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
412 rtm
= (struct rt_msghdr
*)next
;
413 sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
414 sdl
= (struct sockaddr_dl
*)(sin
+ 1);
416 if (addr
!= sin
->sin_addr
.s_addr
)
421 hp
= gethostbyaddr((caddr_t
)&(sin
->sin_addr
),
422 sizeof sin
->sin_addr
, AF_INET
);
429 if (h_errno
== TRY_AGAIN
)
432 printf("%s (%s) at ", host
, inet_ntoa(sin
->sin_addr
));
434 ether_print((u_char
*)LLADDR(sdl
));
436 printf("(incomplete)");
437 if (rtm
->rtm_rmx
.rmx_expire
== 0)
438 printf(" permanent");
439 if (sin
->sin_other
& SIN_PROXY
)
440 printf(" published (proxy only)");
441 if (rtm
->rtm_addrs
& RTA_NETMASK
) {
442 sin
= (struct sockaddr_inarp
*)
443 (sdl
->sdl_len
+ (char *)sdl
);
444 if (sin
->sin_addr
.s_addr
== 0xffffffff)
445 printf(" published");
446 if (sin
->sin_len
!= 8)
457 printf("%x:%x:%x:%x:%x:%x", cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5]);
467 i
= sscanf(a
, "%x:%x:%x:%x:%x:%x", &o
[0], &o
[1], &o
[2],
468 &o
[3], &o
[4], &o
[5]);
470 fprintf(stderr
, "arp: invalid Ethernet address '%s'\n", a
);
481 printf("usage: arp hostname\n");
482 printf(" arp -a [kernel] [kernel_memory]\n");
483 printf(" arp -d hostname\n");
484 printf(" arp -s hostname ether_addr [temp] [pub]\n");
485 printf(" arp -f filename\n");
495 register struct rt_msghdr
*rtm
= &m_rtmsg
.m_rtm
;
496 register char *cp
= m_rtmsg
.m_space
;
500 if (cmd
== RTM_DELETE
)
502 bzero((char *)&m_rtmsg
, sizeof(m_rtmsg
));
503 rtm
->rtm_flags
= flags
;
504 rtm
->rtm_version
= RTM_VERSION
;
508 fprintf(stderr
, "arp: internal wrong cmd\n");
511 rtm
->rtm_addrs
|= RTA_GATEWAY
;
512 rtm
->rtm_rmx
.rmx_expire
= expire_time
;
513 rtm
->rtm_inits
= RTV_EXPIRE
;
514 rtm
->rtm_flags
|= (RTF_HOST
| RTF_STATIC
);
518 sin_m
.sin_other
= SIN_PROXY
;
520 rtm
->rtm_addrs
|= RTA_NETMASK
;
521 rtm
->rtm_flags
&= ~RTF_HOST
;
526 rtm
->rtm_addrs
|= RTA_DST
;
528 #define NEXTADDR(w, s) \
529 if (rtm->rtm_addrs & (w)) { \
530 bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
532 NEXTADDR(RTA_DST
, sin_m
);
533 NEXTADDR(RTA_GATEWAY
, sdl_m
);
534 NEXTADDR(RTA_NETMASK
, so_mask
);
536 rtm
->rtm_msglen
= cp
- (char *)&m_rtmsg
;
539 rtm
->rtm_seq
= ++seq
;
541 if ((rlen
= write(s
, (char *)&m_rtmsg
, l
)) < 0) {
542 if (errno
!= ESRCH
|| cmd
!= RTM_DELETE
) {
543 perror("writing to routing socket");
548 l
= read(s
, (char *)&m_rtmsg
, sizeof(m_rtmsg
));
549 } while (l
> 0 && (rtm
->rtm_seq
!= seq
|| rtm
->rtm_pid
!= pid
));
551 (void) fprintf(stderr
, "arp: read from routing socket: %s\n",