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