No empty .Rs/.Re
[netbsd-mini2440.git] / usr.sbin / mrouted / snmp.c
blobdac7df848a26cd763fcf8bac9a07d6c0f2e8188b
1 /* $NetBSD: snmp.c,v 1.10 2003/03/05 21:12:26 wiz Exp $ */
3 /*
4 * Copyright (c) 1992, 2001 Xerox Corporation. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
9 * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * Neither name of the Xerox, PARC, nor the names of its contributors may be used
17 * to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE XEROX CORPORATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "defs.h"
34 #include <netinet/in_var.h>
35 #include "snmp.h"
36 #include "snmplib/asn1.h"
37 #include "snmplib/party.h"
38 #include "snmplib/snmp_impl.h"
39 #define MROUTED
40 #include "snmpd/snmp_vars.h"
42 in_port_t dest_port = 0;
43 int sdlen = 0;
45 struct addrCache {
46 u_long addr;
47 int status;
48 #define UNUSED 0
49 #define USED 1
50 #define OLD 2
53 static struct addrCache addrCache[10];
56 * Initialize the SNMP part of mrouted
58 int /* returns: 0 on success, true on error */
59 snmp_init(dest_port)
60 in_port_t dest_port;
62 u_long myaddr;
63 int ret;
64 struct partyEntry *pp;
65 struct sockaddr_in me;
66 int index, sd, portlist[32];
68 init_snmp();
69 /* init_mib(); why was this here? */
70 if (read_party_database("/etc/party.conf") > 0){
71 fprintf(stderr, "Couldn't read party database from /etc/party.conf\n");
72 exit(0);
74 if (read_context_database("/etc/context.conf") > 0){
75 fprintf(stderr, "Couldn't read context database from /etc/context.conf\n");
76 exit(0);
78 if (read_acl_database("/etc/acl.conf") > 0){
79 fprintf(stderr, "Couldn't read acl database from /etc/acl.conf\n");
80 exit(0);
82 if (read_view_database("/etc/view.conf") > 0){
83 fprintf(stderr, "Couldn't read view database from /etc/view.conf\n");
84 exit(0);
87 myaddr = get_myaddr();
88 if (ret = agent_party_init(myaddr, ".1.3.6.1")){
89 if (ret == 1){
90 fprintf(stderr, "Conflict found with initial noAuth/noPriv parties... continuing\n");
91 } else if (ret == -1){
92 fprintf(stderr, "Error installing initial noAuth/noPriv parties, exiting\n");
93 exit(1);
94 } else {
95 fprintf(stderr, "Unknown error, exiting\n");
96 exit(2);
100 printf("Opening port(s): ");
101 fflush(stdout);
102 party_scanInit();
103 for(pp = party_scanNext(); pp; pp = party_scanNext()){
104 if ((pp->partyTDomain != DOMAINSNMPUDP)
105 || bcmp((char *)&myaddr, pp->partyTAddress, 4))
106 continue; /* don't listen for non-local parties */
108 dest_port = 0;
109 bcopy(pp->partyTAddress + 4, &dest_port, 2);
110 for(index = 0; index < sdlen; index++)
111 if (dest_port == portlist[index])
112 break;
113 if (index < sdlen) /* found a hit before the end of the list */
114 continue;
115 printf("%u ", dest_port);
116 fflush(stdout);
117 /* Set up connections */
118 sd = socket(AF_INET, SOCK_DGRAM, 0);
119 if (sd < 0){
120 perror("socket");
121 return 1;
123 memset(&me, 0, sizeof(me));
124 me.sin_family = AF_INET;
125 me.sin_addr.s_addr = INADDR_ANY;
126 /* already in network byte order (I think) */
127 me.sin_port = dest_port;
128 if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){
129 perror("bind");
130 return 2;
132 register_input_handler(sd, snmp_read_packet);
133 portlist[sdlen] = dest_port;
134 if (++sdlen == 32){
135 printf("No more sockets... ignoring rest of file\n");
136 break;
139 printf("\n");
140 bzero((char *)addrCache, sizeof(addrCache));
144 * Place an IP address into an OID starting at element n
146 void
147 put_address(name, addr, n)
148 oid *name;
149 u_long addr;
150 int n;
152 int i;
154 for (i=n+3; i>=n+0; i--) {
155 name[i] = addr & 0xFF;
156 addr >>= 8;
160 /* Get an IP address from an OID starting at element n */
162 get_address(name, length, addr, n)
163 oid *name;
164 int length;
165 u_long *addr;
166 int n;
168 int i;
169 int ok = 1;
171 (*addr) = 0;
173 if (length < n+4)
174 return 0;
176 for (i=n; i<n+4; i++) {
177 (*addr) <<= 8;
178 if (i >= length)
179 ok = 0;
180 else
181 (*addr) |= name[i];
183 return ok;
187 * Implements scalar objects from DVMRP and Multicast MIBs
189 u_char *
190 o_scalar(vp, name, length, exact, var_len, write_method)
191 struct variable *vp; /* IN - pointer to variable entry that points here */
192 oid *name; /* IN/OUT - input name requested, output name found */
193 int *length; /* IN/OUT - length of input and output oid's */
194 int exact; /* IN - TRUE if an exact match was requested. */
195 int *var_len; /* OUT - length of variable or 0 if function returned. */
196 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
198 int result;
200 *write_method = 0;
201 result = compare(name, *length, vp->name, (int)vp->namelen);
202 if ((exact && (result != 0)) || (!exact && (result >= 0)))
203 return NULL;
205 bcopy((char *)vp->name, (char *)name,
206 (int)vp->namelen * sizeof(oid));
207 *length = vp->namelen;
208 *var_len = sizeof(long);
210 switch (vp->magic) {
212 case ipMRouteEnable:
213 long_return = 1;
214 return (u_char *) &long_return;
216 case dvmrpVersion: {
217 static char buff[15];
219 snprintf(buff, sizeof(buff), "mrouted%d.%d", PROTOCOL_VERSION,
220 MROUTED_VERSION);
221 *var_len = strlen(buff);
222 return (u_char *)buff;
225 case dvmrpGenerationId:
226 long_return = dvmrp_genid;
227 return (u_char *) &long_return;
229 default:
230 ERROR("");
232 return NULL;
236 * Find if a specific scoped boundary exists on a Vif
238 struct vif_acl *
239 find_boundary(vifi, addr, mask)
240 vifi_t vifi;
241 u_long addr;
242 u_long mask;
244 struct vif_acl *n;
246 for (n = uvifs[vifi].uv_acl; n != NULL; n = n->acl_next) {
247 if (addr == n->acl_addr && mask==n->acl_mask)
248 return n;
250 return NULL;
254 * Find the lowest boundary >= (V,A,M) spec
256 struct vif_acl *
257 next_boundary(vifi, addr, mask)
258 vifi_t *vifi;
259 u_long addr;
260 u_long mask;
262 struct vif_acl *bestn, *n;
263 int i;
265 for (i = *vifi; i < numvifs; i++) {
266 bestn = NULL;
267 for (n = uvifs[i].uv_acl; n; n=n->acl_next) {
268 if ((i > *vifi || n->acl_addr > addr
269 || (n->acl_addr == addr && n->acl_mask >= mask))
270 && (!bestn || n->acl_addr < bestn->acl_addr
271 || (n->acl_addr==bestn->acl_addr && n->acl_mask<bestn->acl_mask)))
272 bestn = n;
274 if (bestn) {
275 *vifi = i;
276 return bestn;
279 return NULL;
283 * Implements the Boundary Table portion of the DVMRP MIB
285 u_char *
286 o_dvmrpBoundaryTable(vp, name, length, exact, var_len, write_method)
287 struct variable *vp; /* IN - pointer to variable entry that points here */
288 oid *name; /* IN/OUT - input name requested, output name found */
289 int *length; /* IN/OUT - length of input and output oid's */
290 int exact; /* IN - TRUE if an exact match was requested. */
291 int *var_len; /* OUT - length of variable or 0 if function returned. */
292 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
294 vifi_t vifi;
295 u_long addr, mask;
296 struct vif_acl *bound;
297 oid newname[MAX_NAME_LEN];
298 int len;
300 /* Copy name OID to new OID */
301 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
303 if (exact) {
304 if (*length != vp->namelen + 9)
305 return NULL;
307 if ((vifi = name[vp->namelen]) >= numvifs)
308 return NULL;
310 if (!get_address(name, *length, &addr, vp->namelen+1)
311 || !get_address(name, *length, &mask, vp->namelen+5))
312 return NULL;
314 if (!(bound = find_boundary(vifi, addr, mask)))
315 return NULL;
317 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
318 } else {
319 len = *length;
320 if (compare(name, *length, vp->name, vp->namelen) < 0)
321 len = vp->namelen;
323 if (len < vp->namelen + 9) { /* get first entry */
325 if (len == vp->namelen) {
326 vifi = addr = mask = 0;
327 } else {
328 vifi = name[vp->namelen];
329 get_address(name, len, &addr, vp->namelen+1);
330 get_address(name, len, &mask, vp->namelen+5);
333 bound = next_boundary(&vifi,addr,mask);
334 if (!bound)
335 return NULL;
337 newname[vp->namelen] = vifi;
338 put_address(newname, bound->acl_addr, vp->namelen+1);
339 put_address(newname, bound->acl_mask, vp->namelen+5);
340 } else { /* get next entry given previous */
341 vifi = name[vp->namelen];
342 get_address(name, *length, &addr, vp->namelen+1);
343 get_address(name, *length, &mask, vp->namelen+5);
345 if (!(bound = next_boundary(&vifi,addr,mask+1)))
346 return NULL;
348 newname[vp->namelen] = vifi;
349 put_address(newname, bound->acl_addr, vp->namelen+1);
350 put_address(newname, bound->acl_mask, vp->namelen+5);
354 /* Save new OID */
355 *length = vp->namelen + 9;
356 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
357 *write_method = 0;
358 *var_len = sizeof(long);
360 switch (vp->magic) {
362 case dvmrpBoundaryVifIndex:
363 long_return = vifi;
364 return (u_char *) &long_return;
366 default:
367 ERROR("");
369 return NULL;
373 * Find the lowest neighbor >= (V,A) spec
375 struct listaddr *
376 next_neighbor(vifi, addr)
377 vifi_t *vifi;
378 u_long addr;
380 struct listaddr *bestn, *n;
381 int i;
383 for (i = *vifi; i < numvifs; i++) {
384 bestn = NULL;
385 for (n = uvifs[i].uv_neighbors; n; n=n->al_next) {
386 if ((i > *vifi || n->al_addr >= addr)
387 && (!bestn || n->al_addr < bestn->al_addr))
388 bestn = n;
390 if (bestn) {
391 *vifi = i;
392 return bestn;
395 return NULL;
399 * Find a neighbor, if it exists off a given Vif
401 struct listaddr *
402 find_neighbor(vifi, addr)
403 vifi_t vifi;
404 u_long addr;
406 struct listaddr *n;
408 for (n = uvifs[vifi].uv_neighbors; n != NULL; n = n->al_next) {
409 if (addr == n->al_addr)
410 return n;
412 return NULL;
415 u_char *
416 o_dvmrpNeighborTable(vp, name, length, exact, var_len, write_method)
417 struct variable *vp; /* IN - pointer to variable entry that points here */
418 oid *name; /* IN/OUT - input name requested, output name found */
419 int *length; /* IN/OUT - length of input and output oid's */
420 int exact; /* IN - TRUE if an exact match was requested. */
421 int *var_len; /* OUT - length of variable or 0 if function returned. */
422 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
424 vifi_t vifi;
425 u_long addr, mask;
426 struct listaddr *neighbor;
427 oid newname[MAX_NAME_LEN];
428 int len;
430 /* Copy name OID to new OID */
431 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
433 if (exact) {
434 if (*length != vp->namelen + 5)
435 return NULL;
437 if ((vifi = name[vp->namelen]) >= numvifs)
438 return NULL;
440 if (!get_address(name, *length, &addr, vp->namelen+1))
441 return NULL;
443 if (!(neighbor = find_neighbor(vifi, addr)))
444 return NULL;
446 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
447 } else {
448 len = *length;
449 if (compare(name, *length, vp->name, vp->namelen) < 0)
450 len = vp->namelen;
452 if (len < vp->namelen + 5) { /* get first entry */
454 if (len == vp->namelen) {
455 vifi = addr = 0;
456 } else {
457 vifi = name[vp->namelen];
458 get_address(name, len, &addr, vp->namelen+1);
461 neighbor = next_neighbor(&vifi,addr);
462 if (!neighbor)
463 return NULL;
465 newname[vp->namelen] = vifi;
466 put_address(newname, neighbor->al_addr, vp->namelen+1);
467 } else { /* get next entry given previous */
468 vifi = name[vp->namelen];
469 get_address(name, *length, &addr, vp->namelen+1);
471 if (!(neighbor = next_neighbor(&vifi,addr+1)))
472 return NULL;
474 newname[vp->namelen] = vifi;
475 put_address(newname, neighbor->al_addr, vp->namelen+1);
479 /* Save new OID */
480 *length = vp->namelen + 5;
481 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
482 *write_method = 0;
483 *var_len = sizeof(long);
485 switch (vp->magic) {
487 case dvmrpNeighborUpTime: {
488 time_t currtime;
489 time(&currtime);
490 long_return = (currtime - neighbor->al_ctime)*100;
491 return (u_char *) &long_return;
494 case dvmrpNeighborExpiryTime:
495 long_return = (NEIGHBOR_EXPIRE_TIME - neighbor->al_timer
496 + secs_remaining_offset()) * 100;
497 return (u_char *) &long_return;
499 case dvmrpNeighborVersion: {
500 static char buff[15];
502 snprintf(buff, sizeof(buff), "%d.%d", neighbor->al_pv, neighbor->al_mv);
503 *var_len = strlen(buff);
504 return (u_char *)buff;
507 case dvmrpNeighborGenerationId:
508 long_return = neighbor->al_genid;
509 return (u_char *) &long_return;
511 default:
512 ERROR("");
514 return NULL;
517 /* Look up ifIndex given uvifs[ifnum].uv_lcl_addr */
518 struct in_ifaddr * /* returns: in_ifaddr structure, or null on error */
519 ipaddr_to_ifindex(ipaddr, ifIndex)
520 u_long ipaddr;
521 int *ifIndex;
523 int interface;
524 static struct in_ifaddr in_ifaddr;
526 Interface_Scan_Init();
527 for (;;) {
528 if (Interface_Scan_Next(&interface, (char *)0, NULL, &in_ifaddr) == 0)
529 return NULL;
531 if (((struct sockaddr_in *) &(in_ifaddr.ia_addr))->sin_addr.s_addr
532 == ipaddr) {
533 *ifIndex = interface;
534 return &in_ifaddr;
540 * Find if a specific scoped boundary exists on a Vif
542 struct listaddr *
543 find_cache(grp, vifi)
544 u_long grp;
545 vifi_t vifi;
547 struct listaddr *n;
549 for (n = uvifs[vifi].uv_groups; n != NULL; n = n->al_next) {
550 if (grp == n->al_addr)
551 return n;
553 return NULL;
557 * Find the next group cache entry >= (A,V) spec
559 struct listaddr *
560 next_cache(addr, vifi)
561 u_long addr;
562 vifi_t *vifi;
564 struct listaddr *bestn=NULL, *n;
565 int i, besti;
567 /* Step through all entries looking for the next one */
568 for (i = 0; i < numvifs; i++) {
569 for (n = uvifs[i].uv_groups; n; n=n->al_next) {
570 if ((n->al_addr > addr || (n->al_addr == addr && i >= *vifi))
571 && (!bestn || n->al_addr < bestn->al_addr
572 || (n->al_addr == bestn->al_addr && i < besti))) {
573 bestn = n;
574 besti = i;
579 if (bestn) {
580 *vifi = besti;
581 return bestn;
583 return NULL;
587 * Implements the IGMP Cache Table portion of the IGMP MIB
589 u_char *
590 o_igmpCacheTable(vp, name, length, exact, var_len, write_method)
591 struct variable *vp; /* IN - pointer to variable entry that points here */
592 oid *name; /* IN/OUT - input name requested, output name found */
593 int *length; /* IN/OUT - length of input and output oid's */
594 int exact; /* IN - TRUE if an exact match was requested. */
595 int *var_len; /* OUT - length of variable or 0 if function returned. */
596 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
598 vifi_t vifi;
599 u_long grp;
600 int ifIndex;
601 struct listaddr *cache;
602 oid newname[MAX_NAME_LEN];
603 int len;
604 struct in_ifaddr *in_ifaddr;
605 struct in_multi in_multi, *inm;
607 /* Copy name OID to new OID */
608 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
610 if (exact) {
611 if (*length != vp->namelen + 5)
612 return NULL;
614 if ((vifi = name[vp->namelen+4]) >= numvifs)
615 return NULL;
617 if (!get_address(name, *length, &grp, vp->namelen))
618 return NULL;
620 if (!(cache = find_cache(grp, vifi)))
621 return NULL;
623 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
624 } else {
625 len = *length;
626 if (compare(name, *length, vp->name, vp->namelen) < 0)
627 len = vp->namelen;
629 if (len < vp->namelen + 5) { /* get first entry */
631 if (len == vp->namelen) {
632 vifi = grp = 0;
633 } else {
634 get_address(name, len, &grp, vp->namelen);
635 vifi = name[vp->namelen+4];
638 cache = next_cache(grp,&vifi);
639 if (!cache)
640 return NULL;
642 put_address(newname, cache->al_addr, vp->namelen);
643 newname[vp->namelen+4] = vifi;
644 } else { /* get next entry given previous */
645 get_address(name, *length, &grp, vp->namelen);
646 vifi = name[vp->namelen+4]+1;
648 if (!(cache = next_cache(grp,&vifi)))
649 return NULL;
651 put_address(newname, cache->al_addr, vp->namelen);
652 newname[vp->namelen+4] = vifi;
656 /* Save new OID */
657 *length = vp->namelen + 5;
658 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
659 *write_method = 0;
660 *var_len = sizeof(long);
662 /* Look up ifIndex given uvifs[vifi].uv_lcl_addr */
663 in_ifaddr = ipaddr_to_ifindex(uvifs[vifi].uv_lcl_addr, &ifIndex);
665 switch (vp->magic) {
667 case igmpCacheSelf:
668 inm = in_ifaddr->ia_multiaddrs;
669 while (inm) {
670 klookup( (int)inm, (char *)&in_multi, sizeof(in_multi));
672 if (in_multi.inm_addr.s_addr == cache->al_addr) {
673 long_return = 1; /* true */
674 return (u_char *) &long_return;
677 inm = in_multi.inm_next;
679 long_return = 2; /* false */
680 return (u_char *) &long_return;
682 case igmpCacheLastReporter:
683 return (u_char *) &cache->al_genid;
685 case igmpCacheUpTime: {
686 time_t currtime;
687 time(&currtime);
688 long_return = (currtime - cache->al_ctime)*100;
689 return (u_char *) &long_return;
692 case igmpCacheExpiryTime:
693 long_return = secs_remaining(cache->al_timerid)*100;
694 return (u_char *) &long_return;
696 case igmpCacheStatus:
697 long_return = 1;
698 return (u_char *) &long_return;
700 default:
701 ERROR("");
703 return NULL;
707 * Implements the IGMP Interface Table portion of the IGMP MIB
709 u_char *
710 o_igmpInterfaceTable(vp, name, length, exact, var_len, write_method)
711 struct variable *vp; /* IN - pointer to variable entry that points here */
712 oid *name; /* IN/OUT - input name requested, output name found */
713 int *length; /* IN/OUT - length of input and output oid's */
714 int exact; /* IN - TRUE if an exact match was requested. */
715 int *var_len; /* OUT - length of variable or 0 if function returned. */
716 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
718 oid newname[MAX_NAME_LEN];
719 int ifnum;
720 int result;
721 static struct sioc_vif_req v_req;
723 /* Copy name OID to new OID */
724 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
726 /* find "next" interface */
727 for(ifnum = 0; ifnum < numvifs; ifnum++){
728 if (!(uvifs[ifnum].uv_flags & VIFF_QUERIER))
729 continue;
730 newname[vp->namelen] = (oid)ifnum;
731 result = compare(name, *length, newname, (int)vp->namelen + 1);
732 if ((exact && (result == 0)) || (!exact && (result < 0)))
733 break;
735 if (ifnum >= numvifs)
736 return NULL;
738 /* Save new OID */
739 bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
740 *length = vp->namelen + 1;
741 *write_method = 0;
742 *var_len = sizeof(long);
744 switch (vp->magic){
746 case igmpInterfaceQueryInterval:
747 long_return = GROUP_QUERY_INTERVAL;
748 return (u_char *) &long_return;
750 case igmpInterfaceStatus:
751 long_return = 1; /* active */
752 return (u_char *) &long_return;
754 default:
755 ERROR("");
757 return NULL;
761 * Given a virtual interface number, make sure we have the current
762 * kernel information for that Vif.
764 refresh_vif(v_req, ifnum)
765 struct sioc_vif_req *v_req;
766 int ifnum;
768 static int lastq = -1;
770 if (quantum!=lastq || v_req->vifi != ifnum) {
771 lastq = quantum;
772 v_req->vifi = ifnum;
773 if (ioctl(igmp_socket, SIOCGETVIFCNT, (char *)v_req) < 0)
774 v_req->icount = v_req->ocount = v_req->ibytes = v_req->obytes = 0;
779 * Implements the Multicast Routing Interface Table portion of the Multicast MIB
781 u_char *
782 o_ipMRouteInterfaceTable(vp, name, length, exact, var_len, write_method)
783 struct variable *vp; /* IN - pointer to variable entry that points here */
784 oid *name; /* IN/OUT - input name requested, output name found */
785 int *length; /* IN/OUT - length of input and output oid's */
786 int exact; /* IN - TRUE if an exact match was requested. */
787 int *var_len; /* OUT - length of variable or 0 if function returned. */
788 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
790 oid newname[MAX_NAME_LEN];
791 int ifnum;
792 int result;
793 static struct sioc_vif_req v_req;
795 /* Copy name OID to new OID */
796 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
798 /* find "next" interface */
799 for(ifnum = 0; ifnum < numvifs; ifnum++){
800 newname[vp->namelen] = (oid)ifnum;
801 result = compare(name, *length, newname, (int)vp->namelen + 1);
802 if ((exact && (result == 0)) || (!exact && (result < 0)))
803 break;
805 if (ifnum >= numvifs)
806 return NULL;
808 /* Save new OID */
809 bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
810 *length = vp->namelen + 1;
811 *write_method = 0;
812 *var_len = sizeof(long);
814 switch (vp->magic){
816 case ipMRouteInterfaceTtl:
817 long_return = uvifs[ifnum].uv_threshold;
818 return (u_char *) &long_return;
820 case dvmrpVInterfaceType:
821 if (uvifs[ifnum].uv_flags & VIFF_SRCRT)
822 long_return = 2;
823 else if (uvifs[ifnum].uv_flags & VIFF_TUNNEL)
824 long_return = 1;
825 else if (uvifs[ifnum].uv_flags & VIFF_QUERIER)
826 long_return = 3;
827 else /* SUBNET */
828 long_return = 4;
829 return (u_char *) &long_return;
831 case dvmrpVInterfaceState:
832 if (uvifs[ifnum].uv_flags & VIFF_DISABLED)
833 long_return = 3;
834 else if ((uvifs[ifnum].uv_flags & VIFF_DOWN)
835 || ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) && (uvifs[ifnum].uv_neighbors==NULL)))
836 long_return = 2;
837 else /* UP */
838 long_return = 1;
839 return (u_char *) &long_return;
841 case dvmrpVInterfaceLocalAddress:
842 return (u_char *) &uvifs[ifnum].uv_lcl_addr;
844 case dvmrpVInterfaceRemoteAddress:
845 return (u_char *) ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) ?
846 &uvifs[ifnum].uv_rmt_addr :
847 &uvifs[ifnum].uv_subnet);
849 case dvmrpVInterfaceRemoteSubnetMask:
850 return (u_char *) &uvifs[ifnum].uv_subnetmask;
852 case dvmrpVInterfaceMetric:
853 long_return = uvifs[ifnum].uv_metric;
854 return (u_char *) &long_return;
856 case dvmrpVInterfaceRateLimit:
857 long_return = uvifs[ifnum].uv_rate_limit;
858 return (u_char *) &long_return;
860 case dvmrpVInterfaceInPkts:
861 refresh_vif(&v_req, ifnum);
862 long_return = v_req.icount;
863 return (u_char *) &long_return;
865 case dvmrpVInterfaceOutPkts:
866 refresh_vif(&v_req, ifnum);
867 long_return = v_req.ocount;
868 return (u_char *) &long_return;
870 case dvmrpVInterfaceInOctets:
871 refresh_vif(&v_req, ifnum);
872 long_return = v_req.ibytes;
873 return (u_char *) &long_return;
875 case dvmrpVInterfaceOutOctets:
876 refresh_vif(&v_req, ifnum);
877 long_return = v_req.obytes;
878 return (u_char *) &long_return;
880 default:
881 ERROR("");
883 return NULL;
887 * Implements the DVMRP Route Table portion of the DVMRP MIB
889 u_char *
890 o_dvmrpRouteTable(vp, name, length, exact, var_len, write_method)
891 struct variable *vp; /* IN - pointer to variable entry that points here */
892 oid *name; /* IN/OUT - input name requested, output name found */
893 int *length; /* IN/OUT - length of input and output oid's */
894 int exact; /* IN - TRUE if an exact match was requested. */
895 int *var_len; /* OUT - length of variable or 0 if function returned. */
896 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
898 u_long src, mask;
899 oid newname[MAX_NAME_LEN];
900 int len;
901 struct rtentry *rt = NULL;
903 /* Copy name OID to new OID */
904 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
906 if (exact) {
907 if (*length != vp->namelen + 8)
908 return NULL;
910 if (!get_address(name, *length, &src, vp->namelen)
911 || !get_address(name, *length, &mask, vp->namelen+4))
912 return NULL;
914 if (!(rt = snmp_find_route(src, mask)))
915 return NULL;
917 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
918 } else {
919 len = *length;
920 if (compare(name, *length, vp->name, vp->namelen) < 0)
921 len = vp->namelen;
923 if (len < vp->namelen + 8) { /* get first entry */
925 if (len == vp->namelen) {
926 src = mask = 0;
927 } else {
928 get_address(name, len, &src, vp->namelen);
929 get_address(name, len, &mask, vp->namelen+4);
932 if (!next_route(&rt,src,mask)) /* Get first entry */
933 return NULL;
935 put_address(newname, rt->rt_origin , vp->namelen);
936 put_address(newname, rt->rt_originmask, vp->namelen+4);
937 } else { /* get next entry given previous */
938 get_address(name, *length, &src, vp->namelen);
939 get_address(name, *length, &mask, vp->namelen+4);
941 if (!next_route(&rt, src,mask))
942 return NULL;
944 put_address(newname, rt->rt_origin, vp->namelen);
945 put_address(newname, rt->rt_originmask, vp->namelen+4);
949 /* Save new OID */
950 *length = vp->namelen + 8;
951 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
952 *write_method = 0;
953 *var_len = sizeof(long);
955 switch (vp->magic) {
957 case dvmrpRouteUpstreamNeighbor:
958 return (u_char *) &rt->rt_gateway;
960 case dvmrpRouteInVifIndex:
961 long_return = rt->rt_parent;
962 return (u_char *) &long_return;
964 case dvmrpRouteMetric:
965 long_return = rt->rt_metric;
966 return (u_char *) &long_return;
968 case dvmrpRouteExpiryTime:
969 long_return = (ROUTE_EXPIRE_TIME - rt->rt_timer
970 + secs_remaining_offset()) * 100;
971 return (u_char *) &long_return;
973 default:
974 ERROR("");
976 return NULL;
980 * Implements the DVMRP Routing Next Hop Table portion of the DVMRP MIB
982 u_char *
983 o_dvmrpRouteNextHopTable(vp, name, length, exact, var_len, write_method)
984 struct variable *vp; /* IN - pointer to variable entry that points here */
985 oid *name; /* IN/OUT - input name requested, output name found */
986 int *length; /* IN/OUT - length of input and output oid's */
987 int exact; /* IN - TRUE if an exact match was requested. */
988 int *var_len; /* OUT - length of variable or 0 if function returned. */
989 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
991 u_long src, mask;
992 vifi_t vifi;
993 struct rtentry *rt = NULL;
994 oid newname[MAX_NAME_LEN];
995 int len;
997 /* Copy name OID to new OID */
998 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
1000 if (exact) {
1001 if (*length != vp->namelen + 9)
1002 return NULL;
1004 if (!get_address(name, *length, &src, vp->namelen)
1005 || !get_address(name, *length, &mask, vp->namelen+4)
1006 || (!(rt=snmp_find_route(src,mask))))
1007 return NULL;
1009 vifi = name[vp->namelen+8];
1010 if (!(VIFM_ISSET(vifi, rt->rt_children)))
1011 return NULL;
1013 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1014 } else {
1015 len = *length;
1016 if (compare(name, *length, vp->name, vp->namelen) < 0)
1017 len = vp->namelen;
1019 if (len < vp->namelen + 9) { /* get first entry */
1021 get_address(name, len, &src, vp->namelen);
1022 get_address(name, len, &mask, vp->namelen+4);
1024 /* Find first child vif */
1025 vifi=0;
1026 if (!next_route_child(&rt, src, mask, &vifi))
1027 return NULL;
1029 put_address(newname, rt->rt_origin, vp->namelen);
1030 put_address(newname, rt->rt_originmask, vp->namelen+4);
1031 newname[vp->namelen+8] = vifi;
1032 } else { /* get next entry given previous */
1033 vifi = name[vp->namelen+8] + 1;
1034 if (!get_address(name, *length, &src, vp->namelen)
1035 || !get_address(name, *length, &mask, vp->namelen+4)
1036 || !next_route_child(&rt, src, mask, &vifi))
1037 return NULL;
1039 put_address(newname, rt->rt_origin, vp->namelen);
1040 put_address(newname, rt->rt_originmask, vp->namelen+4);
1041 newname[vp->namelen+8] = vifi;
1045 /* Save new OID */
1046 *length = vp->namelen + 9;
1047 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1048 *write_method = 0;
1049 *var_len = sizeof(long);
1051 switch (vp->magic) {
1053 case dvmrpRouteNextHopType:
1054 long_return = (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2;
1055 return (u_char *) &long_return;
1057 default:
1058 ERROR("");
1060 return NULL;
1064 * Implements the IP Multicast Route Table portion of the Multicast MIB
1066 u_char *
1067 o_ipMRouteTable(vp, name, length, exact, var_len, write_method)
1068 struct variable *vp; /* IN - pointer to variable entry that points here */
1069 oid *name; /* IN/OUT - input name requested, output name found */
1070 int *length; /* IN/OUT - length of input and output oid's */
1071 int exact; /* IN - TRUE if an exact match was requested. */
1072 int *var_len; /* OUT - length of variable or 0 if function returned. */
1073 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
1075 u_long src, grp, mask;
1076 struct gtable *gt = NULL;
1077 struct stable *st = NULL;
1078 static struct sioc_sg_req sg_req;
1079 oid newname[MAX_NAME_LEN];
1080 int len;
1082 /* Copy name OID to new OID */
1083 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
1085 if (exact) {
1086 if (*length != vp->namelen + 12)
1087 return NULL;
1089 if (!get_address(name, *length, &grp, vp->namelen)
1090 || !get_address(name, *length, &src, vp->namelen+4)
1091 || !get_address(name, *length, &mask, vp->namelen+8)
1092 || (mask != 0xFFFFFFFF) /* we keep sources now, not subnets */
1093 || !(gt = find_grp(grp))
1094 || !(st = find_grp_src(gt,src)))
1095 return NULL;
1097 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1098 } else {
1099 len = *length;
1100 if (compare(name, *length, vp->name, vp->namelen) < 0)
1101 len = vp->namelen;
1103 if (len < vp->namelen + 12) { /* get first entry */
1105 get_address(name, len, &grp, vp->namelen);
1106 get_address(name, len, &src, vp->namelen+4);
1107 get_address(name, len, &mask, vp->namelen+8);
1109 if (!next_grp_src_mask(&gt,&st,grp,src,mask)) /* Get first entry */
1110 return NULL;
1112 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1113 put_address(newname, st->st_origin, vp->namelen+4);
1114 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1115 } else { /* get next entry given previous */
1116 get_address(name, *length, &grp , vp->namelen);
1117 get_address(name, *length, &src , vp->namelen+4);
1118 get_address(name, *length, &mask, vp->namelen+8);
1120 if (!next_grp_src_mask(&gt, &st, grp,src,mask))
1121 return NULL;
1123 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1124 put_address(newname, st->st_origin, vp->namelen+4);
1125 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1129 /* Save new OID */
1130 *length = vp->namelen + 12;
1131 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1132 *write_method = 0;
1133 *var_len = sizeof(long);
1135 switch (vp->magic) {
1137 case ipMRouteUpstreamNeighbor:
1138 return (u_char *) &gt->gt_route->rt_gateway;
1140 case ipMRouteInIfIndex:
1141 long_return = gt->gt_route->rt_parent;
1142 return (u_char *) &long_return;
1144 case ipMRouteUpTime: {
1145 time_t currtime;
1146 time(&currtime);
1147 long_return = (currtime - gt->gt_ctime)*100;
1148 return (u_char *) &long_return;
1151 case ipMRouteExpiryTime:
1152 long_return = 5*((gt->gt_timer+4)/5); /* round up to nearest 5 */
1153 long_return = (long_return + secs_remaining_offset()) * 100;
1154 return (u_char *) &long_return;
1156 case ipMRoutePkts:
1157 refresh_sg(&sg_req, gt, st);
1158 long_return = sg_req.pktcnt;
1159 return (u_char *) &long_return;
1161 case ipMRouteOctets:
1162 refresh_sg(&sg_req, gt, st);
1163 long_return = sg_req.bytecnt;
1164 return (u_char *) &long_return;
1166 case ipMRouteDifferentInIfIndexes:
1167 refresh_sg(&sg_req, gt, st);
1168 long_return = sg_req.wrong_if;
1169 return (u_char *) &long_return;
1171 case ipMRouteProtocol:
1172 long_return = 4;
1173 return (u_char *) &long_return;
1175 default:
1176 ERROR("");
1178 return NULL;
1182 * Implements the IP Multicast Routing Next Hop Table portion of the Multicast
1183 * MIB
1185 u_char *
1186 o_ipMRouteNextHopTable(vp, name, length, exact, var_len, write_method)
1187 struct variable *vp; /* IN - pointer to variable entry that points here */
1188 oid *name; /* IN/OUT - input name requested, output name found */
1189 int *length; /* IN/OUT - length of input and output oid's */
1190 int exact; /* IN - TRUE if an exact match was requested. */
1191 int *var_len; /* OUT - length of variable or 0 if function returned. */
1192 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
1194 u_long src, grp, mask, addr;
1195 vifi_t vifi;
1196 struct gtable *gt;
1197 struct stable *st;
1198 oid newname[MAX_NAME_LEN];
1199 int len;
1201 /* Copy name OID to new OID */
1202 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
1204 if (exact) {
1205 if (*length != vp->namelen + 17)
1206 return NULL;
1208 if (!get_address(name, *length, &grp, vp->namelen)
1209 || !get_address(name, *length, &src, vp->namelen+4)
1210 || !get_address(name, *length, &mask, vp->namelen+8)
1211 || !get_address(name, *length, &addr, vp->namelen+13)
1212 || grp!=addr
1213 || mask!=0xFFFFFFFF
1214 || (!(gt=find_grp(grp)))
1215 || (!(st=find_grp_src(gt,src))))
1216 return NULL;
1218 vifi = name[vp->namelen+12];
1219 if (!(VIFM_ISSET(vifi, gt->gt_route->rt_children)))
1220 return NULL;
1222 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1223 } else {
1224 len = *length;
1225 if (compare(name, *length, vp->name, vp->namelen) < 0)
1226 len = vp->namelen;
1228 if (len < vp->namelen + 17) { /* get first entry */
1230 get_address(name, len, &grp, vp->namelen);
1231 get_address(name, len, &src, vp->namelen+4);
1232 get_address(name, len, &mask, vp->namelen+8);
1234 /* Find first child vif */
1235 vifi=0;
1236 if (!next_child(&gt, &st, grp, src, mask, &vifi))
1237 return NULL;
1239 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1240 put_address(newname, st->st_origin, vp->namelen+4);
1241 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1242 newname[vp->namelen+12] = vifi;
1243 put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
1245 } else { /* get next entry given previous */
1246 vifi = name[vp->namelen+12]+1;
1247 if (!get_address(name, *length, &grp, vp->namelen)
1248 || !get_address(name, *length, &src, vp->namelen+4)
1249 || !get_address(name, *length, &mask, vp->namelen+8)
1250 || !next_child(&gt, &st, grp, src, mask, &vifi))
1251 return NULL;
1253 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1254 put_address(newname, st->st_origin, vp->namelen+4);
1255 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1256 newname[vp->namelen+12] = vifi;
1257 put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
1261 /* Save new OID */
1262 *length = vp->namelen + 17;
1263 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1264 *write_method = 0;
1265 *var_len = sizeof(long);
1267 switch (vp->magic) {
1269 case ipMRouteNextHopState:
1270 long_return = (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1;
1271 return (u_char *) &long_return;
1273 /* Currently equal to ipMRouteUpTime */
1274 case ipMRouteNextHopUpTime: {
1275 time_t currtime;
1276 time(&currtime);
1277 long_return = (currtime - gt->gt_ctime)*100;
1278 return (u_char *) &long_return;
1281 case ipMRouteNextHopExpiryTime:
1282 long_return = 5*((gt->gt_prsent_timer+4)/5); /* round up to nearest 5*/
1283 long_return = (long_return + secs_remaining_offset()) * 100;
1284 return (u_char *) &long_return;
1286 case ipMRouteNextHopClosestMemberHops:
1287 long_return = 0;
1288 return (u_char *) &long_return;
1290 case ipMRouteNextHopProtocol:
1291 long_return = 4;
1292 return (u_char *) &long_return;
1294 default:
1295 ERROR("");
1297 return NULL;
1300 /* sync_timer is called by timer() every TIMER_INTERVAL seconds.
1301 * Its job is to record this time so that we can compute on demand
1302 * the approx # seconds remaining until the next timer() call
1304 static time_t lasttimer;
1306 void
1307 sync_timer()
1309 time(&lasttimer);
1312 int /* in range [-TIMER_INTERVAL..0] */
1313 secs_remaining_offset()
1315 time_t tm;
1317 time(&tm);
1318 return lasttimer-tm;