Print this page
9352 netstat(1M) should be able to print IPv4 networks in CIDR form
*** 21,31 ****
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1990 Mentat Inc.
* netstat.c 2.2, last change 9/9/91
* MROUTING Revision 3.5
! * Copyright (c) 2017, Joyent, Inc.
*/
/*
* simple netstat based on snmp/mib-2 interface to the TCP/IP stack
*
--- 21,31 ----
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1990 Mentat Inc.
* netstat.c 2.2, last change 9/9/91
* MROUTING Revision 3.5
! * Copyright 2018, Joyent, Inc.
*/
/*
* simple netstat based on snmp/mib-2 interface to the TCP/IP stack
*
*** 234,243 ****
--- 234,244 ----
#define MDIFF(diff, elem2, elem1, member) (diff)->member = \
(elem2)->member - (elem1)->member
static boolean_t Aflag = B_FALSE; /* All sockets/ifs/rtng-tbls */
+ static boolean_t CIDRflag = B_FALSE; /* CIDR for IPv4 -i/-r addrs */
static boolean_t Dflag = B_FALSE; /* DCE info */
static boolean_t Iflag = B_FALSE; /* IP Traffic Interfaces */
static boolean_t Mflag = B_FALSE; /* STREAMS Memory Statistics */
static boolean_t Nflag = B_FALSE; /* Numeric Network Addresses */
static boolean_t Rflag = B_FALSE; /* Routing Tables */
*** 444,459 ****
free(default_ip_str);
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
! while ((c = getopt(argc, argv, "adimnrspMgvxf:P:I:DRT:")) != -1) {
switch ((char)c) {
case 'a': /* all connections */
Aflag = B_TRUE;
break;
case 'd': /* DCE info */
Dflag = B_TRUE;
IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
break;
--- 445,464 ----
free(default_ip_str);
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
! while ((c = getopt(argc, argv, "acdimnrspMgvxf:P:I:DRT:")) != -1) {
switch ((char)c) {
case 'a': /* all connections */
Aflag = B_TRUE;
break;
+ case 'c':
+ CIDRflag = B_TRUE;
+ break;
+
case 'd': /* DCE info */
Dflag = B_TRUE;
IFLAGMOD(Iflag_only, 1, 0); /* see macro def'n */
break;
*** 3338,3348 ****
if_report_ip4(mib2_ipAddrEntry_t *ap,
char ifname[], char logintname[], struct ifstat *statptr,
boolean_t ksp_not_null)
{
! char abuf[MAXHOSTNAMELEN + 1];
char dstbuf[MAXHOSTNAMELEN + 1];
if (ksp_not_null) {
(void) printf("%-5s %-4u ",
ifname, ap->ipAdEntInfo.ae_mtu);
--- 3343,3353 ----
if_report_ip4(mib2_ipAddrEntry_t *ap,
char ifname[], char logintname[], struct ifstat *statptr,
boolean_t ksp_not_null)
{
! char abuf[MAXHOSTNAMELEN + 4]; /* Include /<num> for CIDR-printing. */
char dstbuf[MAXHOSTNAMELEN + 1];
if (ksp_not_null) {
(void) printf("%-5s %-4u ",
ifname, ap->ipAdEntInfo.ae_mtu);
*** 4437,4447 ****
static boolean_t
ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first,
const sec_attr_list_t *attrs)
{
! char dstbuf[MAXHOSTNAMELEN + 1];
char maskbuf[MAXHOSTNAMELEN + 1];
char gwbuf[MAXHOSTNAMELEN + 1];
char ifname[LIFNAMSIZ + 1];
char flags[10]; /* RTF_ flags */
uint_t flag_b;
--- 4442,4452 ----
static boolean_t
ire_report_item_v4(const mib2_ipRouteEntry_t *rp, boolean_t first,
const sec_attr_list_t *attrs)
{
! char dstbuf[MAXHOSTNAMELEN + 4]; /* + "/<num>" */
char maskbuf[MAXHOSTNAMELEN + 1];
char gwbuf[MAXHOSTNAMELEN + 1];
char ifname[LIFNAMSIZ + 1];
char flags[10]; /* RTF_ flags */
uint_t flag_b;
*** 5555,5565 ****
struct vifctl *vip;
vifi_t vifi;
struct mfcctl *mfccp;
int numvifs = 0;
int nmfc = 0;
! char abuf[MAXHOSTNAMELEN + 1];
if (!(family_selected(AF_INET)))
return;
/* 'for' loop 1: */
--- 5560,5570 ----
struct vifctl *vip;
vifi_t vifi;
struct mfcctl *mfccp;
int numvifs = 0;
int nmfc = 0;
! char abuf[MAXHOSTNAMELEN + 4]; /* Include CIDR /<num>. */
if (!(family_selected(AF_INET)))
return;
/* 'for' loop 1: */
*** 5974,5983 ****
--- 5979,6039 ----
}
return (dst);
}
/*
+ * Returns -2 to indicate a discontiguous mask. Otherwise returns between
+ * 0 and 32.
+ */
+ static int
+ v4_cidr_len(uint_t mask)
+ {
+ int rc = 0;
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ if (mask & 0x1)
+ rc++;
+ else if (rc > 0)
+ return (-2); /* Discontiguous IPv4 netmask. */
+
+ mask >>= 1;
+ }
+
+ return (rc);
+ }
+
+ static void
+ append_v4_cidr_len(char *dst, uint_t dstlen, int prefixlen)
+ {
+ char *prefixptr;
+
+ /* 4 bytes leaves room for '/' 'N' 'N' '\0' */
+ if (strlen(dst) <= dstlen - 4) {
+ prefixptr = dst + strlen(dst);
+ } else {
+ /*
+ * Cut off last 3 chars of very-long DNS name. All callers
+ * should give us enough room, but name services COULD give us
+ * a way-too-big name (see above).
+ */
+ prefixptr = dst + strlen(dst) - 3;
+ }
+ /* At this point "prefixptr" is guaranteed to point to 4 bytes. */
+
+ if (prefixlen >= 0) {
+ if (prefixlen > 32) /* Shouldn't happen, but... */
+ prefixlen = 32;
+ (void) snprintf(prefixptr, 4, "/%d", prefixlen);
+ } else if (prefixlen == -2) {
+ /* "/NM" == Noncontiguous Mask. */
+ (void) strcat(prefixptr, "/NM");
+ }
+ /* Else print nothing extra. */
+ }
+
+ /*
* Return the name of the network whose address is given. The address is
* assumed to be that of a net or subnet, not a host.
*/
static char *
pr_net(uint_t addr, uint_t mask, char *dst, uint_t dstlen)
*** 5986,6002 ****
struct netent *np = NULL;
struct hostent *hp = NULL;
uint_t net;
int subnetshift;
int error_num;
if (addr == INADDR_ANY && mask == INADDR_ANY) {
! (void) strncpy(dst, "default", dstlen);
! dst[dstlen - 1] = 0;
return (dst);
}
if (!Nflag && addr) {
if (mask == 0) {
if (IN_CLASSA(addr)) {
mask = (uint_t)IN_CLASSA_NET;
subnetshift = 8;
--- 6042,6062 ----
struct netent *np = NULL;
struct hostent *hp = NULL;
uint_t net;
int subnetshift;
int error_num;
+ int prefixlen = -1; /* -1 == Don't print prefix! */
+ /* -2 == Noncontiguous mask... */
if (addr == INADDR_ANY && mask == INADDR_ANY) {
! (void) strlcpy(dst, "default", dstlen);
return (dst);
}
+ if (CIDRflag)
+ prefixlen = v4_cidr_len(ntohl(mask));
+
if (!Nflag && addr) {
if (mask == 0) {
if (IN_CLASSA(addr)) {
mask = (uint_t)IN_CLASSA_NET;
subnetshift = 8;
*** 6014,6023 ****
--- 6074,6085 ----
* fields.
*/
while (addr & ~mask)
/* compiler doesn't sign extend! */
mask = (mask | ((int)mask >> subnetshift));
+ if (CIDRflag)
+ prefixlen = v4_cidr_len(mask);
}
net = addr & mask;
while ((mask & 1) == 0)
mask >>= 1, net >>= 1;
ns_lookup_start();
*** 6036,6050 ****
if (hp)
cp = hp->h_name;
}
}
if (cp != NULL) {
! (void) strncpy(dst, cp, dstlen);
! dst[dstlen - 1] = 0;
} else {
(void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
}
if (hp != NULL)
freehostent(hp);
return (dst);
}
--- 6098,6114 ----
if (hp)
cp = hp->h_name;
}
}
if (cp != NULL) {
! (void) strlcpy(dst, cp, dstlen);
} else {
(void) inet_ntop(AF_INET, (char *)&addr, dst, dstlen);
}
+
+ append_v4_cidr_len(dst, dstlen, prefixlen);
+
if (hp != NULL)
freehostent(hp);
return (dst);
}
*** 6062,6080 ****
uint_t netshifted;
int subnetshift;
struct in_addr in;
int error_num;
uint_t nbo_addr = addr; /* network byte order */
addr = ntohl(addr);
mask = ntohl(mask);
if (addr == INADDR_ANY && mask == INADDR_ANY) {
! (void) strncpy(dst, "default", dstlen);
! dst[dstlen - 1] = 0;
return (dst);
}
/* Figure out network portion of address (with host portion = 0) */
if (addr) {
/* Try figuring out mask if unknown (all 0s). */
if (mask == 0) {
if (IN_CLASSA(addr)) {
--- 6126,6148 ----
uint_t netshifted;
int subnetshift;
struct in_addr in;
int error_num;
uint_t nbo_addr = addr; /* network byte order */
+ int prefixlen = -1; /* -1 == Don't print prefix! */
+ /* -2 == Noncontiguous mask... */
addr = ntohl(addr);
mask = ntohl(mask);
if (addr == INADDR_ANY && mask == INADDR_ANY) {
! (void) strlcpy(dst, "default", dstlen);
return (dst);
}
+ if (CIDRflag)
+ prefixlen = v4_cidr_len(mask);
+
/* Figure out network portion of address (with host portion = 0) */
if (addr) {
/* Try figuring out mask if unknown (all 0s). */
if (mask == 0) {
if (IN_CLASSA(addr)) {
*** 6094,6103 ****
--- 6162,6173 ----
* fields.
*/
while (addr & ~mask)
/* compiler doesn't sign extend! */
mask = (mask | ((int)mask >> subnetshift));
+ if (CIDRflag)
+ prefixlen = v4_cidr_len(mask);
}
net = netshifted = addr & mask;
while ((mask & 1) == 0)
mask >>= 1, netshifted >>= 1;
}
*** 6122,6133 ****
if (hp)
cp = hp->h_name;
}
if (cp != NULL) {
! (void) strncpy(dst, cp, dstlen);
! dst[dstlen - 1] = 0;
if (hp != NULL)
freehostent(hp);
return (dst);
}
/*
--- 6192,6203 ----
if (hp)
cp = hp->h_name;
}
if (cp != NULL) {
! (void) strlcpy(dst, cp, dstlen);
! append_v4_cidr_len(dst, dstlen, prefixlen);
if (hp != NULL)
freehostent(hp);
return (dst);
}
/*
*** 6136,6145 ****
--- 6206,6216 ----
*/
}
in.s_addr = htonl(net);
(void) inet_ntop(AF_INET, (char *)&in, dst, dstlen);
+ append_v4_cidr_len(dst, dstlen, prefixlen);
if (hp != NULL)
freehostent(hp);
return (dst);
}