1 /* $NetBSD: snmp.c,v 1.4 1999/01/23 22:44:43 hwr 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(igmp_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