snmp.c revision 1.3 1 /* $NetBSD: snmp.c,v 1.3 1995/12/10 10:07:16 mycroft Exp $ */
2
3 #include "defs.h"
4 #include <netinet/in_var.h>
5 #include "snmp.h"
6 #include "snmplib/asn1.h"
7 #include "snmplib/party.h"
8 #include "snmplib/snmp_impl.h"
9 #define MROUTED
10 #include "snmpd/snmp_vars.h"
11
12 u_short dest_port = 0;
13 int sdlen = 0;
14
15 struct addrCache {
16 u_long addr;
17 int status;
18 #define UNUSED 0
19 #define USED 1
20 #define OLD 2
21 };
22
23 static struct addrCache addrCache[10];
24
25 /*
26 * Initialize the SNMP part of mrouted
27 */
28 int /* returns: 0 on success, true on error */
29 snmp_init(dest_port)
30 u_short dest_port;
31 {
32 u_long myaddr;
33 int ret;
34 struct partyEntry *pp;
35 struct sockaddr_in me;
36 int index, sd, portlist[32];
37
38 init_snmp();
39 /* init_mib(); why was this here? */
40 if (read_party_database("/etc/party.conf") > 0){
41 fprintf(stderr, "Couldn't read party database from /etc/party.conf\n");
42 exit(0);
43 }
44 if (read_context_database("/etc/context.conf") > 0){
45 fprintf(stderr, "Couldn't read context database from /etc/context.conf\n");
46 exit(0);
47 }
48 if (read_acl_database("/etc/acl.conf") > 0){
49 fprintf(stderr, "Couldn't read acl database from /etc/acl.conf\n");
50 exit(0);
51 }
52 if (read_view_database("/etc/view.conf") > 0){
53 fprintf(stderr, "Couldn't read view database from /etc/view.conf\n");
54 exit(0);
55 }
56
57 myaddr = get_myaddr();
58 if (ret = agent_party_init(myaddr, ".1.3.6.1")){
59 if (ret == 1){
60 fprintf(stderr, "Conflict found with initial noAuth/noPriv parties... continuing\n");
61 } else if (ret == -1){
62 fprintf(stderr, "Error installing initial noAuth/noPriv parties, exiting\n");
63 exit(1);
64 } else {
65 fprintf(stderr, "Unknown error, exiting\n");
66 exit(2);
67 }
68 }
69
70 printf("Opening port(s): ");
71 fflush(stdout);
72 party_scanInit();
73 for(pp = party_scanNext(); pp; pp = party_scanNext()){
74 if ((pp->partyTDomain != DOMAINSNMPUDP)
75 || bcmp((char *)&myaddr, pp->partyTAddress, 4))
76 continue; /* don't listen for non-local parties */
77
78 dest_port = 0;
79 bcopy(pp->partyTAddress + 4, &dest_port, 2);
80 for(index = 0; index < sdlen; index++)
81 if (dest_port == portlist[index])
82 break;
83 if (index < sdlen) /* found a hit before the end of the list */
84 continue;
85 printf("%u ", dest_port);
86 fflush(stdout);
87 /* Set up connections */
88 sd = socket(AF_INET, SOCK_DGRAM, 0);
89 if (sd < 0){
90 perror("socket");
91 return 1;
92 }
93 me.sin_family = AF_INET;
94 me.sin_addr.s_addr = INADDR_ANY;
95 /* already in network byte order (I think) */
96 me.sin_port = dest_port;
97 if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){
98 perror("bind");
99 return 2;
100 }
101 register_input_handler(sd, snmp_read_packet);
102 portlist[sdlen] = dest_port;
103 if (++sdlen == 32){
104 printf("No more sockets... ignoring rest of file\n");
105 break;
106 }
107 }
108 printf("\n");
109 bzero((char *)addrCache, sizeof(addrCache));
110 }
111
112 /*
113 * Place an IP address into an OID starting at element n
114 */
115 void
116 put_address(name, addr, n)
117 oid *name;
118 u_long addr;
119 int n;
120 {
121 int i;
122
123 for (i=n+3; i>=n+0; i--) {
124 name[i] = addr & 0xFF;
125 addr >>= 8;
126 }
127 }
128
129 /* Get an IP address from an OID starting at element n */
130 int
131 get_address(name, length, addr, n)
132 oid *name;
133 int length;
134 u_long *addr;
135 int n;
136 {
137 int i;
138 int ok = 1;
139
140 (*addr) = 0;
141
142 if (length < n+4)
143 return 0;
144
145 for (i=n; i<n+4; i++) {
146 (*addr) <<= 8;
147 if (i >= length)
148 ok = 0;
149 else
150 (*addr) |= name[i];
151 }
152 return ok;
153 }
154
155 /*
156 * Implements scalar objects from DVMRP and Multicast MIBs
157 */
158 u_char *
159 o_scalar(vp, name, length, exact, var_len, write_method)
160 register struct variable *vp; /* IN - pointer to variable entry that points here */
161 register oid *name; /* IN/OUT - input name requested, output name found */
162 register int *length; /* IN/OUT - length of input and output oid's */
163 int exact; /* IN - TRUE if an exact match was requested. */
164 int *var_len; /* OUT - length of variable or 0 if function returned. */
165 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
166 {
167 int result;
168
169 *write_method = 0;
170 result = compare(name, *length, vp->name, (int)vp->namelen);
171 if ((exact && (result != 0)) || (!exact && (result >= 0)))
172 return NULL;
173
174 bcopy((char *)vp->name, (char *)name,
175 (int)vp->namelen * sizeof(oid));
176 *length = vp->namelen;
177 *var_len = sizeof(long);
178
179 switch (vp->magic) {
180
181 case ipMRouteEnable:
182 long_return = 1;
183 return (u_char *) &long_return;
184
185 case dvmrpVersion: {
186 static char buff[15];
187
188 sprintf(buff, "mrouted%d.%d", PROTOCOL_VERSION, MROUTED_VERSION);
189 *var_len = strlen(buff);
190 return (u_char *)buff;
191 }
192
193 case dvmrpGenerationId:
194 long_return = dvmrp_genid;
195 return (u_char *) &long_return;
196
197 default:
198 ERROR("");
199 }
200 return NULL;
201 }
202
203 /*
204 * Find if a specific scoped boundary exists on a Vif
205 */
206 struct vif_acl *
207 find_boundary(vifi, addr, mask)
208 vifi_t vifi;
209 u_long addr;
210 u_long mask;
211 {
212 struct vif_acl *n;
213
214 for (n = uvifs[vifi].uv_acl; n != NULL; n = n->acl_next) {
215 if (addr == n->acl_addr && mask==n->acl_mask)
216 return n;
217 }
218 return NULL;
219 }
220
221 /*
222 * Find the lowest boundary >= (V,A,M) spec
223 */
224 struct vif_acl *
225 next_boundary(vifi, addr, mask)
226 vifi_t *vifi;
227 u_long addr;
228 u_long mask;
229 {
230 struct vif_acl *bestn, *n;
231 int i;
232
233 for (i = *vifi; i < numvifs; i++) {
234 bestn = NULL;
235 for (n = uvifs[i].uv_acl; n; n=n->acl_next) {
236 if ((i > *vifi || n->acl_addr > addr
237 || (n->acl_addr == addr && n->acl_mask >= mask))
238 && (!bestn || n->acl_addr < bestn->acl_addr
239 || (n->acl_addr==bestn->acl_addr && n->acl_mask<bestn->acl_mask)))
240 bestn = n;
241 }
242 if (bestn) {
243 *vifi = i;
244 return bestn;
245 }
246 }
247 return NULL;
248 }
249
250 /*
251 * Implements the Boundary Table portion of the DVMRP MIB
252 */
253 u_char *
254 o_dvmrpBoundaryTable(vp, name, length, exact, var_len, write_method)
255 register struct variable *vp; /* IN - pointer to variable entry that points here */
256 register oid *name; /* IN/OUT - input name requested, output name found */
257 register int *length; /* IN/OUT - length of input and output oid's */
258 int exact; /* IN - TRUE if an exact match was requested. */
259 int *var_len; /* OUT - length of variable or 0 if function returned. */
260 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
261 {
262 vifi_t vifi;
263 u_long addr, mask;
264 struct vif_acl *bound;
265 oid newname[MAX_NAME_LEN];
266 int len;
267
268 /* Copy name OID to new OID */
269 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
270
271 if (exact) {
272 if (*length != vp->namelen + 9)
273 return NULL;
274
275 if ((vifi = name[vp->namelen]) >= numvifs)
276 return NULL;
277
278 if (!get_address(name, *length, &addr, vp->namelen+1)
279 || !get_address(name, *length, &mask, vp->namelen+5))
280 return NULL;
281
282 if (!(bound = find_boundary(vifi, addr, mask)))
283 return NULL;
284
285 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
286 } else {
287 len = *length;
288 if (compare(name, *length, vp->name, vp->namelen) < 0)
289 len = vp->namelen;
290
291 if (len < vp->namelen + 9) { /* get first entry */
292
293 if (len == vp->namelen) {
294 vifi = addr = mask = 0;
295 } else {
296 vifi = name[vp->namelen];
297 get_address(name, len, &addr, vp->namelen+1);
298 get_address(name, len, &mask, vp->namelen+5);
299 }
300
301 bound = next_boundary(&vifi,addr,mask);
302 if (!bound)
303 return NULL;
304
305 newname[vp->namelen] = vifi;
306 put_address(newname, bound->acl_addr, vp->namelen+1);
307 put_address(newname, bound->acl_mask, vp->namelen+5);
308 } else { /* get next entry given previous */
309 vifi = name[vp->namelen];
310 get_address(name, *length, &addr, vp->namelen+1);
311 get_address(name, *length, &mask, vp->namelen+5);
312
313 if (!(bound = next_boundary(&vifi,addr,mask+1)))
314 return NULL;
315
316 newname[vp->namelen] = vifi;
317 put_address(newname, bound->acl_addr, vp->namelen+1);
318 put_address(newname, bound->acl_mask, vp->namelen+5);
319 }
320 }
321
322 /* Save new OID */
323 *length = vp->namelen + 9;
324 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
325 *write_method = 0;
326 *var_len = sizeof(long);
327
328 switch (vp->magic) {
329
330 case dvmrpBoundaryVifIndex:
331 long_return = vifi;
332 return (u_char *) &long_return;
333
334 default:
335 ERROR("");
336 }
337 return NULL;
338 }
339
340 /*
341 * Find the lowest neighbor >= (V,A) spec
342 */
343 struct listaddr *
344 next_neighbor(vifi, addr)
345 vifi_t *vifi;
346 u_long addr;
347 {
348 struct listaddr *bestn, *n;
349 int i;
350
351 for (i = *vifi; i < numvifs; i++) {
352 bestn = NULL;
353 for (n = uvifs[i].uv_neighbors; n; n=n->al_next) {
354 if ((i > *vifi || n->al_addr >= addr)
355 && (!bestn || n->al_addr < bestn->al_addr))
356 bestn = n;
357 }
358 if (bestn) {
359 *vifi = i;
360 return bestn;
361 }
362 }
363 return NULL;
364 }
365
366 /*
367 * Find a neighbor, if it exists off a given Vif
368 */
369 struct listaddr *
370 find_neighbor(vifi, addr)
371 vifi_t vifi;
372 u_long addr;
373 {
374 struct listaddr *n;
375
376 for (n = uvifs[vifi].uv_neighbors; n != NULL; n = n->al_next) {
377 if (addr == n->al_addr)
378 return n;
379 }
380 return NULL;
381 }
382
383 u_char *
384 o_dvmrpNeighborTable(vp, name, length, exact, var_len, write_method)
385 register struct variable *vp; /* IN - pointer to variable entry that points here */
386 register oid *name; /* IN/OUT - input name requested, output name found */
387 register int *length; /* IN/OUT - length of input and output oid's */
388 int exact; /* IN - TRUE if an exact match was requested. */
389 int *var_len; /* OUT - length of variable or 0 if function returned. */
390 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
391 {
392 vifi_t vifi;
393 u_long addr, mask;
394 struct listaddr *neighbor;
395 oid newname[MAX_NAME_LEN];
396 int len;
397
398 /* Copy name OID to new OID */
399 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
400
401 if (exact) {
402 if (*length != vp->namelen + 5)
403 return NULL;
404
405 if ((vifi = name[vp->namelen]) >= numvifs)
406 return NULL;
407
408 if (!get_address(name, *length, &addr, vp->namelen+1))
409 return NULL;
410
411 if (!(neighbor = find_neighbor(vifi, addr)))
412 return NULL;
413
414 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
415 } else {
416 len = *length;
417 if (compare(name, *length, vp->name, vp->namelen) < 0)
418 len = vp->namelen;
419
420 if (len < vp->namelen + 5) { /* get first entry */
421
422 if (len == vp->namelen) {
423 vifi = addr = 0;
424 } else {
425 vifi = name[vp->namelen];
426 get_address(name, len, &addr, vp->namelen+1);
427 }
428
429 neighbor = next_neighbor(&vifi,addr);
430 if (!neighbor)
431 return NULL;
432
433 newname[vp->namelen] = vifi;
434 put_address(newname, neighbor->al_addr, vp->namelen+1);
435 } else { /* get next entry given previous */
436 vifi = name[vp->namelen];
437 get_address(name, *length, &addr, vp->namelen+1);
438
439 if (!(neighbor = next_neighbor(&vifi,addr+1)))
440 return NULL;
441
442 newname[vp->namelen] = vifi;
443 put_address(newname, neighbor->al_addr, vp->namelen+1);
444 }
445 }
446
447 /* Save new OID */
448 *length = vp->namelen + 5;
449 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
450 *write_method = 0;
451 *var_len = sizeof(long);
452
453 switch (vp->magic) {
454
455 case dvmrpNeighborUpTime: {
456 time_t currtime;
457 time(&currtime);
458 long_return = (currtime - neighbor->al_ctime)*100;
459 return (u_char *) &long_return;
460 }
461
462 case dvmrpNeighborExpiryTime:
463 long_return = (NEIGHBOR_EXPIRE_TIME - neighbor->al_timer
464 + secs_remaining_offset()) * 100;
465 return (u_char *) &long_return;
466
467 case dvmrpNeighborVersion: {
468 static char buff[15];
469
470 sprintf(buff, "%d.%d", neighbor->al_pv, neighbor->al_mv);
471 *var_len = strlen(buff);
472 return (u_char *)buff;
473 }
474
475 case dvmrpNeighborGenerationId:
476 long_return = neighbor->al_genid;
477 return (u_char *) &long_return;
478
479 default:
480 ERROR("");
481 }
482 return NULL;
483 }
484
485 /* Look up ifIndex given uvifs[ifnum].uv_lcl_addr */
486 struct in_ifaddr * /* returns: in_ifaddr structure, or null on error */
487 ipaddr_to_ifindex(ipaddr, ifIndex)
488 u_long ipaddr;
489 int *ifIndex;
490 {
491 int interface;
492 static struct in_ifaddr in_ifaddr;
493
494 Interface_Scan_Init();
495 for (;;) {
496 if (Interface_Scan_Next(&interface, (char *)0, NULL, &in_ifaddr) == 0)
497 return NULL;
498
499 if (((struct sockaddr_in *) &(in_ifaddr.ia_addr))->sin_addr.s_addr
500 == ipaddr) {
501 *ifIndex = interface;
502 return &in_ifaddr;
503 }
504 }
505 }
506
507 /*
508 * Find if a specific scoped boundary exists on a Vif
509 */
510 struct listaddr *
511 find_cache(grp, vifi)
512 u_long grp;
513 vifi_t vifi;
514 {
515 struct listaddr *n;
516
517 for (n = uvifs[vifi].uv_groups; n != NULL; n = n->al_next) {
518 if (grp == n->al_addr)
519 return n;
520 }
521 return NULL;
522 }
523
524 /*
525 * Find the next group cache entry >= (A,V) spec
526 */
527 struct listaddr *
528 next_cache(addr, vifi)
529 u_long addr;
530 vifi_t *vifi;
531 {
532 struct listaddr *bestn=NULL, *n;
533 int i, besti;
534
535 /* Step through all entries looking for the next one */
536 for (i = 0; i < numvifs; i++) {
537 for (n = uvifs[i].uv_groups; n; n=n->al_next) {
538 if ((n->al_addr > addr || (n->al_addr == addr && i >= *vifi))
539 && (!bestn || n->al_addr < bestn->al_addr
540 || (n->al_addr == bestn->al_addr && i < besti))) {
541 bestn = n;
542 besti = i;
543 }
544 }
545 }
546
547 if (bestn) {
548 *vifi = besti;
549 return bestn;
550 }
551 return NULL;
552 }
553
554 /*
555 * Implements the IGMP Cache Table portion of the IGMP MIB
556 */
557 u_char *
558 o_igmpCacheTable(vp, name, length, exact, var_len, write_method)
559 register struct variable *vp; /* IN - pointer to variable entry that points here */
560 register oid *name; /* IN/OUT - input name requested, output name found */
561 register int *length; /* IN/OUT - length of input and output oid's */
562 int exact; /* IN - TRUE if an exact match was requested. */
563 int *var_len; /* OUT - length of variable or 0 if function returned. */
564 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
565 {
566 vifi_t vifi;
567 u_long grp;
568 int ifIndex;
569 struct listaddr *cache;
570 oid newname[MAX_NAME_LEN];
571 int len;
572 struct in_ifaddr *in_ifaddr;
573 struct in_multi in_multi, *inm;
574
575 /* Copy name OID to new OID */
576 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
577
578 if (exact) {
579 if (*length != vp->namelen + 5)
580 return NULL;
581
582 if ((vifi = name[vp->namelen+4]) >= numvifs)
583 return NULL;
584
585 if (!get_address(name, *length, &grp, vp->namelen))
586 return NULL;
587
588 if (!(cache = find_cache(grp, vifi)))
589 return NULL;
590
591 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
592 } else {
593 len = *length;
594 if (compare(name, *length, vp->name, vp->namelen) < 0)
595 len = vp->namelen;
596
597 if (len < vp->namelen + 5) { /* get first entry */
598
599 if (len == vp->namelen) {
600 vifi = grp = 0;
601 } else {
602 get_address(name, len, &grp, vp->namelen);
603 vifi = name[vp->namelen+4];
604 }
605
606 cache = next_cache(grp,&vifi);
607 if (!cache)
608 return NULL;
609
610 put_address(newname, cache->al_addr, vp->namelen);
611 newname[vp->namelen+4] = vifi;
612 } else { /* get next entry given previous */
613 get_address(name, *length, &grp, vp->namelen);
614 vifi = name[vp->namelen+4]+1;
615
616 if (!(cache = next_cache(grp,&vifi)))
617 return NULL;
618
619 put_address(newname, cache->al_addr, vp->namelen);
620 newname[vp->namelen+4] = vifi;
621 }
622 }
623
624 /* Save new OID */
625 *length = vp->namelen + 5;
626 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
627 *write_method = 0;
628 *var_len = sizeof(long);
629
630 /* Look up ifIndex given uvifs[vifi].uv_lcl_addr */
631 in_ifaddr = ipaddr_to_ifindex(uvifs[vifi].uv_lcl_addr, &ifIndex);
632
633 switch (vp->magic) {
634
635 case igmpCacheSelf:
636 inm = in_ifaddr->ia_multiaddrs;
637 while (inm) {
638 klookup( (int)inm, (char *)&in_multi, sizeof(in_multi));
639
640 if (in_multi.inm_addr.s_addr == cache->al_addr) {
641 long_return = 1; /* true */
642 return (u_char *) &long_return;
643 }
644
645 inm = in_multi.inm_next;
646 }
647 long_return = 2; /* false */
648 return (u_char *) &long_return;
649
650 case igmpCacheLastReporter:
651 return (u_char *) &cache->al_genid;
652
653 case igmpCacheUpTime: {
654 time_t currtime;
655 time(&currtime);
656 long_return = (currtime - cache->al_ctime)*100;
657 return (u_char *) &long_return;
658 }
659
660 case igmpCacheExpiryTime:
661 long_return = secs_remaining(cache->al_timerid)*100;
662 return (u_char *) &long_return;
663
664 case igmpCacheStatus:
665 long_return = 1;
666 return (u_char *) &long_return;
667
668 default:
669 ERROR("");
670 }
671 return NULL;
672 }
673
674 /*
675 * Implements the IGMP Interface Table portion of the IGMP MIB
676 */
677 u_char *
678 o_igmpInterfaceTable(vp, name, length, exact, var_len, write_method)
679 register struct variable *vp; /* IN - pointer to variable entry that points here */
680 register oid *name; /* IN/OUT - input name requested, output name found */
681 register int *length; /* IN/OUT - length of input and output oid's */
682 int exact; /* IN - TRUE if an exact match was requested. */
683 int *var_len; /* OUT - length of variable or 0 if function returned. */
684 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
685 {
686 oid newname[MAX_NAME_LEN];
687 register int ifnum;
688 int result;
689 static struct sioc_vif_req v_req;
690
691 /* Copy name OID to new OID */
692 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
693
694 /* find "next" interface */
695 for(ifnum = 0; ifnum < numvifs; ifnum++){
696 if (!(uvifs[ifnum].uv_flags & VIFF_QUERIER))
697 continue;
698 newname[vp->namelen] = (oid)ifnum;
699 result = compare(name, *length, newname, (int)vp->namelen + 1);
700 if ((exact && (result == 0)) || (!exact && (result < 0)))
701 break;
702 }
703 if (ifnum >= numvifs)
704 return NULL;
705
706 /* Save new OID */
707 bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
708 *length = vp->namelen + 1;
709 *write_method = 0;
710 *var_len = sizeof(long);
711
712 switch (vp->magic){
713
714 case igmpInterfaceQueryInterval:
715 long_return = GROUP_QUERY_INTERVAL;
716 return (u_char *) &long_return;
717
718 case igmpInterfaceStatus:
719 long_return = 1; /* active */
720 return (u_char *) &long_return;
721
722 default:
723 ERROR("");
724 }
725 return NULL;
726 }
727
728 /*
729 * Given a virtual interface number, make sure we have the current
730 * kernel information for that Vif.
731 */
732 refresh_vif(v_req, ifnum)
733 struct sioc_vif_req *v_req;
734 int ifnum;
735 {
736 static int lastq = -1;
737
738 if (quantum!=lastq || v_req->vifi != ifnum) {
739 lastq = quantum;
740 v_req->vifi = ifnum;
741 if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)v_req) < 0)
742 v_req->icount = v_req->ocount = v_req->ibytes = v_req->obytes = 0;
743 }
744 }
745
746 /*
747 * Implements the Multicast Routing Interface Table portion of the Multicast MIB
748 */
749 u_char *
750 o_ipMRouteInterfaceTable(vp, name, length, exact, var_len, write_method)
751 register struct variable *vp; /* IN - pointer to variable entry that points here */
752 register oid *name; /* IN/OUT - input name requested, output name found */
753 register int *length; /* IN/OUT - length of input and output oid's */
754 int exact; /* IN - TRUE if an exact match was requested. */
755 int *var_len; /* OUT - length of variable or 0 if function returned. */
756 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
757 {
758 oid newname[MAX_NAME_LEN];
759 register int ifnum;
760 int result;
761 static struct sioc_vif_req v_req;
762
763 /* Copy name OID to new OID */
764 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
765
766 /* find "next" interface */
767 for(ifnum = 0; ifnum < numvifs; ifnum++){
768 newname[vp->namelen] = (oid)ifnum;
769 result = compare(name, *length, newname, (int)vp->namelen + 1);
770 if ((exact && (result == 0)) || (!exact && (result < 0)))
771 break;
772 }
773 if (ifnum >= numvifs)
774 return NULL;
775
776 /* Save new OID */
777 bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
778 *length = vp->namelen + 1;
779 *write_method = 0;
780 *var_len = sizeof(long);
781
782 switch (vp->magic){
783
784 case ipMRouteInterfaceTtl:
785 long_return = uvifs[ifnum].uv_threshold;
786 return (u_char *) &long_return;
787
788 case dvmrpVInterfaceType:
789 if (uvifs[ifnum].uv_flags & VIFF_SRCRT)
790 long_return = 2;
791 else if (uvifs[ifnum].uv_flags & VIFF_TUNNEL)
792 long_return = 1;
793 else if (uvifs[ifnum].uv_flags & VIFF_QUERIER)
794 long_return = 3;
795 else /* SUBNET */
796 long_return = 4;
797 return (u_char *) &long_return;
798
799 case dvmrpVInterfaceState:
800 if (uvifs[ifnum].uv_flags & VIFF_DISABLED)
801 long_return = 3;
802 else if ((uvifs[ifnum].uv_flags & VIFF_DOWN)
803 || ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) && (uvifs[ifnum].uv_neighbors==NULL)))
804 long_return = 2;
805 else /* UP */
806 long_return = 1;
807 return (u_char *) &long_return;
808
809 case dvmrpVInterfaceLocalAddress:
810 return (u_char *) &uvifs[ifnum].uv_lcl_addr;
811
812 case dvmrpVInterfaceRemoteAddress:
813 return (u_char *) ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) ?
814 &uvifs[ifnum].uv_rmt_addr :
815 &uvifs[ifnum].uv_subnet);
816
817 case dvmrpVInterfaceRemoteSubnetMask:
818 return (u_char *) &uvifs[ifnum].uv_subnetmask;
819
820 case dvmrpVInterfaceMetric:
821 long_return = uvifs[ifnum].uv_metric;
822 return (u_char *) &long_return;
823
824 case dvmrpVInterfaceRateLimit:
825 long_return = uvifs[ifnum].uv_rate_limit;
826 return (u_char *) &long_return;
827
828 case dvmrpVInterfaceInPkts:
829 refresh_vif(&v_req, ifnum);
830 long_return = v_req.icount;
831 return (u_char *) &long_return;
832
833 case dvmrpVInterfaceOutPkts:
834 refresh_vif(&v_req, ifnum);
835 long_return = v_req.ocount;
836 return (u_char *) &long_return;
837
838 case dvmrpVInterfaceInOctets:
839 refresh_vif(&v_req, ifnum);
840 long_return = v_req.ibytes;
841 return (u_char *) &long_return;
842
843 case dvmrpVInterfaceOutOctets:
844 refresh_vif(&v_req, ifnum);
845 long_return = v_req.obytes;
846 return (u_char *) &long_return;
847
848 default:
849 ERROR("");
850 }
851 return NULL;
852 }
853
854 /*
855 * Implements the DVMRP Route Table portion of the DVMRP MIB
856 */
857 u_char *
858 o_dvmrpRouteTable(vp, name, length, exact, var_len, write_method)
859 register struct variable *vp; /* IN - pointer to variable entry that points here */
860 register oid *name; /* IN/OUT - input name requested, output name found */
861 register int *length; /* IN/OUT - length of input and output oid's */
862 int exact; /* IN - TRUE if an exact match was requested. */
863 int *var_len; /* OUT - length of variable or 0 if function returned. */
864 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
865 {
866 u_long src, mask;
867 oid newname[MAX_NAME_LEN];
868 int len;
869 struct rtentry *rt = NULL;
870
871 /* Copy name OID to new OID */
872 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
873
874 if (exact) {
875 if (*length != vp->namelen + 8)
876 return NULL;
877
878 if (!get_address(name, *length, &src, vp->namelen)
879 || !get_address(name, *length, &mask, vp->namelen+4))
880 return NULL;
881
882 if (!(rt = snmp_find_route(src, mask)))
883 return NULL;
884
885 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
886 } else {
887 len = *length;
888 if (compare(name, *length, vp->name, vp->namelen) < 0)
889 len = vp->namelen;
890
891 if (len < vp->namelen + 8) { /* get first entry */
892
893 if (len == vp->namelen) {
894 src = mask = 0;
895 } else {
896 get_address(name, len, &src, vp->namelen);
897 get_address(name, len, &mask, vp->namelen+4);
898 }
899
900 if (!next_route(&rt,src,mask)) /* Get first entry */
901 return NULL;
902
903 put_address(newname, rt->rt_origin , vp->namelen);
904 put_address(newname, rt->rt_originmask, vp->namelen+4);
905 } else { /* get next entry given previous */
906 get_address(name, *length, &src, vp->namelen);
907 get_address(name, *length, &mask, vp->namelen+4);
908
909 if (!next_route(&rt, src,mask))
910 return NULL;
911
912 put_address(newname, rt->rt_origin, vp->namelen);
913 put_address(newname, rt->rt_originmask, vp->namelen+4);
914 }
915 }
916
917 /* Save new OID */
918 *length = vp->namelen + 8;
919 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
920 *write_method = 0;
921 *var_len = sizeof(long);
922
923 switch (vp->magic) {
924
925 case dvmrpRouteUpstreamNeighbor:
926 return (u_char *) &rt->rt_gateway;
927
928 case dvmrpRouteInVifIndex:
929 long_return = rt->rt_parent;
930 return (u_char *) &long_return;
931
932 case dvmrpRouteMetric:
933 long_return = rt->rt_metric;
934 return (u_char *) &long_return;
935
936 case dvmrpRouteExpiryTime:
937 long_return = (ROUTE_EXPIRE_TIME - rt->rt_timer
938 + secs_remaining_offset()) * 100;
939 return (u_char *) &long_return;
940
941 default:
942 ERROR("");
943 }
944 return NULL;
945 }
946
947 /*
948 * Implements the DVMRP Routing Next Hop Table portion of the DVMRP MIB
949 */
950 u_char *
951 o_dvmrpRouteNextHopTable(vp, name, length, exact, var_len, write_method)
952 register struct variable *vp; /* IN - pointer to variable entry that points here */
953 register oid *name; /* IN/OUT - input name requested, output name found */
954 register int *length; /* IN/OUT - length of input and output oid's */
955 int exact; /* IN - TRUE if an exact match was requested. */
956 int *var_len; /* OUT - length of variable or 0 if function returned. */
957 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
958 {
959 u_long src, mask;
960 vifi_t vifi;
961 struct rtentry *rt = NULL;
962 oid newname[MAX_NAME_LEN];
963 int len;
964
965 /* Copy name OID to new OID */
966 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
967
968 if (exact) {
969 if (*length != vp->namelen + 9)
970 return NULL;
971
972 if (!get_address(name, *length, &src, vp->namelen)
973 || !get_address(name, *length, &mask, vp->namelen+4)
974 || (!(rt=snmp_find_route(src,mask))))
975 return NULL;
976
977 vifi = name[vp->namelen+8];
978 if (!(VIFM_ISSET(vifi, rt->rt_children)))
979 return NULL;
980
981 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
982 } else {
983 len = *length;
984 if (compare(name, *length, vp->name, vp->namelen) < 0)
985 len = vp->namelen;
986
987 if (len < vp->namelen + 9) { /* get first entry */
988
989 get_address(name, len, &src, vp->namelen);
990 get_address(name, len, &mask, vp->namelen+4);
991
992 /* Find first child vif */
993 vifi=0;
994 if (!next_route_child(&rt, src, mask, &vifi))
995 return NULL;
996
997 put_address(newname, rt->rt_origin, vp->namelen);
998 put_address(newname, rt->rt_originmask, vp->namelen+4);
999 newname[vp->namelen+8] = vifi;
1000 } else { /* get next entry given previous */
1001 vifi = name[vp->namelen+8] + 1;
1002 if (!get_address(name, *length, &src, vp->namelen)
1003 || !get_address(name, *length, &mask, vp->namelen+4)
1004 || !next_route_child(&rt, src, mask, &vifi))
1005 return NULL;
1006
1007 put_address(newname, rt->rt_origin, vp->namelen);
1008 put_address(newname, rt->rt_originmask, vp->namelen+4);
1009 newname[vp->namelen+8] = vifi;
1010 }
1011 }
1012
1013 /* Save new OID */
1014 *length = vp->namelen + 9;
1015 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1016 *write_method = 0;
1017 *var_len = sizeof(long);
1018
1019 switch (vp->magic) {
1020
1021 case dvmrpRouteNextHopType:
1022 long_return = (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2;
1023 return (u_char *) &long_return;
1024
1025 default:
1026 ERROR("");
1027 }
1028 return NULL;
1029 }
1030
1031 /*
1032 * Implements the IP Multicast Route Table portion of the Multicast MIB
1033 */
1034 u_char *
1035 o_ipMRouteTable(vp, name, length, exact, var_len, write_method)
1036 register struct variable *vp; /* IN - pointer to variable entry that points here */
1037 register oid *name; /* IN/OUT - input name requested, output name found */
1038 register int *length; /* IN/OUT - length of input and output oid's */
1039 int exact; /* IN - TRUE if an exact match was requested. */
1040 int *var_len; /* OUT - length of variable or 0 if function returned. */
1041 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
1042 {
1043 u_long src, grp, mask;
1044 struct gtable *gt = NULL;
1045 struct stable *st = NULL;
1046 static struct sioc_sg_req sg_req;
1047 oid newname[MAX_NAME_LEN];
1048 int len;
1049
1050 /* Copy name OID to new OID */
1051 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
1052
1053 if (exact) {
1054 if (*length != vp->namelen + 12)
1055 return NULL;
1056
1057 if (!get_address(name, *length, &grp, vp->namelen)
1058 || !get_address(name, *length, &src, vp->namelen+4)
1059 || !get_address(name, *length, &mask, vp->namelen+8)
1060 || (mask != 0xFFFFFFFF) /* we keep sources now, not subnets */
1061 || !(gt = find_grp(grp))
1062 || !(st = find_grp_src(gt,src)))
1063 return NULL;
1064
1065 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1066 } else {
1067 len = *length;
1068 if (compare(name, *length, vp->name, vp->namelen) < 0)
1069 len = vp->namelen;
1070
1071 if (len < vp->namelen + 12) { /* get first entry */
1072
1073 get_address(name, len, &grp, vp->namelen);
1074 get_address(name, len, &src, vp->namelen+4);
1075 get_address(name, len, &mask, vp->namelen+8);
1076
1077 if (!next_grp_src_mask(>,&st,grp,src,mask)) /* Get first entry */
1078 return NULL;
1079
1080 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1081 put_address(newname, st->st_origin, vp->namelen+4);
1082 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1083 } else { /* get next entry given previous */
1084 get_address(name, *length, &grp , vp->namelen);
1085 get_address(name, *length, &src , vp->namelen+4);
1086 get_address(name, *length, &mask, vp->namelen+8);
1087
1088 if (!next_grp_src_mask(>, &st, grp,src,mask))
1089 return NULL;
1090
1091 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1092 put_address(newname, st->st_origin, vp->namelen+4);
1093 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1094 }
1095 }
1096
1097 /* Save new OID */
1098 *length = vp->namelen + 12;
1099 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1100 *write_method = 0;
1101 *var_len = sizeof(long);
1102
1103 switch (vp->magic) {
1104
1105 case ipMRouteUpstreamNeighbor:
1106 return (u_char *) >->gt_route->rt_gateway;
1107
1108 case ipMRouteInIfIndex:
1109 long_return = gt->gt_route->rt_parent;
1110 return (u_char *) &long_return;
1111
1112 case ipMRouteUpTime: {
1113 time_t currtime;
1114 time(&currtime);
1115 long_return = (currtime - gt->gt_ctime)*100;
1116 return (u_char *) &long_return;
1117 }
1118
1119 case ipMRouteExpiryTime:
1120 long_return = 5*((gt->gt_timer+4)/5); /* round up to nearest 5 */
1121 long_return = (long_return + secs_remaining_offset()) * 100;
1122 return (u_char *) &long_return;
1123
1124 case ipMRoutePkts:
1125 refresh_sg(&sg_req, gt, st);
1126 long_return = sg_req.pktcnt;
1127 return (u_char *) &long_return;
1128
1129 case ipMRouteOctets:
1130 refresh_sg(&sg_req, gt, st);
1131 long_return = sg_req.bytecnt;
1132 return (u_char *) &long_return;
1133
1134 case ipMRouteDifferentInIfIndexes:
1135 refresh_sg(&sg_req, gt, st);
1136 long_return = sg_req.wrong_if;
1137 return (u_char *) &long_return;
1138
1139 case ipMRouteProtocol:
1140 long_return = 4;
1141 return (u_char *) &long_return;
1142
1143 default:
1144 ERROR("");
1145 }
1146 return NULL;
1147 }
1148
1149 /*
1150 * Implements the IP Multicast Routing Next Hop Table portion of the Multicast
1151 * MIB
1152 */
1153 u_char *
1154 o_ipMRouteNextHopTable(vp, name, length, exact, var_len, write_method)
1155 register struct variable *vp; /* IN - pointer to variable entry that points here */
1156 register oid *name; /* IN/OUT - input name requested, output name found */
1157 register int *length; /* IN/OUT - length of input and output oid's */
1158 int exact; /* IN - TRUE if an exact match was requested. */
1159 int *var_len; /* OUT - length of variable or 0 if function returned. */
1160 int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
1161 {
1162 u_long src, grp, mask, addr;
1163 vifi_t vifi;
1164 struct gtable *gt;
1165 struct stable *st;
1166 oid newname[MAX_NAME_LEN];
1167 int len;
1168
1169 /* Copy name OID to new OID */
1170 bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
1171
1172 if (exact) {
1173 if (*length != vp->namelen + 17)
1174 return NULL;
1175
1176 if (!get_address(name, *length, &grp, vp->namelen)
1177 || !get_address(name, *length, &src, vp->namelen+4)
1178 || !get_address(name, *length, &mask, vp->namelen+8)
1179 || !get_address(name, *length, &addr, vp->namelen+13)
1180 || grp!=addr
1181 || mask!=0xFFFFFFFF
1182 || (!(gt=find_grp(grp)))
1183 || (!(st=find_grp_src(gt,src))))
1184 return NULL;
1185
1186 vifi = name[vp->namelen+12];
1187 if (!(VIFM_ISSET(vifi, gt->gt_route->rt_children)))
1188 return NULL;
1189
1190 bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1191 } else {
1192 len = *length;
1193 if (compare(name, *length, vp->name, vp->namelen) < 0)
1194 len = vp->namelen;
1195
1196 if (len < vp->namelen + 17) { /* get first entry */
1197
1198 get_address(name, len, &grp, vp->namelen);
1199 get_address(name, len, &src, vp->namelen+4);
1200 get_address(name, len, &mask, vp->namelen+8);
1201
1202 /* Find first child vif */
1203 vifi=0;
1204 if (!next_child(>, &st, grp, src, mask, &vifi))
1205 return NULL;
1206
1207 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1208 put_address(newname, st->st_origin, vp->namelen+4);
1209 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1210 newname[vp->namelen+12] = vifi;
1211 put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
1212
1213 } else { /* get next entry given previous */
1214 vifi = name[vp->namelen+12]+1;
1215 if (!get_address(name, *length, &grp, vp->namelen)
1216 || !get_address(name, *length, &src, vp->namelen+4)
1217 || !get_address(name, *length, &mask, vp->namelen+8)
1218 || !next_child(>, &st, grp, src, mask, &vifi))
1219 return NULL;
1220
1221 put_address(newname, gt->gt_mcastgrp, vp->namelen);
1222 put_address(newname, st->st_origin, vp->namelen+4);
1223 put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1224 newname[vp->namelen+12] = vifi;
1225 put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
1226 }
1227 }
1228
1229 /* Save new OID */
1230 *length = vp->namelen + 17;
1231 bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1232 *write_method = 0;
1233 *var_len = sizeof(long);
1234
1235 switch (vp->magic) {
1236
1237 case ipMRouteNextHopState:
1238 long_return = (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1;
1239 return (u_char *) &long_return;
1240
1241 /* Currently equal to ipMRouteUpTime */
1242 case ipMRouteNextHopUpTime: {
1243 time_t currtime;
1244 time(&currtime);
1245 long_return = (currtime - gt->gt_ctime)*100;
1246 return (u_char *) &long_return;
1247 }
1248
1249 case ipMRouteNextHopExpiryTime:
1250 long_return = 5*((gt->gt_prsent_timer+4)/5); /* round up to nearest 5*/
1251 long_return = (long_return + secs_remaining_offset()) * 100;
1252 return (u_char *) &long_return;
1253
1254 case ipMRouteNextHopClosestMemberHops:
1255 long_return = 0;
1256 return (u_char *) &long_return;
1257
1258 case ipMRouteNextHopProtocol:
1259 long_return = 4;
1260 return (u_char *) &long_return;
1261
1262 default:
1263 ERROR("");
1264 }
1265 return NULL;
1266 }
1267
1268 /* sync_timer is called by timer() every TIMER_INTERVAL seconds.
1269 * Its job is to record this time so that we can compute on demand
1270 * the approx # seconds remaining until the next timer() call
1271 */
1272 static time_t lasttimer;
1273
1274 void
1275 sync_timer()
1276 {
1277 time(&lasttimer);
1278 }
1279
1280 int /* in range [-TIMER_INTERVAL..0] */
1281 secs_remaining_offset()
1282 {
1283 time_t tm;
1284
1285 time(&tm);
1286 return lasttimer-tm;
1287 }
1288