]> git.ipfire.org Git - people/pmueller/ipfire-3.x.git/blob - 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
1 diff -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
428 diff -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