* Copyright (c) 1984 Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* %sccs.include.redist.c%
"@(#) Copyright (c) 1984 Regents of the University of California.\n\
static char sccsid
[] = "@(#)arp.c 5.16 (Berkeley) %G%";
* arp - display, set, and delete arp table entries
#include <net/if_types.h>
#include <netinet/if_ether.h>
while ((ch
= getopt(argc
, argv
, "ands")) != EOF
)
if (argc
< 3 || argc
> 4)
delete(argv
[2], argv
[3]);
if (argc
< 4 || argc
> 7)
exit(set(argc
-2, &argv
[2]) ? 1 : 0);
* Process a file to set standard arp entries
char line
[100], arg
[5][50], *args
[5];
if ((fp
= fopen(name
, "r")) == NULL
) {
fprintf(stderr
, "arp: cannot open %s\n", name
);
while(fgets(line
, 100, fp
) != NULL
) {
i
= sscanf(line
, "%s %s %s %s %s", arg
[0], arg
[1], arg
[2],
fprintf(stderr
, "arp: bad line: %s\n", line
);
s
= socket(PF_ROUTE
, SOCK_RAW
, 0);
struct sockaddr_in so_mask
= {8, 0, 0, { 0xffffffff}};
struct sockaddr_inarp blank_sin
= {sizeof(blank_sin
), AF_INET
}, sin_m
;
struct sockaddr_dl blank_sdl
= {sizeof(blank_sdl
), AF_LINK
}, sdl_m
;
int expire_time
, flags
, export_only
, doing_proxy
, found_entry
;
* Set an individual arp entry
register struct sockaddr_inarp
*sin
= &sin_m
;
register struct sockaddr_dl
*sdl
;
register struct rt_msghdr
*rtm
= &(m_rtmsg
.m_rtm
);
char *host
= argv
[0], *eaddr
= argv
[1];
sin
->sin_addr
.s_addr
= inet_addr(host
);
if (sin
->sin_addr
.s_addr
== -1) {
if (!(hp
= gethostbyname(host
))) {
fprintf(stderr
, "arp: %s: ", host
);
bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
ea
= (u_char
*)LLADDR(&sdl_m
);
if (ether_aton(eaddr
, ea
) == 0)
doing_proxy
= flags
= export_only
= expire_time
= 0;
if (strncmp(argv
[0], "temp", 4) == 0) {
expire_time
= time
.tv_sec
+ 20 * 60;
else if (strncmp(argv
[0], "pub", 3) == 0) {
} else if (strncmp(argv
[0], "trail", 5) == 0) {
printf("%s: Sending trailers is no longer supported\n",
if (rtmsg(RTM_GET
) < 0) {
sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
sdl
= (struct sockaddr_dl
*)(sin
->sin_len
+ (char *)sin
);
if (sin
->sin_addr
.s_addr
== sin_m
.sin_addr
.s_addr
) {
if (sdl
->sdl_family
== AF_LINK
&&
(rtm
->rtm_flags
& RTF_LLINFO
) &&
!(rtm
->rtm_flags
& RTF_GATEWAY
)) switch (sdl
->sdl_type
) {
case IFT_ETHER
: case IFT_FDDI
: case IFT_ISO88023
:
case IFT_ISO88024
: case IFT_ISO88025
:
printf("set: can only proxy for %s\n", host
);
if (sin_m
.sin_other
& SIN_PROXY
) {
printf("set: proxy entry exists for non 802 device\n");
sin_m
.sin_other
= SIN_PROXY
;
if (sdl
->sdl_family
!= AF_LINK
) {
printf("cannot intuit interface index and type for %s\n", host
);
sdl_m
.sdl_type
= sdl
->sdl_type
;
sdl_m
.sdl_index
= sdl
->sdl_index
;
* Display an individual arp entry
struct sockaddr_inarp
*sin
= &sin_m
;
sin
->sin_addr
.s_addr
= inet_addr(host
);
if (sin
->sin_addr
.s_addr
== -1) {
if (!(hp
= gethostbyname(host
))) {
fprintf(stderr
, "arp: %s: ", host
);
bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
dump(sin
->sin_addr
.s_addr
);
printf("%s (%s) -- no entry\n",
host
, inet_ntoa(sin
->sin_addr
));
register struct sockaddr_inarp
*sin
= &sin_m
;
register struct rt_msghdr
*rtm
= &m_rtmsg
.m_rtm
;
if (info
&& strncmp(info
, "pro", 3) )
sin
->sin_addr
.s_addr
= inet_addr(host
);
if (sin
->sin_addr
.s_addr
== -1) {
if (!(hp
= gethostbyname(host
))) {
fprintf(stderr
, "arp: %s: ", host
);
bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
if (rtmsg(RTM_GET
) < 0) {
sin
= (struct sockaddr_inarp
*)(rtm
+ 1);
sdl
= (struct sockaddr_dl
*)(sin
->sin_len
+ (char *)sin
);
if (sin
->sin_addr
.s_addr
== sin_m
.sin_addr
.s_addr
) {
if (sdl
->sdl_family
== AF_LINK
&&
(rtm
->rtm_flags
& RTF_LLINFO
) &&
!(rtm
->rtm_flags
& RTF_GATEWAY
)) switch (sdl
->sdl_type
) {
case IFT_ETHER
: case IFT_FDDI
: case IFT_ISO88023
:
case IFT_ISO88024
: case IFT_ISO88025
:
if (sin_m
.sin_other
& SIN_PROXY
) {
fprintf(stderr
, "delete: can't locate %s\n",host
);
sin_m
.sin_other
= SIN_PROXY
;
if (sdl
->sdl_family
!= AF_LINK
) {
printf("cannot locate %s\n", host
);
if (rtmsg(RTM_DELETE
) == 0)
printf("%s (%s) deleted\n", host
, inet_ntoa(sin
->sin_addr
));
* Dump the entire arp table
long op
= KINFO_RT_FLAGS
| (((long)AF_INET
) << 16);
char *host
, *malloc(), *lim
, *buf
, *next
;
struct sockaddr_inarp
*sin
;
hp
= gethostbyaddr((caddr_t
)&(sin
->sin_addr
),
sizeof sin
->sin_addr
, AF_INET
);
if (h_errno
== TRY_AGAIN
)
printf("%s (%s) at ", host
, inet_ntoa(sin
->sin_addr
));
ether_print(LLADDR(sdl
));
if (rtm
->rtm_rmx
.rmx_expire
== 0)
if (sin
->sin_other
& SIN_PROXY
)
printf(" published (proxy only)");
if (rtm
->rtm_addrs
& RTA_NETMASK
) {
sin
= (struct sockaddr_inarp
*)
(sdl
->sdl_len
+ (char *)sdl
);
if (sin
->sin_addr
.s_addr
== 0xffffffff)
printf("%x:%x:%x:%x:%x:%x", cp
[0], cp
[1], cp
[2], cp
[3], cp
[4], cp
[5]);
i
= sscanf(a
, "%x:%x:%x:%x:%x:%x", &o
[0], &o
[1], &o
[2],
fprintf(stderr
, "arp: invalid Ethernet address '%s'\n", a
);
printf("usage: arp hostname\n");
printf(" arp -a [kernel] [kernel_memory]\n");
printf(" arp -d hostname\n");
printf(" arp -s hostname ether_addr [temp] [pub]\n");
printf(" arp -f filename\n");
register struct rt_msghdr
*rtm
= &m_rtmsg
.m_rtm
;
register char *cp
= m_rtmsg
.m_space
;
bzero((char *)&m_rtmsg
, sizeof(m_rtmsg
));
rtm
->rtm_version
= RTM_VERSION
;
fprintf(stderr
, "arp: internal wrong cmd\n");
rtm
->rtm_addrs
|= RTA_GATEWAY
;
rtm
->rtm_rmx
.rmx_expire
= expire_time
;
rtm
->rtm_inits
= RTV_EXPIRE
;
rtm
->rtm_flags
|= (RTF_HOST
| RTF_STATIC
);
sin_m
.sin_other
= SIN_PROXY
;
rtm
->rtm_addrs
|= RTA_NETMASK
;
rtm
->rtm_flags
&= ~RTF_HOST
;
rtm
->rtm_addrs
|= RTA_DST
;
if (rtm->rtm_addrs & (w)) { \
bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
NEXTADDR(RTA_DST
, sin_m
);
NEXTADDR(RTA_GATEWAY
, sdl_m
);
NEXTADDR(RTA_NETMASK
, so_mask
);
rtm
->rtm_msglen
= cp
- (char *)&m_rtmsg
;
if ((rlen
= write(s
, (char *)&m_rtmsg
, l
)) < 0) {
if (errno
!= ESRCH
|| cmd
!= RTM_DELETE
) {
perror("writing to routing socket");
l
= read(s
, (char *)&m_rtmsg
, sizeof(m_rtmsg
));
} while (l
> 0 && (rtm
->rtm_seq
!= seq
|| rtm
->rtm_pid
!= pid
));
(void) fprintf(stderr
, "arp: read from routing socket: %s\n",
fprintf(stderr
, "%s\n", msg
);