diff options
author | Cedric Berger <cedric@cvs.openbsd.org> | 2004-06-06 17:08:24 +0000 |
---|---|---|
committer | Cedric Berger <cedric@cvs.openbsd.org> | 2004-06-06 17:08:24 +0000 |
commit | 279617b781ec14108b2825952f7d1f0a5140a417 (patch) | |
tree | 6d25610a0394a8a636188a518848e623fdd436d1 /sbin/route | |
parent | 26988a280f12eb6b5489e79481d75404a5199fd3 (diff) |
add new "-src" and "-srcmask" modifiers to make it possible to add a source
selector part to the routing table entry. complements existing "-dst" and
"-dstmask". typical use:
route add -src 20.20.20.22 20.20.20.21
route add -src 192.168.1.0/24 -dst 192.168.2.0/24 20.20.20.21
useful for example to implement symetrical routing on multihomed boxes,
or to better select which packets to send to gif/tun/... tunnels.
new '-S' flag similar to netstat one. ok deraadt@ mcbride@
Diffstat (limited to 'sbin/route')
-rw-r--r-- | sbin/route/keywords.c | 4 | ||||
-rw-r--r-- | sbin/route/keywords.h | 14 | ||||
-rw-r--r-- | sbin/route/keywords.sh | 4 | ||||
-rw-r--r-- | sbin/route/route.8 | 38 | ||||
-rw-r--r-- | sbin/route/route.c | 126 | ||||
-rw-r--r-- | sbin/route/show.c | 47 |
6 files changed, 174 insertions, 59 deletions
diff --git a/sbin/route/keywords.c b/sbin/route/keywords.c index ba38d6ab288..eb6a73237db 100644 --- a/sbin/route/keywords.c +++ b/sbin/route/keywords.c @@ -1,4 +1,4 @@ -/* $OpenBSD: keywords.c,v 1.6 2000/07/27 20:12:24 angelos Exp $ */ +/* $OpenBSD: keywords.c,v 1.7 2004/06/06 17:08:23 cedric Exp $ */ /* WARNING! This file was generated by keywords.sh */ @@ -48,6 +48,8 @@ struct keytab keywords[] = { {"sa", K_SA}, {"sendpipe", K_SENDPIPE}, {"show", K_SHOW}, + {"src", K_SRC}, + {"srcmask", K_SRCMASK}, {"ssthresh", K_SSTHRESH}, {"static", K_STATIC}, {"x25", K_X25}, diff --git a/sbin/route/keywords.h b/sbin/route/keywords.h index 81c547bf986..2c2d9cdae8b 100644 --- a/sbin/route/keywords.h +++ b/sbin/route/keywords.h @@ -1,4 +1,4 @@ -/* $OpenBSD: keywords.h,v 1.6 2000/07/27 20:12:25 angelos Exp $ */ +/* $OpenBSD: keywords.h,v 1.7 2004/06/06 17:08:23 cedric Exp $ */ /* WARNING! This file was generated by keywords.sh */ @@ -50,8 +50,10 @@ extern struct keytab { #define K_SA 40 #define K_SENDPIPE 41 #define K_SHOW 42 -#define K_SSTHRESH 43 -#define K_STATIC 44 -#define K_X25 45 -#define K_XNS 46 -#define K_XRESOLVE 47 +#define K_SRC 43 +#define K_SRCMASK 44 +#define K_SSTHRESH 45 +#define K_STATIC 46 +#define K_X25 47 +#define K_XNS 48 +#define K_XRESOLVE 49 diff --git a/sbin/route/keywords.sh b/sbin/route/keywords.sh index c97c481abee..f79f7330a24 100644 --- a/sbin/route/keywords.sh +++ b/sbin/route/keywords.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $OpenBSD: keywords.sh,v 1.5 2000/07/27 20:12:25 angelos Exp $ +# $OpenBSD: keywords.sh,v 1.6 2004/06/06 17:08:23 cedric Exp $ # $NetBSD: keywords.sh,v 1.2 1996/11/15 18:57:21 gwr Exp $ # @(#)keywords 8.2 (Berkeley) 3/19/94 # @@ -51,6 +51,8 @@ rttvar sa sendpipe show +src +srcmask ssthresh static x25 diff --git a/sbin/route/route.8 b/sbin/route/route.8 index 1eae7b93d85..68f8587641b 100644 --- a/sbin/route/route.8 +++ b/sbin/route/route.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: route.8,v 1.30 2003/08/31 07:03:29 jmc Exp $ +.\" $OpenBSD: route.8,v 1.31 2004/06/06 17:08:23 cedric Exp $ .\" $NetBSD: route.8,v 1.6 1995/03/18 15:00:13 cgd Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 @@ -73,6 +73,10 @@ to forgo this, especially when attempting to repair networking operations.) (verbose) Print additional details. .It Fl q Suppress all output. +.It Fl S +Makes the +.Cm show +command display the source selector part of the routes. .El .Pp The @@ -270,6 +274,38 @@ specify that all ensuing metrics may be locked by the .Fl lockrest meta-modifier. .Pp +The +.Fl src +and +.Fl srcmask +modifiers can be used to specify the source selector of the route, +which will match the source IP address of outgoing packets. +.Fl src +and +.Fl srcmask +work in a similar way than +.Fl dst +and +.Fl netmask . +For example: +.Pp +.Bd -filled -offset indent -compact +.Nm route +.Cm add +.Fl src +180.83.46.98 +180.83.46.97 +.Ed +.Bd -filled -offset indent -compact +.Nm route +.Cm add +.Fl src +192.168.10.0/24 +.Fl dst +10.5.1.0/24 +180.83.46.97 +.Ed +.Pp In a .Cm change or diff --git a/sbin/route/route.c b/sbin/route/route.c index 9f0f0740f44..649dd964b14 100644 --- a/sbin/route/route.c +++ b/sbin/route/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.66 2004/05/15 07:43:34 claudio Exp $ */ +/* $OpenBSD: route.c,v 1.67 2004/06/06 17:08:23 cedric Exp $ */ /* $NetBSD: route.c,v 1.16 1996/04/15 18:27:05 cgd Exp $ */ /* @@ -40,7 +40,7 @@ static const char copyright[] = #if 0 static const char sccsid[] = "@(#)route.c 8.3 (Berkeley) 3/19/94"; #else -static const char rcsid[] = "$OpenBSD: route.c,v 1.66 2004/05/15 07:43:34 claudio Exp $"; +static const char rcsid[] = "$OpenBSD: route.c,v 1.67 2004/06/06 17:08:23 cedric Exp $"; #endif #endif /* not lint */ @@ -83,13 +83,14 @@ union sockunion { struct sockaddr_iso siso; struct sockaddr_dl sdl; struct sockaddr_x25 sx25; -} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; + struct sockaddr_rtin rtin; +} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, so_src, so_srcmask; typedef union sockunion *sup; pid_t pid; int rtm_addrs, s; int forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword(char *); -int iflag, verbose, aflen = sizeof (struct sockaddr_in); +int Sflag, iflag, verbose, aflen = sizeof (struct sockaddr_in); int locking, lockrest, debugonly; struct rt_metrics rt_metrics; u_long rtm_inits; @@ -108,7 +109,7 @@ void print_rtmsg(struct rt_msghdr *, int); void pmsg_common(struct rt_msghdr *); void pmsg_addrs(char *, int); void bprintf(FILE *, int, u_char *); -void mask_addr(void); +void mask_addr(union sockunion *, union sockunion *, int which); #ifdef INET6 static int inet6_makenetandmask(struct sockaddr_in6 *); #endif @@ -119,7 +120,8 @@ __dead void usage(char *cp); void quit(char *s); char *any_ntoa(const struct sockaddr *sa); void set_metric(char *value, int key); -void inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits); +void inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits, + int which); char *ns_print(struct sockaddr_ns *sns); char *ipx_print(struct sockaddr_ipx *sipx); void interfaces(void); @@ -132,7 +134,7 @@ usage(char *cp) if (cp) (void) fprintf(stderr, "route: botched keyword: %s\n", cp); (void) fprintf(stderr, - "usage: route [ -nqv ] cmd [[ -<modifiers> ] args ]\n"); + "usage: route [ -nqSv ] cmd [[ -<modifiers> ] args ]\n"); (void) fprintf(stderr, "keywords: get, add, change, delete, show, flush, monitor.\n"); exit(1); @@ -165,7 +167,7 @@ main(int argc, char **argv) if (argc < 2) usage(NULL); - while ((ch = getopt(argc, argv, "nqdtv")) != -1) + while ((ch = getopt(argc, argv, "nqdtvS")) != -1) switch(ch) { case 'n': nflag = 1; @@ -182,6 +184,9 @@ main(int argc, char **argv) case 'd': debugonly = 1; break; + case 'S': + Sflag = 1; + break; default: usage(NULL); } @@ -601,7 +606,7 @@ set_metric(char *value, int key) int newroute(int argc, char **argv) { - char *cmd, *dest = "", *gateway = "", *err; + char *cmd, *dest = "", *source = "", *gateway = "", *err; int ishost = 0, ret = 0, attempts, oerrno, flags = RTF_STATIC; int key; struct hostent *hp = 0; @@ -718,6 +723,17 @@ newroute(int argc, char **argv) ishost = getaddr(RTA_DST, *++argv, &hp); dest = *argv; break; + case K_SRC: + if (!--argc) + usage(1+*argv); + (void) getaddr(RTA_SRC, *++argv, 0); + source = *argv; + break; + case K_SRCMASK: + if (!--argc) + usage(1+*argv); + (void) getaddr(RTA_SRCMASK, *++argv, 0); + break; case K_NETMASK: if (!--argc) usage(1+*argv); @@ -747,7 +763,7 @@ newroute(int argc, char **argv) usage(1+*argv); } } else { - if ((rtm_addrs & RTA_DST) == 0) { + if ((rtm_addrs & (RTA_DST|RTA_SRC)) == 0) { dest = *argv; ishost = getaddr(RTA_DST, *argv, &hp); } else if ((rtm_addrs & RTA_GATEWAY) == 0) { @@ -786,6 +802,11 @@ newroute(int argc, char **argv) flags |= RTF_HOST; if (iflag == 0) flags |= RTF_GATEWAY; + if (rtm_addrs & (RTA_SRC|RTA_SRCMASK)) { + if (!(rtm_addrs & RTA_DST)) + getaddr(RTA_DST, "default", &hp); + flags |= RTF_SOURCE; + } for (attempts = 1; ; attempts++) { errno = 0; if ((ret = rtmsg(*cmd, flags)) == 0) @@ -804,6 +825,8 @@ newroute(int argc, char **argv) oerrno = errno; if (!qflag) { (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest); + if (*source) + (void) printf(": source %s", source); if (*gateway) { (void) printf(": gateway %s", gateway); if (attempts > 1 && ret == 0 && af == AF_INET) @@ -834,12 +857,12 @@ newroute(int argc, char **argv) } void -inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits) +inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits, int which) { u_int32_t addr, mask = 0; char *cp; - rtm_addrs |= RTA_NETMASK; + rtm_addrs |= (which == RTA_DST) ? RTA_NETMASK : RTA_SRCMASK; if (net == 0) mask = addr = 0; else if (bits) { @@ -866,7 +889,7 @@ inet_makenetandmask(u_int32_t net, struct sockaddr_in *sin, int bits) mask = -1; } sin->sin_addr.s_addr = htonl(addr); - sin = &so_mask.sin; + sin = (which == RTA_DST) ? &so_mask.sin : &so_srcmask.sin; sin->sin_addr.s_addr = htonl(mask); sin->sin_len = 0; sin->sin_family = 0; @@ -948,6 +971,12 @@ getaddr(int which, char *s, struct hostent **hpp) su = &so_ifa; su->sa.sa_family = af; break; + case RTA_SRC: + su = &so_src; + break; + case RTA_SRCMASK: + su = &so_srcmask; + break; default: usage("Internal Error"); /*NOTREACHED*/ @@ -1073,19 +1102,19 @@ getaddr(int which, char *s, struct hostent **hpp) *hpp = NULL; q = strchr(s,'/'); - if (q && which == RTA_DST) { + if (q && (which == RTA_DST || which == RTA_SRC)) { qs = *q; *q = '\0'; val = inet_addr(s); if (val != INADDR_NONE) { inet_makenetandmask(htonl(val), &su->sin, - strtoul(q+1, 0, 0)); + strtoul(q+1, 0, 0), which); return (0); } *q =qs; } if (((val = inet_addr(s)) != INADDR_NONE) && - (which != RTA_DST || forcenet == 0)) { + ((which != RTA_DST && which != RTA_SRC) || forcenet == 0)) { su->sin.sin_addr.s_addr = val; if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) return (1); @@ -1098,8 +1127,8 @@ getaddr(int which, char *s, struct hostent **hpp) (forcehost == 0 && (np = getnetbyname(s)) != NULL && (val = np->n_net) != 0)) { netdone: - if (which == RTA_DST) - inet_makenetandmask(val, &su->sin, 0); + if (which == RTA_DST || which == RTA_SRC) + inet_makenetandmask(val, &su->sin, 0, which); return (0); } hp = gethostbyname(s); @@ -1367,13 +1396,17 @@ rtmsg(int cmd, int flags) rtm.rtm_inits = rtm_inits; if (rtm_addrs & RTA_NETMASK) - mask_addr(); + mask_addr(&so_dst, &so_mask, RTA_DST); + if (rtm_addrs & RTA_SRCMASK) + mask_addr(&so_src, &so_srcmask, RTA_SRC); NEXTADDR(RTA_DST, so_dst); NEXTADDR(RTA_GATEWAY, so_gate); NEXTADDR(RTA_NETMASK, so_mask); NEXTADDR(RTA_GENMASK, so_genmask); NEXTADDR(RTA_IFP, so_ifp); NEXTADDR(RTA_IFA, so_ifa); + NEXTADDR(RTA_SRC, so_src); + NEXTADDR(RTA_SRCMASK, so_srcmask); rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; if (verbose) print_rtmsg(&rtm, l); @@ -1400,19 +1433,19 @@ rtmsg(int cmd, int flags) } void -mask_addr(void) +mask_addr(union sockunion *addr, union sockunion *mask, int which) { - int olen = so_mask.sa.sa_len; - char *cp1 = olen + (char *)&so_mask, *cp2; + int olen = mask->sa.sa_len; + char *cp1 = olen + (char *)mask, *cp2; - for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; ) + for (mask->sa.sa_len = 0; cp1 > (char *)mask; ) if (*--cp1 != 0) { - so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask; + mask->sa.sa_len = 1 + cp1 - (char *)mask; break; } - if ((rtm_addrs & RTA_DST) == 0) + if ((rtm_addrs & which) == 0) return; - switch (so_dst.sa.sa_family) { + switch (addr->sa.sa_family) { case AF_NS: case AF_IPX: case AF_INET: @@ -1423,20 +1456,20 @@ mask_addr(void) case 0: return; case AF_ISO: - olen = MIN(so_dst.siso.siso_nlen, - MAX(so_mask.sa.sa_len - 6, 0)); + olen = MIN(addr->siso.siso_nlen, + MAX(mask->sa.sa_len - 6, 0)); break; } - cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst; - cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst; + cp1 = mask->sa.sa_len + 1 + (char *)addr; + cp2 = addr->sa.sa_len + 1 + (char *)addr; while (cp2 > cp1) *--cp2 = 0; - cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask; - while (cp1 > so_dst.sa.sa_data) + cp2 = mask->sa.sa_len + 1 + (char *)mask; + while (cp1 > addr->sa.sa_data) *--cp1 &= *--cp2; - switch (so_dst.sa.sa_family) { + switch (addr->sa.sa_family) { case AF_ISO: - so_dst.siso.siso_nlen = olen; + addr->siso.siso_nlen = olen; break; } } @@ -1464,11 +1497,11 @@ char *msgtypes[] = { char metricnames[] = "\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount\1mtu"; char routeflags[] = -"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\014STATIC\017PROTO2\020PROTO1\040CLONED"; +"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016PROTO3\017PROTO2\020PROTO1\021CLONED\022SOURCE"; char ifnetflags[] = "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST"; char addrnames[] = -"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; +"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011SRC\012SRCMASK"; void print_rtmsg(struct rt_msghdr *rtm, int msglen) @@ -1538,6 +1571,7 @@ void print_getmsg(struct rt_msghdr *rtm, int msglen) { struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL; + struct sockaddr *src = NULL, *srcmask = NULL; struct sockaddr_dl *ifp = NULL; struct sockaddr *sa; char *cp; @@ -1575,6 +1609,12 @@ print_getmsg(struct rt_msghdr *rtm, int msglen) case RTA_NETMASK: mask = sa; break; + case RTA_SRC: + src = sa; + break; + case RTA_SRCMASK: + srcmask = sa; + break; case RTA_IFP: if (sa->sa_family == AF_LINK && ((struct sockaddr_dl *)sa)->sdl_nlen) @@ -1594,6 +1634,17 @@ print_getmsg(struct rt_msghdr *rtm, int msglen) (void)printf(" mask: %s\n", routename(mask)); nflag = savenflag; } + if (src && srcmask) + srcmask->sa_family = src->sa_family; /* XXX */ + if (src) + (void)printf(" source: %s\n", routename(src)); + if (srcmask) { + int savenflag = nflag; + + nflag = 1; + (void)printf(" mask: %s\n", routename(mask)); + nflag = savenflag; + } if (gate && rtm->rtm_flags & RTF_GATEWAY) (void)printf(" gateway: %s\n", routename(gate)); if (ifp) @@ -1619,7 +1670,8 @@ print_getmsg(struct rt_msghdr *rtm, int msglen) printf("%8d%c\n", (int)rtm->rtm_rmx.rmx_expire, lock(EXPIRE)); #undef lock #undef msec -#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) +#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_SRC|RTA_SRCMASK| \ + RTA_IFP|RTA_IFA|RTA_BRD) if (verbose) pmsg_common(rtm); else if (rtm->rtm_addrs &~ RTA_IGN) { diff --git a/sbin/route/show.c b/sbin/route/show.c index f0e20a63b89..7c5df9b9d2e 100644 --- a/sbin/route/show.c +++ b/sbin/route/show.c @@ -1,4 +1,4 @@ -/* $OpenBSD: show.c,v 1.26 2003/08/26 08:33:12 itojun Exp $ */ +/* $OpenBSD: show.c,v 1.27 2004/06/06 17:08:23 cedric Exp $ */ /* $NetBSD: show.c,v 1.1 1996/11/15 18:01:41 gwr Exp $ */ /* @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94"; #else -static char *rcsid = "$OpenBSD: show.c,v 1.26 2003/08/26 08:33:12 itojun Exp $"; +static char *rcsid = "$OpenBSD: show.c,v 1.27 2004/06/06 17:08:23 cedric Exp $"; #endif #endif /* not lint */ @@ -66,7 +66,7 @@ static char *rcsid = "$OpenBSD: show.c,v 1.26 2003/08/26 08:33:12 itojun Exp $"; extern char *routename(struct sockaddr *); extern char *netname(struct sockaddr *); extern char *ns_print(struct sockaddr_ns *); -extern int nflag; +extern int nflag, Sflag; #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) @@ -97,13 +97,14 @@ static const struct bits bits[] = { { RTF_PROTO2, '2' }, { RTF_PROTO3, '3' }, { RTF_CLONED, 'c' }, + { RTF_SOURCE, 's' }, { 0 } }; static void p_rtentry(struct rt_msghdr *); static void p_sockaddr(struct sockaddr *, int, int); static void p_flags(int, char *); -static void pr_rthdr(void); +static void pr_rthdr(int); static void pr_family(int); int keyword(char *); @@ -193,18 +194,27 @@ bad: usage(*argv); /* column widths; each followed by one space */ #define WID_DST 16 /* width of destination column */ +#define WID_SRC 16 /* width of source column */ #define WID_GW 18 /* width of gateway column */ /* * Print header for routing table columns. */ static void -pr_rthdr() +pr_rthdr(int af) { - printf("%-*.*s %-*.*s %-6.6s\n", - WID_DST, WID_DST, "Destination", - WID_GW, WID_GW, "Gateway", - "Flags"); + if (af == AF_INET && Sflag) { + printf("%-*.*s %-*.*s %-*.*s %-6.6s\n", + WID_SRC, WID_SRC, "Source", + WID_DST, WID_DST, "Destination", + WID_GW, WID_GW, "Gateway", + "Flags"); + } else { + printf("%-*.*s %-*.*s %-6.6s\n", + WID_DST, WID_DST, "Destination", + WID_GW, WID_GW, "Gateway", + "Flags"); + } } /* @@ -214,12 +224,13 @@ static void p_rtentry(rtm) struct rt_msghdr *rtm; { - struct sockaddr *sa = (struct sockaddr *)(rtm + 1); + struct sockaddr *sa = (struct sockaddr *)(rtm + 1), *sa2; #ifdef notdef static int masks_done, banner_printed; #endif static int old_af; - int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST | RTF_MASK; + int i, af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST | + RTF_MASK | RTF_SOURCE; #ifdef notdef /* for the moment, netmasks are skipped over */ @@ -238,9 +249,19 @@ p_rtentry(rtm) if (old_af != af) { old_af = af; pr_family(af); - pr_rthdr(); + pr_rthdr(af); + } + if (af == AF_INET && Sflag) { + if (rtm->rtm_addrs & RTA_SRC) { + for (sa2 = sa, i = 1; i < RTA_SRC; i <<= 1) + if (rtm->rtm_addrs & i) + sa2 = (struct sockaddr *)(ROUNDUP( + sa2->sa_len) + (char *)sa2); + p_sockaddr(sa2, 0, 16); + } else + printf("%-*s ", 16, "default"); } - if (rtm->rtm_addrs == RTA_DST) + if (!(rtm->rtm_addrs & RTA_GATEWAY)) p_sockaddr(sa, 0, 36); else { p_sockaddr(sa, rtm->rtm_flags, 16); |