source: rtems-libbsd/freebsd/usr.bin/netstat/route.c @ 4db7af6

4.115-freebsd-12freebsd-9.3
Last change on this file since 4db7af6 was 4db7af6, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 30, 2013 at 1:21:20 PM

NETSTAT(1): Add const qualifier

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