blob: 78daf6c3edfb4389df5da0a84e24074159bc6f5f [file] [log] [blame]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -05001From 23276afe270009420cfbc52bffafdd25ac0817fe Mon Sep 17 00:00:00 2001
2From: Li Zhou <li.zhou@windriver.com>
3Date: Thu, 14 Jan 2016 17:01:29 +0800
4Subject: [PATCH 1/3] net-tools: add SCTP support for netstat
5
6Upstream-Status: pending
7
8Signed-off-by: Li Zhou <li.zhou@windriver.com>
9---
10 netstat.c | 411 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
11 statistics.c | 68 +++++++++-
12 2 files changed, 465 insertions(+), 14 deletions(-)
13
Brad Bishop316dfdd2018-06-25 12:45:53 -040014Index: net-tools-1.60/netstat.c
15===================================================================
16--- net-tools-1.60.orig/netstat.c
17+++ net-tools-1.60/netstat.c
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050018@@ -58,6 +58,7 @@
19 *
20 *990420 {1.38} Tuan Hoang removed a useless assignment from igmp_do_one()
21 *20010404 {1.39} Arnaldo Carvalho de Melo - use setlocale
22+ *20050516 {1.40} Ivan Skytte Joergensen:Added SCTP support
23 *
24 * This program is free software; you can redistribute it
25 * and/or modify it under the terms of the GNU General
Brad Bishop316dfdd2018-06-25 12:45:53 -040026@@ -106,7 +107,7 @@
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050027 #endif
28
29 /* prototypes for statistics.c */
30-void parsesnmp(int, int, int);
31+void parsesnmp(int, int, int, int);
32 void inittab(void);
33 void parsesnmp6(int, int, int);
34 void inittab6(void);
Brad Bishop316dfdd2018-06-25 12:45:53 -040035@@ -119,6 +120,28 @@ typedef enum {
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050036 SS_DISCONNECTING /* in process of disconnecting */
37 } socket_state;
38
39+#define SCTP_NSTATES 9 /* The number of states in array*/
40+
41+static const char *sctp_state[] = {
42+ N_("EMPTY"),
43+ N_("CLOSED"),
44+ N_("COOKIE_WAIT"),
45+ N_("COOKIE_ECHOED"),
46+ N_("ESTABLISHED"),
47+ N_("SHUTDOWN_PENDING"),
48+ N_("SHUTDOWN_SENT"),
49+ N_("SHUTDOWN_RECEIVED"),
50+ N_("SHUTDOWN_ACK_SENT")
51+};
52+
53+#define SCTP_NTYPES 3 /* The number of types in array */
54+
55+static const char *sctp_type[] = {
56+ N_("udp"),
57+ N_("udp-high-bw"),
58+ N_("tcp")
59+};
60+
61 #define SO_ACCEPTCON (1<<16) /* performed a listen */
62 #define SO_WAITDATA (1<<17) /* wait data to read */
63 #define SO_NOSPACE (1<<18) /* no space to write */
Brad Bishop316dfdd2018-06-25 12:45:53 -040064@@ -149,6 +172,7 @@ int flag_opt = 0;
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050065 int flag_raw = 0;
66 int flag_tcp = 0;
67 int flag_udp = 0;
68+int flag_sctp= 0;
69 int flag_igmp= 0;
70 int flag_rom = 0;
71 int flag_exp = 1;
Brad Bishop316dfdd2018-06-25 12:45:53 -040072@@ -995,6 +1019,365 @@ static int udp_info(void)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050073 udp_do_one);
74 }
75
76+static const char *sctp_socket_type_str(int type) {
77+ if(type>=0 && type<SCTP_NTYPES)
78+ return sctp_type[type];
79+ else {
80+ static char type_str_buf[64];
81+ sprintf(type_str_buf,"UNKNOWN(%d)",type);
82+ return type_str_buf;
83+ }
84+}
85+
86+static const char *sctp_state_str(int state)
87+{
88+ if(state>=0 && state<SCTP_NSTATES)
89+ return sctp_state[state];
90+ else {
91+ static char state_str_buf[64];
92+ sprintf(state_str_buf,"UNKNOWN(%d)",state);
93+ return state_str_buf;
94+ }
95+}
96+
97+static const char *sctp_socket_state_str(int state)
98+{
99+ if(state>=0 && state<=10)
100+ return tcp_state[state];
101+ else {
102+ static char state_str_buf[64];
103+ sprintf(state_str_buf,"UNKNOWN(%d)",state);
104+ return state_str_buf;
105+ }
106+}
107+
108+static struct aftype *process_sctp_addr_str(const char *addr_str, struct sockaddr *sa)
109+{
110+ if (strchr(addr_str,':')) {
111+#if HAVE_AFINET6
112+ extern struct aftype inet6_aftype;
113+ /* Demangle what the kernel gives us */
114+ struct in6_addr in6;
115+ char addr6_str[INET6_ADDRSTRLEN];
116+ unsigned u0,u1,u2,u3,u4,u5,u6,u7;
117+ sscanf(addr_str, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
118+ &u0, &u1, &u2, &u3, &u4, &u5, &u6, &u7);
119+ in6.s6_addr16[0] = htons(u0);
120+ in6.s6_addr16[1] = htons(u1);
121+ in6.s6_addr16[2] = htons(u2);
122+ in6.s6_addr16[3] = htons(u3);
123+ in6.s6_addr16[4] = htons(u4);
124+ in6.s6_addr16[5] = htons(u5);
125+ in6.s6_addr16[6] = htons(u6);
126+ in6.s6_addr16[7] = htons(u7);
127+
128+ inet_ntop(AF_INET6, &in6, addr6_str, sizeof(addr6_str));
129+ inet6_aftype.input(1, addr6_str, sa);
130+ sa->sa_family = AF_INET6;
131+#endif
132+ } else {
133+ ((struct sockaddr_in*)sa)->sin_addr.s_addr = inet_addr(addr_str);
134+ sa->sa_family = AF_INET;
135+ }
136+ return get_afntype(sa->sa_family);
137+}
138+
139+static void sctp_eps_do_one(int lnr, char *line)
140+{
141+ char buffer[1024];
142+ int type, state, port;
143+ int uid;
144+ unsigned long inode;
145+
146+ struct aftype *ap;
147+#if HAVE_AFINET6
148+ struct sockaddr_in6 localaddr;
149+#else
150+ struct sockaddr_in localaddr;
151+#endif
152+ const char *sty_str;
153+ const char *sst_str;
154+ const char *lport_str;
155+ const char *uid_str;
156+ const char *inode_str;
157+ const char *pladdr_str;
158+ char *laddrs_str;
159+
160+ if(lnr == 0) {
161+ /* ENDPT SOCK STY SST HBKT LPORT uid inode pladdr LADDRS*/
162+ return;
163+ }
164+
165+ strtok(line," \t\n"); /*skip ptr*/
166+ strtok(0," \t\n"); /*skip ptr*/
167+ sty_str = strtok(0," \t\n");
168+ sst_str = strtok(0," \t\n");
169+ strtok(0," \t\n"); /*skip hash bucket*/
170+ lport_str=strtok(0," \t\n");
171+ uid_str = strtok(0," \t\n");
172+ inode_str = strtok(0," \t\n");
173+ pladdr_str = strtok(0," \t\n");
174+ laddrs_str=strtok(0,"\t\n");
175+
176+ type = atoi(sty_str);
177+ state = atoi(sst_str);
178+ port = atoi(lport_str);
179+ uid = atoi(uid_str);
180+ inode = strtoul(inode_str,0,0);
181+
182+ if(flag_sctp<=1) {
183+ /* only print the primary address */
184+ char local_addr[64];
185+ char local_port[16];
186+
187+ ap = process_sctp_addr_str(pladdr_str, (struct sockaddr*)&localaddr);
188+ if(ap)
189+ safe_strncpy(local_addr,
190+ ap->sprint((struct sockaddr *) &localaddr, flag_not),
191+ sizeof(local_addr));
192+ else
193+ sprintf(local_addr,_("unsupported address family %d"), ((struct sockaddr*)&localaddr)->sa_family);
194+
195+ snprintf(local_port, sizeof(local_port), "%s",
196+ get_sname(htons(port), "sctp",
197+ flag_not & FLAG_NUM_PORT));
198+
199+ printf("sctp ");
200+ sprintf(buffer,"%s:%s", local_addr, local_port);
201+ printf("%-47s", buffer);
202+ printf(" %-12s", sctp_socket_state_str(state));
203+ } else {
204+ /*print all addresses*/
205+ const char *this_local_addr;
206+ int first=1;
207+ char local_port[16];
208+ snprintf(local_port, sizeof(local_port), "%s",
209+ get_sname(htons(port), "sctp",
210+ flag_not & FLAG_NUM_PORT));
211+ for(this_local_addr=strtok(laddrs_str," \t\n");
212+ this_local_addr;
213+ this_local_addr=strtok(0," \t\n"))
214+ {
215+ char local_addr[64];
216+ ap = process_sctp_addr_str(this_local_addr, (struct sockaddr*)&localaddr);
217+ if(ap)
218+ safe_strncpy(local_addr,
219+ ap->sprint((struct sockaddr *) &localaddr, flag_not),
220+ sizeof(local_addr));
221+ else
222+ sprintf(local_addr,_("unsupported address family %d"), ((struct sockaddr*)&localaddr)->sa_family);
223+
224+ if(!first) printf("\n");
225+ if(first)
226+ printf("sctp ");
227+ else
228+ printf(" ");
229+ sprintf(buffer,"%s:%s", local_addr, local_port);
230+ printf("%-47s", buffer);
231+ printf(" %-12s", first?sctp_socket_state_str(state):"");
232+ first = 0;
233+ }
234+ }
235+
236+ finish_this_one(uid,inode,"");
237+}
238+
239+static void sctp_assoc_do_one(int lnr, char *line)
240+{
241+ char buffer[1024];
242+ int type, state, state2, lport,rport;
243+ int uid;
244+ unsigned rxqueue,txqueue;
245+ unsigned long inode;
246+
247+ struct aftype *ap;
248+#if HAVE_AFINET6
249+ struct sockaddr_in6 localaddr,remoteaddr;
250+#else
251+ struct sockaddr_in localaddr,remoteaddr;
252+#endif
253+ const char *sty_str;
254+ const char *sst_str;
255+ const char *st_str;
256+ const char *txqueue_str;
257+ const char *rxqueue_str;
258+ const char *lport_str,*rport_str;
259+ const char *uid_str;
260+ const char *inode_str;
261+ const char *pladdr_str;
262+ char *laddrs_str;
263+ const char *praddr_str;
264+ char *raddrs_str;
265+
266+ if(lnr == 0) {
267+ /* ASSOC SOCK STY SST ST HBKT tx_queue rx_queue uid inode LPORT RPORT pladdr praddr LADDRS <-> RADDRS*/
268+ return;
269+ }
270+
271+ strtok(line," \t\n"); /*skip ptr*/
272+ strtok(0," \t\n"); /*skip ptr*/
273+ sty_str = strtok(0," \t\n");
274+ sst_str = strtok(0," \t\n");
275+ st_str = strtok(0," \t\n");
276+ strtok(0," \t\n"); /*skip hash bucket*/
277+ txqueue_str = strtok(0," \t\n");
278+ rxqueue_str = strtok(0," \t\n");
279+ uid_str = strtok(0," \t\n");
280+ inode_str = strtok(0," \t\n");
281+ lport_str=strtok(0," \t\n");
282+ rport_str=strtok(0," \t\n");
283+ pladdr_str = strtok(0," \t\n");
284+ praddr_str = strtok(0," \t\n");
285+ laddrs_str=strtok(0,"<->\t\n");
286+ raddrs_str=strtok(0,"<->\t\n");
287+
288+ type = atoi(sty_str);
289+ state = atoi(sst_str);
290+ state2 = atoi(st_str);
291+ txqueue = atoi(txqueue_str);
292+ rxqueue = atoi(rxqueue_str);
293+ uid = atoi(uid_str);
294+ inode = strtoul(inode_str,0,0);
295+ lport = atoi(lport_str);
296+ rport = atoi(rport_str);
297+
298+ if(flag_sctp<=1) {
299+ /* only print the primary addresses */
300+ char local_addr[64];
301+ char local_port[16];
302+ char remote_addr[64];
303+ char remote_port[16];
304+
305+ ap = process_sctp_addr_str(pladdr_str, (struct sockaddr*)&localaddr);
306+ if(ap)
307+ safe_strncpy(local_addr,
308+ ap->sprint((struct sockaddr *) &localaddr, flag_not),
309+ sizeof(local_addr));
310+ else
311+ sprintf(local_addr,_("unsupported address family %d"), ((struct sockaddr*)&localaddr)->sa_family);
312+
313+ snprintf(local_port, sizeof(local_port), "%s",
314+ get_sname(htons(lport), "sctp",
315+ flag_not & FLAG_NUM_PORT));
316+
317+ ap = process_sctp_addr_str(praddr_str, (struct sockaddr*)&remoteaddr);
318+ if(ap)
319+ safe_strncpy(remote_addr,
320+ ap->sprint((struct sockaddr *) &remoteaddr, flag_not),
321+ sizeof(remote_addr));
322+ else
323+ sprintf(remote_addr,_("unsupported address family %d"), ((struct sockaddr*)&remoteaddr)->sa_family);
324+
325+ snprintf(remote_port, sizeof(remote_port), "%s",
326+ get_sname(htons(rport), "sctp",
327+ flag_not & FLAG_NUM_PORT));
328+
329+ printf("sctp");
330+ printf(" %6u %6u ", rxqueue, txqueue);
331+ sprintf(buffer,"%s:%s", local_addr, local_port);
332+ printf("%-23s", buffer);
333+ printf(" ");
334+ sprintf(buffer,"%s:%s", remote_addr, remote_port);
335+ printf("%-23s", buffer);
336+ printf(" %-12s", sctp_socket_state_str(state));
337+ } else {
338+ /*print all addresses*/
339+ const char *this_local_addr;
340+ const char *this_remote_addr;
341+ char *ss1,*ss2;
342+ int first=1;
343+ char local_port[16];
344+ char remote_port[16];
345+ snprintf(local_port, sizeof(local_port), "%s",
346+ get_sname(htons(lport), "sctp",
347+ flag_not & FLAG_NUM_PORT));
348+ snprintf(remote_port, sizeof(remote_port), "%s",
349+ get_sname(htons(rport), "sctp",
350+ flag_not & FLAG_NUM_PORT));
351+
352+ this_local_addr=strtok_r(laddrs_str," \t\n",&ss1);
353+ this_remote_addr=strtok_r(raddrs_str," \t\n",&ss2);
354+ while(this_local_addr || this_remote_addr) {
355+ char local_addr[64];
356+ char remote_addr[64];
357+ if(this_local_addr) {
358+ ap = process_sctp_addr_str(this_local_addr, (struct sockaddr*)&localaddr);
359+ if(ap)
360+ safe_strncpy(local_addr,
361+ ap->sprint((struct sockaddr *) &localaddr, flag_not),
362+ sizeof(local_addr));
363+ else
364+ sprintf(local_addr,_("unsupported address family %d"), ((struct sockaddr*)&localaddr)->sa_family);
365+ }
366+ if(this_remote_addr) {
367+ ap = process_sctp_addr_str(this_remote_addr, (struct sockaddr*)&remoteaddr);
368+ if(ap)
369+ safe_strncpy(remote_addr,
370+ ap->sprint((struct sockaddr *) &remoteaddr, flag_not),
371+ sizeof(remote_addr));
372+ else
373+ sprintf(remote_addr,_("unsupported address family %d"), ((struct sockaddr*)&remoteaddr)->sa_family);
374+ }
375+
376+ if(!first) printf("\n");
377+ if(first)
378+ printf("sctp %6u %6u ", rxqueue, txqueue);
379+ else
380+ printf(" ");
381+ if(this_local_addr) {
382+ if(first)
383+ sprintf(buffer,"%s:%s", local_addr, local_port);
384+ else
385+ sprintf(buffer,"%s", local_addr);
386+ printf("%-23s", buffer);
387+ } else
388+ printf("%-23s", "");
389+ printf(" ");
390+ if(this_remote_addr) {
391+ if(first)
392+ sprintf(buffer,"%s:%s", remote_addr, remote_port);
393+ else
394+ sprintf(buffer,"%s", remote_addr);
395+ printf("%-23s", buffer);
396+ } else
397+ printf("%-23s", "");
398+
399+ printf(" %-12s", first?sctp_socket_state_str(state):"");
400+
401+ first = 0;
402+ this_local_addr=strtok_r(0," \t\n",&ss1);
403+ this_remote_addr=strtok_r(0," \t\n",&ss2);
404+ }
405+ }
406+
407+ finish_this_one(uid,inode,"");
408+}
409+
410+static int sctp_info_eps(void)
411+{
412+#if !defined(_PATH_PROCNET_SCTP_EPS)
413+#define _PATH_PROCNET_SCTP_EPS "/proc/net/sctp/eps"
414+#endif
415+ INFO_GUTS(_PATH_PROCNET_SCTP_EPS, "AF INET (sctp)",
416+ sctp_eps_do_one);
417+}
418+
419+static int sctp_info_assocs(void)
420+{
421+#if !defined(_PATH_PROCNET_SCTP_ASSOCS)
422+#define _PATH_PROCNET_SCTP_ASSOCS "/proc/net/sctp/assocs"
423+#endif
424+ INFO_GUTS(_PATH_PROCNET_SCTP_ASSOCS, "AF INET (sctp)",
425+ sctp_assoc_do_one);
426+}
427+
428+static int sctp_info(void)
429+{
430+ if(flag_all)
431+ sctp_info_eps();
432+ return sctp_info_assocs();
433+}
434+
435 static void raw_do_one(int lnr, const char *line)
436 {
437 char buffer[8192], local_addr[64], rem_addr[64];
Brad Bishop316dfdd2018-06-25 12:45:53 -0400438@@ -1558,7 +1941,7 @@ static void usage(void)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500439 fprintf(stderr, _(" -F, --fib display Forwarding Information Base (default)\n"));
440 fprintf(stderr, _(" -C, --cache display routing cache instead of FIB\n\n"));
441
442- fprintf(stderr, _(" <Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom\n"));
443+ fprintf(stderr, _(" <Socket>={-t|--tcp} {-u|--udp} {-S|--sctp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom\n"));
444 fprintf(stderr, _(" <AF>=Use '-6|-4' or '-A <af>' or '--<af>'; default: %s\n"), DFLT_AF);
445 fprintf(stderr, _(" List of possible address families (which support routing):\n"));
446 print_aflist(1); /* 1 = routeable */
Brad Bishop316dfdd2018-06-25 12:45:53 -0400447@@ -1583,6 +1966,7 @@ int main
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500448 {"protocol", 1, 0, 'A'},
449 {"tcp", 0, 0, 't'},
450 {"udp", 0, 0, 'u'},
451+ {"sctp", 0, 0, 'S' },
452 {"raw", 0, 0, 'w'},
453 {"unix", 0, 0, 'x'},
454 {"listening", 0, 0, 'l'},
Brad Bishop316dfdd2018-06-25 12:45:53 -0400455@@ -1613,7 +1997,7 @@ int main
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500456 getroute_init(); /* Set up AF routing support */
457
458 afname[0] = '\0';
459- while ((i = getopt_long(argc, argv, "MCFA:acdegphinNorstuWVv?wxl64", longopts, &lop)) != EOF)
460+ while ((i = getopt_long(argc, argv, "MCFA:acdegphinNorstuSWVv?wxl64", longopts, &lop)) != EOF)
461 switch (i) {
462 case -1:
463 break;
Brad Bishop316dfdd2018-06-25 12:45:53 -0400464@@ -1705,10 +2089,12 @@ int main
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500465 case 't':
466 flag_tcp++;
467 break;
468-
469 case 'u':
470 flag_udp++;
471 break;
472+ case 'S':
473+ flag_sctp++;
474+ break;
475 case 'w':
476 flag_raw++;
477 break;
Brad Bishop316dfdd2018-06-25 12:45:53 -0400478@@ -1726,13 +2112,13 @@ int main
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500479 if (flag_int + flag_rou + flag_mas + flag_sta > 1)
480 usage();
481
482- if ((flag_inet || flag_inet6 || flag_sta) && !(flag_tcp || flag_udp || flag_raw))
483- flag_tcp = flag_udp = flag_raw = 1;
484+ if ((flag_inet || flag_inet6 || flag_sta) && !(flag_tcp || flag_udp || flag_sctp || flag_raw))
485+ flag_tcp = flag_udp = flag_sctp = flag_raw = 1;
486
487- if ((flag_tcp || flag_udp || flag_raw || flag_igmp) && !(flag_inet || flag_inet6))
488+ if ((flag_tcp || flag_udp || flag_sctp || flag_raw || flag_igmp) && !(flag_inet || flag_inet6))
489 flag_inet = flag_inet6 = 1;
490
491- flag_arg = flag_tcp + flag_udp + flag_raw + flag_unx + flag_ipx
492+ flag_arg = flag_tcp + flag_udp + flag_sctp + flag_raw + flag_unx + flag_ipx
493 + flag_ax25 + flag_netrom + flag_igmp + flag_x25;
494
495 if (flag_mas) {
Brad Bishop316dfdd2018-06-25 12:45:53 -0400496@@ -1760,7 +2146,7 @@ int main
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500497 char buf[256];
498 if (!afname[0]) {
499 inittab();
500- parsesnmp(flag_raw, flag_tcp, flag_udp);
501+ parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp);
502 } else {
503 safe_strncpy(buf, afname, sizeof(buf));
504 tmp1 = buf;
Brad Bishop316dfdd2018-06-25 12:45:53 -0400505@@ -1815,7 +2201,7 @@ int main
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500506 return (i);
507 }
508 for (;;) {
509- if (!flag_arg || flag_tcp || flag_udp || flag_raw) {
510+ if (!flag_arg || flag_tcp || flag_udp || flag_sctp || flag_raw) {
511 #if HAVE_AFINET
512 prg_cache_load();
513 printf(_("Active Internet connections ")); /* xxx */
Brad Bishop316dfdd2018-06-25 12:45:53 -0400514@@ -1854,6 +2240,11 @@ int main
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500515 if (i)
516 return (i);
517 }
518+ if (!flag_arg || flag_sctp) {
519+ i = sctp_info();
520+ if (i)
521+ return (i);
522+ }
523 if (!flag_arg || flag_raw) {
524 i = raw_info();
525 if (i)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400526Index: net-tools-1.60/statistics.c
527===================================================================
528--- net-tools-1.60.orig/statistics.c
529+++ net-tools-1.60/statistics.c
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500530@@ -21,7 +21,7 @@
531 #define UFWARN(x)
532 #endif
533
534-int print_static,f_raw,f_tcp,f_udp,f_unknown = 1;
535+int print_static,f_raw,f_tcp,f_udp,f_sctp,f_unknown = 1;
536
537 enum State {
538 number = 0, opt_number, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg,
539@@ -297,6 +297,27 @@ struct entry Tcpexttab[] =
Brad Bishop316dfdd2018-06-25 12:45:53 -0400540 { "TCPRenoRecoveryFail", N_("%llu classic Reno fast retransmits failed"), opt_number },
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500541 };
542
543+struct entry Sctptab[] =
544+{
545+ {"SctpCurrEstab", N_("%u Current Associations"), number},
546+ {"SctpActiveEstabs", N_("%u Active Associations"), number},
547+ {"SctpPassiveEstabs", N_("%u Passive Associations"), number},
548+ {"SctpAborteds", N_("%u Number of Aborteds "), number},
549+ {"SctpShutdowns", N_("%u Number of Graceful Terminations"), number},
550+ {"SctpOutOfBlues", N_("%u Number of Out of Blue packets"), number},
551+ {"SctpChecksumErrors", N_("%u Number of Packets with invalid Checksum"), number},
552+ {"SctpOutCtrlChunks", N_("%u Number of control chunks sent"), number},
553+ {"SctpOutOrderChunks", N_("%u Number of ordered chunks sent"), number},
554+ {"SctpOutUnorderChunks", N_("%u Number of Unordered chunks sent"), number},
555+ {"SctpInCtrlChunks", N_("%u Number of control chunks received"), number},
556+ {"SctpInOrderChunks", N_("%u Number of ordered chunks received"), number},
557+ {"SctpInUnorderChunks", N_("%u Number of Unordered chunks received"), number},
558+ {"SctpFragUsrMsgs", N_("%u Number of messages fragmented"), number},
559+ {"SctpReasmUsrMsgs", N_("%u Number of messages reassembled "), number},
560+ {"SctpOutSCTPPacks", N_("%u Number of SCTP packets sent"), number},
561+ {"SctpInSCTPPacks", N_("%u Number of SCTP packets received"), number},
562+};
563+
564 struct tabtab {
565 char *title;
566 struct entry *tab;
567@@ -310,6 +331,7 @@ struct tabtab snmptabs[] =
568 {"Icmp", Icmptab, sizeof(Icmptab), &f_raw},
569 {"Tcp", Tcptab, sizeof(Tcptab), &f_tcp},
570 {"Udp", Udptab, sizeof(Udptab), &f_udp},
571+ {"Sctp", Sctptab, sizeof(Sctptab), &f_sctp},
572 {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp},
573 {NULL}
574 };
575@@ -499,12 +521,40 @@ void process6_fd(FILE *f)
576
577 }
578
579-void parsesnmp(int flag_raw, int flag_tcp, int flag_udp)
580+/* Process a file with name-value lines (like /proc/net/sctp/snmp) */
581+void process_fd2(FILE *f, const char *filename)
582+{
583+ char buf1[1024];
584+ char *sp;
585+ struct tabtab *tab;
586+
587+ tab = newtable(snmptabs, "Sctp");
588+
589+ while (fgets(buf1, sizeof buf1, f)) {
590+ sp = buf1 + strcspn(buf1, " \t\n");
591+ if (!sp)
592+ goto formaterr;
593+ *sp = '\0';
594+ sp++;
595+
596+ sp += strspn(sp, " \t\n");
597+
598+ if (*sp != '\0' && *(tab->flag))
599+ printval(tab, buf1, strtoul(sp, 0, 10));
600+ }
601+ return;
602+
603+formaterr:
604+ fprintf(stderr,_("error parsing %s\n"), filename);
605+ return;
606+}
607+
608+void parsesnmp(int flag_raw, int flag_tcp, int flag_udp, int flag_sctp)
609 {
610 FILE *f;
611
612- f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
613-
614+ f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp; f_sctp = flag_sctp;
615+
616 f = proc_fopen("/proc/net/snmp");
617 if (!f) {
618 perror(_("cannot open /proc/net/snmp"));
Brad Bishop316dfdd2018-06-25 12:45:53 -0400619@@ -530,6 +580,16 @@ void parsesnmp(int flag_raw, int flag_tc
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500620
621 fclose(f);
622 }
623+
624+ f = fopen("/proc/net/sctp/snmp", "r");
625+ if (f) {
626+ process_fd2(f,"/proc/net/sctp/snmp");
627+ if (ferror(f))
628+ perror("/proc/net/sctp/snmp");
629+
630+ fclose(f);
631+ }
632+
633 return;
634 }
635