Hello,
I noticed that when doing a netstat -s (running on a kernel without
SCTP support compiled in), I get the following message output to stderr:
netstat: sysctl: net.inet.sctp.stats: No such file or directory
Wondering why it would attempt to fetch SCTP stats when it was
compiled out of the kernel, I noted that netstat could be compiled
without SCTP support as well, but that there is no good way to link
the two compilation conditions, or to have a generic binary that can
run without error regardless of compiled kernel options.
To that end, I added a method to check for environment compatibility
in netstat. For SCTP specifically, I used the FEATURE macros and added
SCTP as a FEATURE.
Other protocols could also be configured to be checked at runtime if
desired, though I haven't implemented any others at this time.
-- Sean
--- main.c@@/main/RELENG_8/RELENG_8_2/plt_ag_os/0 2011-10-21 11:35:33.000000000 -0400
+++ main.c 2011-10-24 14:30:13.000000000 -0400
@@ -198,106 +198,109 @@ struct protox {
void (*pr_stats)(u_long, const char *, int, int);
/* statistics printing routine */
void (*pr_istats)(char *); /* per/if statistics printing routine */
+ int (*feature_test)(void); /* test routine to determine if kernel
+ suppport exists for protocol */
const char *pr_name; /* well-known name */
int pr_usesysctl; /* non-zero if we use sysctl, not kvm */
int pr_protocol;
} protox[] = {
{ N_TCBINFO, N_TCPSTAT, 1, protopr,
- tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ tcp_stats, NULL, NULL, "tcp", 1, IPPROTO_TCP },
{ N_UDBINFO, N_UDPSTAT, 1, protopr,
- udp_stats, NULL, "udp", 1, IPPROTO_UDP },
+ udp_stats, NULL, NULL, "udp", 1, IPPROTO_UDP },
#ifdef SCTP
{ -1, N_SCTPSTAT, 1, sctp_protopr,
- sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP },
+ sctp_stats, NULL, sctp_feature_test, "sctp", 1,
+ IPPROTO_SCTP },
#endif
{ N_DIVCBINFO, -1, 1, protopr,
- NULL, NULL, "divert", 1, IPPROTO_DIVERT },
+ NULL, NULL, NULL, "divert", 1, IPPROTO_DIVERT },
{ N_RIPCBINFO, N_IPSTAT, 1, protopr,
- ip_stats, NULL, "ip", 1, IPPROTO_RAW },
+ ip_stats, NULL, NULL, "ip", 1, IPPROTO_RAW },
{ N_RIPCBINFO, N_ICMPSTAT, 1, protopr,
- icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP },
+ icmp_stats, NULL, NULL, "icmp", 1, IPPROTO_ICMP },
{ N_RIPCBINFO, N_IGMPSTAT, 1, protopr,
- igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP },
+ igmp_stats, NULL, NULL, "igmp", 1, IPPROTO_IGMP },
#ifdef IPSEC
{ -1, N_IPSECSTAT, 1, NULL, /* keep as compat */
- ipsec_stats, NULL, "ipsec", 0, 0},
+ ipsec_stats, NULL, NULL, "ipsec", 0, 0},
{ -1, N_AHSTAT, 1, NULL,
- ah_stats, NULL, "ah", 0, 0},
+ ah_stats, NULL, NULL, "ah", 0, 0},
{ -1, N_ESPSTAT, 1, NULL,
- esp_stats, NULL, "esp", 0, 0},
+ esp_stats, NULL, NULL, "esp", 0, 0},
{ -1, N_IPCOMPSTAT, 1, NULL,
- ipcomp_stats, NULL, "ipcomp", 0, 0},
+ ipcomp_stats, NULL, NULL, "ipcomp", 0, 0},
#endif
{ N_RIPCBINFO, N_PIMSTAT, 1, protopr,
- pim_stats, NULL, "pim", 1, IPPROTO_PIM },
+ pim_stats, NULL, NULL, "pim", 1, IPPROTO_PIM },
{ -1, N_CARPSTAT, 1, NULL,
- carp_stats, NULL, "carp", 1, 0 },
+ carp_stats, NULL, NULL, "carp", 1, 0 },
{ -1, N_PFSYNCSTAT, 1, NULL,
- pfsync_stats, NULL, "pfsync", 1, 0 },
+ pfsync_stats, NULL, NULL, "pfsync", 1, 0 },
{ -1, N_ARPSTAT, 1, NULL,
- arp_stats, NULL, "arp", 1, 0 },
+ arp_stats, NULL, NULL, "arp", 1, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0, 0 }
+ NULL, NULL, NULL, NULL, 0, 0 }
};
#ifdef INET6
struct protox ip6protox[] = {
{ N_TCBINFO, N_TCPSTAT, 1, protopr,
- tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ tcp_stats, NULL, NULL, "tcp", 1, IPPROTO_TCP },
{ N_UDBINFO, N_UDPSTAT, 1, protopr,
- udp_stats, NULL, "udp", 1, IPPROTO_UDP },
+ udp_stats, NULL, NULL, "udp", 1, IPPROTO_UDP },
{ N_RIPCBINFO, N_IP6STAT, 1, protopr,
- ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW },
+ ip6_stats, ip6_ifstats, NULL, "ip6", 1, IPPROTO_RAW },
{ N_RIPCBINFO, N_ICMP6STAT, 1, protopr,
- icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 },
+ icmp6_stats, icmp6_ifstats, NULL, "icmp6", 1, IPPROTO_ICMPV6 },
#ifdef IPSEC
{ -1, N_IPSEC6STAT, 1, NULL,
- ipsec_stats, NULL, "ipsec6", 0, 0 },
+ ipsec_stats, NULL, NULL, "ipsec6", 0, 0 },
#endif
#ifdef notyet
{ -1, N_PIM6STAT, 1, NULL,
- pim6_stats, NULL, "pim6", 1, 0 },
+ pim6_stats, NULL, NULL, "pim6", 1, 0 },
#endif
{ -1, N_RIP6STAT, 1, NULL,
- rip6_stats, NULL, "rip6", 1, 0 },
+ rip6_stats, NULL, NULL, "rip6", 1, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0, 0 }
+ NULL, NULL, NULL, NULL, 0, 0 }
};
#endif /*INET6*/
#ifdef IPSEC
struct protox pfkeyprotox[] = {
{ -1, N_PFKEYSTAT, 1, NULL,
- pfkey_stats, NULL, "pfkey", 0, 0 },
+ pfkey_stats, NULL, NULL, "pfkey", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0, 0 }
+ NULL, NULL, NULL, NULL, 0, 0 }
};
#endif
struct protox atalkprotox[] = {
{ N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
- ddp_stats, NULL, "ddp", 0, 0 },
+ ddp_stats, NULL, NULL, "ddp", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0, 0 }
+ NULL, NULL, NULL, NULL, 0, 0 }
};
#ifdef NETGRAPH
struct protox netgraphprotox[] = {
{ N_NGSOCKS, -1, 1, netgraphprotopr,
- NULL, NULL, "ctrl", 0, 0 },
+ NULL, NULL, NULL, "ctrl", 0, 0 },
{ N_NGSOCKS, -1, 1, netgraphprotopr,
- NULL, NULL, "data", 0, 0 },
+ NULL, NULL, NULL, "data", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, NULL, 0, 0 }
+ NULL, NULL, NULL, NULL, 0, 0 }
};
#endif
#ifdef IPX
struct protox ipxprotox[] = {
{ N_IPX, N_IPXSTAT, 1, ipxprotopr,
- ipx_stats, NULL, "ipx", 0, 0 },
+ ipx_stats, NULL, NULL, "ipx", 0, 0 },
{ N_IPX, N_SPXSTAT, 1, ipxprotopr,
- spx_stats, NULL, "spx", 0, 0 },
+ spx_stats, NULL, NULL, "spx", 0, 0 },
{ -1, -1, 0, NULL,
- NULL, NULL, 0, 0, 0 }
+ NULL, NULL, NULL, 0, 0, 0 }
};
#endif
@@ -624,6 +627,12 @@ printproto(tp, name)
void (*pr)(u_long, const char *, int, int);
u_long off;
+ if (tp->feature_test != NULL && !(*tp->feature_test)()) {
+ if (pflag)
+ fprintf(stderr, "%s: not supported in kernel\n", tp->pr_name);
+ return;
+ }
+
if (sflag) {
if (iflag) {
if (tp->pr_istats)
--- netstat.h@@/main/RELENG_8/RELENG_8_2/plt_ag_os/0 2011-10-21 12:16:04.000000000 -0400
+++ netstat.h 2011-10-24 14:30:13.000000000 -0400
@@ -73,6 +73,7 @@ void protopr(u_long, const char *, int,
void tcp_stats(u_long, const char *, int, int);
void udp_stats(u_long, const char *, int, int);
#ifdef SCTP
+int sctp_feature_test(void);
void sctp_protopr(u_long, const char *, int, int);
void sctp_stats(u_long, const char *, int, int);
#endif
--- sctp.c@@/main/RELENG_8/RELENG_8_2/plt_ag_os/0 2011-10-20 18:00:53.000000000 -0400
+++ sctp.c 2011-10-24 14:30:14.000000000 -0400
@@ -102,6 +102,13 @@ struct xraddr_entry {
LIST_ENTRY(xraddr_entry) xraddr_entries;
};
+int
+sctp_feature_test(void)
+{
+
+ return (feature_present("sctp"));
+}
+
static int
sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
{
--- sctp_sysctl.c@@/main/RELENG_8/RELENG_8_2/plt_ag_os/0 2011-10-20 17:36:01.000000000 -0400
+++ sctp_sysctl.c 2011-10-24 14:30:11.000000000 -0400
@@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_output.h>
#include <sys/smp.h>
+FEATURE(sctp, "Stream Control Transmission Protocol");
+
/*
* sysctl tunable variables
*/
_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"