Print this page
9352 netstat(1M) should be able to print IPv4 networks in CIDR form


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 1990  Mentat Inc.
  24  * netstat.c 2.2, last change 9/9/91
  25  * MROUTING Revision 3.5
  26  * Copyright (c) 2017, Joyent, Inc.
  27  */
  28 
  29 /*
  30  * simple netstat based on snmp/mib-2 interface to the TCP/IP stack
  31  *
  32  * NOTES:
  33  * 1. A comment "LINTED: (note 1)" appears before certain lines where
  34  *    lint would have complained, "pointer cast may result in improper
  35  *    alignment". These are lines where lint had suspected potential
  36  *    improper alignment of a data structure; in each such situation
  37  *    we have relied on the kernel guaranteeing proper alignment.
  38  * 2. Some 'for' loops have been commented as "'for' loop 1", etc
  39  *    because they have 'continue' or 'break' statements in their
  40  *    bodies. 'continue' statements have been used inside some loops
  41  *    where avoiding them would have led to deep levels of indentation.
  42  *
  43  * TODO:
  44  *      Add ability to request subsets from kernel (with level = MIB2_IP;
  45  *      name = 0 meaning everything for compatibility)
  46  */


 219 static int              isnum(char *);
 220 static char             *plural(int n);
 221 static char             *pluraly(int n);
 222 static char             *plurales(int n);
 223 static void             process_filter(char *arg);
 224 static char             *ifindex2str(uint_t, char *);
 225 static boolean_t        family_selected(int family);
 226 
 227 static void             usage(char *);
 228 static void             fatal(int errcode, char *str1, ...);
 229 
 230 #define PLURAL(n) plural((int)n)
 231 #define PLURALY(n) pluraly((int)n)
 232 #define PLURALES(n) plurales((int)n)
 233 #define IFLAGMOD(flg, val1, val2)       if (flg == val1) flg = val2
 234 #define MDIFF(diff, elem2, elem1, member)       (diff)->member = \
 235         (elem2)->member - (elem1)->member
 236 
 237 
 238 static  boolean_t       Aflag = B_FALSE;        /* All sockets/ifs/rtng-tbls */

 239 static  boolean_t       Dflag = B_FALSE;        /* DCE info */
 240 static  boolean_t       Iflag = B_FALSE;        /* IP Traffic Interfaces */
 241 static  boolean_t       Mflag = B_FALSE;        /* STREAMS Memory Statistics */
 242 static  boolean_t       Nflag = B_FALSE;        /* Numeric Network Addresses */
 243 static  boolean_t       Rflag = B_FALSE;        /* Routing Tables */
 244 static  boolean_t       RSECflag = B_FALSE;     /* Security attributes */
 245 static  boolean_t       Sflag = B_FALSE;        /* Per-protocol Statistics */
 246 static  boolean_t       Vflag = B_FALSE;        /* Verbose */
 247 static  boolean_t       Pflag = B_FALSE;        /* Net to Media Tables */
 248 static  boolean_t       Gflag = B_FALSE;        /* Multicast group membership */
 249 static  boolean_t       MMflag = B_FALSE;       /* Multicast routing table */
 250 static  boolean_t       DHCPflag = B_FALSE;     /* DHCP statistics */
 251 static  boolean_t       Xflag = B_FALSE;        /* Debug Info */
 252 
 253 static  int     v4compat = 0;   /* Compatible printing format for status */
 254 
 255 static int      proto = IPPROTO_MAX;    /* all protocols */
 256 kstat_ctl_t     *kc = NULL;
 257 
 258 /*


 429          *  1, IFlag is the only feature-flag enabled
 430          * : trinary variable, modified using IFLAGMOD()
 431          */
 432         int Iflag_only = -1;
 433         boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
 434         extern char     *optarg;
 435         extern int      optind;
 436         char *default_ip_str = NULL;
 437 
 438         name = argv[0];
 439 
 440         v4compat = get_compat_flag(&default_ip_str);
 441         if (v4compat == DEFAULT_PROT_BAD_VALUE)
 442                 fatal(2, "%s: %s: Bad value for %s in %s\n", name,
 443                     default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
 444         free(default_ip_str);
 445 
 446         (void) setlocale(LC_ALL, "");
 447         (void) textdomain(TEXT_DOMAIN);
 448 
 449         while ((c = getopt(argc, argv, "adimnrspMgvxf:P:I:DRT:")) != -1) {
 450                 switch ((char)c) {
 451                 case 'a':               /* all connections */
 452                         Aflag = B_TRUE;
 453                         break;
 454 




 455                 case 'd':               /* DCE info */
 456                         Dflag = B_TRUE;
 457                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 458                         break;
 459 
 460                 case 'i':               /* interface (ill/ipif report) */
 461                         Iflag = B_TRUE;
 462                         IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
 463                         break;
 464 
 465                 case 'm':               /* streams msg report */
 466                         Mflag = B_TRUE;
 467                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 468                         break;
 469 
 470                 case 'n':               /* numeric format */
 471                         Nflag = B_TRUE;
 472                         break;
 473 
 474                 case 'r':               /* route tables */


3323                                         free(cleanlist);
3324                                         cleanlist = tlp;
3325                                 }
3326                         }
3327                         break;
3328                 }
3329                 }
3330                 (void) fflush(stdout);
3331         } /* 'for' loop 1 ends */
3332         if ((Iflag_only == 0) && (!once_only))
3333                 (void) putchar('\n');
3334         reentry = B_TRUE;
3335 }
3336 
3337 static void
3338 if_report_ip4(mib2_ipAddrEntry_t *ap,
3339     char ifname[], char logintname[], struct ifstat *statptr,
3340     boolean_t ksp_not_null)
3341 {
3342 
3343         char abuf[MAXHOSTNAMELEN + 1];
3344         char dstbuf[MAXHOSTNAMELEN + 1];
3345 
3346         if (ksp_not_null) {
3347                 (void) printf("%-5s %-4u ",
3348                     ifname, ap->ipAdEntInfo.ae_mtu);
3349                 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3350                         (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3351                             abuf, sizeof (abuf));
3352                 else
3353                         (void) pr_netaddr(ap->ipAdEntAddr,
3354                             ap->ipAdEntNetMask, abuf, sizeof (abuf));
3355                 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3356                     "%-6llu %-6llu\n",
3357                     abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3358                     statptr->ipackets, statptr->ierrors,
3359                     statptr->opackets, statptr->oerrors,
3360                     statptr->collisions, 0LL);
3361         }
3362         /*
3363          * Print logical interface info if Aflag set (including logical unit 0)


4422 
4423 static const char ire_hdr_v4[] =
4424 "\n%s Table: IPv4\n";
4425 static const char ire_hdr_v4_compat[] =
4426 "\n%s Table:\n";
4427 static const char ire_hdr_v4_verbose[] =
4428 "  Destination             Mask           Gateway          Device "
4429 " MTU  Ref Flg  Out  In/Fwd %s\n"
4430 "-------------------- --------------- -------------------- ------ "
4431 "----- --- --- ----- ------ %s\n";
4432 
4433 static const char ire_hdr_v4_normal[] =
4434 "  Destination           Gateway           Flags  Ref     Use     Interface"
4435 " %s\n-------------------- -------------------- ----- ----- ---------- "
4436 "--------- %s\n";
4437 
4438 static boolean_t
4439 ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first,
4440     const sec_attr_list_t *attrs)
4441 {
4442         char                    dstbuf[MAXHOSTNAMELEN + 1];
4443         char                    maskbuf[MAXHOSTNAMELEN + 1];
4444         char                    gwbuf[MAXHOSTNAMELEN + 1];
4445         char                    ifname[LIFNAMSIZ + 1];
4446         char                    flags[10];      /* RTF_ flags */
4447         uint_t                  flag_b;
4448 
4449         if (!(Aflag || (rp->ipRouteInfo.re_ire_type != IRE_IF_CLONE &&
4450             rp->ipRouteInfo.re_ire_type != IRE_BROADCAST &&
4451             rp->ipRouteInfo.re_ire_type != IRE_MULTICAST &&
4452             rp->ipRouteInfo.re_ire_type != IRE_NOROUTE &&
4453             rp->ipRouteInfo.re_ire_type != IRE_LOCAL))) {
4454                 return (first);
4455         }
4456 
4457         flag_b = form_v4_route_flags(rp, flags);
4458 
4459         if (!ire_filter_match_v4(rp, flag_b))
4460                 return (first);
4461 
4462         if (first) {


5540         } else {
5541                 t = 'g';
5542                 n /= 1024 * 1024 * 1024;
5543         }
5544 
5545         (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5546         return (buf);
5547 }
5548 
5549 /* --------------------- mrt_report (netstat -m) -------------------------- */
5550 
5551 static void
5552 mrt_report(mib_item_t *item)
5553 {
5554         int             jtemp = 0;
5555         struct vifctl   *vip;
5556         vifi_t          vifi;
5557         struct mfcctl   *mfccp;
5558         int             numvifs = 0;
5559         int             nmfc = 0;
5560         char            abuf[MAXHOSTNAMELEN + 1];
5561 
5562         if (!(family_selected(AF_INET)))
5563                 return;
5564 
5565         /* 'for' loop 1: */
5566         for (; item; item = item->next_item) {
5567                 if (Xflag) {
5568                         (void) printf("\n--- Entry %d ---\n", ++jtemp);
5569                         (void) printf("Group = %d, mib_id = %d, "
5570                             "length = %d, valp = 0x%p\n",
5571                             item->group, item->mib_id, item->length,
5572                             item->valp);
5573                 }
5574                 if (item->group != EXPER_DVMRP)
5575                         continue; /* 'for' loop 1 */
5576 
5577                 switch (item->mib_id) {
5578 
5579                 case EXPER_DVMRP_VIF:
5580                         if (Xflag)


5959         char *cp;
5960 
5961         if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
5962                 (void) strncpy(dst, "      *", dstlen);
5963                 dst[dstlen - 1] = 0;
5964         } else {
5965                 (void) pr_addr6(addr, dst, dstlen);
5966         }
5967         /* How much room is left? */
5968         cp = strchr(dst, '\0');
5969         if (dst + dstlen + 1 > cp) {
5970                 *cp++ = '.';
5971                 dstlen -= (cp - dst);
5972                 dstlen--;
5973                 (void) portname(port, proto, cp, dstlen);
5974         }
5975         return (dst);
5976 }
5977 
5978 /*



















































5979  * Return the name of the network whose address is given. The address is
5980  * assumed to be that of a net or subnet, not a host.
5981  */
5982 static char *
5983 pr_net(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
5984 {
5985         char            *cp = NULL;
5986         struct netent   *np = NULL;
5987         struct hostent  *hp = NULL;
5988         uint_t          net;
5989         int             subnetshift;
5990         int             error_num;


5991 
5992         if (addr == INADDR_ANY && mask == INADDR_ANY) {
5993                 (void) strncpy(dst, "default", dstlen);
5994                 dst[dstlen - 1] = 0;
5995                 return (dst);
5996         }
5997 



5998         if (!Nflag && addr) {
5999                 if (mask == 0) {
6000                         if (IN_CLASSA(addr)) {
6001                                 mask = (uint_t)IN_CLASSA_NET;
6002                                 subnetshift = 8;
6003                         } else if (IN_CLASSB(addr)) {
6004                                 mask = (uint_t)IN_CLASSB_NET;
6005                                 subnetshift = 8;
6006                         } else {
6007                                 mask = (uint_t)IN_CLASSC_NET;
6008                                 subnetshift = 4;
6009                         }
6010                         /*
6011                          * If there are more bits than the standard mask
6012                          * would suggest, subnets must be in use. Guess at
6013                          * the subnet mask, assuming reasonable width subnet
6014                          * fields.
6015                          */
6016                         while (addr & ~mask)
6017                                 /* compiler doesn't sign extend! */
6018                                 mask = (mask | ((int)mask >> subnetshift));


6019                 }
6020                 net = addr & mask;
6021                 while ((mask & 1) == 0)
6022                         mask >>= 1, net >>= 1;
6023                 ns_lookup_start();
6024                 np = getnetbyaddr(net, AF_INET);
6025                 ns_lookup_end();
6026                 if (np && np->n_net == net)
6027                         cp = np->n_name;
6028                 else {
6029                         /*
6030                          * Look for subnets in hosts map.
6031                          */
6032                         ns_lookup_start();
6033                         hp = getipnodebyaddr((char *)&addr, sizeof (uint_t),
6034                             AF_INET, &error_num);
6035                         ns_lookup_end();
6036                         if (hp)
6037                                 cp = hp->h_name;
6038                 }
6039         }
6040         if (cp != NULL) {
6041                 (void) strncpy(dst, cp, dstlen);
6042                 dst[dstlen - 1] = 0;
6043         } else {
6044                 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
6045         }



6046         if (hp != NULL)
6047                 freehostent(hp);
6048         return (dst);
6049 }
6050 
6051 /*
6052  * Return the name of the network whose address is given.
6053  * The address is assumed to be a host address.
6054  */
6055 static char *
6056 pr_netaddr(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
6057 {
6058         char            *cp = NULL;
6059         struct netent   *np = NULL;
6060         struct hostent  *hp = NULL;
6061         uint_t          net;
6062         uint_t          netshifted;
6063         int             subnetshift;
6064         struct in_addr in;
6065         int             error_num;
6066         uint_t          nbo_addr = addr;        /* network byte order */


6067 
6068         addr = ntohl(addr);
6069         mask = ntohl(mask);
6070         if (addr == INADDR_ANY && mask == INADDR_ANY) {
6071                 (void) strncpy(dst, "default", dstlen);
6072                 dst[dstlen - 1] = 0;
6073                 return (dst);
6074         }
6075 



6076         /* Figure out network portion of address (with host portion = 0) */
6077         if (addr) {
6078                 /* Try figuring out mask if unknown (all 0s). */
6079                 if (mask == 0) {
6080                         if (IN_CLASSA(addr)) {
6081                                 mask = (uint_t)IN_CLASSA_NET;
6082                                 subnetshift = 8;
6083                         } else if (IN_CLASSB(addr)) {
6084                                 mask = (uint_t)IN_CLASSB_NET;
6085                                 subnetshift = 8;
6086                         } else {
6087                                 mask = (uint_t)IN_CLASSC_NET;
6088                                 subnetshift = 4;
6089                         }
6090                         /*
6091                          * If there are more bits than the standard mask
6092                          * would suggest, subnets must be in use. Guess at
6093                          * the subnet mask, assuming reasonable width subnet
6094                          * fields.
6095                          */
6096                         while (addr & ~mask)
6097                                 /* compiler doesn't sign extend! */
6098                                 mask = (mask | ((int)mask >> subnetshift));


6099                 }
6100                 net = netshifted = addr & mask;
6101                 while ((mask & 1) == 0)
6102                         mask >>= 1, netshifted >>= 1;
6103         }
6104         else
6105                 net = netshifted = 0;
6106 
6107         /* Try looking up name unless -n was specified. */
6108         if (!Nflag) {
6109                 ns_lookup_start();
6110                 np = getnetbyaddr(netshifted, AF_INET);
6111                 ns_lookup_end();
6112                 if (np && np->n_net == netshifted)
6113                         cp = np->n_name;
6114                 else {
6115                         /*
6116                          * Look for subnets in hosts map.
6117                          */
6118                         ns_lookup_start();
6119                         hp = getipnodebyaddr((char *)&nbo_addr, sizeof (uint_t),
6120                             AF_INET, &error_num);
6121                         ns_lookup_end();
6122                         if (hp)
6123                                 cp = hp->h_name;
6124                 }
6125 
6126                 if (cp != NULL) {
6127                         (void) strncpy(dst, cp, dstlen);
6128                         dst[dstlen - 1] = 0;
6129                         if (hp != NULL)
6130                                 freehostent(hp);
6131                         return (dst);
6132                 }
6133                 /*
6134                  * No name found for net: fallthru and return in decimal
6135                  * dot notation.
6136                  */
6137         }
6138 
6139         in.s_addr = htonl(net);
6140         (void) inet_ntop(AF_INET, (char *)&in, dst, dstlen);

6141         if (hp != NULL)
6142                 freehostent(hp);
6143         return (dst);
6144 }
6145 
6146 /*
6147  * Return the filter mode as a string:
6148  *      1 => "INCLUDE"
6149  *      2 => "EXCLUDE"
6150  *      otherwise "<unknown>"
6151  */
6152 static char *
6153 fmodestr(uint_t fmode)
6154 {
6155         switch (fmode) {
6156         case 1:
6157                 return ("INCLUDE");
6158         case 2:
6159                 return ("EXCLUDE");
6160         default:




   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 1990  Mentat Inc.
  24  * netstat.c 2.2, last change 9/9/91
  25  * MROUTING Revision 3.5
  26  * Copyright 2018, Joyent, Inc.
  27  */
  28 
  29 /*
  30  * simple netstat based on snmp/mib-2 interface to the TCP/IP stack
  31  *
  32  * NOTES:
  33  * 1. A comment "LINTED: (note 1)" appears before certain lines where
  34  *    lint would have complained, "pointer cast may result in improper
  35  *    alignment". These are lines where lint had suspected potential
  36  *    improper alignment of a data structure; in each such situation
  37  *    we have relied on the kernel guaranteeing proper alignment.
  38  * 2. Some 'for' loops have been commented as "'for' loop 1", etc
  39  *    because they have 'continue' or 'break' statements in their
  40  *    bodies. 'continue' statements have been used inside some loops
  41  *    where avoiding them would have led to deep levels of indentation.
  42  *
  43  * TODO:
  44  *      Add ability to request subsets from kernel (with level = MIB2_IP;
  45  *      name = 0 meaning everything for compatibility)
  46  */


 219 static int              isnum(char *);
 220 static char             *plural(int n);
 221 static char             *pluraly(int n);
 222 static char             *plurales(int n);
 223 static void             process_filter(char *arg);
 224 static char             *ifindex2str(uint_t, char *);
 225 static boolean_t        family_selected(int family);
 226 
 227 static void             usage(char *);
 228 static void             fatal(int errcode, char *str1, ...);
 229 
 230 #define PLURAL(n) plural((int)n)
 231 #define PLURALY(n) pluraly((int)n)
 232 #define PLURALES(n) plurales((int)n)
 233 #define IFLAGMOD(flg, val1, val2)       if (flg == val1) flg = val2
 234 #define MDIFF(diff, elem2, elem1, member)       (diff)->member = \
 235         (elem2)->member - (elem1)->member
 236 
 237 
 238 static  boolean_t       Aflag = B_FALSE;        /* All sockets/ifs/rtng-tbls */
 239 static  boolean_t       CIDRflag = B_FALSE;     /* CIDR for IPv4 -i/-r addrs */
 240 static  boolean_t       Dflag = B_FALSE;        /* DCE info */
 241 static  boolean_t       Iflag = B_FALSE;        /* IP Traffic Interfaces */
 242 static  boolean_t       Mflag = B_FALSE;        /* STREAMS Memory Statistics */
 243 static  boolean_t       Nflag = B_FALSE;        /* Numeric Network Addresses */
 244 static  boolean_t       Rflag = B_FALSE;        /* Routing Tables */
 245 static  boolean_t       RSECflag = B_FALSE;     /* Security attributes */
 246 static  boolean_t       Sflag = B_FALSE;        /* Per-protocol Statistics */
 247 static  boolean_t       Vflag = B_FALSE;        /* Verbose */
 248 static  boolean_t       Pflag = B_FALSE;        /* Net to Media Tables */
 249 static  boolean_t       Gflag = B_FALSE;        /* Multicast group membership */
 250 static  boolean_t       MMflag = B_FALSE;       /* Multicast routing table */
 251 static  boolean_t       DHCPflag = B_FALSE;     /* DHCP statistics */
 252 static  boolean_t       Xflag = B_FALSE;        /* Debug Info */
 253 
 254 static  int     v4compat = 0;   /* Compatible printing format for status */
 255 
 256 static int      proto = IPPROTO_MAX;    /* all protocols */
 257 kstat_ctl_t     *kc = NULL;
 258 
 259 /*


 430          *  1, IFlag is the only feature-flag enabled
 431          * : trinary variable, modified using IFLAGMOD()
 432          */
 433         int Iflag_only = -1;
 434         boolean_t once_only = B_FALSE; /* '-i' with count > 1 */
 435         extern char     *optarg;
 436         extern int      optind;
 437         char *default_ip_str = NULL;
 438 
 439         name = argv[0];
 440 
 441         v4compat = get_compat_flag(&default_ip_str);
 442         if (v4compat == DEFAULT_PROT_BAD_VALUE)
 443                 fatal(2, "%s: %s: Bad value for %s in %s\n", name,
 444                     default_ip_str, DEFAULT_IP, INET_DEFAULT_FILE);
 445         free(default_ip_str);
 446 
 447         (void) setlocale(LC_ALL, "");
 448         (void) textdomain(TEXT_DOMAIN);
 449 
 450         while ((c = getopt(argc, argv, "acdimnrspMgvxf:P:I:DRT:")) != -1) {
 451                 switch ((char)c) {
 452                 case 'a':               /* all connections */
 453                         Aflag = B_TRUE;
 454                         break;
 455 
 456                 case 'c':
 457                         CIDRflag = B_TRUE;
 458                         break;
 459 
 460                 case 'd':               /* DCE info */
 461                         Dflag = B_TRUE;
 462                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 463                         break;
 464 
 465                 case 'i':               /* interface (ill/ipif report) */
 466                         Iflag = B_TRUE;
 467                         IFLAGMOD(Iflag_only, -1, 1); /* '-i' exists */
 468                         break;
 469 
 470                 case 'm':               /* streams msg report */
 471                         Mflag = B_TRUE;
 472                         IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
 473                         break;
 474 
 475                 case 'n':               /* numeric format */
 476                         Nflag = B_TRUE;
 477                         break;
 478 
 479                 case 'r':               /* route tables */


3328                                         free(cleanlist);
3329                                         cleanlist = tlp;
3330                                 }
3331                         }
3332                         break;
3333                 }
3334                 }
3335                 (void) fflush(stdout);
3336         } /* 'for' loop 1 ends */
3337         if ((Iflag_only == 0) && (!once_only))
3338                 (void) putchar('\n');
3339         reentry = B_TRUE;
3340 }
3341 
3342 static void
3343 if_report_ip4(mib2_ipAddrEntry_t *ap,
3344     char ifname[], char logintname[], struct ifstat *statptr,
3345     boolean_t ksp_not_null)
3346 {
3347 
3348         char abuf[MAXHOSTNAMELEN + 4];  /* Include /<num> for CIDR-printing. */
3349         char dstbuf[MAXHOSTNAMELEN + 1];
3350 
3351         if (ksp_not_null) {
3352                 (void) printf("%-5s %-4u ",
3353                     ifname, ap->ipAdEntInfo.ae_mtu);
3354                 if (ap->ipAdEntInfo.ae_flags & IFF_POINTOPOINT)
3355                         (void) pr_addr(ap->ipAdEntInfo.ae_pp_dst_addr,
3356                             abuf, sizeof (abuf));
3357                 else
3358                         (void) pr_netaddr(ap->ipAdEntAddr,
3359                             ap->ipAdEntNetMask, abuf, sizeof (abuf));
3360                 (void) printf("%-13s %-14s %-6llu %-5llu %-6llu %-5llu "
3361                     "%-6llu %-6llu\n",
3362                     abuf, pr_addr(ap->ipAdEntAddr, dstbuf, sizeof (dstbuf)),
3363                     statptr->ipackets, statptr->ierrors,
3364                     statptr->opackets, statptr->oerrors,
3365                     statptr->collisions, 0LL);
3366         }
3367         /*
3368          * Print logical interface info if Aflag set (including logical unit 0)


4427 
4428 static const char ire_hdr_v4[] =
4429 "\n%s Table: IPv4\n";
4430 static const char ire_hdr_v4_compat[] =
4431 "\n%s Table:\n";
4432 static const char ire_hdr_v4_verbose[] =
4433 "  Destination             Mask           Gateway          Device "
4434 " MTU  Ref Flg  Out  In/Fwd %s\n"
4435 "-------------------- --------------- -------------------- ------ "
4436 "----- --- --- ----- ------ %s\n";
4437 
4438 static const char ire_hdr_v4_normal[] =
4439 "  Destination           Gateway           Flags  Ref     Use     Interface"
4440 " %s\n-------------------- -------------------- ----- ----- ---------- "
4441 "--------- %s\n";
4442 
4443 static boolean_t
4444 ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first,
4445     const sec_attr_list_t *attrs)
4446 {
4447         char                    dstbuf[MAXHOSTNAMELEN + 4]; /* + "/<num>" */
4448         char                    maskbuf[MAXHOSTNAMELEN + 1];
4449         char                    gwbuf[MAXHOSTNAMELEN + 1];
4450         char                    ifname[LIFNAMSIZ + 1];
4451         char                    flags[10];      /* RTF_ flags */
4452         uint_t                  flag_b;
4453 
4454         if (!(Aflag || (rp->ipRouteInfo.re_ire_type != IRE_IF_CLONE &&
4455             rp->ipRouteInfo.re_ire_type != IRE_BROADCAST &&
4456             rp->ipRouteInfo.re_ire_type != IRE_MULTICAST &&
4457             rp->ipRouteInfo.re_ire_type != IRE_NOROUTE &&
4458             rp->ipRouteInfo.re_ire_type != IRE_LOCAL))) {
4459                 return (first);
4460         }
4461 
4462         flag_b = form_v4_route_flags(rp, flags);
4463 
4464         if (!ire_filter_match_v4(rp, flag_b))
4465                 return (first);
4466 
4467         if (first) {


5545         } else {
5546                 t = 'g';
5547                 n /= 1024 * 1024 * 1024;
5548         }
5549 
5550         (void) snprintf(buf, sizeof (buf), "%4u%c", n, t);
5551         return (buf);
5552 }
5553 
5554 /* --------------------- mrt_report (netstat -m) -------------------------- */
5555 
5556 static void
5557 mrt_report(mib_item_t *item)
5558 {
5559         int             jtemp = 0;
5560         struct vifctl   *vip;
5561         vifi_t          vifi;
5562         struct mfcctl   *mfccp;
5563         int             numvifs = 0;
5564         int             nmfc = 0;
5565         char            abuf[MAXHOSTNAMELEN + 4]; /* Include CIDR /<num>. */
5566 
5567         if (!(family_selected(AF_INET)))
5568                 return;
5569 
5570         /* 'for' loop 1: */
5571         for (; item; item = item->next_item) {
5572                 if (Xflag) {
5573                         (void) printf("\n--- Entry %d ---\n", ++jtemp);
5574                         (void) printf("Group = %d, mib_id = %d, "
5575                             "length = %d, valp = 0x%p\n",
5576                             item->group, item->mib_id, item->length,
5577                             item->valp);
5578                 }
5579                 if (item->group != EXPER_DVMRP)
5580                         continue; /* 'for' loop 1 */
5581 
5582                 switch (item->mib_id) {
5583 
5584                 case EXPER_DVMRP_VIF:
5585                         if (Xflag)


5964         char *cp;
5965 
5966         if (IN6_IS_ADDR_UNSPECIFIED(addr)) {
5967                 (void) strncpy(dst, "      *", dstlen);
5968                 dst[dstlen - 1] = 0;
5969         } else {
5970                 (void) pr_addr6(addr, dst, dstlen);
5971         }
5972         /* How much room is left? */
5973         cp = strchr(dst, '\0');
5974         if (dst + dstlen + 1 > cp) {
5975                 *cp++ = '.';
5976                 dstlen -= (cp - dst);
5977                 dstlen--;
5978                 (void) portname(port, proto, cp, dstlen);
5979         }
5980         return (dst);
5981 }
5982 
5983 /*
5984  * Returns -2 to indicate a discontiguous mask.  Otherwise returns between
5985  * 0 and 32.
5986  */
5987 static int
5988 v4_cidr_len(uint_t mask)
5989 {
5990         int rc = 0;
5991         int i;
5992 
5993         for (i = 0; i < 32; i++) {
5994                 if (mask & 0x1)
5995                         rc++;
5996                 else if (rc > 0)
5997                         return (-2);    /* Discontiguous IPv4 netmask. */
5998 
5999                 mask >>= 1;
6000         }
6001 
6002         return (rc);
6003 }
6004 
6005 static void
6006 append_v4_cidr_len(char *dst, uint_t dstlen, int prefixlen)
6007 {
6008         char *prefixptr;
6009 
6010         /* 4 bytes leaves room for '/' 'N' 'N' '\0' */
6011         if (strlen(dst) <= dstlen - 4) {
6012                 prefixptr = dst + strlen(dst);
6013         } else {
6014                 /*
6015                  * Cut off last 3 chars of very-long DNS name.  All callers
6016                  * should give us enough room, but name services COULD give us
6017                  * a way-too-big name (see above).
6018                  */
6019                 prefixptr = dst + strlen(dst) - 3;
6020         }
6021         /* At this point "prefixptr" is guaranteed to point to 4 bytes. */
6022 
6023         if (prefixlen >= 0) {
6024                 if (prefixlen > 32)  /* Shouldn't happen, but... */
6025                         prefixlen = 32;
6026                 (void) snprintf(prefixptr, 4, "/%d", prefixlen);
6027         } else if (prefixlen == -2) {
6028                 /* "/NM" == Noncontiguous Mask. */
6029                 (void) strcat(prefixptr, "/NM");
6030         }
6031         /* Else print nothing extra. */
6032 }
6033 
6034 /*
6035  * Return the name of the network whose address is given. The address is
6036  * assumed to be that of a net or subnet, not a host.
6037  */
6038 static char *
6039 pr_net(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
6040 {
6041         char            *cp = NULL;
6042         struct netent   *np = NULL;
6043         struct hostent  *hp = NULL;
6044         uint_t          net;
6045         int             subnetshift;
6046         int             error_num;
6047         int             prefixlen = -1; /* -1 == Don't print prefix! */
6048                                         /* -2 == Noncontiguous mask... */
6049 
6050         if (addr == INADDR_ANY && mask == INADDR_ANY) {
6051                 (void) strlcpy(dst, "default", dstlen);

6052                 return (dst);
6053         }
6054 
6055         if (CIDRflag)
6056                 prefixlen = v4_cidr_len(ntohl(mask));
6057 
6058         if (!Nflag && addr) {
6059                 if (mask == 0) {
6060                         if (IN_CLASSA(addr)) {
6061                                 mask = (uint_t)IN_CLASSA_NET;
6062                                 subnetshift = 8;
6063                         } else if (IN_CLASSB(addr)) {
6064                                 mask = (uint_t)IN_CLASSB_NET;
6065                                 subnetshift = 8;
6066                         } else {
6067                                 mask = (uint_t)IN_CLASSC_NET;
6068                                 subnetshift = 4;
6069                         }
6070                         /*
6071                          * If there are more bits than the standard mask
6072                          * would suggest, subnets must be in use. Guess at
6073                          * the subnet mask, assuming reasonable width subnet
6074                          * fields.
6075                          */
6076                         while (addr & ~mask)
6077                                 /* compiler doesn't sign extend! */
6078                                 mask = (mask | ((int)mask >> subnetshift));
6079                         if (CIDRflag)
6080                                 prefixlen = v4_cidr_len(mask);
6081                 }
6082                 net = addr & mask;
6083                 while ((mask & 1) == 0)
6084                         mask >>= 1, net >>= 1;
6085                 ns_lookup_start();
6086                 np = getnetbyaddr(net, AF_INET);
6087                 ns_lookup_end();
6088                 if (np && np->n_net == net)
6089                         cp = np->n_name;
6090                 else {
6091                         /*
6092                          * Look for subnets in hosts map.
6093                          */
6094                         ns_lookup_start();
6095                         hp = getipnodebyaddr((char *)&addr, sizeof (uint_t),
6096                             AF_INET, &error_num);
6097                         ns_lookup_end();
6098                         if (hp)
6099                                 cp = hp->h_name;
6100                 }
6101         }
6102         if (cp != NULL) {
6103                 (void) strlcpy(dst, cp, dstlen);

6104         } else {
6105                 (void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
6106         }
6107 
6108         append_v4_cidr_len(dst, dstlen, prefixlen);
6109 
6110         if (hp != NULL)
6111                 freehostent(hp);
6112         return (dst);
6113 }
6114 
6115 /*
6116  * Return the name of the network whose address is given.
6117  * The address is assumed to be a host address.
6118  */
6119 static char *
6120 pr_netaddr(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
6121 {
6122         char            *cp = NULL;
6123         struct netent   *np = NULL;
6124         struct hostent  *hp = NULL;
6125         uint_t          net;
6126         uint_t          netshifted;
6127         int             subnetshift;
6128         struct in_addr in;
6129         int             error_num;
6130         uint_t          nbo_addr = addr;        /* network byte order */
6131         int             prefixlen = -1; /* -1 == Don't print prefix! */
6132                                         /* -2 == Noncontiguous mask... */
6133 
6134         addr = ntohl(addr);
6135         mask = ntohl(mask);
6136         if (addr == INADDR_ANY && mask == INADDR_ANY) {
6137                 (void) strlcpy(dst, "default", dstlen);

6138                 return (dst);
6139         }
6140 
6141         if (CIDRflag)
6142                 prefixlen = v4_cidr_len(mask);
6143 
6144         /* Figure out network portion of address (with host portion = 0) */
6145         if (addr) {
6146                 /* Try figuring out mask if unknown (all 0s). */
6147                 if (mask == 0) {
6148                         if (IN_CLASSA(addr)) {
6149                                 mask = (uint_t)IN_CLASSA_NET;
6150                                 subnetshift = 8;
6151                         } else if (IN_CLASSB(addr)) {
6152                                 mask = (uint_t)IN_CLASSB_NET;
6153                                 subnetshift = 8;
6154                         } else {
6155                                 mask = (uint_t)IN_CLASSC_NET;
6156                                 subnetshift = 4;
6157                         }
6158                         /*
6159                          * If there are more bits than the standard mask
6160                          * would suggest, subnets must be in use. Guess at
6161                          * the subnet mask, assuming reasonable width subnet
6162                          * fields.
6163                          */
6164                         while (addr & ~mask)
6165                                 /* compiler doesn't sign extend! */
6166                                 mask = (mask | ((int)mask >> subnetshift));
6167                         if (CIDRflag)
6168                                 prefixlen = v4_cidr_len(mask);
6169                 }
6170                 net = netshifted = addr & mask;
6171                 while ((mask & 1) == 0)
6172                         mask >>= 1, netshifted >>= 1;
6173         }
6174         else
6175                 net = netshifted = 0;
6176 
6177         /* Try looking up name unless -n was specified. */
6178         if (!Nflag) {
6179                 ns_lookup_start();
6180                 np = getnetbyaddr(netshifted, AF_INET);
6181                 ns_lookup_end();
6182                 if (np && np->n_net == netshifted)
6183                         cp = np->n_name;
6184                 else {
6185                         /*
6186                          * Look for subnets in hosts map.
6187                          */
6188                         ns_lookup_start();
6189                         hp = getipnodebyaddr((char *)&nbo_addr, sizeof (uint_t),
6190                             AF_INET, &error_num);
6191                         ns_lookup_end();
6192                         if (hp)
6193                                 cp = hp->h_name;
6194                 }
6195 
6196                 if (cp != NULL) {
6197                         (void) strlcpy(dst, cp, dstlen);
6198                         append_v4_cidr_len(dst, dstlen, prefixlen);
6199                         if (hp != NULL)
6200                                 freehostent(hp);
6201                         return (dst);
6202                 }
6203                 /*
6204                  * No name found for net: fallthru and return in decimal
6205                  * dot notation.
6206                  */
6207         }
6208 
6209         in.s_addr = htonl(net);
6210         (void) inet_ntop(AF_INET, (char *)&in, dst, dstlen);
6211         append_v4_cidr_len(dst, dstlen, prefixlen);
6212         if (hp != NULL)
6213                 freehostent(hp);
6214         return (dst);
6215 }
6216 
6217 /*
6218  * Return the filter mode as a string:
6219  *      1 => "INCLUDE"
6220  *      2 => "EXCLUDE"
6221  *      otherwise "<unknown>"
6222  */
6223 static char *
6224 fmodestr(uint_t fmode)
6225 {
6226         switch (fmode) {
6227         case 1:
6228                 return ("INCLUDE");
6229         case 2:
6230                 return ("EXCLUDE");
6231         default: