|
|
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.