source: rtems-libbsd/freebsd-userspace/commands/usr.bin/netstat/route.c @ f1710b6

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since f1710b6 was f1710b6, checked in by Joel Sherrill <joel.sherrill@…>, on 09/07/12 at 17:50:18

netstat: New command - Almost completely compiles

Currently disable in Makefile until all builds. Adding it so
others can assist in debugging issues.

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