]>
git.saurik.com Git - apple/network_cmds.git/blob - arp.tproj/arp.c
d366781786eefa5e2f71dc2db0e3a6790fe47f79
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>
102 static int aflag
= 0;
105 int delete __P((char *, char *));
106 void dump
__P((u_long
));
107 int ether_aton
__P((char *, u_char
*));
108 void ether_print
__P((u_char
*));
109 int file
__P((char *));
110 void get
__P((char *));
111 void getsocket
__P((void));
112 int rtmsg
__P((int));
113 int set
__P((int, char **));
114 void usage
__P((void));
124 while ((ch
= getopt(argc
, argv
, "ands")) != EOF
)
130 if (argc
< 3 || argc
> 4)
132 delete(argv
[2], argv
[3]);
138 if (argc
< 4 || argc
> 7)
140 exit(set(argc
-2, &argv
[2]) ? 1 : 0);
149 if( nflag
&& (argc
== 3) ) {
160 * Process a file to set standard arp entries
168 char line
[100], arg
[5][50], *args
[5];
170 if ((fp
= fopen(name
, "r")) == NULL
) {
171 fprintf(stderr
, "arp: cannot open %s\n", name
);
174 args
[0] = &arg
[0][0];
175 args
[1] = &arg
[1][0];
176 args
[2] = &arg
[2][0];
177 args
[3] = &arg
[3][0];
178 args
[4] = &arg
[4][0];
180 while(fgets(line
, 100, fp
) != NULL
) {
181 i
= sscanf(line
, "%s %s %s %s %s", arg
[0], arg
[1], arg
[2],
184 fprintf(stderr
, "arp: bad line: %s\n", line
);
198 s
= socket(PF_ROUTE
, SOCK_RAW
, 0);
200 perror("arp: socket");
206 struct sockaddr_in so_mask
= {8, 0, 0, { 0xffffffff}};
207 struct sockaddr_inarp blank_sin
= {sizeof(blank_sin
), AF_INET
}, sin_m
;
208 struct sockaddr_dl blank_sdl
= {sizeof(blank_sdl
), AF_LINK
}, sdl_m
;
209 int expire_time
, flags
, export_only
, doing_proxy
, found_entry
;
211 struct rt_msghdr m_rtm
;
216 * Set an individual arp entry
224 register struct sockaddr_inarp
*sin
= &sin_m
;
225 register struct sockaddr_dl
*sdl
;
226 register struct rt_msghdr
*rtm
= &(m_rtmsg
.m_rtm
);
228 char *host
= argv
[0], *eaddr
= argv
[1];
235 sin
->sin_addr
.s_addr
= inet_addr(host
);
236 if (sin
->sin_addr
.s_addr
== -1) {
237 if (!(hp
= gethostbyname(host
))) {
238 fprintf(stderr
, "arp: %s: ", host
);
239 herror((char *)NULL
);
242 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
243 sizeof sin
->sin_addr
);
245 ea
= (u_char
*)LLADDR(&sdl_m
);
246 if (ether_aton(eaddr
, ea
) == 0)
248 doing_proxy
= flags
= export_only
= expire_time
= 0;
250 if (strncmp(argv
[0], "temp", 4) == 0) {
252 gettimeofday(&time
, 0);
253 expire_time
= time
.tv_sec
+ 20 * 60;
255 else if (strncmp(argv
[0], "pub", 3) == 0) {
256 flags
|= RTF_ANNOUNCE
;
257 doing_proxy
= SIN_PROXY
;
258 } else if (strncmp(argv
[0], "trail", 5) == 0) {
259 printf("%s: Sending trailers is no longer supported\n",
265 if (rtmsg(RTM_GET
) < 0) {
269 sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
270 sdl
= (struct sockaddr_dl
*)(sin
->sin_len
+ (char *)sin
);
271 if (sin
->sin_addr
.s_addr
== sin_m
.sin_addr
.s_addr
) {
272 if (sdl
->sdl_family
== AF_LINK
&&
273 (rtm
->rtm_flags
& RTF_LLINFO
) &&
274 !(rtm
->rtm_flags
& RTF_GATEWAY
)) switch (sdl
->sdl_type
) {
275 case IFT_ETHER
: case IFT_FDDI
: case IFT_ISO88023
:
276 case IFT_ISO88024
: case IFT_ISO88025
:
279 if (doing_proxy
== 0) {
280 printf("set: can only proxy for %s\n", host
);
283 if (sin_m
.sin_other
& SIN_PROXY
) {
284 printf("set: proxy entry exists for non 802 device\n");
287 sin_m
.sin_other
= SIN_PROXY
;
292 if (sdl
->sdl_family
!= AF_LINK
) {
293 printf("cannot intuit interface index and type for %s\n", host
);
296 sdl_m
.sdl_type
= sdl
->sdl_type
;
297 sdl_m
.sdl_index
= sdl
->sdl_index
;
298 return (rtmsg(RTM_ADD
));
302 * Display an individual arp entry
309 struct sockaddr_inarp
*sin
= &sin_m
;
312 sin
->sin_addr
.s_addr
= inet_addr(host
);
313 if (sin
->sin_addr
.s_addr
== -1) {
314 if (!(hp
= gethostbyname(host
))) {
315 fprintf(stderr
, "arp: %s: ", host
);
316 herror((char *)NULL
);
319 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
320 sizeof sin
->sin_addr
);
322 dump(sin
->sin_addr
.s_addr
);
323 if (found_entry
== 0) {
324 printf("%s (%s) -- no entry\n",
325 host
, inet_ntoa(sin
->sin_addr
));
331 * Delete an arp entry
339 register struct sockaddr_inarp
*sin
= &sin_m
;
340 register struct rt_msghdr
*rtm
= &m_rtmsg
.m_rtm
;
341 struct sockaddr_dl
*sdl
;
343 if (info
&& strncmp(info
, "pro", 3) )
347 sin
->sin_addr
.s_addr
= inet_addr(host
);
348 if (sin
->sin_addr
.s_addr
== -1) {
349 if (!(hp
= gethostbyname(host
))) {
350 fprintf(stderr
, "arp: %s: ", host
);
351 herror((char *)NULL
);
354 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
355 sizeof sin
->sin_addr
);
358 if (rtmsg(RTM_GET
) < 0) {
362 sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
363 sdl
= (struct sockaddr_dl
*)(sin
->sin_len
+ (char *)sin
);
364 if (sin
->sin_addr
.s_addr
== sin_m
.sin_addr
.s_addr
) {
365 if (sdl
->sdl_family
== AF_LINK
&&
366 (rtm
->rtm_flags
& RTF_LLINFO
) &&
367 !(rtm
->rtm_flags
& RTF_GATEWAY
)) switch (sdl
->sdl_type
) {
368 case IFT_ETHER
: case IFT_FDDI
: case IFT_ISO88023
:
369 case IFT_ISO88024
: case IFT_ISO88025
:
373 if (sin_m
.sin_other
& SIN_PROXY
) {
374 fprintf(stderr
, "delete: can't locate %s\n",host
);
377 sin_m
.sin_other
= SIN_PROXY
;
381 if (sdl
->sdl_family
!= AF_LINK
) {
382 printf("cannot locate %s\n", host
);
385 if (rtmsg(RTM_DELETE
))
387 printf("%s (%s) deleted\n", host
, inet_ntoa(sin
->sin_addr
));
392 * Dump the entire arp table
400 char *host
, *lim
, *buf
, *next
;
401 struct rt_msghdr
*rtm
;
402 struct sockaddr_inarp
*sin
;
403 struct sockaddr_dl
*sdl
;
411 mib
[4] = NET_RT_FLAGS
;
413 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
414 err(1, "route-sysctl-estimate");
415 if ((buf
= malloc(needed
)) == NULL
)
417 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
418 err(1, "actual retrieval of routing table");
420 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
421 rtm
= (struct rt_msghdr
*)next
;
422 sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
423 sdl
= (struct sockaddr_dl
*)(sin
+ 1);
425 if (addr
!= sin
->sin_addr
.s_addr
)
430 hp
= gethostbyaddr((caddr_t
)&(sin
->sin_addr
),
431 sizeof sin
->sin_addr
, AF_INET
);
438 if (h_errno
== TRY_AGAIN
)
441 printf("%s (%s) at ", host
, inet_ntoa(sin
->sin_addr
));
443 ether_print((u_char
*)LLADDR(sdl
));
445 printf("(incomplete)");
446 if (rtm
->rtm_rmx
.rmx_expire
== 0)
447 printf(" permanent");
448 if (sin
->sin_other
& SIN_PROXY
)
449 printf(" published (proxy only)");
450 if (rtm
->rtm_addrs
& RTA_NETMASK
) {
451 sin
= (struct sockaddr_inarp
*)
452 (sdl
->sdl_len
+ (char *)sdl
);
453 if (sin
->sin_addr
.s_addr
== 0xffffffff)
454 printf(" published");
455 if (sin
->sin_len
!= 8)
466 printf("%x:%x:%x:%x:%x:%x", cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5]);
476 i
= sscanf(a
, "%x:%x:%x:%x:%x:%x", &o
[0], &o
[1], &o
[2],
477 &o
[3], &o
[4], &o
[5]);
479 fprintf(stderr
, "arp: invalid Ethernet address '%s'\n", a
);
490 printf("usage: arp [-n] hostname\n");
491 printf(" arp [-n] -a\n");
492 printf(" arp -d hostname\n");
493 printf(" arp -s hostname ether_addr [temp] [pub]\n");
494 printf(" arp -f filename\n");
504 register struct rt_msghdr
*rtm
= &m_rtmsg
.m_rtm
;
505 register char *cp
= m_rtmsg
.m_space
;
509 if (cmd
== RTM_DELETE
)
511 bzero((char *)&m_rtmsg
, sizeof(m_rtmsg
));
512 rtm
->rtm_flags
= flags
;
513 rtm
->rtm_version
= RTM_VERSION
;
517 fprintf(stderr
, "arp: internal wrong cmd\n");
520 rtm
->rtm_addrs
|= RTA_GATEWAY
;
521 rtm
->rtm_rmx
.rmx_expire
= expire_time
;
522 rtm
->rtm_inits
= RTV_EXPIRE
;
523 rtm
->rtm_flags
|= (RTF_HOST
| RTF_STATIC
);
527 sin_m
.sin_other
= SIN_PROXY
;
529 rtm
->rtm_addrs
|= RTA_NETMASK
;
530 rtm
->rtm_flags
&= ~RTF_HOST
;
535 rtm
->rtm_addrs
|= RTA_DST
;
537 #define NEXTADDR(w, s) \
538 if (rtm->rtm_addrs & (w)) { \
539 bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
541 NEXTADDR(RTA_DST
, sin_m
);
542 NEXTADDR(RTA_GATEWAY
, sdl_m
);
543 NEXTADDR(RTA_NETMASK
, so_mask
);
545 rtm
->rtm_msglen
= cp
- (char *)&m_rtmsg
;
548 rtm
->rtm_seq
= ++seq
;
550 if ((rlen
= write(s
, (char *)&m_rtmsg
, l
)) < 0) {
551 if (errno
!= ESRCH
|| cmd
!= RTM_DELETE
) {
552 perror("writing to routing socket");
557 l
= read(s
, (char *)&m_rtmsg
, sizeof(m_rtmsg
));
558 } while (l
> 0 && (rtm
->rtm_seq
!= seq
|| rtm
->rtm_pid
!= pid
));
560 (void) fprintf(stderr
, "arp: read from routing socket: %s\n",