int del_route(ip_addr dest, ip_addr mask, int iface) { RTMIB rtp; int retval = 0; struct net * ifp; /* set the route interface pointer according to the index passed. This allows * the passed index to be used to access dynamic interfaces, which do not appear * in the nets[] array. */ if(iface == -1) ifp = NULL; /* wildcard */ else ifp = if_getbynum(iface); if (rt_mib == NULL) /* Make sure we're up */ return 0; for (rtp = rt_mib; rtp < rt_mib + ipRoutes; rtp++) { if (!rtp->ipRouteNextHop) /* empty slot */ continue; if(ifp != NULL && ifp != rtp->ifp) continue; /* interface didn't match */ if ((rtp->ipRouteDest & mask) == (dest & mask)) { MEMSET(rtp, 0, sizeof(*rtp)); /* clear entry */ retval++; } if (cachedRoute == rtp) /* clear cache if it's being deleted */ cachedRoute = NULL; } return retval; }
NET if_netbytext(void * pio, char * iftext) { unsigned iface; NET ifp; if((strlen(iftext) == 1) && (isdigit(*iftext))) { iface = (unsigned)(*iftext - '0') - 1; if((iface >= ifNumber) || ((ifp = if_getbynum((int)iface)) == NULL)) { ns_printf(pio,"interface number must be 1 to %d.\n", ifNumber); return NULL; } else return (ifp); } else /* not a single digit, look up as name */ { for(ifp = (NET)(netlist.q_head); ifp; ifp = ifp->n_next) { if(strcmp(iftext, ifp->name) == 0) return ifp; } if(!ifp) ns_printf(pio,"no interface named \"%s\".\n", iftext); } return NULL; }
int del_route(ip_addr dest, ip_addr mask, int iface) { struct net * ifp; ip_addr key; if(!rt_mib) /* no route yet? */ return 0; /* set the route interface pointer according to the index passed. This allows * the passed index to be used to access dynamic interfaces, which do not appear * in the nets[] array. */ if(iface == -1) ifp = NULL; /* wildcard */ else ifp = if_getbynum(iface); /* If an iface was specified and a mask was given then just delete * the passed IP address entry and return. */ if(mask == 0xFFFFFFFF) { struct avl_node * delnode; /* node to delete */ /* If the cached route is the one being deleted then clear the cache */ if (cachedRoute->ipRouteDest == dest) cachedRoute = NULL; /* call btree route to remove the actual entry */ delnode = avlv4_access((struct avl_node *)btreeRoot, (ntohl(dest))); if(!delnode) { dtrap(); /* node not in tree??? */ return 0; /* deleted 0 entries */ } ((RTMIB)delnode)->ipRouteNextHop = 0; /* clear route */ key = htonl((((RTMIB)delnode)->ipRouteDest)); avlremove((struct avl_node **)&btreeRoot, &key); return 1; /* done, deleted one route entry */ } /* fall to here if we are doing a wildcard delete. To do this we * traverse the whole tree, using a callback function to delete any * entry with the passed net. This is not really reentrant since * we use a static variable to count deletions, but the only ill * effect of reentering will be a bogus return count.. */ if(ifp == NULL) { dtrap(); /* illegal parameter combo */ return ENP_PARAM; } rtdeletions = 0; /* init number of routes deleted */ avldepthfirst((struct avl_node *)btreeRoot, rtdel, (long)ifp, 0); return(rtdeletions); }
/* FUNCTION: netmain_route_del() * * Delete IP route table entry * * PARAM1: CLI_CTX CLI context * * RETURNS: int 0 or error code */ STATIC int netmain_route_del(CLI_CTX ctx) { struct cli_addr *cap; ip_addr dst; ip_addr mask; int ifindex; int rc; /* extract the destination IP address */ cap = (struct cli_addr *)CLI_VALUE(ctx, 'd'); if (cap->type == CLI_IPV4) { dst = *((ip_addr *)&cap->addr[0]); } else { /* failed to parse destination IP address */ return (CLI_ERR_PARAM); } /* extract the address mask */ cap = (struct cli_addr *)CLI_VALUE(ctx, 'm'); if (cap->type == CLI_IPV4) { mask = *((ip_addr *)&cap->addr[0]); } else { /* failed to parse address mask */ return (CLI_ERR_PARAM); } /* extract the interface identifier (zero-based) */ ifindex = (int)CLI_VALUE(ctx, 'i') - 1; if ((ifindex < 0) || (ifindex >= MAXNETS) || (if_getbynum(ifindex) == (NET)NULL)) { /* bad interface index */ return (CLI_ERR_PARAM); } /* del_route() returns the number of routes deleted */ rc = del_route(dst, mask, ifindex); return ((rc > 0) ? 0 : CLI_ERR_EXECUTE); }
RTMIB add_route( ip_addr dest, /* ultimate destination */ ip_addr mask, /* net mask, 0xFFFFFFFF if dest is host address */ ip_addr nexthop, /* where to forward to */ int iface, /* interface (net) for nexthop */ int prot) /* how we know it: icmp, table, etc */ { RTMIB rtp; /* scratch route table entry pointer */ struct net * ifp; /* interface (net) for nexthop */ int i; /* masks array index */ ifp = if_getbynum(iface); if(!ifp) return NULL; if (!rt_mib) return NULL; /* Don't add null masks or IP addresses - they give false positives on * net matches and don't belong here anyway. */ if((dest == 0) || (mask == 0)) { dtrap(); /* bad configuration? */ return NULL; } /* Check that host portion of dest and host portion of mask don't overlap */ if((~mask & dest) != 0) { dtrap(); /* programming error or bad user input */ return NULL; } /* add mask to array */ for(i = 0; i < 32; i++) { if(rt_masks[i] == mask) /* Mask already in table? */ break; /* don't add it again */ /* This array is ordered, highest value first. See if new mask goes here */ if(rt_masks[i] < mask) /* mask gets inserted here */ { int j; /* secondary index */ /* move subsequent masks back one slot */ for(j = 31; j > i; j--) rt_masks[j] = rt_masks[j - 1]; rt_masks[i] = mask; /* put new mask in it's slot */ break; /* done inserting mask */ } } /* this is just to find a particular entry, * so exact mask. */ rtp = rt_lookup_unmasked(dest); if(rtp && (rtp->ipRouteDest == dest)) /* found existing entry */ { /* just update and exit */ rtp_fillin(rtp, dest, mask, nexthop, ifp, prot); return(rtp); } /* fall to here if no entry found. Make new route entry */ /* find an empty entry */ for (rtp = rt_mib; rtp < rt_mib + ipRoutes; rtp++) if (!rtp->ipRouteNextHop) /* empty slot */ break; if (rtp >= (rt_mib + ipRoutes)) return NULL; /* set default values in new route entry */ rtp_fillin(rtp, dest, mask, nexthop, ifp, prot); #ifdef RIP_TRIGGERED_UPDATES rtp->ipRouteFlags |= RIP_TRIGGER ; rtp->ipRouteFlags |= RIP_VALID ; #endif /* RIP_TRIGGERED_UPDATES */ /* add route to tree. */ if(avlinsert((struct avl_node **)&btreeRoot, (struct avl_node *)rtp) == BT_ERROR) { dprintf("*** add_route - avlinsert, BT_ERROR\n"); dtrap(); return NULL; } return(rtp); }
RTMIB add_route( ip_addr dest, /* ultimate destination */ ip_addr mask, /* net mask, 0xFFFFFFFF if dest is host address */ ip_addr nexthop, /* where to forward to */ int iface, /* interface (net) for nexthop */ int prot) /* how we know it: icmp, table, etc */ { RTMIB rtp; /* scratch route table entrry pointer */ RTMIB newrt; /* best entry for new route */ struct net * ifp; /* interface (net) for nexthop */ newrt = NULL; /* may be replaced with empty or more expendable entry */ /* set the route interface pointer according to the index passed. This allows * the passed index to be used to access dynamic interfaces, which do not appear * in the nets[] array. */ ifp = if_getbynum(iface); if(!ifp) return NULL; if (rt_mib == NULL) return NULL; /* Don't add null masks or IP addresses - they give false positives on * net matches and don't belong here anyway. */ if((dest == 0) || (mask == 0)) { dtrap(); /* bad configuration? */ dprintf("add_route: rejected null parm; dest: %lx, mask: %lx\n", htonl(dest), htonl(mask) ); return NULL; } /* if it's already in the route table, just update it. */ for (rtp = rt_mib; rtp < rt_mib + ipRoutes; rtp++) { if (rtp->ipRouteDest == dest) /* found existing entry for target */ { rtp->ipRouteNextHop = nexthop; /* fix entry */ rtp->ipRouteAge = cticks; /* timestamp it */ /* set the rfc1213 1-based SNMP-ish interface index */ rtp->ipRouteIfIndex = (long)(iface) + 1; rtp->ipRouteProto = prot; /* icmp, or whatever */ rtp->ipRouteMask = mask; rtp->ifp = ifp; return(rtp); /* just update and exit */ } /* if we didn't find empty slot yet, look for good slot to recycle */ if (!newrt || (newrt->ipRouteProto != 0)) { if (!rtp->ipRouteNextHop) /* found empty slot for use */ { newrt = rtp; /* record empty route for use */ newrt->ipRouteProto = 0; continue; } /* else see if the new route has higher priority than this slot: */ if (rtp_priority[prot] >= rtp_priority[rtp->ipRouteProto]) { if (!newrt) { newrt = rtp; continue; } /* see if rtp is less important then newrtp */ if (rtp_priority[rtp->ipRouteProto] < rtp_priority[newrt->ipRouteProto]) { newrt = rtp; /* save lower priority entry for recycle */ } else if(rtp_priority[rtp->ipRouteProto] == rtp_priority[newrt->ipRouteProto]) { /* if equal priority, keep the older entry for deletion */ if (c_older(rtp->ipRouteAge, newrt->ipRouteAge) == rtp->ipRouteAge) newrt = rtp; /* got an older one */ } } } } /* fall to here if not in table: create a new route */ if (newrt) /* did we find an empty or lower priority route entry? */ rtp = newrt; /* create new entry in lowest priority slot */ else /* all slots have higher priority, new entry looses */ return NULL; /* set default value in new route entry, caller can modiy further. */ rtp->ifp = ifp; rtp->ipRouteDest = dest; rtp->ipRouteIfIndex = (long)(if_netnumber(ifp)) + 1; /* set interface number */ rtp->ipRouteMetric1 = ip_mib.ipDefaultTTL; rtp->ipRouteMetric2 = -1; rtp->ipRouteMetric3 = -1; rtp->ipRouteMetric4 = -1; rtp->ipRouteNextHop = nexthop; rtp->ipRouteProto = prot; /* icmp, or whatever */ if ((dest & mask) == (nexthop & mask)) rtp->ipRouteType = IPRT_DIRECT; else rtp->ipRouteType = IPRT_INDIRECT; rtp->ipRouteAge = cticks; /* timestamp it */ rtp->ipRouteMask = mask; rtp->ipRouteMetric5 = -1; return(rtp); }