1 /*
2 * UDP MIB group Table implementation - udpTable.c
3 *
4 */
5
6 /* Portions of this file are subject to the following copyright(s). See
7 * the Net-SNMP's COPYING file for more details and other copyrights
8 * that may apply:
9 */
10 /*
11 * Portions of this file are copyrighted by:
12 * Copyright � 2003 Sun Microsystems, Inc. All rights reserved.
13 * Use is subject to license terms specified in the COPYING file
14 * distributed with the Net-SNMP package.
15 */
16
17 #include <net-snmp/net-snmp-config.h>
18 #include "mibII_common.h"
19
20 #if HAVE_NETINET_UDP_H
21 #include <netinet/udp.h>
22 #endif
23 #if HAVE_NETINET_UDP_VAR_H
24 #include <netinet/udp_var.h>
25 #endif
26
27 #if HAVE_KVM_GETFILES
28 #if defined(HAVE_KVM_GETFILE2) || !defined(openbsd5)
29 #undef HAVE_KVM_GETFILES
30 #endif
31 #endif
32
33 #if HAVE_KVM_GETFILES
34 #include <kvm.h>
35 #include <sys/sysctl.h>
36 #define _KERNEL
37 #include <sys/file.h>
38 #undef _KERNEL
39 #endif
40
41 #if defined(cygwin) || defined(mingw32)
42 #include <winerror.h>
43 #endif
44
45 #include <net-snmp/net-snmp-includes.h>
46 #include <net-snmp/agent/net-snmp-agent-includes.h>
47 #include <net-snmp/agent/auto_nlist.h>
48
49 #ifdef linux
50 #include "tcpTable.h"
51 #endif
52 #include "udp.h"
53 #include "udpTable.h"
54
55 #ifdef hpux11
56 #define UDPTABLE_ENTRY_TYPE mib_udpLsnEnt
57 #define UDPTABLE_LOCALADDRESS LocalAddress
58 #define UDPTABLE_LOCALPORT LocalPort
59 #define UDPTABLE_IS_TABLE
60
61 #elif defined(solaris2)
62 typedef struct netsnmp_udpEntry_s netsnmp_udpEntry;
63 struct netsnmp_udpEntry_s {
64 mib2_udpEntry_t entry;
65 netsnmp_udpEntry *inp_next;
66 };
67 #define UDPTABLE_ENTRY_TYPE netsnmp_udpEntry
68 #define UDPTABLE_LOCALADDRESS entry.udpLocalAddress
69 #define UDPTABLE_LOCALPORT entry.udpLocalPort
70 #define UDPTABLE_IS_LINKED_LIST
71
72 #elif defined(HAVE_IPHLPAPI_H)
73 #include <iphlpapi.h>
74 #define UDPTABLE_ENTRY_TYPE MIB_UDPROW /* ??? */
75 #define UDPTABLE_LOCALADDRESS dwLocalAddr
76 #define UDPTABLE_LOCALPORT dwLocalPort
77 #define UDPTABLE_IS_TABLE
78
79 #elif defined(HAVE_KVM_GETFILES)
80 #define UDPTABLE_ENTRY_TYPE struct kinfo_file
81 #define UDPTABLE_LOCALADDRESS inp_laddru[0]
82 #define UDPTABLE_LOCALPORT inp_lport
83 #define UDPTABLE_IS_TABLE
84
85 #elif defined(linux)
86 #define INP_NEXT_SYMBOL inp_next
87 #define UDPTABLE_ENTRY_TYPE struct inpcb
88 #define UDPTABLE_LOCALADDRESS inp_laddr.s_addr
89 #define UDPTABLE_LOCALPORT inp_lport
90 #define UDPTABLE_IS_LINKED_LIST
91
92 #else
93 #ifdef openbsd4
94 #define INP_NEXT_SYMBOL inp_queue.cqe_next /* or set via <net-snmp/system/openbsd.h> */
95 #endif
96
97 #if defined(freebsd4) || defined(darwin) || defined(osf5)
98 typedef struct netsnmp_inpcb_s netsnmp_inpcb;
99 struct netsnmp_inpcb_s {
100 #if __FreeBSD_version >= 1200026
101 struct xinpcb pcb;
102 #else
103 struct inpcb pcb;
104 #endif
105 int state;
106 netsnmp_inpcb *inp_next;
107 };
108 #define UDPTABLE_ENTRY_TYPE netsnmp_inpcb
109 #define UDPTABLE_LOCALADDRESS pcb.inp_laddr.s_addr
110 #define UDPTABLE_LOCALPORT pcb.inp_lport
111 #else
112 #define UDPTABLE_ENTRY_TYPE struct inpcb
113 #define UDPTABLE_LOCALADDRESS inp_laddr.s_addr
114 #define UDPTABLE_LOCALPORT inp_lport
115 #endif
116 #define UDPTABLE_IS_LINKED_LIST
117
118 #endif /* hpux11 */
119
120 /* Head of linked list, or root of table */
121 UDPTABLE_ENTRY_TYPE *udp_head = NULL;
122 int udp_size = 0; /* Only used for table-based systems */
123
124
125 /*
126 *
127 * Initialization and handler routines are common to all architectures
128 *
129 */
130 #ifndef MIB_STATS_CACHE_TIMEOUT
131 #define MIB_STATS_CACHE_TIMEOUT 5
132 #endif
133 #ifndef UDP_STATS_CACHE_TIMEOUT
134 #define UDP_STATS_CACHE_TIMEOUT MIB_STATS_CACHE_TIMEOUT
135 #endif
136
137 #ifdef UDP_ADDRESSES_IN_HOST_ORDER
138 #define UDP_ADDRESS_TO_HOST_ORDER(x) x
139 #define UDP_ADDRESS_TO_NETWORK_ORDER(x) htonl(x)
140 #else
141 #define UDP_ADDRESS_TO_HOST_ORDER(x) ntohl(x)
142 #define UDP_ADDRESS_TO_NETWORK_ORDER(x) x
143 #endif
144
145 #ifdef UDP_PORTS_IN_HOST_ORDER
146 #define UDP_PORT_TO_HOST_ORDER(x) x
147 #else
148 #define UDP_PORT_TO_HOST_ORDER(x) ntohs(x)
149 #endif
150
151
152 oid udpTable_oid[] = { SNMP_OID_MIB2, 7, 5 };
153
154 void
init_udpTable(void)155 init_udpTable(void)
156 {
157 netsnmp_table_registration_info *table_info;
158 netsnmp_iterator_info *iinfo;
159 netsnmp_handler_registration *reginfo;
160 int rc;
161
162 DEBUGMSGTL(("mibII/udpTable", "Initialising UDP Table\n"));
163 /*
164 * Create the table data structure, and define the indexing....
165 */
166 table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
167 if (!table_info) {
168 return;
169 }
170 netsnmp_table_helper_add_indexes(table_info, ASN_IPADDRESS,
171 ASN_INTEGER, 0);
172 table_info->min_column = UDPLOCALADDRESS;
173 table_info->max_column = UDPLOCALPORT;
174
175
176 /*
177 * .... and iteration information ....
178 */
179 iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
180 if (!iinfo) {
181 netsnmp_table_registration_info_free(table_info);
182 return;
183 }
184 iinfo->get_first_data_point = udpTable_first_entry;
185 iinfo->get_next_data_point = udpTable_next_entry;
186 iinfo->table_reginfo = table_info;
187 #if defined (WIN32) || defined (cygwin)
188 iinfo->flags |= NETSNMP_ITERATOR_FLAG_SORTED;
189 #endif /* WIN32 || cygwin */
190
191
192 /*
193 * .... and register the table with the agent.
194 */
195 reginfo = netsnmp_create_handler_registration("udpTable",
196 udpTable_handler,
197 udpTable_oid, OID_LENGTH(udpTable_oid),
198 HANDLER_CAN_RONLY),
199 rc = netsnmp_register_table_iterator2(reginfo, iinfo);
200 if (rc != SNMPERR_SUCCESS)
201 return;
202
203 /*
204 * .... with a local cache
205 */
206 netsnmp_inject_handler( reginfo,
207 netsnmp_get_cache_handler(UDP_STATS_CACHE_TIMEOUT,
208 udpTable_load, udpTable_free,
209 udpTable_oid, OID_LENGTH(udpTable_oid)));
210 }
211
212
213
214 int
udpTable_handler(netsnmp_mib_handler * handler,netsnmp_handler_registration * reginfo,netsnmp_agent_request_info * reqinfo,netsnmp_request_info * requests)215 udpTable_handler(netsnmp_mib_handler *handler,
216 netsnmp_handler_registration *reginfo,
217 netsnmp_agent_request_info *reqinfo,
218 netsnmp_request_info *requests)
219 {
220 netsnmp_request_info *request;
221 netsnmp_variable_list *requestvb;
222 netsnmp_table_request_info *table_info;
223 UDPTABLE_ENTRY_TYPE *entry;
224 oid subid;
225 long port;
226 in_addr_t addr;
227
228 DEBUGMSGTL(("mibII/udpTable", "Handler - mode %s\n",
229 se_find_label_in_slist("agent_mode", reqinfo->mode)));
230 switch (reqinfo->mode) {
231 case MODE_GET:
232 for (request=requests; request; request=request->next) {
233 requestvb = request->requestvb;
234 DEBUGMSGTL(( "mibII/udpTable", "oid: "));
235 DEBUGMSGOID(("mibII/udpTable", requestvb->name,
236 requestvb->name_length));
237 DEBUGMSG(( "mibII/udpTable", "\n"));
238
239 entry = (UDPTABLE_ENTRY_TYPE *)netsnmp_extract_iterator_context(request);
240 if (!entry)
241 continue;
242 table_info = netsnmp_extract_table_info(request);
243 subid = table_info->colnum;
244
245 switch (subid) {
246 case UDPLOCALADDRESS:
247 #if defined(osf5) && defined(IN6_EXTRACT_V4ADDR)
248 addr = ntohl(IN6_EXTRACT_V4ADDR(&entry->pcb.inp_laddr));
249 snmp_set_var_typed_value(requestvb, ASN_IPADDRESS,
250 (u_char*)&addr,
251 sizeof(uint32_t));
252 #else
253 addr = UDP_ADDRESS_TO_HOST_ORDER(entry->UDPTABLE_LOCALADDRESS);
254 snmp_set_var_typed_value(requestvb, ASN_IPADDRESS,
255 (u_char *)&addr,
256 sizeof(uint32_t));
257 #endif
258 break;
259 case UDPLOCALPORT:
260 port = UDP_PORT_TO_HOST_ORDER((u_short)entry->UDPTABLE_LOCALPORT);
261 snmp_set_var_typed_value(requestvb, ASN_INTEGER,
262 (u_char *)&port, sizeof(port));
263 break;
264 }
265 }
266 break;
267
268 case MODE_GETNEXT:
269 case MODE_GETBULK:
270 #ifndef NETSNMP_NO_WRITE_SUPPORT
271 case MODE_SET_RESERVE1:
272 case MODE_SET_RESERVE2:
273 case MODE_SET_ACTION:
274 case MODE_SET_COMMIT:
275 case MODE_SET_FREE:
276 case MODE_SET_UNDO:
277 #endif /* !NETSNMP_NO_WRITE_SUPPORT */
278 snmp_log(LOG_WARNING, "mibII/udpTable: Unsupported mode (%d)\n",
279 reqinfo->mode);
280 break;
281 default:
282 snmp_log(LOG_WARNING, "mibII/udpTable: Unrecognised mode (%d)\n",
283 reqinfo->mode);
284 break;
285 }
286
287 return SNMP_ERR_NOERROR;
288 }
289
290 /*
291 * Two forms of iteration hook routines:
292 * One for when the UDP table is stored as a table
293 * One for when the UDP table is stored as a linked list
294 *
295 * Also applies to the cache-handler free routine
296 */
297
298 #ifdef UDPTABLE_IS_TABLE
299 netsnmp_variable_list *
udpTable_first_entry(void ** loop_context,void ** data_context,netsnmp_variable_list * index,netsnmp_iterator_info * data)300 udpTable_first_entry(void **loop_context,
301 void **data_context,
302 netsnmp_variable_list *index,
303 netsnmp_iterator_info *data)
304 {
305 /*
306 * XXX - How can we tell if the cache is valid?
307 * No access to 'reqinfo'
308 */
309 if (udp_size == 0)
310 return NULL;
311
312 /*
313 * Point to the first entry, and use the
314 * 'next_entry' hook to retrieve this row
315 */
316 *loop_context = 0;
317 return udpTable_next_entry( loop_context, data_context, index, data );
318 }
319
320 netsnmp_variable_list *
udpTable_next_entry(void ** loop_context,void ** data_context,netsnmp_variable_list * index,netsnmp_iterator_info * data)321 udpTable_next_entry( void **loop_context,
322 void **data_context,
323 netsnmp_variable_list *index,
324 netsnmp_iterator_info *data)
325 {
326 int i = (intptr_t)*loop_context;
327 long port;
328
329 #if HAVE_KVM_GETFILES
330 while (i < udp_size && (udp_head[i].so_protocol != IPPROTO_UDP
331 || udp_head[i].so_family != AF_INET))
332 i++;
333 #endif
334 if (udp_size < i)
335 return NULL;
336
337 /*
338 * Set up the indexing for the specified row...
339 */
340 #if defined (WIN32) || defined (cygwin) || defined(openbsd5)
341 port = ntohl((u_long)udp_head[i].UDPTABLE_LOCALADDRESS);
342 snmp_set_var_value(index, (u_char *)&port,
343 sizeof(udp_head[i].UDPTABLE_LOCALADDRESS));
344 #else
345 snmp_set_var_value(index, (u_char *)&udp_head[i].UDPTABLE_LOCALADDRESS,
346 sizeof(udp_head[i].UDPTABLE_LOCALADDRESS));
347 #endif
348 port = UDP_PORT_TO_HOST_ORDER((u_short)udp_head[i].UDPTABLE_LOCALPORT);
349 snmp_set_var_value(index->next_variable,
350 (u_char*)&port, sizeof(port));
351 /*
352 * ... return the data structure for this row,
353 * and update the loop context ready for the next one.
354 */
355 *data_context = (void*)&udp_head[i];
356 *loop_context = (void*)(intptr_t)++i;
357 return index;
358 }
359
360 void
udpTable_free(netsnmp_cache * cache,void * magic)361 udpTable_free(netsnmp_cache *cache, void *magic)
362 {
363 #if defined (WIN32) || defined (cygwin)
364 if (udp_head) {
365 /* the allocated structure is a count followed by table entries */
366 free((char *)(udp_head) - sizeof(DWORD));
367 }
368 #elif defined(openbsd5)
369 #else
370 if (udp_head)
371 free(udp_head);
372 #endif
373 udp_head = NULL;
374 udp_size = 0;
375 }
376 #else
377 #ifdef UDPTABLE_IS_LINKED_LIST
378 netsnmp_variable_list *
udpTable_first_entry(void ** loop_context,void ** data_context,netsnmp_variable_list * index,netsnmp_iterator_info * data)379 udpTable_first_entry(void **loop_context,
380 void **data_context,
381 netsnmp_variable_list *index,
382 netsnmp_iterator_info *data)
383 {
384 /*
385 * XXX - How can we tell if the cache is valid?
386 * No access to 'reqinfo'
387 */
388 if (udp_head == NULL)
389 return NULL;
390
391 /*
392 * Point to the first entry, and use the
393 * 'next_entry' hook to retrieve this row
394 */
395 *loop_context = (void*)udp_head;
396 return udpTable_next_entry( loop_context, data_context, index, data );
397 }
398
399 netsnmp_variable_list *
udpTable_next_entry(void ** loop_context,void ** data_context,netsnmp_variable_list * index,netsnmp_iterator_info * data)400 udpTable_next_entry( void **loop_context,
401 void **data_context,
402 netsnmp_variable_list *index,
403 netsnmp_iterator_info *data)
404 {
405 UDPTABLE_ENTRY_TYPE *entry = (UDPTABLE_ENTRY_TYPE *)*loop_context;
406 long port;
407 in_addr_t addr;
408
409 if (!entry)
410 return NULL;
411
412 /*
413 * Set up the indexing for the specified row...
414 */
415 #if defined(osf5) && defined(IN6_EXTRACT_V4ADDR)
416 snmp_set_var_value(index,
417 (u_char*)&IN6_EXTRACT_V4ADDR(&entry->pcb.inp_laddr),
418 sizeof(IN6_EXTRACT_V4ADDR(&entry->pcb.inp_laddr)));
419 #else
420 addr = UDP_ADDRESS_TO_NETWORK_ORDER((in_addr_t)entry->UDPTABLE_LOCALADDRESS);
421 snmp_set_var_value(index, (u_char *)&addr,
422 sizeof(addr));
423 #endif
424 port = UDP_PORT_TO_HOST_ORDER(entry->UDPTABLE_LOCALPORT);
425 snmp_set_var_value(index->next_variable,
426 (u_char*)&port, sizeof(port));
427
428 /*
429 * ... return the data structure for this row,
430 * and update the loop context ready for the next one.
431 */
432 *data_context = (void*)entry;
433 *loop_context = (void*)entry->INP_NEXT_SYMBOL;
434 return index;
435 }
436
437 void
udpTable_free(netsnmp_cache * cache,void * magic)438 udpTable_free(netsnmp_cache *cache, void *magic)
439 {
440 UDPTABLE_ENTRY_TYPE *p;
441 while (udp_head) {
442 p = udp_head;
443 udp_head = udp_head->INP_NEXT_SYMBOL;
444 free(p);
445 }
446
447 udp_head = NULL;
448 }
449 #endif /* UDPTABLE_IS_LINKED_LIST */
450 #endif /* UDPTABLE_IS_TABLE */
451
452
453 /*
454 *
455 * The cache-handler loading routine is the main
456 * place for architecture-specific code
457 *
458 * Load into either a table structure, or a linked list
459 * depending on the system architecture
460 */
461
462
463 #ifdef hpux11
464 int
udpTable_load(netsnmp_cache * cache,void * vmagic)465 udpTable_load(netsnmp_cache *cache, void *vmagic)
466 {
467 int fd;
468 struct nmparms p;
469 int val = 0;
470 unsigned int ulen;
471 int ret;
472
473 udpTable_free(NULL, NULL);
474
475 if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
476 p.objid = ID_udpLsnNumEnt;
477 p.buffer = (void *) &val;
478 ulen = sizeof(int);
479 p.len = &ulen;
480 if ((ret = get_mib_info(fd, &p)) == 0)
481 udp_size = val;
482
483 if (udp_size > 0) {
484 ulen = (unsigned) udp_size *sizeof(mib_udpLsnEnt);
485 udp_head = (mib_udpLsnEnt *) malloc(ulen);
486 p.objid = ID_udpLsnTable;
487 p.buffer = (void *) udp_head;
488 p.len = &ulen;
489 if ((ret = get_mib_info(fd, &p)) < 0) {
490 udp_size = 0;
491 }
492 }
493
494 close_mib(fd);
495 }
496
497 if (udp_size > 0) {
498 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (hpux11)\n"));
499 return 0;
500 }
501 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (hpux11)\n"));
502 return -1;
503 }
504
505 #elif defined(linux)
506 int
udpTable_load(netsnmp_cache * cache,void * vmagic)507 udpTable_load(netsnmp_cache *cache, void *vmagic)
508 {
509 FILE *in;
510 char line[256];
511
512 udpTable_free(cache, NULL);
513
514 if (!(in = fopen("/proc/net/udp", "r"))) {
515 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (linux)\n"));
516 NETSNMP_LOGONCE((LOG_ERR, "snmpd: cannot open /proc/net/udp ...\n"));
517 return -1;
518 }
519
520 /*
521 * scan proc-file and build up a linked list
522 * This will actually be built up in reverse,
523 * but since the entries are unsorted, that doesn't matter.
524 */
525 while (line == fgets(line, sizeof(line), in)) {
526 struct inpcb pcb, *nnew;
527 unsigned int state, lport;
528
529 memset(&pcb, 0, sizeof(pcb));
530
531 if (3 != sscanf(line, "%*d: %x:%x %*x:%*x %x",
532 &pcb.inp_laddr.s_addr, &lport, &state))
533 continue;
534
535 if (state != 7) /* fix me: UDP_LISTEN ??? */
536 continue;
537
538 /* store in network byte order */
539 pcb.inp_laddr.s_addr = htonl(pcb.inp_laddr.s_addr);
540 pcb.inp_lport = htons((unsigned short) (lport));
541
542 nnew = SNMP_MALLOC_TYPEDEF(struct inpcb);
543 if (nnew == NULL)
544 break;
545 memcpy(nnew, &pcb, sizeof(struct inpcb));
546 nnew->inp_next = udp_head;
547 udp_head = nnew;
548 }
549
550 fclose(in);
551
552 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (linux)\n"));
553 return 0;
554 }
555
556 #elif HAVE_KVM_GETFILES
557
558 int
udpTable_load(netsnmp_cache * cache,void * vmagic)559 udpTable_load(netsnmp_cache *cache, void *vmagic)
560 {
561 int count;
562 udp_head = kvm_getfiles(kd, KERN_FILE_BYFILE, DTYPE_SOCKET, sizeof(struct kinfo_file), &count);
563 udp_size = count;
564 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (kvm_getfiles)\n"));
565 return 0;
566 }
567
568 #elif defined(solaris2)
569 static int
UDP_Cmp(void * addr,void * ep)570 UDP_Cmp(void *addr, void *ep)
571 {
572 if (memcmp((mib2_udpEntry_t *) ep, (mib2_udpEntry_t *) addr,
573 sizeof(mib2_udpEntry_t)) == 0)
574 return (0);
575 else
576 return (1);
577 }
578
579
580 int
udpTable_load(netsnmp_cache * cache,void * vmagic)581 udpTable_load(netsnmp_cache *cache, void *vmagic)
582 {
583 mib2_udpEntry_t entry;
584 netsnmp_udpEntry *nnew;
585 netsnmp_udpEntry *prev_entry = NULL;
586
587
588 udpTable_free(NULL, NULL);
589
590 if (getMibstat(MIB_UDP_LISTEN, &entry, sizeof(mib2_udpEntry_t),
591 GET_FIRST, &UDP_Cmp, &entry) != 0) {
592 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (solaris)\n"));
593 return -1;
594 }
595
596 while (1) {
597 /*
598 * Not interested in 'idle' entries, apparently....
599 */
600 DEBUGMSGTL(("mibII/udpTable", "UDP Entry %x:%d (%d)\n",
601 entry.udpLocalAddress, entry.udpLocalPort, entry.udpEntryInfo.ue_state));
602 if (entry.udpEntryInfo.ue_state == MIB2_UDP_idle) {
603 /*
604 * Build up a linked list copy of the getMibstat results
605 * Note that since getMibstat returns rows in sorted order,
606 * we need to retain this order while building the list
607 * so new entries are added onto the end of the list.
608 * xxx-rks: WARNING: this is NOT TRUE on the sf cf solaris boxes.
609 */
610 nnew = SNMP_MALLOC_TYPEDEF(netsnmp_udpEntry);
611 if (nnew == NULL)
612 break;
613 memcpy(&(nnew->entry), &entry, sizeof(mib2_udpEntry_t));
614 if (!prev_entry)
615 udp_head = nnew;
616 else
617 prev_entry->inp_next = nnew;
618 prev_entry = nnew;
619 }
620
621 if (getMibstat(MIB_UDP_LISTEN, &entry, sizeof(mib2_udpEntry_t),
622 GET_NEXT, &UDP_Cmp, &entry) != 0)
623 break;
624 }
625
626 if (udp_head) {
627 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (solaris)\n"));
628 return 0;
629 }
630 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (solaris)\n"));
631 return -1;
632 }
633
634 #elif defined (WIN32) || defined (cygwin)
635 int
udpTable_load(netsnmp_cache * cache,void * vmagic)636 udpTable_load(netsnmp_cache *cache, void *vmagic)
637 {
638 PMIB_UDPTABLE pUdpTable = NULL;
639 DWORD dwActualSize = 0;
640 DWORD status = NO_ERROR;
641
642 /*
643 * query for the buffer size needed
644 */
645 status = GetUdpTable(pUdpTable, &dwActualSize, TRUE);
646 if (status == ERROR_INSUFFICIENT_BUFFER) {
647 pUdpTable = (PMIB_UDPTABLE) malloc(dwActualSize);
648 if (pUdpTable != NULL) {
649 /*
650 * Get the sorted UDP table
651 */
652 status = GetUdpTable(pUdpTable, &dwActualSize, TRUE);
653 }
654 }
655 if (status == NO_ERROR) {
656 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (win32)\n"));
657 udp_size = pUdpTable->dwNumEntries -1; /* entries are counted starting with 0 */
658 udp_head = pUdpTable->table;
659 return 0;
660 }
661 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (win32)\n"));
662 if (pUdpTable)
663 free(pUdpTable);
664 return -1;
665 }
666
667 #elif (defined(NETSNMP_CAN_USE_SYSCTL) && defined(UDPCTL_PCBLIST))
668 int
udpTable_load(netsnmp_cache * cache,void * vmagic)669 udpTable_load(netsnmp_cache *cache, void *vmagic)
670 {
671 size_t len;
672 int sname[] = { CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_PCBLIST };
673 char *udpcb_buf = NULL;
674 #if defined(dragonfly)
675 struct xinpcb *xig = NULL;
676 #else
677 struct xinpgen *xig = NULL;
678 #endif
679 UDPTABLE_ENTRY_TYPE *nnew;
680
681 udpTable_free(NULL, NULL);
682
683 /*
684 * Read in the buffer containing the UDP table data
685 */
686 len = 0;
687 if (sysctl(sname, 4, 0, &len, 0, 0) < 0 ||
688 (udpcb_buf = malloc(len)) == NULL)
689 return -1;
690 if (sysctl(sname, 4, udpcb_buf, &len, 0, 0) < 0) {
691 free(udpcb_buf);
692 return -1;
693 }
694
695 /*
696 * Unpick this into the constituent 'xinpgen' structures, and extract
697 * the 'inpcb' elements into a linked list (built in reverse)
698 */
699 #if defined(dragonfly)
700 xig = (struct xinpcb *) udpcb_buf;
701 #else
702 xig = (struct xinpgen *) udpcb_buf;
703 xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
704 #endif
705
706 #if defined(dragonfly)
707 while (xig && ((char *)xig + xig->xi_len < udpcb_buf + len))
708 #else
709 while (xig && (xig->xig_len > sizeof(struct xinpgen)))
710 #endif
711 {
712 nnew = SNMP_MALLOC_TYPEDEF(UDPTABLE_ENTRY_TYPE);
713 if (!nnew)
714 break;
715 #if __FreeBSD_version >= 1200026
716 memcpy(&nnew->pcb, xig, sizeof(struct xinpcb));
717 #else
718 memcpy(&nnew->pcb, &((struct xinpcb *) xig)->xi_inp, sizeof(struct inpcb));
719 #endif
720 nnew->inp_next = udp_head;
721 udp_head = nnew;
722 #if defined(dragonfly)
723 xig = (struct xinpcb *) ((char *) xig + xig->xi_len);
724 #else
725 xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
726 #endif
727 }
728
729 free(udpcb_buf);
730 if (udp_head) {
731 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (sysctl)\n"));
732 return 0;
733 }
734 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (sysctl)\n"));
735 return -1;
736 }
737
738 #elif defined(PCB_TABLE)
739 int
udpTable_load(netsnmp_cache * cache,void * vmagic)740 udpTable_load(netsnmp_cache *cache, void *vmagic)
741 {
742 struct inpcbtable table;
743 struct inpcb *nnew, *entry;
744
745 udpTable_free(NULL, NULL);
746
747 if (!auto_nlist(UDB_SYMBOL, (char *) &table, sizeof(table))) {
748 DEBUGMSGTL(("mibII/udpTable", "Failed to read inpcbtable\n"));
749 return -1;
750 }
751
752 /*
753 * Set up a linked list
754 */
755 entry = table.INP_FIRST_SYMBOL;
756 while (entry) {
757
758 nnew = SNMP_MALLOC_TYPEDEF(struct inpcb);
759 if (!nnew)
760 break;
761
762 if (!NETSNMP_KLOOKUP(entry, (char *) nnew, sizeof(struct inpcb))) {
763 DEBUGMSGTL(("mibII/udpTable:udpTable_load", "klookup failed\n"));
764 break;
765 }
766
767 entry = nnew->INP_NEXT_SYMBOL; /* Next kernel entry */
768 nnew->INP_NEXT_SYMBOL = udp_head;
769 udp_head = nnew;
770
771 if (entry == table.INP_FIRST_SYMBOL)
772 break;
773 }
774
775 if (udp_head) {
776 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (pcb_table)\n"));
777 return 0;
778 }
779 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (pcb_table)\n"));
780 return -1;
781 }
782
783 #elif defined(UDB_SYMBOL)
784 int
udpTable_load(netsnmp_cache * cache,void * vmagic)785 udpTable_load(netsnmp_cache *cache, void *vmagic)
786 {
787 struct inpcb udp_inpcb;
788 struct inpcb *nnew, *entry;
789
790 udpTable_free(NULL, NULL);
791
792 if (!auto_nlist(UDB_SYMBOL, (char *) &udp_inpcb, sizeof(udp_inpcb))) {
793 DEBUGMSGTL(("mibII/udpTable", "Failed to read udb_symbol\n"));
794 return -1;
795 }
796
797 /*
798 * Set up a linked list
799 */
800 entry = udp_inpcb.INP_NEXT_SYMBOL;
801 while (entry) {
802
803 nnew = SNMP_MALLOC_TYPEDEF(struct inpcb);
804 if (!nnew)
805 break;
806
807 if (!NETSNMP_KLOOKUP(entry, (char *) nnew, sizeof(struct inpcb))) {
808 DEBUGMSGTL(("mibII/udpTable:udpTable_load", "klookup failed\n"));
809 break;
810 }
811
812 entry = nnew->INP_NEXT_SYMBOL; /* Next kernel entry */
813 nnew->INP_NEXT_SYMBOL = udp_head;
814 udp_head = nnew;
815
816 if (entry == udp_inpcb.INP_NEXT_SYMBOL)
817 break;
818 }
819
820 if (udp_head) {
821 DEBUGMSGTL(("mibII/udpTable", "Loaded UDP Table (udb_symbol)\n"));
822 return 0;
823 }
824 DEBUGMSGTL(("mibII/udpTable", "Failed to load UDP Table (udb_symbol)\n"));
825 return -1;
826 }
827
828 #else /* UDB_SYMBOL */
829 int
udpTable_load(netsnmp_cache * cache,void * vmagic)830 udpTable_load(netsnmp_cache *cache, void *vmagic)
831 {
832 DEBUGMSGTL(("mibII/udpTable", "Loading UDP Table not implemented\n"));
833 return -1;
834 }
835 #endif /* UDB_SYMBOL */
836