]>
Commit | Line | Data |
---|---|---|
44f64d91 SS |
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 |