3 * arp.c --- arp utility for AmiTCP/IP
5 * Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
6 * Helsinki University of Technology, Finland.
8 * Copyright © 2005 Pavel Fedin
10 * Created : Sun Apr 18 05:08:20 1993 ppessi
11 * Last modified: Wed Feb 16 19:48:50 1994 ppessi
14 * Revision 1.2 2005/12/22 06:44:55 sonic_amiga
15 * - Fixed address printout in "arp" tool.
16 * - "netstat" fully works now.
17 * - Improved hostname handling.
18 * - Fixed FD_ACCEPT generation
19 * - DHCP client now supports nameservers option
21 * Revision 1.1.1.1 2005/12/07 10:50:36 sonic_amiga
22 * First full import into the CVS
24 * Revision 3.2 1994/05/02 19:39:03 jraja
25 * Update for the new net.lib
27 * Revision 3.1 1994/02/21 20:32:19 ppessi
28 * Changed the version tag.
30 * Revision 1.10 1993/11/07 00:19:45 ppessi
31 * Reverted back to scanf()
33 * Revision 1.9 1993/10/29 01:26:40 ppessi
34 * Implemented dumping of arp tables.
35 * Cleaned up code, fixed close() bug.
38 static const char version
[] = "$VER: arp 3.2 (12.09.2005) "
39 "Copyright © 2005 Pavel Fedin <sonic_amiga@rambler.ru>\n"
40 "Copyright © 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>\n"
41 "Helsinki University of Technology, Finland.\n"
42 "Copyright © 1984 The Regents of the University of California.\n"
43 "All rights reserved.\n";
47 * Copyright © 1984 Regents of the University of California.
48 * All rights reserved.
50 * This code is derived from software contributed to Berkeley by
51 * Sun Microsystems, Inc.
53 * Redistribution and use in source and binary forms, with or without
54 * modification, are permitted provided that the following conditions
56 * 1. Redistributions of source code must retain the above copyright
57 * notice, this list of conditions and the following disclaimer.
58 * 2. Redistributions in binary form must reproduce the above copyright
59 * notice, this list of conditions and the following disclaimer in the
60 * documentation and/or other materials provided with the distribution.
61 * 3. All advertising materials mentioning features or use of this software
62 * must display the following acknowledgement:
63 * This product includes software developed by the University of
64 * California, Berkeley and its contributors.
65 * 4. Neither the name of the University nor the names of its contributors
66 * may be used to endorse or promote products derived from this software
67 * without specific prior written permission.
69 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
70 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
71 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
72 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
73 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
74 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
75 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
76 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
77 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
78 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82 /****** netutil.doc/arp *****************************************************
85 * Arp - address resolution display and control
89 * arp -a [netname | hostname]
91 * arp -s hostname address [temp] [pub]
95 * Arp displays and modifies the Internet to hardware address
96 * translation tables used by the Address Resolution Protocol. The
97 * hardware address is a hexadecimal string with each octet separated
98 * by a colon, for instance 0:12:ff:a. The length of the address must
99 * be correct for the specified interface.
102 * none If no options are specified (first form above), arp displays
103 * the current ARP entry for hostname. The hostname must either
104 * appear in the hostname database (SEE hosts), or be a DARPA
105 * Internet address expressed in Internet standard "dot
106 * notation". Hostname can also be resolved by nameserver.
108 * -a Display all current ARP entries by reading the address mapping
109 * table of the specified (sub)network. `Hostname' is used to as
110 * default network specifier.
112 * -d If an ARP entry exists for the host called hostname, delete
113 * it. [This requires super-user privileges.]
115 * -s Create an ARP entry for the host called hostname with the
116 * hardware station address address. The hardware station address
117 * is given as hexadecimal bytes separated by colons. If an ARP
118 * entry already exists for hostname, the existing entry is
119 * updated with the new information. The entry is permanent
120 * unless the word temp is given in the command. If the word pub
121 * is specified, the entry is published, which means that this
122 * system will act as an ARP server responding to requests for
123 * hostname even though the host address is not its own.
125 * -f Read file filename and set multiple entries in the ARP tables.
126 * Entries in the file should be of the form:
128 * hostname address [temp] [pub]
130 * Argument meanings are the same as for the -s option.
133 * Arp was developed by the University of California, Berkeley, for the
137 * ifconfig, netif.protocols/arp, "net/if_arp.h"
139 *****************************************************************************
144 * arp - display, set, and delete arp table entries
148 #include <proto/dos.h>
149 #include <proto/socket.h>
150 #if !defined(__AROS__)
151 #include <clib/netlib_protos.h>
153 #include <proto/exec.h>
157 #include <sys/param.h>
158 #include <sys/socket.h>
159 #include <sys/sockio.h>
161 #include <arpa/inet.h>
163 #include <netinet/in.h>
169 #if defined(__AROS__)
174 struct Library
* SocketBase
;
176 #define max(a,b) ((a) > (b) ? (a) : (b))
179 #warning "TODO: NicJA - h_errno should be extern .."
182 static int file(char *name
);
183 static int set(int argc
, char **argv
);
184 static void get(char *host
);
185 static void delete(char *host
);
186 static int arpreq_print(struct arpreq
*ar
, int bynumber
);
187 static void sana_print(const u_char
*cp
, int len
);
188 static int sana_aton(const char *a
, u_char
*n
, u_char
*lenp
);
189 static void usage(void);
190 static void dump(char *name
);
191 char * strsep(register char **stringp
, register const char *delim
);
194 "usage: arp hostname\n"
195 " arp -a [netname | hostname]\n"
197 " arp -s hostname address [temp] [pub]\n"
198 " arp -f filename\n";
200 #define SOCKET_VERSION 3
201 const TEXT socket_name
[] = "bsdsocket.library";
209 if (!(SocketBase
= OpenLibrary(socket_name
, SOCKET_VERSION
)))
214 while ((ch
= getopt(argc
, argv
, "adsf")) != EOF
)
218 char myname
[MAXHOSTNAMELEN
];
226 gethostname(myname
, sizeof(myname
));
237 if (argc
< 4 || argc
> 7)
239 exit(set(argc
-2, &argv
[2]) ? 1 : 0);
243 exit (file(argv
[2]) ? 1 : 0);
255 * Process a file to set standard arp entries
262 char line
[100], arg
[5][50], *args
[5];
264 if ((fp
= fopen(name
, "r")) == NULL
) {
265 fprintf(stderr
, "arp: cannot open %s\n", name
);
269 args
[0] = &arg
[0][0];
270 args
[1] = &arg
[1][0];
271 args
[2] = &arg
[2][0];
272 args
[3] = &arg
[3][0];
273 args
[4] = &arg
[4][0];
276 while(fgets(line
, 100, fp
) != NULL
) {
277 i
= sscanf(line
, "%s %s %s %s %s", arg
[0], arg
[1], arg
[2], arg
[3], arg
[4]);
279 fprintf(stderr
, "arp: bad line: %s\n", line
);
291 * Set an individual arp entry
294 set(int argc
, char **argv
)
298 struct sockaddr_in
*sin
;
301 char *host
= argv
[0], *eaddr
= argv
[1];
305 bzero((caddr_t
)&ar
, sizeof ar
);
306 sin
= (struct sockaddr_in
*)&ar
.arp_pa
;
307 sin
->sin_len
= sizeof(*sin
);
308 sin
->sin_family
= AF_INET
;
309 sin
->sin_addr
.s_addr
= inet_addr(host
);
310 if (sin
->sin_addr
.s_addr
== -1) {
311 if (!(hp
= gethostbyname(host
))) {
312 fprintf(stderr
, "arp: %s: ", host
);
313 #warning "TODO: NicJA - Implement herror()"
314 #if !defined(__AROS__)
315 herror((char *)NULL
);
319 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
320 sizeof sin
->sin_addr
);
322 ea
= (u_char
*)ar
.arp_ha
.sa_data
;
323 if (sana_aton(eaddr
, ea
, &ar
.arp_ha
.sa_len
))
325 ar
.arp_ha
.sa_len
+= 2;
326 ar
.arp_flags
= ATF_PERM
;
328 if (strncmp(argv
[0], "temp", 4) == 0)
329 ar
.arp_flags
&= ~ATF_PERM
;
330 else if (strncmp(argv
[0], "pub", 3) == 0)
331 ar
.arp_flags
|= ATF_PUBL
;
332 else if (strncmp(argv
[0], "trail", 5) == 0)
333 ar
.arp_flags
|= ATF_USETRAILERS
;
337 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
339 perror("arp: socket");
342 if (IoctlSocket(s
, SIOCSARP
, (caddr_t
)&ar
) < 0) {
352 * Display an individual arp entry
359 struct sockaddr_in
*sin
;
362 bzero((caddr_t
)&ar
, sizeof ar
);
363 sin
= (struct sockaddr_in
*)&ar
.arp_pa
;
364 sin
->sin_len
= sizeof(*sin
);
365 sin
->sin_family
= AF_INET
;
366 sin
->sin_addr
.s_addr
= inet_addr(host
);
367 if (sin
->sin_addr
.s_addr
== -1) {
368 if (!(hp
= gethostbyname(host
))) {
369 fprintf(stderr
, "arp: %s: ", host
);
370 #warning "TODO: NicJA - Implement herror()"
371 #if !defined(__AROS__)
372 herror((char *)NULL
);
376 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
, sizeof sin
->sin_addr
);
378 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
380 perror("arp: socket");
383 if (IoctlSocket(s
, SIOCGARP
, (caddr_t
)&ar
) < 0) {
385 printf("%s (%s) -- no entry\n", host
, inet_ntoa(sin
->sin_addr
));
392 (void)arpreq_print(&ar
, 0);
396 * Delete an arp entry
403 struct sockaddr_in
*sin
;
406 bzero((caddr_t
)&ar
, sizeof ar
);
407 sin
= (struct sockaddr_in
*)&ar
.arp_pa
;
408 sin
->sin_len
= sizeof(*sin
);
409 sin
->sin_family
= AF_INET
;
410 sin
->sin_addr
.s_addr
= inet_addr(host
);
411 if (sin
->sin_addr
.s_addr
== -1) {
412 if (!(hp
= gethostbyname(host
))) {
413 fprintf(stderr
, "arp: %s: ", host
);
414 #warning "TODO: NicJA - Implement herror()"
415 #if !defined(__AROS__)
416 herror((char *)NULL
);
420 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
,
421 sizeof sin
->sin_addr
);
423 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
425 perror("arp: socket");
428 if (IoctlSocket(s
, SIOCDARP
, (caddr_t
)&ar
) < 0) {
430 printf("%s (%s) -- no entry\n",
431 host
, inet_ntoa(sin
->sin_addr
));
437 printf("%s (%s) deleted\n", host
, inet_ntoa(sin
->sin_addr
));
441 * Dump the entire arp table
446 struct arptabreq atr
;
448 struct sockaddr_in
*sin
;
452 bzero((caddr_t
)&atr
, sizeof atr
);
454 /* Identify the used interface according the host/net name */
455 sin
= (struct sockaddr_in
*)&atr
.atr_arpreq
.arp_pa
;
456 sin
->sin_len
= sizeof(*sin
);
457 sin
->sin_family
= AF_INET
;
458 sin
->sin_addr
.s_addr
= inet_addr(host
);
459 if (sin
->sin_addr
.s_addr
== -1) {
461 struct netent
*np
= NULL
;
462 if (!(hp
= gethostbyname(host
)) &&
463 !(np
= getnetbyname(host
))) {
464 fprintf(stderr
, "arp: %s: ", host
);
465 #warning "TODO: NicJA - Implement herror()"
466 #if !defined(__AROS__)
467 herror((char *)NULL
);
472 bcopy((char *)hp
->h_addr
, (char *)&sin
->sin_addr
, sizeof sin
->sin_addr
);
474 bcopy((char *)&np
->n_net
, (char *)&sin
->sin_addr
, sizeof np
->n_net
);
477 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
479 perror("arp: socket");
483 if (IoctlSocket(s
, SIOCGARPT
, (caddr_t
)&atr
) < 0) {
488 n
= atr
.atr_size
= atr
.atr_inuse
;
490 ar
= atr
.atr_table
= malloc(sizeof(*ar
) * n
);
492 perror("arp: malloc");
495 if (IoctlSocket(s
, SIOCGARPT
, (caddr_t
)&atr
) < 0) {
499 /* Entries may be deleted */
500 n
= max(n
, atr
.atr_inuse
);
506 bynumber
= arpreq_print(ar
++, bynumber
);
511 arpreq_print(struct arpreq
*ar
, int bynumber
)
513 struct sockaddr_in
*sin
;
517 sin
= (struct sockaddr_in
*)&ar
->arp_pa
;
520 hp
= gethostbyaddr((caddr_t
)&sin
->sin_addr
,
521 sizeof(struct in_addr
), AF_INET
);
529 if (h_errno
== TRY_AGAIN
)
533 Printf("%s (%s) at ", host
, inet_ntoa(sin
->sin_addr
));
534 if (ar
->arp_flags
& ATF_COM
)
535 sana_print(ar
->arp_ha
.sa_data
, ar
->arp_ha
.sa_len
- 2);
537 Printf("(incomplete)");
538 if (ar
->arp_flags
& ATF_PERM
)
539 Printf(" permanent");
540 if (ar
->arp_flags
& ATF_PUBL
)
541 Printf(" published");
542 if (ar
->arp_flags
& ATF_USETRAILERS
)
550 sana_print(const u_char
*cp
, int len
)
553 "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx";
557 format
[4*len
- 1] = '\0';
558 for (i
= 0; i
< len
; i
++)
560 // vprintf(format, (va_list)o);
566 sana_aton(const char *str
, u_char
*n
, u_char
*lenp
)
572 for (i
= 0; i
< 16; a
++) {
574 while ((c
= *a
- '0') <= 9
575 || (c
= c
- 'A' + '0' + 10) >= 9 && c
< 16 /*ABCDEF*/
576 || (c
= c
- 'a' + 'A') >= 9 && c
< 16) /*abcdef*/ {
578 o
[i
] = (o
[i
] << 4) + c
;
593 fprintf(stderr
, "arp: invalid SANA-II address '%s'\n", str
);