source: rtems-libbsd/freebsd/usr.bin/netstat/route.c @ 6da9b23

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 6da9b23 was 6da9b23, checked in by Sebastian Huber <sebastian.huber@…>, on 10/30/13 at 14:42:53

NETSTAT(1): Initialize global variables

Use BSD program lock.

  • Property mode set to 100644
File size: 25.4 KB
Line 
1/*-
2 * Copyright (c) 1983, 1988, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#if 0
35#ifndef lint
36static char sccsid[] = "From: @(#)route.c       8.6 (Berkeley) 4/28/95";
37#endif /* not lint */
38#endif
39
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD$");
42
43#include <rtems/bsd/sys/param.h>
44#include <sys/protosw.h>
45#include <sys/socket.h>
46#include <sys/socketvar.h>
47#include <rtems/bsd/sys/time.h>
48
49#include <net/ethernet.h>
50#include <net/if.h>
51#include <net/if_var.h>
52#include <net/if_dl.h>
53#include <net/if_types.h>
54#include <net/radix.h>
55#include <net/route.h>
56
57#include <netinet/in.h>
58#ifdef __rtems__
59/* no IPX on RTEMS */
60/* no AppleTalk on RTEMS */
61#else /* __rtems__ */
62#include <netipx/ipx.h>
63#include <netatalk/at.h>
64#endif /* __rtems__ */
65#ifdef __rtems__
66/* why isn't this protected by a NETGRAPH define */
67#else /* __rtems__ */
68#include <netgraph/ng_socket.h>
69#endif /* __rtems__ */
70
71#include <sys/sysctl.h>
72
73#include <arpa/inet.h>
74#include <libutil.h>
75#include <netdb.h>
76#include <stdint.h>
77#include <stdio.h>
78#include <stdlib.h>
79#include <string.h>
80#include <sysexits.h>
81#include <unistd.h>
82#include <err.h>
83#include "netstat.h"
84
85#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
86
87/*
88 * Definitions for showing gateway flags.
89 */
90struct bits {
91        u_long  b_mask;
92        char    b_val;
93} static const bits[] = {
94        { RTF_UP,       'U' },
95        { RTF_GATEWAY,  'G' },
96        { RTF_HOST,     'H' },
97        { RTF_REJECT,   'R' },
98        { RTF_DYNAMIC,  'D' },
99        { RTF_MODIFIED, 'M' },
100        { RTF_DONE,     'd' }, /* Completed -- for routing messages only */
101        { RTF_XRESOLVE, 'X' },
102        { RTF_STATIC,   'S' },
103        { RTF_PROTO1,   '1' },
104        { RTF_PROTO2,   '2' },
105        { RTF_PRCLONING,'c' },
106        { RTF_PROTO3,   '3' },
107        { RTF_BLACKHOLE,'B' },
108        { RTF_BROADCAST,'b' },
109#ifdef RTF_LLINFO
110        { RTF_LLINFO,   'L' },
111#endif
112#ifdef RTF_WASCLONED
113        { RTF_WASCLONED,'W' },
114#endif
115#ifdef RTF_CLONING
116        { RTF_CLONING,  'C' },
117#endif
118        { 0 , 0 }
119};
120
121typedef union {
122        long    dummy;          /* Helps align structure. */
123        struct  sockaddr u_sa;
124        u_short u_data[128];
125} sa_u;
126
127static sa_u pt_u;
128
129static int      fibnum;
130static struct   rtentry rtentry;
131static struct   radix_node rnode;
132static struct   radix_mask rmask;
133
134static const int        NewTree = 0;
135
136static struct   timespec uptime;
137
138static struct sockaddr *kgetsa(struct sockaddr *);
139static void size_cols(int ef, struct radix_node *rn);
140static void size_cols_tree(struct radix_node *rn);
141static void size_cols_rtentry(struct rtentry *rt);
142static void p_tree(struct radix_node *);
143static void p_rtnode(void);
144static void ntreestuff(void);
145static void np_rtentry(struct rt_msghdr *);
146static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
147static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask,
148    int flags);
149static void p_flags(int, const char *);
150static const char *fmt_flags(int f);
151static void p_rtentry(struct rtentry *);
152static void domask(char *, in_addr_t, u_long);
153
154/*
155 * Print routing tables.
156 */
157void
158routepr(u_long rtree)
159{
160        struct radix_node_head **rnhp, *rnh, head;
161        size_t intsize;
162        int i;
163        int numfibs;
164
165        intsize = sizeof(int);
166        if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
167                fibnum = 0;
168        if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
169                numfibs = 1;
170        rt_tables = calloc(numfibs * (AF_MAX+1),
171            sizeof(struct radix_node_head *));
172        if (rt_tables == NULL)
173                err(EX_OSERR, "memory allocation failed");
174        /*
175         * Since kernel & userland use different timebase
176         * (time_uptime vs time_second) and we are reading kernel memory
177         * directly we should do rt_rmx.rmx_expire --> expire_time conversion.
178         */
179#ifdef __rtems__
180        {
181          rtems_clock_get_uptime(&uptime);
182        }
183#else
184        if (clock_gettime(CLOCK_UPTIME, &uptime) < 0)
185                err(EX_OSERR, "clock_gettime() failed");
186#endif
187
188        printf("Routing tables\n");
189
190        if (Aflag == 0 && NewTree)
191                ntreestuff();
192        else {
193                if (rtree == 0) {
194                        printf("rt_tables: symbol not in namelist\n");
195                        return;
196                }
197
198                if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs *
199                    (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0)
200                        return;
201                for (i = 0; i <= AF_MAX; i++) {
202                        int tmpfib;
203                        if (i != AF_INET)
204                                tmpfib = 0;
205                        else
206                                tmpfib = fibnum;
207                        rnhp = (struct radix_node_head **)*rt_tables;
208                        /* Calculate the in-kernel address. */
209                        rnhp += tmpfib * (AF_MAX+1) + i;
210                        /* Read the in kernel rhn pointer. */
211                        if (kget(rnhp, rnh) != 0)
212                                continue;
213                        if (rnh == NULL)
214                                continue;
215#ifdef __rtems__
216                        /* printf( "rnh %p %p\n", (void *)rnhp, (void *)rnh ); */
217                        /* We get a 1 here on some fields. Why? XXX */
218#endif
219                        /* Read the rnh data. */
220                        if (kget(rnh, head) != 0)
221                                continue;
222                        if (i == AF_UNSPEC) {
223                                if (Aflag && af == 0) {
224                                        printf("Netmasks:\n");
225                                        p_tree(head.rnh_treetop);
226                                }
227                        } else if (af == AF_UNSPEC || af == i) {
228                                size_cols(i, head.rnh_treetop);
229                                pr_family(i);
230                                do_rtent = 1;
231                                pr_rthdr(i);
232                                p_tree(head.rnh_treetop);
233                        }
234                }
235        }
236}
237
238/*
239 * Print address family header before a section of the routing table.
240 */
241void
242pr_family(int af1)
243{
244        const char *afname;
245
246        switch (af1) {
247        case AF_INET:
248                afname = "Internet";
249                break;
250#ifdef INET6
251        case AF_INET6:
252                afname = "Internet6";
253                break;
254#endif /*INET6*/
255        case AF_IPX:
256                afname = "IPX";
257                break;
258        case AF_ISO:
259                afname = "ISO";
260                break;
261        case AF_APPLETALK:
262                afname = "AppleTalk";
263                break;
264        case AF_CCITT:
265                afname = "X.25";
266                break;
267        case AF_NETGRAPH:
268                afname = "Netgraph";
269                break;
270        default:
271                afname = NULL;
272                break;
273        }
274        if (afname)
275                printf("\n%s:\n", afname);
276        else
277                printf("\nProtocol Family %d:\n", af1);
278}
279
280/* column widths; each followed by one space */
281#ifndef INET6
282#define WID_DST_DEFAULT(af)     18      /* width of destination column */
283#define WID_GW_DEFAULT(af)      18      /* width of gateway column */
284#define WID_IF_DEFAULT(af)      (Wflag ? 8 : 6) /* width of netif column */
285#else
286#define WID_DST_DEFAULT(af) \
287        ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18)
288#define WID_GW_DEFAULT(af) \
289        ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18)
290#define WID_IF_DEFAULT(af)      ((af) == AF_INET6 ? 8 : (Wflag ? 8 : 6))
291#endif /*INET6*/
292
293static int wid_dst;
294static int wid_gw;
295static int wid_flags;
296static int wid_refs;
297static int wid_use;
298static int wid_mtu;
299static int wid_if;
300static int wid_expire;
301
302static void
303size_cols(int ef __unused, struct radix_node *rn)
304{
305        wid_dst = WID_DST_DEFAULT(ef);
306        wid_gw = WID_GW_DEFAULT(ef);
307        wid_flags = 6;
308        wid_refs = 6;
309        wid_use = 8;
310        wid_mtu = 6;
311        wid_if = WID_IF_DEFAULT(ef);
312        wid_expire = 6;
313
314        if (Wflag)
315                size_cols_tree(rn);
316}
317
318static void
319size_cols_tree(struct radix_node *rn)
320{
321again:
322        if (kget(rn, rnode) != 0)
323                return;
324        if (!(rnode.rn_flags & RNF_ACTIVE))
325                return;
326        if (rnode.rn_bit < 0) {
327                if ((rnode.rn_flags & RNF_ROOT) == 0) {
328                        if (kget(rn, rtentry) != 0)
329                                return;
330                        size_cols_rtentry(&rtentry);
331                }
332                if ((rn = rnode.rn_dupedkey))
333                        goto again;
334        } else {
335                rn = rnode.rn_right;
336                size_cols_tree(rnode.rn_left);
337                size_cols_tree(rn);
338        }
339}
340
341static void
342size_cols_rtentry(struct rtentry *rt)
343{
344        static struct ifnet ifnet, *lastif;
345        static char buffer[100];
346        const char *bp;
347        struct sockaddr *sa;
348        sa_u addr, mask;
349        int len;
350
351        bzero(&addr, sizeof(addr));
352        if ((sa = kgetsa(rt_key(rt))))
353                bcopy(sa, &addr, sa->sa_len);
354        bzero(&mask, sizeof(mask));
355        if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
356                bcopy(sa, &mask, sa->sa_len);
357        bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags);
358        len = strlen(bp);
359        wid_dst = MAX(len, wid_dst);
360
361        bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST);
362        len = strlen(bp);
363        wid_gw = MAX(len, wid_gw);
364
365        bp = fmt_flags(rt->rt_flags);
366        len = strlen(bp);
367        wid_flags = MAX(len, wid_flags);
368
369        if (addr.u_sa.sa_family == AF_INET || Wflag) {
370                len = snprintf(buffer, sizeof(buffer), "%d", rt->rt_refcnt);
371                wid_refs = MAX(len, wid_refs);
372                len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_use);
373                wid_use = MAX(len, wid_use);
374                if (Wflag && rt->rt_rmx.rmx_mtu != 0) {
375                        len = snprintf(buffer, sizeof(buffer),
376                                       "%lu", rt->rt_rmx.rmx_mtu);
377                        wid_mtu = MAX(len, wid_mtu);
378                }
379        }
380        if (rt->rt_ifp) {
381                if (rt->rt_ifp != lastif) {
382                        if (kget(rt->rt_ifp, ifnet) == 0)
383                                len = strlen(ifnet.if_xname);
384                        else
385                                len = strlen("---");
386                        lastif = rt->rt_ifp;
387                        wid_if = MAX(len, wid_if);
388                }
389                if (rt->rt_rmx.rmx_expire) {
390                        time_t expire_time;
391
392                        if ((expire_time =
393                            rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) {
394                                len = snprintf(buffer, sizeof(buffer), "%d",
395                                               (int)expire_time);
396                                wid_expire = MAX(len, wid_expire);
397                        }
398                }
399        }
400}
401
402
403/*
404 * Print header for routing table columns.
405 */
406void
407pr_rthdr(int af1)
408{
409
410        if (Aflag)
411                printf("%-8.8s ","Address");
412        if (af1 == AF_INET || Wflag) {
413                if (Wflag) {
414                        printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n",
415                                wid_dst,        wid_dst,        "Destination",
416                                wid_gw,         wid_gw,         "Gateway",
417                                wid_flags,      wid_flags,      "Flags",
418                                wid_refs,       wid_refs,       "Refs",
419                                wid_use,        wid_use,        "Use",
420                                wid_mtu,        wid_mtu,        "Mtu",
421                                wid_if,         wid_if,         "Netif",
422                                wid_expire,                     "Expire");
423                } else {
424                        printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n",
425                                wid_dst,        wid_dst,        "Destination",
426                                wid_gw,         wid_gw,         "Gateway",
427                                wid_flags,      wid_flags,      "Flags",
428                                wid_refs,       wid_refs,       "Refs",
429                                wid_use,        wid_use,        "Use",
430                                wid_if,         wid_if,         "Netif",
431                                wid_expire,                     "Expire");
432                }
433        } else {
434                printf("%-*.*s %-*.*s %-*.*s  %*.*s %*s\n",
435                        wid_dst,        wid_dst,        "Destination",
436                        wid_gw,         wid_gw,         "Gateway",
437                        wid_flags,      wid_flags,      "Flags",
438                        wid_if,         wid_if,         "Netif",
439                        wid_expire,                     "Expire");
440        }
441}
442
443static struct sockaddr *
444kgetsa(struct sockaddr *dst)
445{
446
447        if (kget(dst, pt_u.u_sa) != 0)
448                return (NULL);
449        if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
450                kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
451        return (&pt_u.u_sa);
452}
453
454static void
455p_tree(struct radix_node *rn)
456{
457
458again:
459        if (kget(rn, rnode) != 0)
460                return;
461        if (!(rnode.rn_flags & RNF_ACTIVE))
462                return;
463        if (rnode.rn_bit < 0) {
464                if (Aflag)
465                        printf("%-8.8lx ", (u_long)rn);
466                if (rnode.rn_flags & RNF_ROOT) {
467                        if (Aflag)
468                                printf("(root node)%s",
469                                    rnode.rn_dupedkey ? " =>\n" : "\n");
470                } else if (do_rtent) {
471                        if (kget(rn, rtentry) == 0) {
472                                p_rtentry(&rtentry);
473                                if (Aflag)
474                                        p_rtnode();
475                        }
476                } else {
477                        p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
478                                   NULL, 0, 44);
479                        putchar('\n');
480                }
481                if ((rn = rnode.rn_dupedkey))
482                        goto again;
483        } else {
484                if (Aflag && do_rtent) {
485                        printf("%-8.8lx ", (u_long)rn);
486                        p_rtnode();
487                }
488                rn = rnode.rn_right;
489                p_tree(rnode.rn_left);
490                p_tree(rn);
491        }
492}
493
494static char     nbuf[20];
495
496static void
497p_rtnode(void)
498{
499        struct radix_mask *rm = rnode.rn_mklist;
500
501        if (rnode.rn_bit < 0) {
502                if (rnode.rn_mask) {
503                        printf("\t  mask ");
504                        p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
505                                   NULL, 0, -1);
506                } else if (rm == 0)
507                        return;
508        } else {
509                sprintf(nbuf, "(%d)", rnode.rn_bit);
510                printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right);
511        }
512        while (rm) {
513                if (kget(rm, rmask) != 0)
514                        break;
515                sprintf(nbuf, " %d refs, ", rmask.rm_refs);
516                printf(" mk = %8.8lx {(%d),%s",
517                        (u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " ");
518                if (rmask.rm_flags & RNF_NORMAL) {
519                        struct radix_node rnode_aux;
520                        printf(" <normal>, ");
521                        if (kget(rmask.rm_leaf, rnode_aux) == 0)
522                                p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
523                                    NULL, 0, -1);
524                        else
525                                p_sockaddr(NULL, NULL, 0, -1);
526                } else
527                    p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
528                                NULL, 0, -1);
529                putchar('}');
530                if ((rm = rmask.rm_mklist))
531                        printf(" ->");
532        }
533        putchar('\n');
534}
535
536static void
537ntreestuff(void)
538{
539        size_t needed;
540        int mib[6];
541        char *buf, *next, *lim;
542        struct rt_msghdr *rtm;
543
544        mib[0] = CTL_NET;
545        mib[1] = PF_ROUTE;
546        mib[2] = 0;
547        mib[3] = 0;
548        mib[4] = NET_RT_DUMP;
549        mib[5] = 0;
550        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
551                err(1, "sysctl: net.route.0.0.dump estimate");
552        }
553
554        if ((buf = malloc(needed)) == 0) {
555                errx(2, "malloc(%lu)", (unsigned long)needed);
556        }
557        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
558                err(1, "sysctl: net.route.0.0.dump");
559        }
560        lim  = buf + needed;
561        for (next = buf; next < lim; next += rtm->rtm_msglen) {
562                rtm = (struct rt_msghdr *)next;
563                np_rtentry(rtm);
564        }
565}
566
567static void
568np_rtentry(struct rt_msghdr *rtm)
569{
570        struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
571#ifdef notdef
572        static int masks_done, banner_printed;
573#endif
574        static int old_af;
575        int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
576
577#ifdef notdef
578        /* for the moment, netmasks are skipped over */
579        if (!banner_printed) {
580                printf("Netmasks:\n");
581                banner_printed = 1;
582        }
583        if (masks_done == 0) {
584                if (rtm->rtm_addrs != RTA_DST ) {
585                        masks_done = 1;
586                        af1 = sa->sa_family;
587                }
588        } else
589#endif
590                af1 = sa->sa_family;
591        if (af1 != old_af) {
592                pr_family(af1);
593                old_af = af1;
594        }
595        if (rtm->rtm_addrs == RTA_DST)
596                p_sockaddr(sa, NULL, 0, 36);
597        else {
598                p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
599                sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
600                p_sockaddr(sa, NULL, 0, 18);
601        }
602        p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
603        putchar('\n');
604}
605
606static void
607p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
608{
609        const char *cp;
610
611        cp = fmt_sockaddr(sa, mask, flags);
612
613        if (width < 0 )
614                printf("%s ", cp);
615        else {
616                if (numeric_addr)
617                        printf("%-*s ", width, cp);
618                else
619                        printf("%-*.*s ", width, width, cp);
620        }
621}
622
623static const char *
624fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
625{
626        static char workbuf[128];
627        const char *cp;
628
629        if (sa == NULL)
630                return ("null");
631
632        switch(sa->sa_family) {
633        case AF_INET:
634            {
635                struct sockaddr_in *sockin = (struct sockaddr_in *)sa;
636
637                if ((sockin->sin_addr.s_addr == INADDR_ANY) &&
638                        mask &&
639                        ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr)
640                                ==0L)
641                                cp = "default" ;
642                else if (flags & RTF_HOST)
643                        cp = routename(sockin->sin_addr.s_addr);
644                else if (mask)
645                        cp = netname(sockin->sin_addr.s_addr,
646                                     ntohl(((struct sockaddr_in *)mask)
647                                           ->sin_addr.s_addr));
648                else
649                        cp = netname(sockin->sin_addr.s_addr, 0L);
650                break;
651            }
652
653#ifdef INET6
654        case AF_INET6:
655            {
656                struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
657                struct in6_addr *in6 = &sa6->sin6_addr;
658
659                /*
660                 * XXX: This is a special workaround for KAME kernels.
661                 * sin6_scope_id field of SA should be set in the future.
662                 */
663                if (IN6_IS_ADDR_LINKLOCAL(in6) ||
664                    IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
665                    /* XXX: override is ok? */
666                    sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
667                    *(u_short *)&in6->s6_addr[2] = 0;
668                }
669
670                if (flags & RTF_HOST)
671                    cp = routename6(sa6);
672                else if (mask)
673                    cp = netname6(sa6,
674                                  &((struct sockaddr_in6 *)mask)->sin6_addr);
675                else {
676                    cp = netname6(sa6, NULL);
677                }
678                break;
679            }
680#endif /*INET6*/
681
682#ifndef __rtems__
683        case AF_IPX:
684            {
685                struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
686                if (ipx_nullnet(satoipx_addr(work)))
687                        cp = "default";
688                else
689                        cp = ipx_print(sa);
690                break;
691            }
692        case AF_APPLETALK:
693            {
694                if (!(flags & RTF_HOST) && mask)
695                        cp = atalk_print2(sa,mask,9);
696                else
697                        cp = atalk_print(sa,11);
698                break;
699            }
700#endif
701        case AF_NETGRAPH:
702            {
703#ifdef __rtems__
704                /* netgraph not supported yet */
705                err(EX_OSERR, "memory allocation failed");
706#else
707                strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data,
708                        sizeof(workbuf));
709                cp = workbuf;
710#endif
711                break;
712            }
713
714        case AF_LINK:
715            {
716                struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
717
718                if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
719                    sdl->sdl_slen == 0) {
720                        (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
721                        cp = workbuf;
722                } else
723                        switch (sdl->sdl_type) {
724
725                        case IFT_ETHER:
726                        case IFT_L2VLAN:
727                        case IFT_BRIDGE:
728                                if (sdl->sdl_alen == ETHER_ADDR_LEN) {
729                                        cp = ether_ntoa((struct ether_addr *)
730                                            (sdl->sdl_data + sdl->sdl_nlen));
731                                        break;
732                                }
733                                /* FALLTHROUGH */
734                        default:
735                                cp = link_ntoa(sdl);
736                                break;
737                        }
738                break;
739            }
740
741        default:
742            {
743                u_char *s = (u_char *)sa->sa_data, *slim;
744                char *cq, *cqlim;
745
746                cq = workbuf;
747                slim =  sa->sa_len + (u_char *) sa;
748                cqlim = cq + sizeof(workbuf) - 6;
749                cq += sprintf(cq, "(%d)", sa->sa_family);
750                while (s < slim && cq < cqlim) {
751                        cq += sprintf(cq, " %02x", *s++);
752                        if (s < slim)
753                            cq += sprintf(cq, "%02x", *s++);
754                }
755                cp = workbuf;
756            }
757        }
758
759        return (cp);
760}
761
762static void
763p_flags(int f, const char *format)
764{
765        printf(format, fmt_flags(f));
766}
767
768static const char *
769fmt_flags(int f)
770{
771        static char name[33];
772        char *flags;
773        const struct bits *p = bits;
774
775        for (flags = name; p->b_mask; p++)
776                if (p->b_mask & f)
777                        *flags++ = p->b_val;
778        *flags = '\0';
779        return (name);
780}
781
782static void
783p_rtentry(struct rtentry *rt)
784{
785        static struct ifnet ifnet, *lastif;
786        static char buffer[128];
787        static char prettyname[128];
788        struct sockaddr *sa;
789        sa_u addr, mask;
790
791        bzero(&addr, sizeof(addr));
792        if ((sa = kgetsa(rt_key(rt))))
793                bcopy(sa, &addr, sa->sa_len);
794        bzero(&mask, sizeof(mask));
795        if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
796                bcopy(sa, &mask, sa->sa_len);
797        p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst);
798        p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw);
799        snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
800        p_flags(rt->rt_flags, buffer);
801        if (addr.u_sa.sa_family == AF_INET || Wflag) {
802                printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
803                                     wid_use, rt->rt_use);
804                if (Wflag) {
805                        if (rt->rt_rmx.rmx_mtu != 0)
806                                printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
807                        else
808                                printf("%*s ", wid_mtu, "");
809                }
810        }
811        if (rt->rt_ifp) {
812                if (rt->rt_ifp != lastif) {
813                        if (kget(rt->rt_ifp, ifnet) == 0)
814                                strlcpy(prettyname, ifnet.if_xname,
815                                    sizeof(prettyname));
816                        else
817                                strlcpy(prettyname, "---", sizeof(prettyname));
818                        lastif = rt->rt_ifp;
819                }
820                printf("%*.*s", wid_if, wid_if, prettyname);
821                if (rt->rt_rmx.rmx_expire) {
822                        time_t expire_time;
823
824                        if ((expire_time =
825                            rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0)
826                                printf(" %*d", wid_expire, (int)expire_time);
827                }
828                if (rt->rt_nodes[0].rn_dupedkey)
829                        printf(" =>");
830        }
831        putchar('\n');
832}
833
834char *
835routename(in_addr_t in)
836{
837        char *cp;
838        static char line[MAXHOSTNAMELEN];
839        struct hostent *hp;
840
841        cp = 0;
842        if (!numeric_addr) {
843                hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET);
844                if (hp) {
845                        cp = hp->h_name;
846                        trimdomain(cp, strlen(cp));
847                }
848        }
849        if (cp) {
850                strlcpy(line, cp, sizeof(line));
851        } else {
852#define C(x)    ((x) & 0xff)
853                in = ntohl(in);
854                sprintf(line, "%u.%u.%u.%u",
855                    C(in >> 24), C(in >> 16), C(in >> 8), C(in));
856        }
857        return (line);
858}
859
860#define NSHIFT(m) (                                                     \
861        (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT :                       \
862        (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT :                       \
863        (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT :                       \
864        0)
865
866static void
867domask(char *dst, in_addr_t addr __unused, u_long mask)
868{
869        int b, i;
870
871        if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) {
872                *dst = '\0';
873                return;
874        }
875        i = 0;
876        for (b = 0; b < 32; b++)
877                if (mask & (1 << b)) {
878                        int bb;
879
880                        i = b;
881                        for (bb = b+1; bb < 32; bb++)
882                                if (!(mask & (1 << bb))) {
883                                        i = -1; /* noncontig */
884                                        break;
885                                }
886                        break;
887                }
888        if (i == -1)
889                sprintf(dst, "&0x%lx", mask);
890        else
891                sprintf(dst, "/%d", 32-i);
892}
893
894/*
895 * Return the name of the network whose address is given.
896 * The address is assumed to be that of a net or subnet, not a host.
897 */
898char *
899netname(in_addr_t in, u_long mask)
900{
901        char *cp = 0;
902        static char line[MAXHOSTNAMELEN];
903        struct netent *np = 0;
904        in_addr_t i;
905
906        i = ntohl(in);
907        if (!numeric_addr && i) {
908                np = getnetbyaddr(i >> NSHIFT(mask), AF_INET);
909                if (np != NULL) {
910                        cp = np->n_name;
911                        trimdomain(cp, strlen(cp));
912                }
913        }
914        if (cp != NULL) {
915                strlcpy(line, cp, sizeof(line));
916        } else {
917                inet_ntop(AF_INET, &in, line, sizeof(line) - 1);
918        }
919        domask(line + strlen(line), i, mask);
920        return (line);
921}
922
923#undef NSHIFT
924
925#ifdef INET6
926const char *
927netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask)
928{
929        static char line[MAXHOSTNAMELEN];
930        u_char *p = (u_char *)mask;
931        u_char *lim;
932        int masklen, illegal = 0, flag = 0;
933
934        if (mask) {
935                for (masklen = 0, lim = p + 16; p < lim; p++) {
936                        switch (*p) {
937                         case 0xff:
938                                 masklen += 8;
939                                 break;
940                         case 0xfe:
941                                 masklen += 7;
942                                 break;
943                         case 0xfc:
944                                 masklen += 6;
945                                 break;
946                         case 0xf8:
947                                 masklen += 5;
948                                 break;
949                         case 0xf0:
950                                 masklen += 4;
951                                 break;
952                         case 0xe0:
953                                 masklen += 3;
954                                 break;
955                         case 0xc0:
956                                 masklen += 2;
957                                 break;
958                         case 0x80:
959                                 masklen += 1;
960                                 break;
961                         case 0x00:
962                                 break;
963                         default:
964                                 illegal ++;
965                                 break;
966                        }
967                }
968                if (illegal)
969                        fprintf(stderr, "illegal prefixlen\n");
970        }
971        else
972                masklen = 128;
973
974        if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
975                return("default");
976
977        if (numeric_addr)
978                flag |= NI_NUMERICHOST;
979        getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
980                    NULL, 0, flag);
981
982        if (numeric_addr)
983                sprintf(&line[strlen(line)], "/%d", masklen);
984
985        return line;
986}
987
988char *
989routename6(struct sockaddr_in6 *sa6)
990{
991        static char line[MAXHOSTNAMELEN];
992        int flag = 0;
993        /* use local variable for safety */
994        struct sockaddr_in6 sa6_local;
995
996        sa6_local.sin6_family = AF_INET6;
997        sa6_local.sin6_len = sizeof(sa6_local);
998        sa6_local.sin6_addr = sa6->sin6_addr;
999        sa6_local.sin6_scope_id = sa6->sin6_scope_id;
1000
1001        if (numeric_addr)
1002                flag |= NI_NUMERICHOST;
1003
1004        getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len,
1005                    line, sizeof(line), NULL, 0, flag);
1006
1007        return line;
1008}
1009#endif /*INET6*/
1010
1011/*
1012 * Print routing statistics
1013 */
1014void
1015rt_stats(u_long rtsaddr, u_long rttaddr)
1016{
1017        struct rtstat rtstat;
1018        int rttrash;
1019
1020        if (rtsaddr == 0) {
1021                printf("rtstat: symbol not in namelist\n");
1022                return;
1023        }
1024        if (rttaddr == 0) {
1025                printf("rttrash: symbol not in namelist\n");
1026                return;
1027        }
1028        kread(rtsaddr, (char *)&rtstat, sizeof (rtstat));
1029        kread(rttaddr, (char *)&rttrash, sizeof (rttrash));
1030        printf("routing:\n");
1031
1032#define p(f, m) if (rtstat.f || sflag <= 1) \
1033        printf(m, rtstat.f, plural(rtstat.f))
1034
1035        p(rts_badredirect, "\t%hu bad routing redirect%s\n");
1036        p(rts_dynamic, "\t%hu dynamically created route%s\n");
1037        p(rts_newgateway, "\t%hu new gateway%s due to redirects\n");
1038        p(rts_unreach, "\t%hu destination%s found unreachable\n");
1039        p(rts_wildcard, "\t%hu use%s of a wildcard route\n");
1040#undef p
1041
1042        if (rttrash || sflag <= 1)
1043                printf("\t%u route%s not in table but not freed\n",
1044                    rttrash, plural(rttrash));
1045}
1046
1047#ifndef __rtems__
1048char *
1049ipx_print(struct sockaddr *sa)
1050{
1051        u_short port;
1052        struct servent *sp = 0;
1053        const char *net = "", *host = "";
1054        char *p;
1055        u_char *q;
1056        struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
1057        static char mybuf[50];
1058        char cport[10], chost[15], cnet[15];
1059
1060        port = ntohs(work.x_port);
1061
1062        if (ipx_nullnet(work) && ipx_nullhost(work)) {
1063
1064                if (port) {
1065                        if (sp)
1066                                sprintf(mybuf, "*.%s", sp->s_name);
1067                        else
1068                                sprintf(mybuf, "*.%x", port);
1069                } else
1070                        sprintf(mybuf, "*.*");
1071
1072                return (mybuf);
1073        }
1074
1075        if (ipx_wildnet(work))
1076                net = "any";
1077        else if (ipx_nullnet(work))
1078                net = "*";
1079        else {
1080                q = work.x_net.c_net;
1081                sprintf(cnet, "%02x%02x%02x%02x",
1082                        q[0], q[1], q[2], q[3]);
1083                for (p = cnet; *p == '0' && p < cnet + 8; p++)
1084                        continue;
1085                net = p;
1086        }
1087
1088        if (ipx_wildhost(work))
1089                host = "any";
1090        else if (ipx_nullhost(work))
1091                host = "*";
1092        else {
1093                q = work.x_host.c_host;
1094                sprintf(chost, "%02x%02x%02x%02x%02x%02x",
1095                        q[0], q[1], q[2], q[3], q[4], q[5]);
1096                for (p = chost; *p == '0' && p < chost + 12; p++)
1097                        continue;
1098                host = p;
1099        }
1100
1101        if (port) {
1102                if (strcmp(host, "*") == 0)
1103                        host = "";
1104                if (sp)
1105                        snprintf(cport, sizeof(cport),
1106                                "%s%s", *host ? "." : "", sp->s_name);
1107                else
1108                        snprintf(cport, sizeof(cport),
1109                                "%s%x", *host ? "." : "", port);
1110        } else
1111                *cport = 0;
1112
1113        snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport);
1114        return(mybuf);
1115}
1116
1117char *
1118ipx_phost(struct sockaddr *sa)
1119{
1120        struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa;
1121        struct sockaddr_ipx work;
1122        static union ipx_net ipx_zeronet;
1123        char *p;
1124        struct ipx_addr in;
1125
1126        work = *sipx;
1127        in = work.sipx_addr;
1128
1129        work.sipx_addr.x_port = 0;
1130        work.sipx_addr.x_net = ipx_zeronet;
1131        p = ipx_print((struct sockaddr *)&work);
1132        if (strncmp("*.", p, 2) == 0) p += 2;
1133
1134        return(p);
1135}
1136#endif
1137
1138void
1139upHex(char *p0)
1140{
1141        char *p = p0;
1142
1143        for (; *p; p++)
1144                switch (*p) {
1145
1146                case 'a':
1147                case 'b':
1148                case 'c':
1149                case 'd':
1150                case 'e':
1151                case 'f':
1152                        *p += ('A' - 'a');
1153                        break;
1154                }
1155}
Note: See TracBrowser for help on using the repository browser.