1 #ifdef BUILD_SNMP_UDP_MIB
3 * UDP MIB group Table implementation - udpTable.c
7 #include <net-snmp/net-snmp-config.h>
14 #include <sys/types.h>
20 #include <sys/param.h>
24 #include <netinet/in.h>
27 #include <sys/sysmp.h>
29 #if HAVE_SYS_TCPIPSTATS_H
30 #include <sys/tcpipstats.h>
32 #if defined(IFNET_NEEDS_KERNEL) && !defined(_KERNEL)
34 #define _I_DEFINED_KERNEL
37 #include <sys/socket.h>
43 #include <net/if_var.h>
45 #ifdef _I_DEFINED_KERNEL
50 #include <sys/stream.h>
53 #include <net/route.h>
55 #if HAVE_NETINET_IN_SYSTM_H
56 #include <netinet/in_systm.h>
59 #include <netinet/ip.h>
62 #include <sys/queue.h>
64 #if HAVE_SYS_SOCKETVAR_H
65 #include <sys/socketvar.h>
67 #if HAVE_NETINET_IP_VAR_H
68 #include <netinet/ip_var.h>
71 #if HAVE_NETINET6_IP6_VAR_H
72 #include <netinet6/ip6_var.h>
75 #if HAVE_NETINET_IN_PCB_H
76 #include <netinet/in_pcb.h>
78 #if HAVE_NETINET_UDP_H
79 #include <netinet/udp.h>
81 #if HAVE_NETINET_UDP_VAR_H
82 #include <netinet/udp_var.h>
85 #include <inet/mib2.h>
89 #include "kernel_sunos5.h"
99 #include <net-snmp/net-snmp-includes.h>
100 #include <net-snmp/agent/net-snmp-agent-includes.h>
101 #include <net-snmp/agent/auto_nlist.h>
105 #include <netinet/mib_kern.h>
109 #include "tcpTable.h"
112 #include "udpTable.h"
113 #include "sysORTable.h"
115 #ifdef CAN_USE_SYSCTL
116 #include <sys/sysctl.h>
123 /*********************
125 * Kernel & interface information,
126 * and internal forward declarations
128 *********************/
131 static void UDP_Scan_Init(void);
133 static int UDP_Scan_Next(mib_udpLsnEnt *);
135 static int UDP_Scan_Next(struct inpcb *);
139 /*********************
141 * Initialisation & common implementation functions
143 *********************/
146 /*********************
148 * System specific implementation functions
150 *********************/
156 var_udpEntry(struct variable *vp,
159 int exact, size_t * var_len, WriteMethod ** write_method)
162 oid newname[MAX_OID_LEN], lowest[MAX_OID_LEN], *op;
166 static mib_udpLsnEnt udp, Lowudp;
168 static struct inpcb inpcb, Lowinpcb;
171 memcpy((char *) newname, (char *) vp->name,
172 (int) vp->namelen * sizeof(oid));
174 * find the "next" pseudo-connection
179 LowState = -1; /* UDP doesn't have 'State', but it's a useful flag */
183 if ((i = UDP_Scan_Next(&udp)) == 0)
185 cp = (u_char *) & udp.LocalAddress;
187 if ((i = UDP_Scan_Next(&inpcb)) < 0)
191 cp = (u_char *) & inpcb.inp_laddr.s_addr;
200 newname[14] = (unsigned short) udp.LocalPort;
202 newname[14] = ntohs(inpcb.inp_lport);
206 if (snmp_oid_compare(newname, 15, name, *length) == 0) {
207 memcpy((char *) lowest, (char *) newname,
215 break; /* no need to search further */
218 if ((snmp_oid_compare(newname, 15, name, *length) > 0) &&
220 || (snmp_oid_compare(newname, 15, lowest, 15) < 0))) {
222 * if new one is greater than input and closer to input than
223 * previous lowest, save this one as the "next" one.
225 memcpy((char *) lowest, (char *) newname,
238 memcpy((char *) name, (char *) lowest,
239 ((int) vp->namelen + 10) * sizeof(oid));
240 *length = vp->namelen + 5;
242 *var_len = sizeof(long);
244 case UDPLOCALADDRESS:
246 return (u_char *) & Lowudp.LocalAddress;
248 return (u_char *) & Lowinpcb.inp_laddr.s_addr;
252 long_return = (unsigned short) Lowudp.LocalPort;
254 long_return = ntohs(Lowinpcb.inp_lport);
256 return (u_char *) & long_return;
258 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_udpEntry\n",
264 #else /* solaris2 - udp */
267 UDP_Cmp(void *addr, void *ep)
269 if (memcmp((mib2_udpEntry_t *) ep, (mib2_udpEntry_t *) addr,
270 sizeof(mib2_udpEntry_t)) == 0)
277 var_udpEntry(struct variable * vp,
280 int exact, size_t * var_len, WriteMethod ** write_method)
282 oid newname[MAX_OID_LEN], lowest[MAX_OID_LEN], *op;
285 #define UDP_LISTEN_LENGTH 15
286 #define UDP_LOCADDR_OFF 10
287 #define UDP_LOCPORT_OFF 14
288 mib2_udpEntry_t Lowentry, Nextentry, entry;
292 memset(&Lowentry, 0, sizeof(Lowentry));
293 memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
294 if (*length == UDP_LISTEN_LENGTH) /* Assume that the input name is the lowest */
295 memcpy((char *) lowest, (char *) name,
296 UDP_LISTEN_LENGTH * sizeof(oid));
297 for (Nextentry.udpLocalAddress = (u_long) - 1, req_type = GET_FIRST;;
298 req_type = GET_NEXT) {
300 (MIB_UDP_LISTEN, &entry, sizeof(mib2_udpEntry_t), req_type,
301 &UDP_Cmp, &entry) != 0)
303 if (entry.udpEntryInfo.ue_state != MIB2_UDP_idle)
304 continue; /* we only want to get listen ports */
305 COPY_IPADDR(cp, (u_char *) & entry.udpLocalAddress, op,
306 newname + UDP_LOCADDR_OFF);
307 newname[UDP_LOCPORT_OFF] = entry.udpLocalPort;
310 if (snmp_oid_compare(newname, UDP_LISTEN_LENGTH, name, *length)
312 memcpy((char *) lowest, (char *) newname,
313 UDP_LISTEN_LENGTH * sizeof(oid));
316 break; /* no need to search further */
319 if ((snmp_oid_compare
320 (newname, UDP_LISTEN_LENGTH, name, *length) > 0)
321 && ((Nextentry.udpLocalAddress == (u_long) - 1)
324 (newname, UDP_LISTEN_LENGTH, lowest,
325 UDP_LISTEN_LENGTH) < 0)
328 (name, *length, lowest, UDP_LISTEN_LENGTH) == 0))) {
330 * if new one is greater than input and closer to input than
331 * * previous lowest, and is not equal to it, save this one as
334 memcpy((char *) lowest, (char *) newname,
335 UDP_LISTEN_LENGTH * sizeof(oid));
344 memcpy((char *) name, (char *) lowest,
345 (vp->namelen + UDP_LISTEN_LENGTH -
346 UDP_LOCADDR_OFF) * sizeof(oid));
347 *length = vp->namelen + UDP_LISTEN_LENGTH - UDP_LOCADDR_OFF;
349 *var_len = sizeof(long);
351 case UDPLOCALADDRESS:
352 long_return = Lowentry.udpLocalAddress;
353 return (u_char *) & long_return;
355 long_return = Lowentry.udpLocalPort;
356 return (u_char *) & long_return;
358 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_udpEntry\n",
363 #endif /* solaris2 - udp */
366 /*********************
368 * Internal implementation functions
370 *********************/
373 static struct inpcb *udp_inpcb_list;
379 static int udptab_size, udptab_current;
380 static mib_udpLsnEnt *udp = (mib_udpLsnEnt *) 0;
382 static struct inpcb udp_inpcb, *udp_prev;
384 static struct inpcb *udp_head, *udp_next;
386 #if defined(CAN_USE_SYSCTL) && defined(UDPCTL_PCBLIST)
387 static char *udpcb_buf = NULL;
388 static struct xinpgen *xig = NULL;
389 #endif /* !defined(CAN_USE_SYSCTL) || !define(UDPCTL_PCBLIST) */
406 udp = (mib_udpLsnEnt *) 0;
409 if ((fd = open_mib("/dev/ip", O_RDONLY, 0, NM_ASYNC_OFF)) >= 0) {
410 p.objid = ID_udpLsnNumEnt;
411 p.buffer = (void *) &val;
414 if ((ret = get_mib_info(fd, &p)) == 0)
417 if (udptab_size > 0) {
418 ulen = (unsigned) udptab_size *sizeof(mib_udpLsnEnt);
419 udp = (mib_udpLsnEnt *) malloc(ulen);
420 p.objid = ID_udpLsnTable;
421 p.buffer = (void *) udp;
423 if ((ret = get_mib_info(fd, &p)) < 0)
434 #if !defined(CAN_USE_SYSCTL) || !defined(UDPCTL_PCBLIST)
436 struct inpcbtable table;
440 auto_nlist(UDB_SYMBOL, (char *) &table, sizeof(table));
441 udp_next = table.inpt_queue.cqh_first;
442 udp_head = udp_prev =
443 (struct inpcb *) &((struct inpcbtable *)
444 auto_nlist_value(UDB_SYMBOL))->inpt_queue.
447 auto_nlist(UDB_SYMBOL, (char *) &udp_inpcb, sizeof(udp_inpcb));
448 #if !(defined(freebsd2) || defined(netbsd1) || defined(openbsd2))
449 udp_prev = (struct inpcb *) auto_nlist_value(UDB_SYMBOL);
457 static unsigned long Time_Of_Last_Reload = 0;
460 * save some cpu-cycles, and reload after 5 secs...
462 gettimeofday(&now, (struct timezone *) 0);
463 if (Time_Of_Last_Reload + 5 > now.tv_sec) {
464 udp_prev = udp_inpcb_list;
467 Time_Of_Last_Reload = now.tv_sec;
470 if (!(in = fopen("/proc/net/udp", "r"))) {
471 snmp_log(LOG_ERR, "snmpd: cannot open /proc/net/udp ...\n");
479 while (udp_inpcb_list) {
480 struct inpcb *p = udp_inpcb_list;
481 udp_inpcb_list = udp_inpcb_list->inp_next;
486 * scan proc-file and append:
489 pp = &udp_inpcb_list;
491 while (line == fgets(line, sizeof(line), in)) {
492 struct inpcb pcb, *nnew;
493 unsigned int state, lport;
495 if (3 != sscanf(line, "%*d: %x:%x %*x:%*x %x",
496 &pcb.inp_laddr.s_addr, &lport, &state))
499 if (state != 7) /* fix me: UDP_LISTEN ??? */
502 pcb.inp_lport = htons((unsigned short) (lport));
503 pcb.inp_fport = htons(pcb.inp_fport);
505 nnew = (struct inpcb *) malloc(sizeof(struct inpcb));
512 pp = &nnew->inp_next;
520 udp_prev = udp_inpcb_list;
522 #else /* !defined(CAN_USE_SYSCTL) || !defined(UDPCTL_PCBLIST) */
526 { CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_PCBLIST };
535 if (sysctl(sname, 4, 0, &len, 0, 0) < 0) {
538 if ((udpcb_buf = malloc(len)) == NULL) {
541 if (sysctl(sname, 4, udpcb_buf, &len, 0, 0) < 0) {
547 xig = (struct xinpgen *) udpcb_buf;
548 xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
551 #endif /* !defined(CAN_USE_SYSCTL) || !defined(UDPCTL_PCBLIST) */
558 UDP_Scan_Next(mib_udpLsnEnt * RetUdp)
560 if (udptab_current < udptab_size) {
564 *RetUdp = udp[udptab_current];
566 * increment to point to next entry
582 UDP_Scan_Next(struct inpcb *RetInPcb)
584 #if !defined(CAN_USE_SYSCTL) || !defined(UDPCTL_PCBLIST)
585 register struct inpcb *next;
589 if (udp_next == udp_head)
592 if ((udp_inpcb.INP_NEXT_SYMBOL == NULL) ||
593 (udp_inpcb.INP_NEXT_SYMBOL ==
594 (struct inpcb *) auto_nlist_value(UDB_SYMBOL))) {
595 return (0); /* "EOF" */
600 klookup((unsigned long) udp_next, (char *) &udp_inpcb,
602 udp_next = udp_inpcb.inp_queue.cqe_next;
604 next = udp_inpcb.INP_NEXT_SYMBOL;
606 klookup((unsigned long) next, (char *) &udp_inpcb, sizeof(udp_inpcb));
607 #if !(defined(netbsd1) || defined(freebsd2) || defined(linux) || defined(openbsd2))
608 if (udp_inpcb.INP_PREV_SYMBOL != udp_prev) /* ??? */
609 return (-1); /* "FAILURE" */
612 *RetInPcb = udp_inpcb;
613 #if !(defined(netbsd1) || defined(freebsd2) || defined(openbsd2))
620 udp_inpcb = *udp_prev;
621 next = udp_inpcb.inp_next;
622 *RetInPcb = udp_inpcb;
625 #else /* !defined(CAN_USE_SYSCTL) || !defined(UDPCTL_PCBLIST) */
629 if ((xig == NULL) || (xig->xig_len <= sizeof(struct xinpgen)))
632 *RetInPcb = ((struct xinpcb *) xig)->xi_inp;
635 * Prepare for Next read
637 xig = (struct xinpgen *) ((char *) xig + xig->xig_len);
638 #endif /* !defined(CAN_USE_SYSCTL) || !defined(UDPCTL_PCBLIST) */
639 return (1); /* "OK" */
642 #endif /* solaris2 */
645 #include <iphlpapi.h>
648 var_udpEntry(struct variable *vp,
651 int exact, size_t * var_len, WriteMethod ** write_method)
653 oid newname[MAX_OID_LEN], lowest[MAX_OID_LEN], *op;
656 static PMIB_UDPTABLE pUdpTable = NULL;
657 DWORD status = NO_ERROR;
658 DWORD dwActualSize = 0;
661 static long Time_Of_Last_Reload = 0;
662 struct in_addr inadLocal;
663 memcpy((char *) newname, (char *) vp->name,
664 (int) vp->namelen * sizeof(oid));
667 * save some cpu-cycles, and reload after 5 secs...
669 gettimeofday(&now, (struct timezone *) 0);
670 if ((Time_Of_Last_Reload + 5 <= now.tv_sec) || (pUdpTable == NULL)) {
671 if (pUdpTable != NULL)
673 Time_Of_Last_Reload = now.tv_sec;
675 * query for the buffer size needed
677 status = GetUdpTable(pUdpTable, &dwActualSize, TRUE);
678 if (status == ERROR_INSUFFICIENT_BUFFER) {
679 pUdpTable = (PMIB_UDPTABLE) malloc(dwActualSize);
680 if (pUdpTable != NULL) {
682 * Get the sorted UDP table
684 status = GetUdpTable(pUdpTable, &dwActualSize, TRUE);
689 if (status == NO_ERROR) {
690 for (i = 0; i < pUdpTable->dwNumEntries; ++i) {
691 inadLocal.s_addr = pUdpTable->table[i].dwLocalAddr;
692 cp = (u_char *) & pUdpTable->table[i].dwLocalAddr;
701 ntohs((unsigned short) (0x0000FFFF & pUdpTable->table[i].
705 if (snmp_oid_compare(newname, 15, name, *length) == 0) {
706 memcpy((char *) lowest, (char *) newname,
709 break; /* no need to search further */
712 if (snmp_oid_compare(newname, 15, name, *length) > 0) {
713 memcpy((char *) lowest, (char *) newname,
716 inadLocal.s_addr = pUdpTable->table[i].dwLocalAddr;
717 break; /* As the table is sorted, no need to search further */
728 memcpy((char *) name, (char *) lowest,
729 ((int) vp->namelen + 10) * sizeof(oid));
730 *length = vp->namelen + 5;
732 *var_len = sizeof(long);
734 case UDPLOCALADDRESS:
735 return (u_char *) & pUdpTable->table[i].dwLocalAddr;
738 ntohs((unsigned short) (0x0000FFFF & pUdpTable->table[i].
740 return (u_char *) & long_return;
742 DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_udpEntry\n",
750 #endif /* BUILD_SNMP_UDP_MIB */