|
|
1.1 ! root 1: /* routes.c - MIB support of the routing tables */ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/snmp/RCS/routes.c,v 7.2 90/05/22 20:30:31 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/snmp/RCS/routes.c,v 7.2 90/05/22 20:30:31 mrose Exp $ ! 9: * ! 10: * Contributed by NYSERNet Inc. This work was partially supported by the ! 11: * U.S. Defense Advanced Research Projects Agency and the Rome Air Development ! 12: * Center of the U.S. Air Force Systems Command under contract number ! 13: * F30602-88-C-0016. ! 14: * ! 15: * ! 16: * $Log: routes.c,v $ ! 17: * Revision 7.2 90/05/22 20:30:31 mrose ! 18: * cache ! 19: * ! 20: * Revision 7.1 89/12/01 08:25:48 mrose ! 21: * touch-up ! 22: * ! 23: * Revision 7.0 89/11/23 22:23:21 mrose ! 24: * Release 6.0 ! 25: * ! 26: */ ! 27: ! 28: /* ! 29: * NOTICE ! 30: * ! 31: * Acquisition, use, and distribution of this module and related ! 32: * materials are subject to the restrictions of a license agreement. ! 33: * Consult the Preface in the User's Manual for the full terms of ! 34: * this agreement. ! 35: * ! 36: */ ! 37: ! 38: ! 39: #include <stdio.h> ! 40: #include "mib.h" ! 41: #include "interfaces.h" ! 42: #include "routes.h" ! 43: ! 44: /* */ ! 45: ! 46: static int routeNumber; ! 47: static struct rtetab *rts = NULL; ! 48: static struct rtetab **rtp; ! 49: ! 50: struct rtetab *rts_inet = NULL; ! 51: #ifdef BSD44 ! 52: struct rtetab *rts_iso = NULL; ! 53: #endif ! 54: ! 55: static int first_time = 1; ! 56: static int flush_cache = 0; ! 57: ! 58: /* */ ! 59: ! 60: static int rt_compar (a, b) ! 61: register struct rtetab **a, ! 62: **b; ! 63: { ! 64: int i; ! 65: ! 66: if ((i = (*a) -> rt_dst.sa.sa_family - (*b) -> rt_dst.sa.sa_family)) ! 67: return (i > 0 ? 1 : -1); ! 68: ! 69: return elem_cmp ((*a) -> rt_instance, (*a) -> rt_insize, ! 70: (*b) -> rt_instance, (*b) -> rt_insize); ! 71: } ! 72: ! 73: ! 74: int get_routes (offset) ! 75: int offset; ! 76: { ! 77: register int i; ! 78: int rthashsize, ! 79: tblsize; ! 80: struct mbuf **rtaddr, ! 81: **rtnet, ! 82: **rthost; ! 83: register struct rtetab *rt, ! 84: *rp; ! 85: struct nlist nzs; ! 86: register struct nlist *nz = &nzs; ! 87: static int lastq = -1; ! 88: ! 89: if (quantum == lastq) ! 90: return OK; ! 91: if (!flush_cache ! 92: && offset == type_SNMP_PDUs_get__next__request ! 93: && quantum == lastq + 1) { /* XXX: caching! */ ! 94: lastq = quantum; ! 95: return OK; ! 96: } ! 97: lastq = quantum, flush_cache = 0; ! 98: ! 99: for (rt = rts; rt; rt = rp) { ! 100: rp = rt -> rt_next; ! 101: ! 102: free ((char *) rt); ! 103: } ! 104: rts = rts_inet = NULL; ! 105: #ifdef BSD44 ! 106: rts_iso = NULL; ! 107: #endif ! 108: ! 109: rtp = &rts, routeNumber = 0; ! 110: #ifdef BSD44 ! 111: if (nl[N_RADIX_NODE_HEAD].n_value) { ! 112: if (get_radix_nodes () == NOTOK) ! 113: goto out1; ! 114: ! 115: goto sort_routes; ! 116: } ! 117: #endif ! 118: ! 119: if (getkmem (nl + N_RTHASHSIZE, (caddr_t) &rthashsize, sizeof rthashsize) ! 120: == NOTOK) ! 121: return NOTOK; ! 122: if (rthashsize == 0) /* XXX: why is this? */ ! 123: rthashsize = 8; ! 124: tblsize = rthashsize * sizeof *rtaddr; ! 125: if ((rtnet = (struct mbuf **) malloc ((unsigned) (tblsize))) == NULL ! 126: || (rthost = (struct mbuf **) malloc ((unsigned) (tblsize))) ! 127: == NULL) ! 128: adios (NULLCP, "out of memory"); ! 129: if (getkmem (nl + N_RTNET, (caddr_t) rtnet, tblsize) == NOTOK ! 130: || getkmem (nl + N_RTHOST, (caddr_t) rthost, tblsize) == NOTOK) ! 131: goto out2; ! 132: ! 133: nz -> n_name = "struct route"; ! 134: for (rtaddr = rtnet; rtaddr; rtaddr = rthost, rthost = NULL) ! 135: for (i = 0; i < rthashsize; i++) { ! 136: register struct mbuf *m; ! 137: struct mbuf ms; ! 138: register struct rtentry *re; ! 139: ! 140: for (m = rtaddr[i]; ! 141: nz -> n_value = (unsigned long) m; ! 142: m = ms.m_next) { ! 143: if (getkmem (nz, (char *) &ms, sizeof ms) == NOTOK) ! 144: goto out2; ! 145: ! 146: #ifndef BSD44 ! 147: re = mtod (&ms, struct rtentry *); ! 148: #else ! 149: re = (struct rtentry *) ms.m_dat; ! 150: #endif ! 151: if (get_route (re) == NOTOK) ! 152: goto out2; ! 153: } ! 154: } ! 155: ! 156: free ((char *) rtnet); ! 157: free ((char *) rthost); ! 158: ! 159: #ifdef BSD44 ! 160: sort_routes: ; ! 161: #endif ! 162: if (routeNumber > 1) { ! 163: register struct rtetab **base, ! 164: **rte; ! 165: ! 166: if ((base = (struct rtetab **) ! 167: malloc ((unsigned) (routeNumber * sizeof *base))) ! 168: == NULL) ! 169: adios (NULLCP, "out of memory"); ! 170: ! 171: rte = base; ! 172: for (rt = rts; rt; rt = rt -> rt_next) ! 173: *rte++ = rt; ! 174: ! 175: qsort ((char *) base, routeNumber, sizeof *base, rt_compar); ! 176: ! 177: rtp = base; ! 178: rt = rts = *rtp++; ! 179: rts_inet = NULL; ! 180: #ifdef BSD44 ! 181: rts_iso = NULL; ! 182: #endif ! 183: while (rtp < rte) { ! 184: switch (rt -> rt_dst.sa.sa_family) { ! 185: case AF_INET: ! 186: if (rts_inet == NULL) ! 187: rts_inet = rt; ! 188: break; ! 189: ! 190: #ifdef BSD44 ! 191: case AF_ISO: ! 192: if (rts_iso == NULL) ! 193: rts_iso = rt; ! 194: break; ! 195: #endif ! 196: } ! 197: ! 198: rt -> rt_next = *rtp; ! 199: rt = *rtp++; ! 200: } ! 201: switch (rt -> rt_dst.sa.sa_family) { ! 202: case AF_INET: ! 203: if (rts_inet == NULL) ! 204: rts_inet = rt; ! 205: break; ! 206: ! 207: #ifdef BSD44 ! 208: case AF_ISO: ! 209: if (rts_iso == NULL) ! 210: rts_iso = rt; ! 211: break; ! 212: #endif ! 213: } ! 214: rt -> rt_next = NULL; ! 215: ! 216: free ((char *) base); ! 217: } ! 218: ! 219: first_time = 0; ! 220: return OK; ! 221: ! 222: out2: ; ! 223: free ((char *) rtnet); ! 224: free ((char *) rthost); ! 225: ! 226: #ifdef BSD44 ! 227: out1: ; ! 228: #endif ! 229: for (rt = rts; rt; rt = rp) { ! 230: rp = rt -> rt_next; ! 231: ! 232: free ((char *) rt); ! 233: } ! 234: rts = rts_inet = NULL; ! 235: #ifdef BSD44 ! 236: rts_iso = NULL; ! 237: #endif ! 238: ! 239: return NOTOK; ! 240: } ! 241: ! 242: /* */ ! 243: ! 244: static int get_route (re) ! 245: register struct rtentry *re; ! 246: { ! 247: register struct rtetab *rt, ! 248: *rz; ! 249: #ifdef BSD44 ! 250: union sockaddr_un rtsock; ! 251: struct nlist nzs; ! 252: register struct nlist *nz = &nzs; ! 253: #endif ! 254: OIDentifier oids; ! 255: ! 256: #ifdef BSD44 ! 257: nz -> n_name = "union sockaddr_un", ! 258: nz -> n_value = (unsigned long) rt_key (re); ! 259: if (getkmem (nz, (caddr_t) &rtsock, sizeof rtsock) == NOTOK) ! 260: return NOTOK; ! 261: #endif ! 262: ! 263: if ((rt = (struct rtetab *) calloc (1, sizeof *rt)) == NULL) ! 264: adios (NULLCP, "out of memory"); ! 265: rt -> rt_rt = *re; /* struct copy */ ! 266: ! 267: #ifndef BSD44 ! 268: rt -> rt_dst.sa = re -> rt_dst; /* struct copy */ ! 269: ! 270: rt -> rt_gateway.sa = re -> rt_gateway; /* .. */ ! 271: #else ! 272: rt -> rt_dst = rtsock; /* struct copy */ ! 273: ! 274: nz -> n_name = "union sockaddr_un", ! 275: nz -> n_value = (unsigned long) re -> rt_gateway; ! 276: if (getkmem (nz, (caddr_t) &rt -> rt_gateway, sizeof rt -> rt_gateway) ! 277: == NOTOK) ! 278: return NOTOK; ! 279: #endif ! 280: ! 281: switch (rt -> rt_dst.sa.sa_family) { ! 282: case AF_INET: ! 283: rt -> rt_insize = ! 284: ipaddr2oid (rt -> rt_instance, &rt -> rt_dst.un_in.sin_addr); ! 285: if (rts_inet == NULL) /* in case routeNumber == 1 */ ! 286: rts_inet = rt; ! 287: break; ! 288: ! 289: #ifdef BSD44 ! 290: case AF_ISO: ! 291: rt -> rt_insize = ! 292: clnpaddr2oid (rt -> rt_instance, ! 293: &rt -> rt_dst.un_iso.siso_addr); ! 294: if (rts_iso == NULL) /* in case routeNumber == 1 */ ! 295: rts_iso = rt; ! 296: break; ! 297: #endif ! 298: ! 299: default: ! 300: bzero ((char *) rt -> rt_instance, sizeof rt -> rt_instance); ! 301: rt -> rt_insize = 0; ! 302: break; ! 303: } ! 304: ! 305: for (rz = rts; rz; rz = rz -> rt_next) ! 306: if (rz -> rt_dst.sa.sa_family == rt -> rt_dst.sa.sa_family ! 307: && elem_cmp (rz -> rt_instance, rz -> rt_insize, ! 308: rt -> rt_instance, rt -> rt_insize) == 0) ! 309: break; ! 310: if (rz) { ! 311: if (first_time) { ! 312: oids.oid_elements = rt -> rt_instance; ! 313: oids.oid_nelem = rt -> rt_insize; ! 314: advise (LLOG_EXCEPTIONS, NULLCP, ! 315: "duplicate routes for destination %d/%s", ! 316: rt -> rt_dst.sa.sa_family, sprintoid (&oids)); ! 317: } ! 318: ! 319: rt -> rt_instance[rt -> rt_insize++] = ++rz -> rt_magic; ! 320: } ! 321: ! 322: *rtp = rt, rtp = &rt -> rt_next, routeNumber++; ! 323: ! 324: if (debug && first_time) { ! 325: oids.oid_elements = rt -> rt_instance; ! 326: oids.oid_nelem = rt -> rt_insize; ! 327: advise (LLOG_DEBUG, NULLCP, ! 328: "add route: %d/%s on interface 0x%x with flags %d", ! 329: rt -> rt_dst.sa.sa_family, sprintoid (&oids), re -> rt_ifp, ! 330: re -> rt_flags); ! 331: } ! 332: ! 333: return OK; ! 334: } ! 335: ! 336: /* */ ! 337: ! 338: #ifdef BSD44 ! 339: static int get_radix_nodes () { ! 340: struct radix_node_head *rnh, ! 341: head; ! 342: struct nlist nzs; ! 343: register struct nlist *nz = &nzs; ! 344: ! 345: if (getkmem (nl + N_RADIX_NODE_HEAD, (caddr_t) &rnh, sizeof rnh) == NOTOK) ! 346: return NOTOK; ! 347: ! 348: while (rnh) { ! 349: nz -> n_name = "struct radix_node_head", ! 350: nz -> n_value = (unsigned long) rnh; ! 351: if (getkmem (nz, (caddr_t) &head, sizeof head) == NOTOK) ! 352: return NOTOK; ! 353: rnh = head.rnh_next; ! 354: ! 355: if (head.rnh_af == AF_UNSPEC) ! 356: continue; ! 357: ! 358: if (get_radix_node (head.rnh_treetop) == NOTOK) ! 359: return NOTOK; ! 360: } ! 361: ! 362: return OK; ! 363: } ! 364: ! 365: /* */ ! 366: ! 367: static int get_radix_node (rn) ! 368: struct radix_node *rn; ! 369: { ! 370: struct radix_node rnode; ! 371: struct rtentry rtentry; ! 372: struct nlist nzs; ! 373: register struct nlist *nz = &nzs; ! 374: ! 375: for (;;) { ! 376: nz -> n_name = "struct radix_node", ! 377: nz -> n_value = (unsigned long) rn; ! 378: if (getkmem (nz, (caddr_t) &rnode, sizeof rnode) == NOTOK) ! 379: return NOTOK; ! 380: ! 381: if (rnode.rn_b < 0) { ! 382: if (!(rnode.rn_flags & RNF_ROOT)) { ! 383: nz -> n_name = "struct rtentry", ! 384: nz -> n_value = (unsigned long) rn; ! 385: if (getkmem (nz, (caddr_t) &rtentry, sizeof rtentry) == NOTOK) ! 386: return NOTOK; ! 387: ! 388: if (get_route (&rtentry) == NOTOK) ! 389: return NOTOK; ! 390: } ! 391: ! 392: if (rn = rnode.rn_dupedkey) ! 393: continue; ! 394: } ! 395: else { ! 396: if (get_radix_node (rnode.rn_l) == NOTOK ! 397: || get_radix_node (rnode.rn_r) == NOTOK) ! 398: return NOTOK; ! 399: } ! 400: ! 401: return OK; ! 402: } ! 403: } ! 404: #endif ! 405: ! 406: /* */ ! 407: ! 408: struct rtetab *get_rtent (ip, len, head, isnext) ! 409: register unsigned int *ip; ! 410: int len; ! 411: struct rtetab *head; ! 412: int isnext; ! 413: { ! 414: int family; ! 415: register struct rtetab *rt; ! 416: ! 417: if (head) ! 418: family = head -> rt_dst.sa.sa_family; ! 419: for (rt = head; rt; rt = rt -> rt_next) ! 420: if (rt -> rt_dst.sa.sa_family != family) ! 421: break; ! 422: else ! 423: switch (elem_cmp (rt -> rt_instance, rt -> rt_insize, ip, len)) { ! 424: case 0: ! 425: if (!isnext) ! 426: return rt; ! 427: if ((rt = rt -> rt_next) == NULL ! 428: || rt -> rt_dst.sa.sa_family != family) ! 429: goto out; ! 430: /* else fall... */ ! 431: ! 432: case 1: ! 433: return (isnext ? rt : NULL); ! 434: } ! 435: ! 436: out: ; ! 437: flush_cache = 1; ! 438: ! 439: return NULL; ! 440: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.