From owner-freebsd-net@FreeBSD.ORG Tue Oct 25 18:41:09 2011 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE9BC106564A for ; Tue, 25 Oct 2011 18:41:09 +0000 (UTC) (envelope-from smahood@uwaterloo.ca) Received: from ecserv7.uwaterloo.ca (ecserv7.uwaterloo.ca [129.97.50.127]) by mx1.freebsd.org (Postfix) with ESMTP id 8A75A8FC0A for ; Tue, 25 Oct 2011 18:41:09 +0000 (UTC) Received: from ecserv7.uwaterloo.ca (localhost [127.0.0.1]) by ecserv7.uwaterloo.ca (8.14.3/8.14.3) with ESMTP id p9PIHk12012106 for ; Tue, 25 Oct 2011 14:17:46 -0400 (EDT) (envelope-from smahood@uwaterloo.ca) Received: (from www@localhost) by ecserv7.uwaterloo.ca (8.14.3/8.14.3/Submit) id p9PIHfbq012105 for freebsd-net@freebsd.org; Tue, 25 Oct 2011 14:17:41 -0400 (EDT) (envelope-from smahood@uwaterloo.ca) X-Authentication-Warning: ecserv7.uwaterloo.ca: www set sender to smahood@uwaterloo.ca using -f Received: from 64.7.137.182 ([64.7.137.182]) by www.nexusmail.uwaterloo.ca (Horde Framework) with HTTP; Tue, 25 Oct 2011 14:17:41 -0400 Message-ID: <20111025141741.26891k8ib38ekmkg@www.nexusmail.uwaterloo.ca> Date: Tue, 25 Oct 2011 14:17:41 -0400 From: Sean Mahood To: freebsd-net@freebsd.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=_1gddn2ugd0sg" Content-Transfer-Encoding: 7bit User-Agent: Internet Messaging Program (IMP) H3 (4.3.5) / FreeBSD-7.2 X-Originated-By: smahood@engmail.uwaterloo.ca X-Originating-IP: 64.7.137.182 X-Remote-Browser: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 Subject: [PATCH] Have netstat test for sctp kernel support X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: smahood@engmail.uwaterloo.ca List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Oct 2011 18:41:09 -0000 This message is in MIME format. --=_1gddn2ugd0sg Content-Type: text/plain; charset=ISO-8859-1; DelSp="Yes"; format="flowed" Content-Disposition: inline Content-Transfer-Encoding: 7bit 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 --=_1gddn2ugd0sg Content-Type: text/x-patch; charset=UTF-8; name="main.c.diff" Content-Disposition: attachment; filename="main.c.diff" Content-Transfer-Encoding: 7bit --- 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) --=_1gddn2ugd0sg Content-Type: text/x-patch; charset=UTF-8; name="netstat.h.diff" Content-Disposition: attachment; filename="netstat.h.diff" Content-Transfer-Encoding: 7bit --- 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 --=_1gddn2ugd0sg Content-Type: text/x-patch; charset=UTF-8; name="sctp.c.diff" Content-Disposition: attachment; filename="sctp.c.diff" Content-Transfer-Encoding: 7bit --- 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) { --=_1gddn2ugd0sg Content-Type: text/x-patch; charset=UTF-8; name="sctp_sysctl.c.diff" Content-Disposition: attachment; filename="sctp_sysctl.c.diff" Content-Transfer-Encoding: 7bit --- 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 #include +FEATURE(sctp, "Stream Control Transmission Protocol"); + /* * sysctl tunable variables */ --=_1gddn2ugd0sg--