]>
git.saurik.com Git - apple/network_cmds.git/blob - route.tproj/route.c
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) 1983, 1989, 1991, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 static const char copyright
[] =
59 "@(#) Copyright (c) 1983, 1989, 1991, 1993\n\
60 The Regents of the University of California. All rights reserved.\n";
65 static char sccsid
[] = "@(#)route.c 8.3 (Berkeley) 3/19/94";
67 static const char rcsid
[] =
68 "$Id: route.c,v 1.2 2002/03/05 20:35:16 lindak Exp $";
71 #include <sys/param.h>
73 #include <sys/socket.h>
74 #include <sys/ioctl.h>
75 #include <sys/sysctl.h>
76 #include <sys/types.h>
79 #include <net/route.h>
80 #include <net/if_dl.h>
81 #include <netinet/in.h>
83 #include <netatalk/at.h>
88 #include <arpa/inet.h>
106 #include "keywords.h"
110 struct ortentry route
;
113 struct sockaddr_in sin
;
115 struct sockaddr_in6 sin6
;
118 struct sockaddr_at sat
;
121 struct sockaddr_ns sns
;
123 struct sockaddr_dl sdl
;
124 struct sockaddr_storage ss
; /* added to avoid memory overrun */
125 } so_dst
, so_gate
, so_mask
, so_genmask
, so_ifa
, so_ifp
;
127 typedef union sockunion
*sup
;
128 int pid
, rtm_addrs
, uid
;
130 int forcehost
, forcenet
, doflush
, nflag
, af
, qflag
, tflag
, keyword();
131 int iflag
, verbose
, aflen
= sizeof (struct sockaddr_in
);
132 int locking
, lockrest
, debugonly
;
133 struct rt_metrics rt_metrics
;
136 int atalk_aton
__P((const char *, struct at_addr
*));
137 char *atalk_ntoa
__P((struct at_addr
));
139 const char *routename(), *netname();
140 void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
141 void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
142 int getaddr(), rtmsg(), x25_makemask();
144 extern char *iso_ntoa();
146 void usage
__P((const char *));
153 warnx("bad keyword: %s", cp
);
154 (void) fprintf(stderr
,
155 "usage: route [-dnqtv] command [[modifiers] args]\n");
161 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
162 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
174 while ((ch
= getopt(argc
, argv
, "nqdtv")) != -1)
201 s
= open(_PATH_DEVNULL
, O_WRONLY
, 0);
203 s
= socket(PF_ROUTE
, SOCK_RAW
, 0);
205 err(EX_OSERR
, "socket");
208 switch (keyword(*argv
)) {
216 newroute(argc
, argv
);
225 flushroutes(argc
, argv
);
234 * Purge all entries in the routing tables not
235 * associated with network interfaces.
238 flushroutes(argc
, argv
)
243 int mib
[6], rlen
, seqno
;
244 char *buf
, *next
, *lim
;
245 register struct rt_msghdr
*rtm
;
248 errx(EX_NOPERM
, "must be root to alter routing table");
250 shutdown(s
, 0); /* Don't want to read back our messages */
253 if (argc
== 2 && **argv
== '-')
254 switch (keyword(*argv
+ 1)) {
283 mib
[2] = 0; /* protocol */
284 mib
[3] = 0; /* wildcard address family */
285 mib
[4] = NET_RT_DUMP
;
286 mib
[5] = 0; /* no flags */
287 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
288 err(EX_OSERR
, "route-sysctl-estimate");
289 if ((buf
= malloc(needed
)) == NULL
)
290 errx(EX_OSERR
, "malloc failed");
291 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
292 err(EX_OSERR
, "route-sysctl-get");
295 (void) printf("Examining routing table from sysctl\n");
297 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
298 rtm
= (struct rt_msghdr
*)next
;
300 print_rtmsg(rtm
, rtm
->rtm_msglen
);
301 if ((rtm
->rtm_flags
& RTF_GATEWAY
) == 0)
304 struct sockaddr
*sa
= (struct sockaddr
*)(rtm
+ 1);
306 if (sa
->sa_family
!= af
)
311 rtm
->rtm_type
= RTM_DELETE
;
312 rtm
->rtm_seq
= seqno
;
313 rlen
= write(s
, next
, rtm
->rtm_msglen
);
314 if (rlen
< (int)rtm
->rtm_msglen
) {
315 warn("write to routing socket");
316 (void) printf("got only %d for rlen\n", rlen
);
323 print_rtmsg(rtm
, rlen
);
325 struct sockaddr
*sa
= (struct sockaddr
*)(rtm
+ 1);
326 (void) printf("%-20.20s ", rtm
->rtm_flags
& RTF_HOST
?
327 routename(sa
) : netname(sa
));
328 sa
= (struct sockaddr
*)(ROUNDUP(sa
->sa_len
) + (char *)sa
);
329 (void) printf("%-20.20s ", routename(sa
));
330 (void) printf("done\n");
340 static char line
[MAXHOSTNAMELEN
+ 1];
342 static char domain
[MAXHOSTNAMELEN
+ 1];
343 static int first
= 1;
350 if (gethostname(domain
, MAXHOSTNAMELEN
) == 0 &&
351 (cp
= index(domain
, '.'))) {
352 domain
[MAXHOSTNAMELEN
] = '\0';
353 (void) strcpy(domain
, cp
+ 1);
359 strcpy(line
, "default");
360 else switch (sa
->sa_family
) {
364 in
= ((struct sockaddr_in
*)sa
)->sin_addr
;
367 if (in
.s_addr
== INADDR_ANY
|| sa
->sa_len
< 4)
369 if (cp
== 0 && !nflag
) {
370 hp
= gethostbyaddr((char *)&in
, sizeof (struct in_addr
),
373 if ((cp
= index(hp
->h_name
, '.')) &&
374 !strcmp(cp
+ 1, domain
))
380 strncpy(line
, cp
, sizeof(line
) - 1);
381 line
[sizeof(line
) - 1] = '\0';
383 /* XXX - why not inet_ntoa()? */
384 #define C(x) (unsigned)((x) & 0xff)
385 in
.s_addr
= ntohl(in
.s_addr
);
386 (void) sprintf(line
, "%u.%u.%u.%u", C(in
.s_addr
>> 24),
387 C(in
.s_addr
>> 16), C(in
.s_addr
>> 8), C(in
.s_addr
));
395 struct sockaddr_in6 sin6
; /* use static var for safety */
397 #ifdef NI_WITHSCOPEID
398 niflags
= NI_WITHSCOPEID
;
401 memset(&sin6
, 0, sizeof(sin6
));
402 memcpy(&sin6
, sa
, sa
->sa_len
);
403 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
404 sin6
.sin6_family
= AF_INET6
;
406 if (sa
->sa_len
== sizeof(struct sockaddr_in6
) &&
407 (IN6_IS_ADDR_LINKLOCAL(&sin6
.sin6_addr
) ||
408 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
)) &&
409 sin6
.sin6_scope_id
== 0) {
411 ntohs(*(u_int16_t
*)&sin6
.sin6_addr
.s6_addr
[2]);
412 sin6
.sin6_addr
.s6_addr
[2] = 0;
413 sin6
.sin6_addr
.s6_addr
[3] = 0;
417 niflags
|= NI_NUMERICHOST
;
418 if (getnameinfo((struct sockaddr
*)&sin6
, sin6
.sin6_len
,
419 line
, sizeof(line
), NULL
, 0, niflags
) != 0)
420 strncpy(line
, "invalid", sizeof(line
));
427 (void) snprintf(line
, sizeof(line
), "atalk %s",
428 atalk_ntoa(((struct sockaddr_at
*)sa
)->sat_addr
));
434 return (ns_print((struct sockaddr_ns
*)sa
));
438 return (link_ntoa((struct sockaddr_dl
*)sa
));
441 { u_short
*s
= (u_short
*)sa
;
442 u_short
*slim
= s
+ ((sa
->sa_len
+ 1) >> 1);
443 char *cp
= line
+ sprintf(line
, "(%d)", sa
->sa_family
);
444 char *cpe
= line
+ sizeof(line
);
446 while (++s
< slim
&& cp
< cpe
) /* start with sa->sa_data */
447 cp
+= snprintf(cp
, cpe
- cp
, " %x", *s
);
455 * Return the name of the network whose address is given.
456 * The address is assumed to be that of a net or subnet, not a host.
463 static char line
[MAXHOSTNAMELEN
+ 1];
464 struct netent
*np
= 0;
472 switch (sa
->sa_family
) {
476 in
= ((struct sockaddr_in
*)sa
)->sin_addr
;
478 i
= in
.s_addr
= ntohl(in
.s_addr
);
483 mask
= IN_CLASSA_NET
;
485 } else if (IN_CLASSB(i
)) {
486 mask
= IN_CLASSB_NET
;
489 mask
= IN_CLASSC_NET
;
493 * If there are more bits than the standard mask
494 * would suggest, subnets must be in use.
495 * Guess at the subnet mask, assuming reasonable
496 * width subnet fields.
498 while (in
.s_addr
&~ mask
)
499 mask
= (long)mask
>> subnetshift
;
500 net
= in
.s_addr
& mask
;
501 while ((mask
& 1) == 0)
502 mask
>>= 1, net
>>= 1;
503 np
= getnetbyaddr(net
, AF_INET
);
508 strncpy(line
, cp
, sizeof(line
));
509 else if ((in
.s_addr
& 0xffffff) == 0)
510 (void) sprintf(line
, "%u", C(in
.s_addr
>> 24));
511 else if ((in
.s_addr
& 0xffff) == 0)
512 (void) sprintf(line
, "%u.%u", C(in
.s_addr
>> 24),
514 else if ((in
.s_addr
& 0xff) == 0)
515 (void) sprintf(line
, "%u.%u.%u", C(in
.s_addr
>> 24),
516 C(in
.s_addr
>> 16), C(in
.s_addr
>> 8));
518 (void) sprintf(line
, "%u.%u.%u.%u", C(in
.s_addr
>> 24),
519 C(in
.s_addr
>> 16), C(in
.s_addr
>> 8),
527 struct sockaddr_in6 sin6
; /* use static var for safety */
529 #ifdef NI_WITHSCOPEID
530 niflags
= NI_WITHSCOPEID
;
533 memset(&sin6
, 0, sizeof(sin6
));
534 memcpy(&sin6
, sa
, sa
->sa_len
);
535 sin6
.sin6_len
= sizeof(struct sockaddr_in6
);
536 sin6
.sin6_family
= AF_INET6
;
538 if (sa
->sa_len
== sizeof(struct sockaddr_in6
) &&
539 (IN6_IS_ADDR_LINKLOCAL(&sin6
.sin6_addr
) ||
540 IN6_IS_ADDR_MC_LINKLOCAL(&sin6
.sin6_addr
)) &&
541 sin6
.sin6_scope_id
== 0) {
543 ntohs(*(u_int16_t
*)&sin6
.sin6_addr
.s6_addr
[2]);
544 sin6
.sin6_addr
.s6_addr
[2] = 0;
545 sin6
.sin6_addr
.s6_addr
[3] = 0;
549 niflags
|= NI_NUMERICHOST
;
550 if (getnameinfo((struct sockaddr
*)&sin6
, sin6
.sin6_len
,
551 line
, sizeof(line
), NULL
, 0, niflags
) != 0)
552 strncpy(line
, "invalid", sizeof(line
));
560 (void) snprintf(line
, sizeof(line
), "atalk %s",
561 atalk_ntoa(((struct sockaddr_at
*)sa
)->sat_addr
));
567 return (ns_print((struct sockaddr_ns
*)sa
));
572 return (link_ntoa((struct sockaddr_dl
*)sa
));
576 { u_short
*s
= (u_short
*)sa
->sa_data
;
577 u_short
*slim
= s
+ ((sa
->sa_len
+ 1)>>1);
578 char *cp
= line
+ sprintf(line
, "af %d:", sa
->sa_family
);
579 char *cpe
= line
+ sizeof(line
);
581 while (s
< slim
&& cp
< cpe
)
582 cp
+= snprintf(cp
, cpe
- cp
, " %x", *s
++);
590 set_metric(value
, key
)
595 u_long noval
, *valp
= &noval
;
598 #define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break
599 caseof(K_MTU
, RTV_MTU
, rmx_mtu
);
600 caseof(K_HOPCOUNT
, RTV_HOPCOUNT
, rmx_hopcount
);
601 caseof(K_EXPIRE
, RTV_EXPIRE
, rmx_expire
);
602 caseof(K_RECVPIPE
, RTV_RPIPE
, rmx_recvpipe
);
603 caseof(K_SENDPIPE
, RTV_SPIPE
, rmx_sendpipe
);
604 caseof(K_SSTHRESH
, RTV_SSTHRESH
, rmx_ssthresh
);
605 caseof(K_RTT
, RTV_RTT
, rmx_rtt
);
606 caseof(K_RTTVAR
, RTV_RTTVAR
, rmx_rttvar
);
609 if (lockrest
|| locking
)
610 rt_metrics
.rmx_locks
|= flag
;
619 register char **argv
;
621 char *cmd
, *dest
= "", *gateway
= "", *err
;
622 int ishost
= 0, ret
, attempts
, oerrno
, flags
= RTF_STATIC
;
624 struct hostent
*hp
= 0;
627 errx(EX_NOPERM
, "must be root to alter routing table");
631 shutdown(s
, 0); /* Don't want to read back our messages */
633 if (**(++argv
)== '-') {
634 switch (key
= keyword(1 + *argv
)) {
637 aflen
= sizeof(struct sockaddr_dl
);
641 aflen
= sizeof(struct sockaddr_in
);
646 aflen
= sizeof(struct sockaddr_in6
);
652 aflen
= sizeof(struct sockaddr_at
);
657 aflen
= sizeof(union sockunion
);
662 aflen
= sizeof(struct sockaddr_ns
);
670 flags
&= ~RTF_STATIC
;
688 flags
|= RTF_BLACKHOLE
;
697 flags
|= RTF_CLONING
;
700 flags
|= RTF_XRESOLVE
;
708 (void) getaddr(RTA_IFA
, *++argv
, 0);
713 (void) getaddr(RTA_IFP
, *++argv
, 0);
718 (void) getaddr(RTA_GENMASK
, *++argv
, 0);
723 (void) getaddr(RTA_GATEWAY
, *++argv
, 0);
728 ishost
= getaddr(RTA_DST
, *++argv
, &hp
);
734 (void) getaddr(RTA_NETMASK
, *++argv
, 0);
742 if (prefixlen(*++argv
) == -1) {
760 set_metric(*++argv
, key
);
766 if ((rtm_addrs
& RTA_DST
) == 0) {
768 ishost
= getaddr(RTA_DST
, *argv
, &hp
);
769 } else if ((rtm_addrs
& RTA_GATEWAY
) == 0) {
771 (void) getaddr(RTA_GATEWAY
, *argv
, &hp
);
773 (void) getaddr(RTA_NETMASK
, *argv
, 0);
780 if (af
== AF_INET6
) {
781 rtm_addrs
&= ~RTA_NETMASK
;
782 memset((void *)&so_mask
, 0, sizeof(so_mask
));
792 flags
|= RTF_GATEWAY
;
793 for (attempts
= 1; ; attempts
++) {
795 if ((ret
= rtmsg(*cmd
, flags
)) == 0)
797 if (errno
!= ENETUNREACH
&& errno
!= ESRCH
)
799 if (af
== AF_INET
&& *gateway
&& hp
&& hp
->h_addr_list
[1]) {
801 bcopy(hp
->h_addr_list
[0], &so_gate
.sin
.sin_addr
,
802 MIN(hp
->h_length
, sizeof(so_gate
.sin
.sin_addr
)));
809 (void) printf("%s %s %s", cmd
, ishost
? "host" : "net", dest
);
811 (void) printf(": gateway %s", gateway
);
812 if (attempts
> 1 && ret
== 0 && af
== AF_INET
)
813 (void) printf(" (%s)",
814 inet_ntoa(((struct sockaddr_in
*)&route
.rt_gateway
)->sin_addr
));
821 err
= "not in table";
824 err
= "entry in use";
827 err
= "routing table overflow";
830 err
= strerror(oerrno
);
833 (void) printf(": %s\n", err
);
838 inet_makenetandmask(net
, sin
, bits
)
840 register struct sockaddr_in
*sin
;
842 u_long addr
, mask
= 0;
845 rtm_addrs
|= RTA_NETMASK
;
848 mask
= 0xffffffff << (32 - bits
);
851 else if (net
< 128) {
852 addr
= net
<< IN_CLASSA_NSHIFT
;
853 mask
= IN_CLASSA_NET
;
854 } else if (net
< 65536) {
855 addr
= net
<< IN_CLASSB_NSHIFT
;
856 mask
= IN_CLASSB_NET
;
857 } else if (net
< 16777216L) {
858 addr
= net
<< IN_CLASSC_NSHIFT
;
859 mask
= IN_CLASSC_NET
;
862 if ((addr
& IN_CLASSA_HOST
) == 0)
863 mask
= IN_CLASSA_NET
;
864 else if ((addr
& IN_CLASSB_HOST
) == 0)
865 mask
= IN_CLASSB_NET
;
866 else if ((addr
& IN_CLASSC_HOST
) == 0)
867 mask
= IN_CLASSC_NET
;
871 sin
->sin_addr
.s_addr
= htonl(addr
);
873 sin
->sin_addr
.s_addr
= htonl(mask
);
876 cp
= (char *)(&sin
->sin_addr
+ 1);
877 while (*--cp
== 0 && cp
> (char *)sin
)
879 sin
->sin_len
= 1 + cp
- (char *)sin
;
883 * Interpret an argument as a network address of some kind,
884 * returning 1 if a host address, 0 if a network address.
887 getaddr(which
, s
, hpp
)
890 struct hostent
**hpp
;
897 int afamily
; /* local copy of af so we can change it */
901 aflen
= sizeof(struct sockaddr_in
);
912 struct ifaddrs
*ifap
, *ifa
;
913 struct sockaddr_dl
*sdl
= NULL
;
915 if (getifaddrs(&ifap
))
916 err(1, "getifaddrs");
918 for (ifa
= ifap
; ifa
; ifa
= ifa
->ifa_next
) {
919 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
)
922 if (strcmp(s
, ifa
->ifa_name
))
925 sdl
= (struct sockaddr_dl
*)ifa
->ifa_addr
;
927 /* If we found it, then use it */
930 * Copy is safe since we have a
931 * sockaddr_storage member in sockunion{}.
932 * Note that we need to copy before calling
935 memcpy(&su
->sdl
, sdl
, sdl
->sdl_len
);
956 usage("internal error");
959 su
->sa
.sa_len
= aflen
;
960 su
->sa
.sa_family
= afamily
; /* cases that don't want it have left already */
961 if (strcmp(s
, "default") == 0) {
963 * Default is net 0.0.0.0/0
968 /* bzero(su, sizeof(*su)); *//* for readability */
969 (void) getaddr(RTA_NETMASK
, s
, 0);
973 /* bzero(su, sizeof(*su)); *//* for readability */
982 struct addrinfo hints
, *res
;
984 memset(&hints
, 0, sizeof(hints
));
985 hints
.ai_family
= afamily
; /*AF_INET6*/
986 hints
.ai_flags
= AI_NUMERICHOST
;
987 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
988 if (getaddrinfo(s
, "0", &hints
, &res
) != 0 ||
989 res
->ai_family
!= AF_INET6
||
990 res
->ai_addrlen
!= sizeof(su
->sin6
)) {
991 (void) fprintf(stderr
, "%s: bad value\n", s
);
994 memcpy(&su
->sin6
, res
->ai_addr
, sizeof(su
->sin6
));
996 if ((IN6_IS_ADDR_LINKLOCAL(&su
->sin6
.sin6_addr
) ||
997 IN6_IS_ADDR_LINKLOCAL(&su
->sin6
.sin6_addr
)) &&
998 su
->sin6
.sin6_scope_id
) {
999 *(u_int16_t
*)&su
->sin6
.sin6_addr
.s6_addr
[2] =
1000 htons(su
->sin6
.sin6_scope_id
);
1001 su
->sin6
.sin6_scope_id
= 0;
1011 if (which
== RTA_DST
) {
1012 extern short ns_bh
[3];
1013 struct sockaddr_ns
*sms
= &(so_mask
.sns
);
1014 bzero((char *)sms
, sizeof(*sms
));
1015 sms
->sns_family
= 0;
1017 sms
->sns_addr
.x_net
= *(union ns_net
*)ns_bh
;
1018 rtm_addrs
|= RTA_NETMASK
;
1020 su
->sns
.sns_addr
= ns_addr(s
);
1021 return (!ns_nullhost(su
->sns
.sns_addr
));
1027 if (!atalk_aton(s
, &su
->sat
.sat_addr
))
1028 errx(EX_NOHOST
, "bad address: %s", s
);
1029 rtm_addrs
|= RTA_NETMASK
;
1030 return(forcehost
|| su
->sat
.sat_addr
.s_node
!= 0);
1034 link_addr(s
, &su
->sdl
);
1039 su
->sa
.sa_len
= sizeof(*su
);
1040 sockaddr(s
, &su
->sa
);
1053 if (q
&& which
== RTA_DST
) {
1055 if ((val
= inet_addr(s
)) != INADDR_NONE
) {
1056 inet_makenetandmask(
1057 ntohl(val
), &su
->sin
, strtoul(q
+1, 0, 0));
1062 if ((which
!= RTA_DST
|| forcenet
== 0) &&
1063 (val
= inet_addr(s
)) != INADDR_NONE
) {
1064 su
->sin
.sin_addr
.s_addr
= val
;
1065 if (which
!= RTA_DST
||
1066 inet_lnaof(su
->sin
.sin_addr
) != INADDR_ANY
)
1073 if (which
== RTA_DST
&& forcehost
== 0 &&
1074 ((val
= inet_network(s
)) != INADDR_NONE
||
1075 ((np
= getnetbyname(s
)) != NULL
&& (val
= np
->n_net
) != 0))) {
1077 inet_makenetandmask(val
, &su
->sin
, 0);
1080 hp
= gethostbyname(s
);
1083 su
->sin
.sin_family
= hp
->h_addrtype
;
1084 bcopy(hp
->h_addr
, (char *)&su
->sin
.sin_addr
,
1085 MIN(hp
->h_length
, sizeof(su
->sin
.sin_addr
)));
1088 errx(EX_NOHOST
, "bad address: %s", s
);
1095 int len
= atoi(s
), q
, r
;
1099 rtm_addrs
|= RTA_NETMASK
;
1104 p
= (char *)&so_mask
.sin6
.sin6_addr
;
1109 p
= (char *)&so_mask
.sin
.sin_addr
;
1112 (void) fprintf(stderr
, "prefixlen not supported in this af\n");
1117 if (len
< 0 || max
< len
) {
1118 (void) fprintf(stderr
, "%s: bad value\n", s
);
1124 so_mask
.sa
.sa_family
= af
;
1125 so_mask
.sa
.sa_len
= aflen
;
1126 memset((void *)p
, 0, max
/ 8);
1128 memset((void *)p
, 0xff, q
);
1130 *((u_char
*)p
+ q
) = (0xff00 >> r
) & 0xff;
1138 short ns_nullh
[] = {0,0,0};
1139 short ns_bh
[] = {-1,-1,-1};
1143 struct sockaddr_ns
*sns
;
1145 struct ns_addr work
;
1146 union { union ns_net net_e
; u_long long_e
; } net
;
1148 static char mybuf
[50+MAXHOSTNAMELEN
], cport
[10], chost
[25];
1153 work
= sns
->sns_addr
;
1154 port
= ntohs(work
.x_port
);
1156 net
.net_e
= work
.x_net
;
1157 if (ns_nullhost(work
) && net
.long_e
== 0) {
1160 (void) sprintf(mybuf
, "*.%XH", port
);
1164 if (bcmp((char *)ns_bh
, (char *)work
.x_host
.c_host
, 6) == 0)
1166 else if (bcmp((char *)ns_nullh
, (char *)work
.x_host
.c_host
, 6) == 0)
1169 q
= work
.x_host
.c_host
;
1170 (void) sprintf(chost
, "%02X%02X%02X%02X%02X%02XH",
1171 q
[0], q
[1], q
[2], q
[3], q
[4], q
[5]);
1172 for (p
= chost
; *p
== '0' && p
< chost
+ 12; p
++)
1177 (void) sprintf(cport
, ".%XH", htons(port
));
1181 (void) snprintf(mybuf
, sizeof(mybuf
), "%lxH.%s%s",
1182 (unsigned long)ntohl(net
.long_e
),
1193 char *buf
, *lim
, *next
;
1194 register struct rt_msghdr
*rtm
;
1198 mib
[2] = 0; /* protocol */
1199 mib
[3] = 0; /* wildcard address family */
1200 mib
[4] = NET_RT_IFLIST
;
1201 mib
[5] = 0; /* no flags */
1202 if (sysctl(mib
, 6, NULL
, &needed
, NULL
, 0) < 0)
1203 err(EX_OSERR
, "route-sysctl-estimate");
1204 if ((buf
= malloc(needed
)) == NULL
)
1205 errx(EX_OSERR
, "malloc failed");
1206 if (sysctl(mib
, 6, buf
, &needed
, NULL
, 0) < 0)
1207 err(EX_OSERR
, "actual retrieval of interface table");
1209 for (next
= buf
; next
< lim
; next
+= rtm
->rtm_msglen
) {
1210 rtm
= (struct rt_msghdr
*)next
;
1211 print_rtmsg(rtm
, rtm
->rtm_msglen
);
1228 n
= read(s
, msg
, 2048);
1230 (void) printf("\ngot message of size %d on %s", n
, ctime(&now
));
1231 print_rtmsg((struct rt_msghdr
*)msg
, n
);
1236 struct rt_msghdr m_rtm
;
1246 register char *cp
= m_rtmsg
.m_space
;
1249 #define NEXTADDR(w, u) \
1250 if (rtm_addrs & (w)) {\
1251 l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
1252 if (verbose) sodump(&(u),"u");\
1256 bzero((char *)&m_rtmsg
, sizeof(m_rtmsg
));
1259 else if (cmd
== 'c')
1261 else if (cmd
== 'g') {
1263 if (so_ifp
.sa
.sa_family
== 0) {
1264 so_ifp
.sa
.sa_family
= AF_LINK
;
1265 so_ifp
.sa
.sa_len
= sizeof(struct sockaddr_dl
);
1266 rtm_addrs
|= RTA_IFP
;
1270 #define rtm m_rtmsg.m_rtm
1272 rtm
.rtm_flags
= flags
;
1273 rtm
.rtm_version
= RTM_VERSION
;
1274 rtm
.rtm_seq
= ++seq
;
1275 rtm
.rtm_addrs
= rtm_addrs
;
1276 rtm
.rtm_rmx
= rt_metrics
;
1277 rtm
.rtm_inits
= rtm_inits
;
1279 if (rtm_addrs
& RTA_NETMASK
)
1281 NEXTADDR(RTA_DST
, so_dst
);
1282 NEXTADDR(RTA_GATEWAY
, so_gate
);
1283 NEXTADDR(RTA_NETMASK
, so_mask
);
1284 NEXTADDR(RTA_GENMASK
, so_genmask
);
1285 NEXTADDR(RTA_IFP
, so_ifp
);
1286 NEXTADDR(RTA_IFA
, so_ifa
);
1287 rtm
.rtm_msglen
= l
= cp
- (char *)&m_rtmsg
;
1289 print_rtmsg(&rtm
, l
);
1292 if ((rlen
= write(s
, (char *)&m_rtmsg
, l
)) < 0) {
1293 warn("writing to routing socket");
1296 if (cmd
== RTM_GET
) {
1298 l
= read(s
, (char *)&m_rtmsg
, sizeof(m_rtmsg
));
1299 } while (l
> 0 && (rtm
.rtm_seq
!= seq
|| rtm
.rtm_pid
!= pid
));
1301 warn("read from routing socket");
1303 print_getmsg(&rtm
, l
);
1312 int olen
= so_mask
.sa
.sa_len
;
1313 register char *cp1
= olen
+ (char *)&so_mask
, *cp2
;
1315 for (so_mask
.sa
.sa_len
= 0; cp1
> (char *)&so_mask
; )
1317 so_mask
.sa
.sa_len
= 1 + cp1
- (char *)&so_mask
;
1320 if ((rtm_addrs
& RTA_DST
) == 0)
1322 switch (so_dst
.sa
.sa_family
) {
1334 cp1
= so_mask
.sa
.sa_len
+ 1 + (char *)&so_dst
;
1335 cp2
= so_dst
.sa
.sa_len
+ 1 + (char *)&so_dst
;
1338 cp2
= so_mask
.sa
.sa_len
+ 1 + (char *)&so_mask
;
1339 while (cp1
> so_dst
.sa
.sa_data
)
1343 char *msgtypes
[] = {
1345 "RTM_ADD: Add Route",
1346 "RTM_DELETE: Delete Route",
1347 "RTM_CHANGE: Change Metrics or flags",
1348 "RTM_GET: Report Metrics",
1349 "RTM_LOSING: Kernel Suspects Partitioning",
1350 "RTM_REDIRECT: Told to use different route",
1351 "RTM_MISS: Lookup failed on this address",
1352 "RTM_LOCK: fix specified metrics",
1353 "RTM_OLDADD: caused by SIOCADDRT",
1354 "RTM_OLDDEL: caused by SIOCDELRT",
1355 "RTM_RESOLVE: Route created by cloning",
1356 "RTM_NEWADDR: address being added to iface",
1357 "RTM_DELADDR: address being removed from iface",
1358 "RTM_IFINFO: iface status change",
1359 "RTM_NEWMADDR: new multicast group membership on iface",
1360 "RTM_DELMADDR: multicast group membership removed from iface",
1364 char metricnames
[] =
1365 "\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount"
1368 "\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT"
1369 "\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016"
1370 "\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024CHAINDELETE"
1371 "\025PINNED\026LOCAL\027BROADCAST\030MULTICAST";
1373 "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
1374 "\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
1375 "\017LINK2\020MULTICAST";
1377 "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
1380 print_rtmsg(rtm
, msglen
)
1381 register struct rt_msghdr
*rtm
;
1384 struct if_msghdr
*ifm
;
1385 struct ifa_msghdr
*ifam
;
1387 struct ifma_msghdr
*ifmam
;
1392 if (rtm
->rtm_version
!= RTM_VERSION
) {
1393 (void) printf("routing message version %d not understood\n",
1397 (void)printf("%s: len %d, ", msgtypes
[rtm
->rtm_type
], rtm
->rtm_msglen
);
1398 switch (rtm
->rtm_type
) {
1400 ifm
= (struct if_msghdr
*)rtm
;
1401 (void) printf("if# %d, flags:", ifm
->ifm_index
);
1402 bprintf(stdout
, ifm
->ifm_flags
, ifnetflags
);
1403 pmsg_addrs((char *)(ifm
+ 1), ifm
->ifm_addrs
);
1407 ifam
= (struct ifa_msghdr
*)rtm
;
1408 (void) printf("metric %d, flags:", ifam
->ifam_metric
);
1409 bprintf(stdout
, ifam
->ifam_flags
, routeflags
);
1410 pmsg_addrs((char *)(ifam
+ 1), ifam
->ifam_addrs
);
1415 ifmam
= (struct ifma_msghdr
*)rtm
;
1416 pmsg_addrs((char *)(ifmam
+ 1), ifmam
->ifmam_addrs
);
1420 (void) printf("pid: %ld, seq %d, errno %d, flags:",
1421 (long)rtm
->rtm_pid
, rtm
->rtm_seq
, rtm
->rtm_errno
);
1422 bprintf(stdout
, rtm
->rtm_flags
, routeflags
);
1428 print_getmsg(rtm
, msglen
)
1429 register struct rt_msghdr
*rtm
;
1432 struct sockaddr
*dst
= NULL
, *gate
= NULL
, *mask
= NULL
;
1433 struct sockaddr_dl
*ifp
= NULL
;
1434 register struct sockaddr
*sa
;
1438 (void) printf(" route to: %s\n", routename(&so_dst
));
1439 if (rtm
->rtm_version
!= RTM_VERSION
) {
1440 warnx("routing message version %d not understood",
1444 if (rtm
->rtm_msglen
> msglen
) {
1445 warnx("message length mismatch, in packet %d, returned %d",
1446 rtm
->rtm_msglen
, msglen
);
1448 if (rtm
->rtm_errno
) {
1449 errno
= rtm
->rtm_errno
;
1450 warn("message indicates error %d", errno
);
1453 cp
= ((char *)(rtm
+ 1));
1455 for (i
= 1; i
; i
<<= 1)
1456 if (i
& rtm
->rtm_addrs
) {
1457 sa
= (struct sockaddr
*)cp
;
1469 if (sa
->sa_family
== AF_LINK
&&
1470 ((struct sockaddr_dl
*)sa
)->sdl_nlen
)
1471 ifp
= (struct sockaddr_dl
*)sa
;
1477 mask
->sa_family
= dst
->sa_family
; /* XXX */
1479 (void)printf("destination: %s\n", routename(dst
));
1481 int savenflag
= nflag
;
1484 (void)printf(" mask: %s\n", routename(mask
));
1487 if (gate
&& rtm
->rtm_flags
& RTF_GATEWAY
)
1488 (void)printf(" gateway: %s\n", routename(gate
));
1490 (void)printf(" interface: %.*s\n",
1491 ifp
->sdl_nlen
, ifp
->sdl_data
);
1492 (void)printf(" flags: ");
1493 bprintf(stdout
, rtm
->rtm_flags
, routeflags
);
1495 #define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ')
1496 #define msec(u) (((u) + 500) / 1000) /* usec to msec */
1498 (void) printf("\n%s\n", "\
1499 recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire");
1500 printf("%8ld%c ", rtm
->rtm_rmx
.rmx_recvpipe
, lock(RPIPE
));
1501 printf("%8ld%c ", rtm
->rtm_rmx
.rmx_sendpipe
, lock(SPIPE
));
1502 printf("%8ld%c ", rtm
->rtm_rmx
.rmx_ssthresh
, lock(SSTHRESH
));
1503 printf("%8ld%c ", msec(rtm
->rtm_rmx
.rmx_rtt
), lock(RTT
));
1504 printf("%8ld%c ", msec(rtm
->rtm_rmx
.rmx_rttvar
), lock(RTTVAR
));
1505 printf("%8ld%c ", rtm
->rtm_rmx
.rmx_hopcount
, lock(HOPCOUNT
));
1506 printf("%8ld%c ", rtm
->rtm_rmx
.rmx_mtu
, lock(MTU
));
1507 if (rtm
->rtm_rmx
.rmx_expire
)
1508 rtm
->rtm_rmx
.rmx_expire
-= time(0);
1509 printf("%8ld%c\n", rtm
->rtm_rmx
.rmx_expire
, lock(EXPIRE
));
1512 #define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
1515 else if (rtm
->rtm_addrs
&~ RTA_IGN
) {
1516 (void) printf("sockaddrs: ");
1517 bprintf(stdout
, rtm
->rtm_addrs
, addrnames
);
1525 register struct rt_msghdr
*rtm
;
1527 (void) printf("\nlocks: ");
1528 bprintf(stdout
, rtm
->rtm_rmx
.rmx_locks
, metricnames
);
1529 (void) printf(" inits: ");
1530 bprintf(stdout
, rtm
->rtm_inits
, metricnames
);
1531 pmsg_addrs(((char *)(rtm
+ 1)), rtm
->rtm_addrs
);
1535 pmsg_addrs(cp
, addrs
)
1539 register struct sockaddr
*sa
;
1543 (void) putchar('\n');
1546 (void) printf("\nsockaddrs: ");
1547 bprintf(stdout
, addrs
, addrnames
);
1548 (void) putchar('\n');
1549 for (i
= 1; i
; i
<<= 1)
1551 sa
= (struct sockaddr
*)cp
;
1552 (void) printf(" %s", routename(sa
));
1555 (void) putchar('\n');
1556 (void) fflush(stdout
);
1570 while ((i
= *s
++) != 0) {
1571 if (b
& (1 << (i
-1))) {
1578 for (; (i
= *s
) > 32; s
++)
1585 (void) putc('>', fp
);
1592 register struct keytab
*kt
= keywords
;
1594 while (kt
->kt_cp
&& strcmp(kt
->kt_cp
, cp
))
1604 switch (su
->sa
.sa_family
) {
1606 (void) printf("%s: link %s; ",
1607 which
, link_ntoa(&su
->sdl
));
1610 (void) printf("%s: inet %s; ",
1611 which
, inet_ntoa(su
->sin
.sin_addr
));
1615 (void) printf("%s: atalk %s; ",
1616 which
, atalk_ntoa(su
->sat
.sat_addr
));
1621 (void) printf("%s: xns %s; ",
1622 which
, ns_ntoa(su
->sns
.sns_addr
));
1626 (void) fflush(stdout
);
1640 register char *addr
;
1641 register struct sockaddr
*sa
;
1643 register char *cp
= (char *)sa
;
1644 int size
= sa
->sa_len
;
1645 char *cplim
= cp
+ size
;
1646 register int byte
= 0, state
= VIRGIN
, new = 0 /* foil gcc */;
1651 if ((*addr
>= '0') && (*addr
<= '9')) {
1653 } else if ((*addr
>= 'a') && (*addr
<= 'f')) {
1654 new = *addr
- 'a' + 10;
1655 } else if ((*addr
>= 'A') && (*addr
<= 'F')) {
1656 new = *addr
- 'A' + 10;
1657 } else if (*addr
== 0)
1662 switch (state
/* | INPUT */) {
1663 case GOTTWO
| DIGIT
:
1664 *cp
++ = byte
; /*FALLTHROUGH*/
1665 case VIRGIN
| DIGIT
:
1666 state
= GOTONE
; byte
= new; continue;
1667 case GOTONE
| DIGIT
:
1668 state
= GOTTWO
; byte
= new + (byte
<< 4); continue;
1669 default: /* | DELIM */
1670 state
= VIRGIN
; *cp
++ = byte
; byte
= 0; continue;
1673 *cp
++ = byte
; /* FALLTHROUGH */
1678 } while (cp
< cplim
);
1679 sa
->sa_len
= cp
- (char *)sa
;
1684 atalk_aton(const char *text
, struct at_addr
*addr
)
1688 if (sscanf(text
, "%u.%u", &net
, &node
) != 2
1689 || net
> 0xffff || node
> 0xff)
1691 addr
->s_net
= htons(net
);
1692 addr
->s_node
= node
;
1697 atalk_ntoa(struct at_addr at
)
1699 static char buf
[20];
1701 (void) snprintf(buf
, sizeof(buf
), "%u.%u", ntohs(at
.s_net
), at
.s_node
);