Annotation of embedaddon/pimdd/mrt.c, revision 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>