]> git.ipfire.org Git - people/pmueller/ipfire-3.x.git/blame - net-tools/patches/008-net-tools-sctp-statistics.patch
net-tools: Update to 2.0 git-rev e5f1be13.
[people/pmueller/ipfire-3.x.git] / net-tools / patches / 008-net-tools-sctp-statistics.patch
CommitLineData
44f64d91
SS
1diff -up net-tools-2.0/netstat.c.sctp net-tools-2.0/netstat.c
2--- net-tools-2.0/netstat.c.sctp 2013-09-23 15:14:59.524866201 +0200
3+++ net-tools-2.0/netstat.c 2013-09-23 15:24:20.259143969 +0200
4@@ -115,7 +115,7 @@
5 #endif
6
7 /* prototypes for statistics.c */
8-int parsesnmp(int, int, int);
9+int parsesnmp(int, int, int, int);
10 void inittab(void);
11 int parsesnmp6(int, int, int);
12 void inittab6(void);
13@@ -888,159 +888,269 @@ static int igmp_info(void)
14 igmp_do_one, "igmp", "igmp6");
15 }
16
17-static int ip_parse_dots(uint32_t *addr, char const *src) {
18- unsigned a, b, c, d;
19- unsigned ret = 4-sscanf(src, "%u.%u.%u.%u", &a, &b, &c, &d);
20- *addr = htonl((a << 24)|(b << 16)|(c << 8)|d);
21- return ret;
22-}
23-
24-static void print_ip_service(struct sockaddr_in *addr, char const *protname,
25- char *buf, unsigned size) {
26- struct aftype *ap;
27-
28- if(size == 0) return;
29-
30- /* print host */
31- if((ap = get_afntype(addr->sin_family)) == NULL) {
32- fprintf(stderr, _("netstat: unsupported address family %d !\n"),
33- addr->sin_family);
34- return;
35- }
36- safe_strncpy(buf, ap->sprint((struct sockaddr*)addr, flag_not), size);
37-
38- /* print service */
39- if(flag_all || (flag_lst && !addr->sin_port) || (!flag_lst && addr->sin_port)) {
40- char bfs[32];
41-
42- snprintf(bfs, sizeof(bfs), "%s",
43- get_sname(addr->sin_port, (char*)protname, flag_not & FLAG_NUM_PORT));
44-
45- /* check if we must cut on host and/or service name */
46- {
47- unsigned const bufl = strlen(buf);
48- unsigned const bfsl = strlen(bfs);
49-
50- if(bufl+bfsl+2 > size) {
51- unsigned const half = (size-2)>>1;
52- if(bufl > half) {
53- if(bfsl > half) {
54- buf[size-2-half] = '\0';
55- bfs[half+1] = '\0';
56- }
57- else buf[size-2-bfsl] = '\0';
58- }
59- else bfs[size-2-bufl] = '\0';
60- }
61+static const char *sctp_socket_state_str(int state)
62+{
63+ if(state>=0 && state<=10)
64+ return tcp_state[state];
65+ else {
66+ static char state_str_buf[64];
67+ sprintf(state_str_buf,"UNKNOWN(%d)",state);
68+ return state_str_buf;
69 }
70- strcat(buf, ":");
71- strcat(buf, bfs);
72- }
73 }
74
75-/* process single SCTP endpoint */
76-static void sctp_do_ept(int lnr, char const *line, const char *prot)
77+static struct aftype *process_sctp_addr_str(const char *addr_str, struct sockaddr *sa)
78 {
79- struct sockaddr_in laddr, raddr;
80- unsigned uid, inode;
81-
82- char l_addr[23], r_addr[23];
83-
84- /* fill sockaddr_in structures */
85- {
86- unsigned lport;
87- unsigned ate;
88-
89- if(lnr == 0) return;
90- if(sscanf(line, "%*X %*X %*u %*u %*u %u %u %u %n",
91- &lport, &uid, &inode, &ate) < 3) goto err;
92-
93- /* decode IP address */
94- if(ip_parse_dots(&laddr.sin_addr.s_addr, line+ate)) goto err;
95- raddr.sin_addr.s_addr = htonl(0);
96- laddr.sin_family = raddr.sin_family = AF_INET;
97- laddr.sin_port = htons(lport);
98- raddr.sin_port = htons(0);
99- }
100+ if (strchr(addr_str,':')) {
101+#if HAVE_AFINET6
102+ extern struct aftype inet6_aftype;
103+ /* Demangle what the kernel gives us */
104+ struct in6_addr in6;
105+ char addr6_str[INET6_ADDRSTRLEN];
106+ unsigned u0,u1,u2,u3,u4,u5,u6,u7;
107+ sscanf(addr_str, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
108+ &u0, &u1, &u2, &u3, &u4, &u5, &u6, &u7);
109+ in6.s6_addr16[0] = htons(u0);
110+ in6.s6_addr16[1] = htons(u1);
111+ in6.s6_addr16[2] = htons(u2);
112+ in6.s6_addr16[3] = htons(u3);
113+ in6.s6_addr16[4] = htons(u4);
114+ in6.s6_addr16[5] = htons(u5);
115+ in6.s6_addr16[6] = htons(u6);
116+ in6.s6_addr16[7] = htons(u7);
117+
118+ inet_ntop(AF_INET6, &in6, addr6_str, sizeof(addr6_str));
119+ inet6_aftype.input(1, addr6_str, sa);
120+ sa->sa_family = AF_INET6;
121+#endif
122+ } else {
123+ ((struct sockaddr_in*)sa)->sin_addr.s_addr = inet_addr(addr_str);
124+ sa->sa_family = AF_INET;
125+ }
126+ return get_afntype(sa->sa_family);
127+}
128
129- /* print IP:service to l_addr and r_addr */
130- print_ip_service(&laddr, prot, l_addr, sizeof(l_addr));
131- print_ip_service(&raddr, prot, r_addr, sizeof(r_addr));
132-
133- /* Print line */
134- printf("%-4s %6d %6d %-*s %-*s %-11s",
135- prot, 0, 0,
136- (int)netmax(23,strlen(l_addr)), l_addr,
137- (int)netmax(23,strlen(r_addr)), r_addr,
138- _(tcp_state[TCP_LISTEN]));
139- finish_this_one(uid, inode, "");
140- return;
141- err:
142- fprintf(stderr, "SCTP error in line: %d\n", lnr);
143-}
144-
145-/* process single SCTP association */
146-static void sctp_do_assoc(int lnr, char const *line, const char *prot)
147-{
148- struct sockaddr_in laddr, raddr;
149- unsigned long rxq, txq;
150- unsigned uid, inode;
151-
152- char l_addr[23], r_addr[23];
153-
154- /* fill sockaddr_in structures */
155- {
156- unsigned lport, rport;
157- unsigned ate;
158- char const *addr;
159-
160- if(lnr == 0) return;
161- if(sscanf(line, "%*X %*X %*u %*u %*u %*u %*u %lu %lu %u %u %u %u %n",
162- &txq, &rxq, &uid, &inode, &lport, &rport, &ate) < 6) goto err;
163-
164- /* decode IP addresses */
165- addr = strchr(line+ate, '*');
166- if(addr == 0) goto err;
167- if(ip_parse_dots(&laddr.sin_addr.s_addr, ++addr)) goto err;
168- addr = strchr(addr, '*');
169- if(addr == 0) goto err;
170- if(ip_parse_dots(&raddr.sin_addr.s_addr, ++addr)) goto err;
171-
172- /* complete sockaddr_in structures */
173- laddr.sin_family = raddr.sin_family = AF_INET;
174- laddr.sin_port = htons(lport);
175- raddr.sin_port = htons(rport);
176- }
177+static void sctp_eps_do_one(int lnr, char *line, const char *proto)
178+{
179+ char buffer[1024];
180+ int state, port;
181+ int uid;
182+ unsigned long inode;
183+ struct aftype *ap;
184+#if HAVE_AFINET6
185+ struct sockaddr_in6 localaddr;
186+#else
187+ struct sockaddr_in localaddr;
188+#endif
189+ const char *sst_str;
190+ const char *lport_str;
191+ const char *uid_str;
192+ const char *inode_str;
193+ char *laddrs_str;
194+
195+ if(lnr == 0) {
196+ /* ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS */
197+ return;
198+ }
199+ strtok(line," \t\n"); /*skip endpt*/
200+ strtok(0," \t\n"); /*skip sock*/
201+ strtok(0," \t\n"); /*skp sty*/
202+ sst_str = strtok(0," \t\n");
203+ strtok(0," \t\n"); /*skip hash bucket*/
204+ lport_str=strtok(0," \t\n");
205+ uid_str = strtok(0," \t\n");
206+ inode_str = strtok(0," \t\n");
207+ laddrs_str=strtok(0,"\t\n");
208+
209+ if (!sst_str || !lport_str || !uid_str || !inode_str) {
210+ fprintf(stderr, _("warning, got bogus sctp eps line.\n"));
211+ return;
212+ }
213+ state = atoi(sst_str);
214+ port = atoi(lport_str);
215+ uid = atoi(uid_str);
216+ inode = strtoul(inode_str,0,0);
217+
218+ const char *this_local_addr;
219+ int first=1;
220+ char local_port[16];
221+ snprintf(local_port, sizeof(local_port), "%s",
222+ get_sname(htons(port), proto, flag_not & FLAG_NUM_PORT));
223+ for(this_local_addr=strtok(laddrs_str," \t\n");
224+ this_local_addr;
225+ this_local_addr=strtok(0," \t\n"))
226+ {
227+ char local_addr[64];
228+ ap = process_sctp_addr_str(this_local_addr, (struct sockaddr*)&localaddr);
229+ if(ap)
230+ safe_strncpy(local_addr,
231+ ap->sprint((struct sockaddr *) &localaddr, flag_not),
232+ sizeof(local_addr));
233+ else
234+ sprintf(local_addr,_("unsupported address family %d"), ((struct sockaddr*)&localaddr)->sa_family);
235+
236+ if(!first) printf("\n");
237+ if(first)
238+ printf("sctp ");
239+ else
240+ printf(" ");
241+ sprintf(buffer,"%s:%s", local_addr, local_port);
242+ printf("%-47s", buffer);
243+ printf(" %-11s", first?sctp_socket_state_str(state):"");
244+ first = 0;
245+ }
246+ finish_this_one(uid,inode,"");
247+}
248+
249+static void sctp_assoc_do_one(int lnr, char *line, const char *proto)
250+{
251+ char buffer[1024];
252+ int state, lport,rport;
253+ int uid;
254+ unsigned rxqueue,txqueue;
255+ unsigned long inode;
256+
257+ struct aftype *ap;
258+#if HAVE_AFINET6
259+ struct sockaddr_in6 localaddr,remoteaddr;
260+#else
261+ struct sockaddr_in localaddr,remoteaddr;
262+#endif
263+ const char *sst_str;
264+ const char *txqueue_str;
265+ const char *rxqueue_str;
266+ const char *lport_str,*rport_str;
267+ const char *uid_str;
268+ const char *inode_str;
269+ char *laddrs_str;
270+ char *raddrs_str;
271+
272+ if(lnr == 0) {
273+ /* ASSOC SOCK STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT RPORT LADDRS <-> RADDRS */
274+ return;
275+ }
276+
277+ strtok(line," \t\n"); /*skip assoc*/
278+ strtok(0," \t\n"); /*skip sock*/
279+ strtok(0," \t\n"); /*skp sty*/
280+ sst_str = strtok(0," \t\n");
281+ strtok(0," \t\n");
282+ strtok(0," \t\n"); /*skip hash bucket*/
283+ strtok(0," \t\n"); /*skip hash assoc-id*/
284+ txqueue_str = strtok(0," \t\n");
285+ rxqueue_str = strtok(0," \t\n");
286+ uid_str = strtok(0," \t\n");
287+ inode_str = strtok(0," \t\n");
288+ lport_str=strtok(0," \t\n");
289+ rport_str=strtok(0," \t\n");
290+ laddrs_str = strtok(0,"<->\t\n");
291+ raddrs_str = strtok(0,"<->\t\n");
292+
293+ if (!sst_str || !txqueue_str || !rxqueue_str || !uid_str ||
294+ !inode_str || !lport_str || !rport_str) {
295+ fprintf(stderr, _("warning, got bogus sctp assoc line.\n"));
296+ return;
297+ }
298+
299+ state = atoi(sst_str);
300+ txqueue = atoi(txqueue_str);
301+ rxqueue = atoi(rxqueue_str);
302+ uid = atoi(uid_str);
303+ inode = strtoul(inode_str,0,0);
304+ lport = atoi(lport_str);
305+ rport = atoi(rport_str);
306+
307+ /*print all addresses*/
308+ const char *this_local_addr;
309+ const char *this_remote_addr;
310+ char *ss1,*ss2;
311+ int first=1;
312+ char local_port[16];
313+ char remote_port[16];
314+ snprintf(local_port, sizeof(local_port), "%s",
315+ get_sname(htons(lport), proto,
316+ flag_not & FLAG_NUM_PORT));
317+ snprintf(remote_port, sizeof(remote_port), "%s",
318+ get_sname(htons(rport), proto,
319+ flag_not & FLAG_NUM_PORT));
320+
321+ this_local_addr=strtok_r(laddrs_str," \t\n",&ss1);
322+ this_remote_addr=strtok_r(raddrs_str," \t\n",&ss2);
323+ while(this_local_addr || this_remote_addr) {
324+ char local_addr[64];
325+ char remote_addr[64];
326+
327+ if(this_local_addr) {
328+ if (this_local_addr[0] == '*') {
329+ /* skip * */
330+ this_local_addr++;
331+ }
332+ ap = process_sctp_addr_str(this_local_addr, (struct sockaddr*)&localaddr);
333+ if(ap)
334+ safe_strncpy(local_addr,
335+ ap->sprint((struct sockaddr *) &localaddr, flag_not), sizeof(local_addr));
336+ else
337+ sprintf(local_addr,_("unsupported address family %d"), ((struct sockaddr*)&localaddr)->sa_family);
338+ }
339+ if(this_remote_addr) {
340+ if (this_remote_addr[0] == '*') {
341+ /* skip * */
342+ this_remote_addr++;
343+ }
344+ ap = process_sctp_addr_str(this_remote_addr, (struct sockaddr*)&remoteaddr);
345+ if(ap)
346+ safe_strncpy(remote_addr,
347+ ap->sprint((struct sockaddr *) &remoteaddr, flag_not), sizeof(remote_addr));
348+ else
349+ sprintf(remote_addr,_("unsupported address family %d"), ((struct sockaddr*)&remoteaddr)->sa_family);
350+ }
351
352- /* print IP:service to l_addr and r_addr */
353- print_ip_service(&laddr, prot, l_addr, sizeof(l_addr));
354- print_ip_service(&raddr, prot, r_addr, sizeof(r_addr));
355-
356- /* Print line */
357- printf("%-4s %6ld %6ld %-*s %-*s %-11s",
358- prot, rxq, txq,
359- (int)netmax(23,strlen(l_addr)), l_addr,
360- (int)netmax(23,strlen(r_addr)), r_addr,
361- _(tcp_state[TCP_ESTABLISHED]));
362- finish_this_one(uid, inode, "");
363- return;
364- err:
365- fprintf(stderr, "SCTP error in line: %d\n", lnr);
366+ if(!first) printf("\n");
367+ if(first)
368+ printf("sctp %6u %6u ", rxqueue, txqueue);
369+ else
370+ printf(" ");
371+ if(this_local_addr) {
372+ if(first)
373+ sprintf(buffer,"%s:%s", local_addr, local_port);
374+ else
375+ sprintf(buffer,"%s", local_addr);
376+ printf("%-23s", buffer);
377+ } else
378+ printf("%-23s", "");
379+ printf(" ");
380+ if(this_remote_addr) {
381+ if(first)
382+ sprintf(buffer,"%s:%s", remote_addr, remote_port);
383+ else
384+ sprintf(buffer,"%s", remote_addr);
385+ printf("%-23s", buffer);
386+ } else
387+ printf("%-23s", "");
388+
389+ printf(" %-11s", first?sctp_socket_state_str(state):"");
390+
391+ first = 0;
392+ this_local_addr=strtok_r(0," \t\n",&ss1);
393+ this_remote_addr=strtok_r(0," \t\n",&ss2);
394+ }
395+ finish_this_one(uid,inode,"");
396 }
397
398-static int sctp_info_epts(void) {
399+static int sctp_info_eps(void)
400+{
401 INFO_GUTS6(_PATH_PROCNET_SCTPEPTS, _PATH_PROCNET_SCTP6EPTS, "AF INET (sctp)",
402- sctp_do_ept, "sctp", "sctp6");
403+ sctp_eps_do_one, "sctp", "sctp6");
404 }
405
406 static int sctp_info_assocs(void) {
407 INFO_GUTS6(_PATH_PROCNET_SCTPASSOCS, _PATH_PROCNET_SCTP6ASSOCS, "AF INET (sctp)",
408- sctp_do_assoc, "sctp", "sctp6");
409+ sctp_assoc_do_one, "sctp", "sctp6");
410 }
411
412 static int sctp_info(void) {
413 int res;
414- res = sctp_info_epts();
415+ res = sctp_info_eps();
416 if(res) return res;
417 return sctp_info_assocs();
418 }
419@@ -2234,7 +2344,7 @@ int main
420 if (!strcmp(afname, "inet")) {
421 #if HAVE_AFINET
422 inittab();
423- i = parsesnmp(flag_raw, flag_tcp, flag_udp);
424+ i = parsesnmp(flag_raw, flag_tcp, flag_udp, flag_sctp);
425 #else
426 ENOSUPP("netstat", "AF INET");
427 #endif
428diff -up net-tools-2.0/statistics.c.sctp net-tools-2.0/statistics.c
429--- net-tools-2.0/statistics.c.sctp 2013-09-23 15:14:59.501866518 +0200
430+++ net-tools-2.0/statistics.c 2013-09-23 15:14:59.534866063 +0200
431@@ -21,7 +21,7 @@
432 #define UFWARN(x)
433 #endif
434
435-int print_static,f_raw,f_tcp,f_udp,f_unknown = 1;
436+int print_static,f_raw,f_tcp,f_udp,f_sctp,f_unknown = 1;
437
438 enum State {
439 number = 0, opt_number, i_forward, i_inp_icmp, i_outp_icmp, i_rto_alg,
440@@ -299,6 +299,27 @@ struct entry Tcpexttab[] =
441 { "TCPRenoRecoveryFail", N_("%llu classic Reno fast retransmits failed"), opt_number },
442 };
443
444+struct entry Sctptab[] =
445+{
446+ {"SctpCurrEstab", N_("%llu Current Associations"), number},
447+ {"SctpActiveEstabs", N_("%llu Active Associations"), number},
448+ {"SctpPassiveEstabs", N_("%llu Passive Associations"), number},
449+ {"SctpAborteds", N_("%llu Number of Aborteds "), number},
450+ {"SctpShutdowns", N_("%llu Number of Graceful Terminations"), number},
451+ {"SctpOutOfBlues", N_("%llu Number of Out of Blue packets"), number},
452+ {"SctpChecksumErrors", N_("%llu Number of Packets with invalid Checksum"), number},
453+ {"SctpOutCtrlChunks", N_("%llu Number of control chunks sent"), number},
454+ {"SctpOutOrderChunks", N_("%llu Number of ordered chunks sent"), number},
455+ {"SctpOutUnorderChunks", N_("%llu Number of Unordered chunks sent"), number},
456+ {"SctpInCtrlChunks", N_("%llu Number of control chunks received"), number},
457+ {"SctpInOrderChunks", N_("%llu Number of ordered chunks received"), number},
458+ {"SctpInUnorderChunks", N_("%llu Number of Unordered chunks received"), number},
459+ {"SctpFragUsrMsgs", N_("%llu Number of messages fragmented"), number},
460+ {"SctpReasmUsrMsgs", N_("%llu Number of messages reassembled "), number},
461+ {"SctpOutSCTPPacks", N_("%llu Number of SCTP packets sent"), number},
462+ {"SctpInSCTPPacks", N_("%llu Number of SCTP packets received"), number},
463+};
464+
465 struct tabtab {
466 char *title;
467 struct entry *tab;
468@@ -312,6 +333,7 @@ struct tabtab snmptabs[] =
469 {"Icmp", Icmptab, sizeof(Icmptab), &f_raw},
470 {"Tcp", Tcptab, sizeof(Tcptab), &f_tcp},
471 {"Udp", Udptab, sizeof(Udptab), &f_udp},
472+ {"Sctp", Sctptab, sizeof(Sctptab), &f_sctp},
473 {"TcpExt", Tcpexttab, sizeof(Tcpexttab), &f_tcp},
474 {NULL}
475 };
476@@ -502,11 +524,38 @@ void process6_fd(FILE *f)
477
478 }
479
480-int parsesnmp(int flag_raw, int flag_tcp, int flag_udp)
481+/* Process a file with name-value lines (like /proc/net/sctp/snmp) */
482+void process_fd2(FILE *f, const char *filename)
483+{
484+ char buf1[1024];
485+ char *sp;
486+ struct tabtab *tab;
487+
488+ tab = newtable(snmptabs, "Sctp");
489+
490+ while (fgets(buf1, sizeof buf1, f)) {
491+ sp = buf1 + strcspn(buf1, " \t\n");
492+ if (!sp) {
493+ fprintf(stderr,_("error parsing %s\n"), filename);
494+ return;
495+ }
496+ *sp = '\0';
497+ sp++;
498+
499+ sp += strspn(sp, " \t\n");
500+
501+ if (*sp != '\0' && *(tab->flag))
502+ printval(tab, buf1, strtoul(sp, 0, 10));
503+ }
504+ return;
505+}
506+
507+int parsesnmp(int flag_raw, int flag_tcp, int flag_udp, int flag_sctp)
508+
509 {
510 FILE *f;
511
512- f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp;
513+ f_raw = flag_raw; f_tcp = flag_tcp; f_udp = flag_udp; f_sctp = flag_sctp;
514
515 f = proc_fopen("/proc/net/snmp");
516 if (!f) {
517@@ -539,6 +588,17 @@ int parsesnmp(int flag_raw, int flag_tcp
518
519 fclose(f);
520 }
521+
522+ f = proc_fopen("/proc/net/sctp/snmp");
523+ if (f) {
524+ process_fd2(f,"/proc/net/sctp/snmp");
525+ if (ferror(f)) {
526+ perror("/proc/net/sctp/snmp");
527+ fclose(f);
528+ return(1);
529+ }
530+ }
531+
532 return(0);
533 }
534