Annotation of embedaddon/pimdd/mrt.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1998 by the University of Oregon.
3: * All rights reserved.
4: *
5: * Permission to use, copy, modify, and distribute this software and
6: * its documentation in source and binary forms for lawful
7: * purposes and without fee is hereby granted, provided
8: * that the above copyright notice appear in all copies and that both
9: * the copyright notice and this permission notice appear in supporting
10: * documentation, and that any documentation, advertising materials,
11: * and other materials related to such distribution and use acknowledge
12: * that the software was developed by the University of Oregon.
13: * The name of the University of Oregon may not be used to endorse or
14: * promote products derived from this software without specific prior
15: * written permission.
16: *
17: * THE UNIVERSITY OF OREGON DOES NOT MAKE ANY REPRESENTATIONS
18: * ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
19: * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
20: * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
22: * NON-INFRINGEMENT.
23: *
24: * IN NO EVENT SHALL UO, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
25: * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
26: * TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
27: * THE USE OR PERFORMANCE OF THIS SOFTWARE.
28: *
29: * Other copyrights might apply to parts of this software and are so
30: * noted when applicable.
31: */
32: /*
33: * Questions concerning this software should be directed to
34: * Kurt Windisch (kurtw@antc.uoregon.edu)
35: *
36: * $Id: mrt.c,v 1.16 1998/12/22 21:50:17 kurtw Exp $
37: */
38: /*
39: * Part of this program has been derived from PIM sparse-mode pimd.
40: * The pimd program is covered by the license in the accompanying file
41: * named "LICENSE.pimd".
42: *
43: * The pimd program is COPYRIGHT 1998 by University of Southern California.
44: *
45: * Part of this program has been derived from mrouted.
46: * The mrouted program is covered by the license in the accompanying file
47: * named "LICENSE.mrouted".
48: *
49: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
50: * Leland Stanford Junior University.
51: *
52: */
53:
54: #include "defs.h"
55:
56: srcentry_t *srclist;
57: grpentry_t *grplist;
58:
59: /*
60: * Local functions definition
61: */
62: static srcentry_t *create_srcentry __P((u_int32 source));
63: static int search_srclist __P((u_int32 source,
64: srcentry_t **sourceEntry));
65: static int search_srcmrtlink __P((srcentry_t *srcentry_ptr,
66: u_int32 group,
67: mrtentry_t **mrtPtr));
68: static void insert_srcmrtlink __P((mrtentry_t *elementPtr,
69: mrtentry_t *insertPtr,
70: srcentry_t *srcListPtr));
71: static grpentry_t *create_grpentry __P((u_int32 group));
72: static int search_grplist __P((u_int32 group,
73: grpentry_t **groupEntry));
74: static int search_grpmrtlink __P((grpentry_t *grpentry_ptr,
75: u_int32 source,
76: mrtentry_t **mrtPtr));
77: static void insert_grpmrtlink __P((mrtentry_t *elementPtr,
78: mrtentry_t *insertPtr,
79: grpentry_t *grpListPtr));
80: static mrtentry_t *alloc_mrtentry __P((srcentry_t *srcentry_ptr,
81: grpentry_t *grpentry_ptr));
82: static mrtentry_t *create_mrtentry __P((srcentry_t *srcentry_ptr,
83: grpentry_t *grpentry_ptr,
84: u_int16 flags));
85:
86:
87: void
88: init_pim_mrt()
89: {
90:
91: /* TODO: delete any existing routing table */
92:
93: /* Initialize the source list */
94: /* The first entry has address 'INADDR_ANY' and is not used */
95: /* The order is the smallest address first. */
96: srclist = (srcentry_t *)malloc(sizeof(srcentry_t));
97: srclist->next = (srcentry_t *)NULL;
98: srclist->prev = (srcentry_t *)NULL;
99: srclist->address = INADDR_ANY_N;
100: srclist->mrtlink = (mrtentry_t *)NULL;
101: srclist->incoming = NO_VIF;
102: srclist->upstream = (pim_nbr_entry_t *)NULL;
103: srclist->metric = 0;
104: srclist->preference = 0;
105: RESET_TIMER(srclist->timer);
106:
107: /* Initialize the group list */
108: /* The first entry has address 'INADDR_ANY' and is not used */
109: /* The order is the smallest address first. */
110: grplist = (grpentry_t *)malloc(sizeof(grpentry_t));
111: grplist->next = (grpentry_t *)NULL;
112: grplist->prev = (grpentry_t *)NULL;
113: grplist->group = INADDR_ANY_N;
114: grplist->mrtlink = (mrtentry_t *)NULL;
115: }
116:
117:
118: grpentry_t*
119: find_group(group)
120: u_int32 group;
121: {
122: grpentry_t *grpentry_ptr;
123:
124: if (!IN_MULTICAST(ntohl(group)))
125: return (grpentry_t *)NULL;
126:
127: if (search_grplist(group, &grpentry_ptr) == TRUE) {
128: /* Group found! */
129: return (grpentry_ptr);
130: }
131: return (grpentry_t *)NULL;
132: }
133:
134:
135: srcentry_t *
136: find_source(source)
137: u_int32 source;
138: {
139: srcentry_t *srcentry_ptr;
140:
141: if (!inet_valid_host(source))
142: return (srcentry_t *)NULL;
143:
144: if (search_srclist(source, &srcentry_ptr) == TRUE) {
145: /* Source found! */
146: return (srcentry_ptr);
147: }
148: return (srcentry_t *)NULL;
149: }
150:
151:
152: mrtentry_t *
153: find_route(source, group, flags, create)
154: u_int32 source, group;
155: u_int16 flags;
156: char create;
157: {
158: srcentry_t *srcentry_ptr;
159: grpentry_t *grpentry_ptr;
160: mrtentry_t *mrtentry_ptr;
161:
162: if (!IN_MULTICAST(ntohl(group)))
163: return (mrtentry_t *)NULL;
164:
165: if (!inet_valid_host(source))
166: return (mrtentry_t *)NULL;
167:
168: if (create == DONT_CREATE) {
169: if (search_grplist(group, &grpentry_ptr) == FALSE)
170: return (mrtentry_t *)NULL;
171: /* Search for the source */
172: if (search_grpmrtlink(grpentry_ptr, source,
173: &mrtentry_ptr) == TRUE) {
174: /* Exact (S,G) entry found */
175: return (mrtentry_ptr);
176: }
177: return (mrtentry_t *)NULL;
178: }
179:
180:
181: /* Creation allowed */
182:
183: grpentry_ptr = create_grpentry(group);
184: if (grpentry_ptr == (grpentry_t *)NULL) {
185: return (mrtentry_t *)NULL;
186: }
187:
188: /* Setup the (S,G) routing entry */
189: srcentry_ptr = create_srcentry(source);
190: if (srcentry_ptr == (srcentry_t *)NULL) {
191: if (grpentry_ptr->mrtlink == (mrtentry_t *)NULL) {
192: /* New created grpentry. Delete it. */
193: delete_grpentry(grpentry_ptr);
194: }
195: return (mrtentry_t *)NULL;
196: }
197:
198: mrtentry_ptr = create_mrtentry(srcentry_ptr, grpentry_ptr, MRTF_SG);
199: if (mrtentry_ptr == (mrtentry_t *)NULL) {
200: if (grpentry_ptr->mrtlink == (mrtentry_t *)NULL) {
201: /* New created grpentry. Delete it. */
202: delete_grpentry(grpentry_ptr);
203: }
204: if (srcentry_ptr->mrtlink == (mrtentry_t *)NULL) {
205: /* New created srcentry. Delete it. */
206: delete_srcentry(srcentry_ptr);
207: }
208: return (mrtentry_t *)NULL;
209: }
210:
211: if (mrtentry_ptr->flags & MRTF_NEW) {
212: /* The mrtentry pref/metric should be the pref/metric of the
213: * _upstream_ assert winner. Since this isn't known now,
214: * set it to the config'ed default
215: */
216: mrtentry_ptr->incoming = srcentry_ptr->incoming;
217: mrtentry_ptr->upstream = srcentry_ptr->upstream;
218: mrtentry_ptr->metric = srcentry_ptr->metric;
219: mrtentry_ptr->preference = srcentry_ptr->preference;
220: }
221:
222: return (mrtentry_ptr);
223: }
224:
225:
226: void
227: delete_srcentry(srcentry_ptr)
228: srcentry_t *srcentry_ptr;
229: {
230: mrtentry_t *mrtentry_ptr;
231: mrtentry_t *mrtentry_next;
232:
233: if (srcentry_ptr == (srcentry_t *)NULL)
234: return;
235: /* TODO: XXX: the first entry is unused and always there */
236: srcentry_ptr->prev->next = srcentry_ptr->next;
237: if (srcentry_ptr->next != (srcentry_t *)NULL)
238: srcentry_ptr->next->prev = srcentry_ptr->prev;
239:
240: for (mrtentry_ptr = srcentry_ptr->mrtlink;
241: mrtentry_ptr != (mrtentry_t *)NULL;
242: mrtentry_ptr = mrtentry_next) {
243: mrtentry_next = mrtentry_ptr->srcnext;
244: if (mrtentry_ptr->grpprev != (mrtentry_t *)NULL)
245: mrtentry_ptr->grpprev->grpnext = mrtentry_ptr->grpnext;
246: else {
247: mrtentry_ptr->group->mrtlink = mrtentry_ptr->grpnext;
248: if (mrtentry_ptr->grpnext == (mrtentry_t *)NULL) {
249: /* Delete the group entry */
250: delete_grpentry(mrtentry_ptr->group);
251: }
252: }
253: if (mrtentry_ptr->grpnext != (mrtentry_t *)NULL)
254: mrtentry_ptr->grpnext->grpprev = mrtentry_ptr->grpprev;
255: FREE_MRTENTRY(mrtentry_ptr);
256: }
257: free((char *)srcentry_ptr);
258: }
259:
260:
261: void
262: delete_grpentry(grpentry_ptr)
263: grpentry_t *grpentry_ptr;
264: {
265: mrtentry_t *mrtentry_ptr;
266: mrtentry_t *mrtentry_next;
267:
268: if (grpentry_ptr == (grpentry_t *)NULL)
269: return;
270: /* TODO: XXX: the first entry is unused and always there */
271: grpentry_ptr->prev->next = grpentry_ptr->next;
272: if (grpentry_ptr->next != (grpentry_t *)NULL)
273: grpentry_ptr->next->prev = grpentry_ptr->prev;
274:
275: for (mrtentry_ptr = grpentry_ptr->mrtlink;
276: mrtentry_ptr != (mrtentry_t *)NULL;
277: mrtentry_ptr = mrtentry_next) {
278: mrtentry_next = mrtentry_ptr->grpnext;
279: if (mrtentry_ptr->srcprev != (mrtentry_t *)NULL)
280: mrtentry_ptr->srcprev->srcnext = mrtentry_ptr->srcnext;
281: else {
282: mrtentry_ptr->source->mrtlink = mrtentry_ptr->srcnext;
283: if (mrtentry_ptr->srcnext == (mrtentry_t *)NULL) {
284: /* Delete the srcentry if this was the last routing entry */
285: delete_srcentry(mrtentry_ptr->source);
286: }
287: }
288: if (mrtentry_ptr->srcnext != (mrtentry_t *)NULL)
289: mrtentry_ptr->srcnext->srcprev = mrtentry_ptr->srcprev;
290: FREE_MRTENTRY(mrtentry_ptr);
291: }
292: free((char *)grpentry_ptr);
293: }
294:
295:
296: void
297: delete_mrtentry(mrtentry_ptr)
298: mrtentry_t *mrtentry_ptr;
299: {
300: if (mrtentry_ptr == (mrtentry_t *)NULL)
301: return;
302:
303: /* Delete the kernel cache first */
304: k_del_mfc(igmp_socket, mrtentry_ptr->source->address,
305: mrtentry_ptr->group->group);
306:
307: #ifdef RSRR
308: /* Tell the reservation daemon */
309: rsrr_cache_clean(mrtentry_ptr);
310: #endif /* RSRR */
311:
312: /* (S,G) mrtentry */
313: /* Delete from the grpentry MRT chain */
314: if (mrtentry_ptr->grpprev != (mrtentry_t *)NULL)
315: mrtentry_ptr->grpprev->grpnext = mrtentry_ptr->grpnext;
316: else {
317: mrtentry_ptr->group->mrtlink = mrtentry_ptr->grpnext;
318: if (mrtentry_ptr->grpnext == (mrtentry_t *)NULL) {
319: /* Delete the group entry */
320: delete_grpentry(mrtentry_ptr->group);
321: }
322: }
323:
324: if (mrtentry_ptr->grpnext != (mrtentry_t *)NULL)
325: mrtentry_ptr->grpnext->grpprev = mrtentry_ptr->grpprev;
326:
327: /* Delete from the srcentry MRT chain */
328: if (mrtentry_ptr->srcprev != (mrtentry_t *)NULL)
329: mrtentry_ptr->srcprev->srcnext = mrtentry_ptr->srcnext;
330: else {
331: mrtentry_ptr->source->mrtlink = mrtentry_ptr->srcnext;
332: if (mrtentry_ptr->srcnext == (mrtentry_t *)NULL) {
333: /* Delete the srcentry if this was the last routing entry */
334: delete_srcentry(mrtentry_ptr->source);
335: }
336: }
337: if (mrtentry_ptr->srcnext != (mrtentry_t *)NULL)
338: mrtentry_ptr->srcnext->srcprev = mrtentry_ptr->srcprev;
339:
340: FREE_MRTENTRY(mrtentry_ptr);
341: }
342:
343:
344: static int
345: search_srclist(source, sourceEntry)
346: u_int32 source;
347: register srcentry_t **sourceEntry;
348: {
349: register srcentry_t *s_prev,*s;
350: u_int32 source_h = ntohl(source);
351:
352: for (s_prev = srclist, s = s_prev->next; s != (srcentry_t *)NULL;
353: s_prev = s, s = s->next) {
354: /* The srclist is ordered with the smallest addresses first.
355: * The first entry is not used.
356: */
357: if (ntohl(s->address) < source_h)
358: continue;
359: if (s->address == source) {
360: *sourceEntry = s;
361: return(TRUE);
362: }
363: break;
364: }
365: *sourceEntry = s_prev; /* The insertion point is between s_prev and s */
366: return(FALSE);
367: }
368:
369:
370: static int
371: search_grplist(group, groupEntry)
372: u_int32 group;
373: register grpentry_t **groupEntry;
374: {
375: register grpentry_t *g_prev, *g;
376: u_int32 group_h = ntohl(group);
377:
378: for (g_prev = grplist, g = g_prev->next; g != (grpentry_t *)NULL;
379: g_prev = g, g = g->next) {
380: /* The grplist is ordered with the smallest address first.
381: * The first entry is not used.
382: */
383: if (ntohl(g->group) < group_h)
384: continue;
385: if (g->group == group) {
386: *groupEntry = g;
387: return(TRUE);
388: }
389: break;
390: }
391: *groupEntry = g_prev; /* The insertion point is between g_prev and g */
392: return(FALSE);
393: }
394:
395:
396: static srcentry_t *
397: create_srcentry(source)
398: u_int32 source;
399: {
400: register srcentry_t *srcentry_ptr;
401: srcentry_t *srcentry_prev;
402:
403: if (search_srclist(source, &srcentry_prev) == TRUE)
404: return (srcentry_prev);
405:
406: srcentry_ptr = (srcentry_t *)malloc(sizeof(srcentry_t));
407: if (srcentry_ptr == (srcentry_t *)NULL) {
408: log(LOG_WARNING, 0, "Memory allocation error for srcentry %s",
409: inet_fmt(source, s1));
410: return (srcentry_t *)NULL;
411: }
412:
413: srcentry_ptr->address = source;
414: /*
415: * Free the memory if there is error getting the iif and
416: * the next hop (upstream) router.
417: */
418: if (set_incoming(srcentry_ptr, PIM_IIF_SOURCE) == FALSE) {
419: free((char *)srcentry_ptr);
420: return (srcentry_t *)NULL;
421: }
422: srcentry_ptr->mrtlink = (mrtentry_t *)NULL;
423: RESET_TIMER(srcentry_ptr->timer);
424: srcentry_ptr->next = srcentry_prev->next;
425: srcentry_prev->next = srcentry_ptr;
426: srcentry_ptr->prev = srcentry_prev;
427: if (srcentry_ptr->next != (srcentry_t *)NULL)
428: srcentry_ptr->next->prev = srcentry_ptr;
429:
430: IF_DEBUG(DEBUG_MFC)
431: log(LOG_DEBUG, 0, "create source entry, source %s",
432: inet_fmt(source, s1));
433: return (srcentry_ptr);
434: }
435:
436:
437: static grpentry_t *
438: create_grpentry(group)
439: u_int32 group;
440: {
441: register grpentry_t *grpentry_ptr;
442: grpentry_t *grpentry_prev;
443:
444: if (search_grplist(group, &grpentry_prev) == TRUE)
445: return (grpentry_prev);
446:
447: grpentry_ptr = (grpentry_t *)malloc(sizeof(grpentry_t));
448: if (grpentry_ptr == (grpentry_t *)NULL) {
449: log(LOG_WARNING, 0, "Memory allocation error for grpentry %s",
450: inet_fmt(group, s1));
451: return (grpentry_t *)NULL;
452: }
453:
454: grpentry_ptr->group = group;
455: grpentry_ptr->mrtlink = (mrtentry_t *)NULL;
456:
457: /* Now it is safe to include the new group entry */
458: grpentry_ptr->next = grpentry_prev->next;
459: grpentry_prev->next = grpentry_ptr;
460: grpentry_ptr->prev = grpentry_prev;
461: if (grpentry_ptr->next != (grpentry_t *)NULL)
462: grpentry_ptr->next->prev = grpentry_ptr;
463:
464: IF_DEBUG(DEBUG_MFC)
465: log(LOG_DEBUG, 0, "create group entry, group %s", inet_fmt(group, s1));
466: return(grpentry_ptr);
467: }
468:
469:
470: /*
471: * Return TRUE if the entry is found and then *mrtPtr is set to point to that
472: * entry. Otherwise return FALSE and *mrtPtr points the the previous entry
473: * (or NULL if first in the chain.
474: */
475: static int
476: search_srcmrtlink(srcentry_ptr, group, mrtPtr)
477: srcentry_t *srcentry_ptr;
478: u_int32 group;
479: mrtentry_t **mrtPtr;
480: {
481: register mrtentry_t *mrtentry_ptr;
482: register mrtentry_t *m_prev = (mrtentry_t *)NULL;
483: u_int32 group_h = ntohl(group);
484:
485: for(mrtentry_ptr = srcentry_ptr->mrtlink;
486: mrtentry_ptr != (mrtentry_t *)NULL;
487: m_prev = mrtentry_ptr, mrtentry_ptr = mrtentry_ptr->srcnext) {
488: /* The entries are ordered with the smaller group address first.
489: * The addresses are in network order.
490: */
491: if (ntohl(mrtentry_ptr->group->group) < group_h)
492: continue;
493: if (mrtentry_ptr->group->group == group) {
494: *mrtPtr = mrtentry_ptr;
495: return(TRUE);
496: }
497: break;
498: }
499: *mrtPtr = m_prev;
500: return(FALSE);
501: }
502:
503:
504: /*
505: * Return TRUE if the entry is found and then *mrtPtr is set to point to that
506: * entry. Otherwise return FALSE and *mrtPtr points the the previous entry
507: * (or NULL if first in the chain.
508: */
509: static int
510: search_grpmrtlink(grpentry_ptr, source, mrtPtr)
511: grpentry_t *grpentry_ptr;
512: u_int32 source;
513: mrtentry_t **mrtPtr;
514: {
515: register mrtentry_t *mrtentry_ptr;
516: register mrtentry_t *m_prev = (mrtentry_t *)NULL;
517: u_int32 source_h = ntohl(source);
518:
519: for (mrtentry_ptr = grpentry_ptr->mrtlink;
520: mrtentry_ptr != (mrtentry_t *)NULL;
521: m_prev = mrtentry_ptr, mrtentry_ptr = mrtentry_ptr->grpnext) {
522: /* The entries are ordered with the smaller source address first.
523: * The addresses are in network order.
524: */
525: if (ntohl(mrtentry_ptr->source->address) < source_h)
526: continue;
527: if (source == mrtentry_ptr->source->address) {
528: *mrtPtr = mrtentry_ptr;
529: return(TRUE);
530: }
531: break;
532: }
533: *mrtPtr = m_prev;
534: return(FALSE);
535: }
536:
537:
538: static void
539: insert_srcmrtlink(mrtentry_new, mrtentry_prev, srcentry_ptr)
540: mrtentry_t *mrtentry_new;
541: mrtentry_t *mrtentry_prev;
542: srcentry_t *srcentry_ptr;
543: {
544: if (mrtentry_prev == (mrtentry_t *)NULL) {
545: /* Has to be insert as the head entry for this source */
546: mrtentry_new->srcnext = srcentry_ptr->mrtlink;
547: mrtentry_new->srcprev = (mrtentry_t *)NULL;
548: srcentry_ptr->mrtlink = mrtentry_new;
549: }
550: else {
551: /* Insert right after the mrtentry_prev */
552: mrtentry_new->srcnext = mrtentry_prev->srcnext;
553: mrtentry_new->srcprev = mrtentry_prev;
554: mrtentry_prev->srcnext = mrtentry_new;
555: }
556: if (mrtentry_new->srcnext != (mrtentry_t *)NULL)
557: mrtentry_new->srcnext->srcprev = mrtentry_new;
558: }
559:
560:
561: static void
562: insert_grpmrtlink(mrtentry_new, mrtentry_prev, grpentry_ptr)
563: mrtentry_t *mrtentry_new;
564: mrtentry_t *mrtentry_prev;
565: grpentry_t *grpentry_ptr;
566: {
567: if (mrtentry_prev == (mrtentry_t *)NULL) {
568: /* Has to be insert as the head entry for this group */
569: mrtentry_new->grpnext = grpentry_ptr->mrtlink;
570: mrtentry_new->grpprev = (mrtentry_t *)NULL;
571: grpentry_ptr->mrtlink = mrtentry_new;
572: }
573: else {
574: /* Insert right after the mrtentry_prev */
575: mrtentry_new->grpnext = mrtentry_prev->grpnext;
576: mrtentry_new->grpprev = mrtentry_prev;
577: mrtentry_prev->grpnext = mrtentry_new;
578: }
579: if (mrtentry_new->grpnext != (mrtentry_t *)NULL)
580: mrtentry_new->grpnext->grpprev = mrtentry_new;
581: }
582:
583:
584: static mrtentry_t *
585: alloc_mrtentry(srcentry_ptr, grpentry_ptr)
586: srcentry_t *srcentry_ptr;
587: grpentry_t *grpentry_ptr;
588: {
589: register mrtentry_t *mrtentry_ptr;
590: u_int16 i, *i_ptr;
591: u_long *il_ptr;
592: u_int8 vif_numbers;
593:
594: mrtentry_ptr = (mrtentry_t *)malloc(sizeof(mrtentry_t));
595: if (mrtentry_ptr == (mrtentry_t *)NULL) {
596: log(LOG_WARNING, 0, "alloc_mrtentry(): out of memory");
597: return (mrtentry_t *)NULL;
598: }
599:
600: /*
601: * grpnext, grpprev, srcnext, srcprev will be setup when we link the
602: * mrtentry to the source and group chains
603: */
604: mrtentry_ptr->source = srcentry_ptr;
605: mrtentry_ptr->group = grpentry_ptr;
606: mrtentry_ptr->incoming = NO_VIF;
607: VIFM_CLRALL(mrtentry_ptr->leaves);
608: VIFM_CLRALL(mrtentry_ptr->pruned_oifs);
609: VIFM_CLRALL(mrtentry_ptr->oifs);
610: mrtentry_ptr->upstream = (pim_nbr_entry_t *)NULL;
611: mrtentry_ptr->metric = 0;
612: mrtentry_ptr->preference = 0;
613: #ifdef RSRR
614: mrtentry_ptr->rsrr_cache = (struct rsrr_cache *)NULL;
615: #endif /* RSRR */
616:
617: /*
618: * XXX: TODO: if we are short in memory, we can reserve as few as possible
619: * space for vif timers (per group and/or routing entry), but then everytime
620: * when a new interfaces is configured, the router will be restarted and
621: * will delete the whole routing table. The "memory is cheap" solution is
622: * to reserve timer space for all potential vifs in advance and then no
623: * need to delete the routing table and disturb the forwarding.
624: */
625: #ifdef SAVE_MEMORY
626: mrtentry_ptr->prune_timers = (u_int16 *)malloc(sizeof(u_int16) * numvifs);
627: mrtentry_ptr->prune_delay_timerids =
628: (u_long *)malloc(sizeof(u_long) * numvifs);
629: mrtentry_ptr->last_assert = (u_long *)malloc(sizeof(u_long) * numvifs);
630: mrtentry_ptr->last_prune = (u_long *)malloc(sizeof(u_long) * numvifs);
631: vif_numbers = numvifs;
632: #else
633: mrtentry_ptr->prune_timers =
634: (u_int16 *)malloc(sizeof(u_int16) * total_interfaces);
635: mrtentry_ptr->prune_delay_timerids =
636: (u_long *)malloc(sizeof(u_long) * total_interfaces);
637: mrtentry_ptr->last_assert =
638: (u_long *)malloc(sizeof(u_long) * total_interfaces);
639: mrtentry_ptr->last_prune =
640: (u_long *)malloc(sizeof(u_long) * total_interfaces);
641: vif_numbers = total_interfaces;
642: #endif /* SAVE_MEMORY */
643: if ((mrtentry_ptr->prune_timers == (u_int16 *)NULL) ||
644: (mrtentry_ptr->prune_delay_timerids == (u_long *)NULL) ||
645: (mrtentry_ptr->last_assert == (u_long *)NULL) ||
646: (mrtentry_ptr->last_prune == (u_long *)NULL)) {
647: log(LOG_WARNING, 0, "alloc_mrtentry(): out of memory");
648: FREE_MRTENTRY(mrtentry_ptr);
649: return (mrtentry_t *)NULL;
650: }
651: /* Reset the timers */
652: for (i = 0, i_ptr = mrtentry_ptr->prune_timers; i < vif_numbers;
653: i++, i_ptr++)
654: RESET_TIMER(*i_ptr);
655: for (i = 0, il_ptr = mrtentry_ptr->prune_delay_timerids; i < vif_numbers;
656: i++, il_ptr++)
657: RESET_TIMER(*il_ptr);
658: for (i = 0, il_ptr = mrtentry_ptr->last_assert; i < vif_numbers;
659: i++, il_ptr++)
660: RESET_TIMER(*il_ptr);
661: for (i = 0, il_ptr = mrtentry_ptr->last_prune; i < vif_numbers;
662: i++, il_ptr++)
663: RESET_TIMER(*il_ptr);
664:
665: mrtentry_ptr->flags = MRTF_NEW;
666: RESET_TIMER(mrtentry_ptr->timer);
667: mrtentry_ptr->join_delay_timerid = 0;
668: RESET_TIMER(mrtentry_ptr->assert_timer);
669: mrtentry_ptr->graft = (pim_graft_entry_t *)NULL;
670:
671: return(mrtentry_ptr);
672: }
673:
674:
675: static mrtentry_t *
676: create_mrtentry(srcentry_ptr, grpentry_ptr, flags)
677: srcentry_t *srcentry_ptr;
678: grpentry_t *grpentry_ptr;
679: u_int16 flags;
680: {
681: mrtentry_t *r_new;
682: mrtentry_t *r_grp_insert, *r_src_insert; /* pointers to insert */
683: u_int32 source;
684: u_int32 group;
685:
686: /* (S,G) entry */
687: source = srcentry_ptr->address;
688: group = grpentry_ptr->group;
689:
690: if (search_grpmrtlink(grpentry_ptr, source, &r_grp_insert) == TRUE) {
691: return(r_grp_insert);
692: }
693: if (search_srcmrtlink(srcentry_ptr, group, &r_src_insert) == TRUE) {
694: /*
695: * Hmmm, search_grpmrtlink() didn't find the entry, but
696: * search_srcmrtlink() did find it! Shoudn't happen. Panic!
697: */
698: log(LOG_ERR, 0, "MRT inconsistency for src %s and grp %s\n",
699: inet_fmt(source, s1), inet_fmt(group, s2));
700: /* not reached but to make lint happy */
701: return (mrtentry_t *)NULL;
702: }
703: /*
704: * Create and insert in group mrtlink and source mrtlink chains.
705: */
706: r_new = alloc_mrtentry(srcentry_ptr, grpentry_ptr);
707: if (r_new == (mrtentry_t *)NULL)
708: return (mrtentry_t *)NULL;
709: /*
710: * r_new has to be insert right after r_grp_insert in the
711: * grp mrtlink chain and right after r_src_insert in the
712: * src mrtlink chain
713: */
714: insert_grpmrtlink(r_new, r_grp_insert, grpentry_ptr);
715: insert_srcmrtlink(r_new, r_src_insert, srcentry_ptr);
716: r_new->flags |= MRTF_SG;
717: return (r_new);
718: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>