"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/route.c" between
mrouted-4.3.tar.gz and mrouted-4.4.tar.gz

About: mrouted is an implementation of the DVMRP multicast routing protocol.

route.c  (mrouted-4.3):route.c  (mrouted-4.4)
skipping to change at line 39 skipping to change at line 39
uint32_t bh_dst; uint32_t bh_dst;
uint32_t bh_level; uint32_t bh_level;
int32_t bh_datalen; int32_t bh_datalen;
}; };
/* /*
* Exported variables. * Exported variables.
*/ */
int routes_changed; /* 1=>some routes have changed */ int routes_changed; /* 1=>some routes have changed */
int delay_change_reports; /* 1=>postpone change reports */ int delay_change_reports; /* 1=>postpone change reports */
unsigned int nroutes; /* current number of route entries */ unsigned int nroutes; /* number of routes */
struct rtentry *routing_table; /* pointer to list of route entries */
/* /*
* Private variables. * Private variables.
*/ */
static struct rtentry *rtp; /* pointer to a route entry */ static TAILQ_HEAD(rthead, rtentry) rtable;
static struct rtentry *rt_end; /* pointer to last route entry */ static struct rtentry *rtp; /* pointer to a route entry */
/* /*
* Private functions. * Private functions.
*/ */
static int init_children_and_leaves (struct rtentry *r, vifi_t parent, int firs t); static int init_children_and_leaves (struct rtentry *r, vifi_t parent, int firs t);
static int find_route (uint32_t origin, uint32_t mask); static int find_route (uint32_t origin, uint32_t mask);
static void create_route (uint32_t origin, uint32_t mask); static void create_route (uint32_t origin, uint32_t mask);
static void discard_route (struct rtentry *rt); static void discard_route (struct rtentry *rt);
static int compare_rts (const void *rt1, const void *rt2); static int compare_rts (const void *rt1, const void *rt2);
static int report_chunk (int, struct rtentry *start_rt, vifi_t vifi , uint32_t dst); static struct rtentry *report_chunk (int, struct rtentry *, vifi_t, uint32_t, i nt *);
static void queue_blaster_report (vifi_t vifi, uint32_t src, uint32_t dst, c har *p, size_t datalen, uint32_t level); static void queue_blaster_report (vifi_t vifi, uint32_t src, uint32_t dst, c har *p, size_t datalen, uint32_t level);
static void process_blaster_report (void *vifip); static void process_blaster_report (void *vifip);
/* /*
* Initialize the routing table and associated variables. * Initialize the routing table and associated variables.
*/ */
void init_routes(void) void init_routes(void)
{ {
routing_table = NULL; TAILQ_INIT(&rtable);
rt_end = NULL;
nroutes = 0; nroutes = 0;
routes_changed = FALSE; routes_changed = FALSE;
delay_change_reports = FALSE; delay_change_reports = FALSE;
} }
/* /*
* Initialize the children bits for route 'r', along with the * Initialize the children bits for route 'r', along with the
* associated dominant and subordinate data structures. * associated dominant and subordinate data structures.
* If first is set, initialize dominants, otherwise keep old * If first is set, initialize dominants, otherwise keep old
* dominants on non-parent interfaces. * dominants on non-parent interfaces.
skipping to change at line 122 skipping to change at line 120
/* /*
* A new vif has come up -- update the children bitmaps in all route * A new vif has come up -- update the children bitmaps in all route
* entries to take that into account. * entries to take that into account.
*/ */
void add_vif_to_routes(vifi_t vifi) void add_vif_to_routes(vifi_t vifi)
{ {
struct rtentry *r; struct rtentry *r;
struct uvif *uv; struct uvif *uv;
uv = find_uvif(vifi); uv = find_uvif(vifi);
for (r = routing_table; r; r = r->rt_next) { TAILQ_FOREACH(r, &rtable, rt_link) {
if (r->rt_metric != UNREACHABLE && if (r->rt_metric != UNREACHABLE && !VIFM_ISSET(vifi, r->rt_children)) {
!VIFM_ISSET(vifi, r->rt_children)) {
VIFM_SET(vifi, r->rt_children); VIFM_SET(vifi, r->rt_children);
r->rt_dominants[vifi] = 0; r->rt_dominants[vifi] = 0;
/*XXX isn't uv_nbrmap going to be empty?*/ /*XXX isn't uv_nbrmap going to be empty?*/
NBRM_CLRMASK(r->rt_subordinates, uv->uv_nbrmap); NBRM_CLRMASK(r->rt_subordinates, uv->uv_nbrmap);
update_table_entry(r, r->rt_gateway); update_table_entry(r, r->rt_gateway);
} }
} }
} }
/* /*
* A vif has gone down -- expire all routes that have that vif as parent, * A vif has gone down -- expire all routes that have that vif as parent,
* and update the children bitmaps in all other route entries to take into * and update the children bitmaps in all other route entries to take into
* account the failed vif. * account the failed vif.
*/ */
void delete_vif_from_routes(vifi_t vifi) void delete_vif_from_routes(vifi_t vifi)
{ {
struct rtentry *r; struct rtentry *r;
struct uvif *uv; struct uvif *uv;
uv = find_uvif(vifi); uv = find_uvif(vifi);
for (r = routing_table; r; r = r->rt_next) { TAILQ_FOREACH(r, &rtable, rt_link) {
if (r->rt_metric != UNREACHABLE) { if (r->rt_metric != UNREACHABLE) {
if (vifi == r->rt_parent) { if (vifi == r->rt_parent) {
del_table_entry(r, 0, DEL_ALL_ROUTES); del_table_entry(r, 0, DEL_ALL_ROUTES);
r->rt_timer = ROUTE_EXPIRE_TIME; r->rt_timer = ROUTE_EXPIRE_TIME;
r->rt_metric = UNREACHABLE; r->rt_metric = UNREACHABLE;
r->rt_flags |= RTF_CHANGED; r->rt_flags |= RTF_CHANGED;
routes_changed = TRUE; routes_changed = TRUE;
} else if (VIFM_ISSET(vifi, r->rt_children)) { } else if (VIFM_ISSET(vifi, r->rt_children)) {
VIFM_CLR(vifi, r->rt_children); VIFM_CLR(vifi, r->rt_children);
NBRM_CLRMASK(r->rt_subordinates, uv->uv_nbrmap); NBRM_CLRMASK(r->rt_subordinates, uv->uv_nbrmap);
skipping to change at line 178 skipping to change at line 175
*/ */
void add_neighbor_to_routes(vifi_t vifi, uint32_t index) void add_neighbor_to_routes(vifi_t vifi, uint32_t index)
{ {
struct rtentry *r; struct rtentry *r;
struct uvif *uv; struct uvif *uv;
uv = find_uvif(vifi); uv = find_uvif(vifi);
if (uv->uv_flags & VIFF_NOFLOOD) if (uv->uv_flags & VIFF_NOFLOOD)
return; return;
for (r = routing_table; r; r = r->rt_next) { TAILQ_FOREACH(r, &rtable, rt_link) {
if (r->rt_metric != UNREACHABLE && r->rt_parent != vifi && !AVOID_TRANSIT (vifi, uv, r)) { if (r->rt_metric != UNREACHABLE && r->rt_parent != vifi && !AVOID_TRANSIT (vifi, uv, r)) {
NBRM_SET(index, r->rt_subordinates); NBRM_SET(index, r->rt_subordinates);
update_table_entry(r, r->rt_gateway); update_table_entry(r, r->rt_gateway);
} }
} }
} }
/* /*
* A neighbor has failed or become unreachable. If that neighbor was * A neighbor has failed or become unreachable. If that neighbor was
* considered a dominant or subordinate router in any route entries, * considered a dominant or subordinate router in any route entries,
* take appropriate action. Expire all routes this neighbor advertised * take appropriate action. Expire all routes this neighbor advertised
* to us. * to us.
*/ */
void delete_neighbor_from_routes(uint32_t addr, vifi_t vifi, uint32_t index) void delete_neighbor_from_routes(uint32_t addr, vifi_t vifi, uint32_t index)
{ {
struct rtentry *r; struct rtentry *r;
struct uvif *uv; struct uvif *uv;
uv = find_uvif(vifi); uv = find_uvif(vifi);
for (r = routing_table; r; r = r->rt_next) { TAILQ_FOREACH(r, &rtable, rt_link) {
if (r->rt_metric != UNREACHABLE) { if (r->rt_metric != UNREACHABLE) {
if (r->rt_parent == vifi && r->rt_gateway == addr) { if (r->rt_parent == vifi && r->rt_gateway == addr) {
del_table_entry(r, 0, DEL_ALL_ROUTES); del_table_entry(r, 0, DEL_ALL_ROUTES);
r->rt_timer = ROUTE_EXPIRE_TIME; r->rt_timer = ROUTE_EXPIRE_TIME;
r->rt_metric = UNREACHABLE; r->rt_metric = UNREACHABLE;
r->rt_flags |= RTF_CHANGED; r->rt_flags |= RTF_CHANGED;
routes_changed = TRUE; routes_changed = TRUE;
} else if (r->rt_dominants[vifi] == addr) { } else if (r->rt_dominants[vifi] == addr) {
VIFM_SET(vifi, r->rt_children); VIFM_SET(vifi, r->rt_children);
r->rt_dominants[vifi] = 0; r->rt_dominants[vifi] = 0;
skipping to change at line 253 skipping to change at line 250
* If no match is found, return FALSE and leave 'rtp' pointing to the route * If no match is found, return FALSE and leave 'rtp' pointing to the route
* entry preceding the point at which the new origin should be inserted. * entry preceding the point at which the new origin should be inserted.
* This code is optimized for the normal case in which the first entry to * This code is optimized for the normal case in which the first entry to
* be examined is the matching entry. * be examined is the matching entry.
*/ */
static int find_route(uint32_t origin, uint32_t mask) static int find_route(uint32_t origin, uint32_t mask)
{ {
struct rtentry *r; struct rtentry *r;
/* /*
* If rtp is NULL, we are preceding routing_table, so our first search * If rtp is NULL, we are preceding rtable, so our first search
* candidate should be the routing_table. * candidate should be the rtable.
*/ */
r = rtp ? rtp : routing_table; r = rtp ? rtp : TAILQ_FIRST(&rtable);
while (r != NULL) { while (r != NULL) {
if (origin == r->rt_origin && mask == r->rt_originmask) { if (origin == r->rt_origin && mask == r->rt_originmask) {
rtp = r; rtp = r;
return TRUE; return TRUE;
} }
if (ntohl(mask) < ntohl(r->rt_originmask) || if (ntohl(mask) < ntohl(r->rt_originmask) ||
(mask == r->rt_originmask && (mask == r->rt_originmask &&
ntohl(origin) < ntohl(r->rt_origin))) { ntohl(origin) < ntohl(r->rt_origin))) {
rtp = r; rtp = r;
r = r->rt_next; r = TAILQ_NEXT(r, rt_link);
} else { } else
break; break;
}
} }
return FALSE; return FALSE;
} }
/* /*
* Create a new routing table entry for the specified origin and link it into * Create a new routing table entry for the specified origin and link it into
* the routing table. The shared variable 'rtp' is assumed to point to the * the routing table. The shared variable 'rtp' is assumed to point to the
* routing entry after which the new one should be inserted. It is left * routing entry after which the new one should be inserted. It is left
* pointing to the new entry. * pointing to the new entry.
* *
* Only the origin, originmask, originwidth and flags fields are initialized * Only the origin, originmask, originwidth and flags fields are initialized
skipping to change at line 313 skipping to change at line 311
else if (((char *)&mask)[2] != 0) rt->rt_originwidth = 3; else if (((char *)&mask)[2] != 0) rt->rt_originwidth = 3;
else if (((char *)&mask)[1] != 0) rt->rt_originwidth = 2; else if (((char *)&mask)[1] != 0) rt->rt_originwidth = 2;
else rt->rt_originwidth = 1; else rt->rt_originwidth = 1;
rt->rt_flags = 0; rt->rt_flags = 0;
rt->rt_groups = NULL; rt->rt_groups = NULL;
VIFM_CLRALL(rt->rt_children); VIFM_CLRALL(rt->rt_children);
NBRM_CLRALL(rt->rt_subordinates); NBRM_CLRALL(rt->rt_subordinates);
NBRM_CLRALL(rt->rt_subordadv); NBRM_CLRALL(rt->rt_subordadv);
/* Link in 'rt', where rtp points */ if (rtp)
if (rtp) { TAILQ_INSERT_AFTER(&rtable, rtp, rt, rt_link);
rt->rt_prev = rtp; else
rt->rt_next = rtp->rt_next; TAILQ_INSERT_HEAD(&rtable, rt, rt_link);
if (rt->rt_next)
(rt->rt_next)->rt_prev = rt;
else
rt_end = rt;
rtp->rt_next = rt;
} else {
if (routing_table) {
/* Change existing head to rt */
rt->rt_next = routing_table;
routing_table->rt_prev = rt;
}
else {
/* rt is the first route entry that exists */
rt_end = rt;
}
routing_table = rt;
}
rtp = rt; rtp = rt;
++nroutes; ++nroutes;
} }
/* /*
* Discard the routing table entry following the one to which 'rt' points. * Discard the routing table entry following the one to which 'rt' points.
* [.|prev|.]--->[.|rt|.]<---[.|next|.] * [.|prev|.]--->[.|rt|.]<---[.|next|.]
*/ */
static void discard_route(struct rtentry *rt) static void discard_route(struct rtentry *rt)
{ {
struct rtentry *prev, *next;
struct uvif *uv; struct uvif *uv;
if (!rt) if (!rt)
return; return;
/* Find previous and next link */ /* Update meta pointers */
prev = rt->rt_prev; if (rtp == rt)
next = rt->rt_next; rtp = TAILQ_NEXT(rt, rt_link);
/* Unlink 'rt' */ TAILQ_REMOVE(&rtable, rt, rt_link);
if (prev)
prev->rt_next = next; /* Handles case when 'rt' is last link. */
else
routing_table = next; /* 'rt' is first link. */
if (next)
next->rt_prev = prev;
/* Update the books */ /* Update the books */
uv = find_uvif(rt->rt_parent); uv = find_uvif(rt->rt_parent);
uv->uv_nroutes--; uv->uv_nroutes--;
/*???nbr???.al_nroutes--;*/ /*???nbr???.al_nroutes--;*/
--nroutes; --nroutes;
/* Update meta pointers */
if (rtp == rt)
rtp = next;
if (rt_end == rt)
rt_end = next;
free(rt->rt_dominants); free(rt->rt_dominants);
free(rt); free(rt);
} }
/* /*
* Process a route report for a single origin, creating or updating the * Process a route report for a single origin, creating or updating the
* corresponding routing table entry if necessary. 'src' is either the * corresponding routing table entry if necessary. 'src' is either the
* address of a neighboring router from which the report arrived, or zero * address of a neighboring router from which the report arrived, or zero
* to indicate a change of status of one of our own interfaces. * to indicate a change of status of one of our own interfaces.
*/ */
skipping to change at line 676 skipping to change at line 644
} }
} }
} }
} }
/* /*
* On every timer interrupt, advance the timer in each routing entry. * On every timer interrupt, advance the timer in each routing entry.
*/ */
void age_routes(void) void age_routes(void)
{ {
struct rtentry *r, *next;
extern uint32_t virtual_time; /* from main.c */ extern uint32_t virtual_time; /* from main.c */
struct rtentry *r, *tmp;
r = routing_table; TAILQ_FOREACH_SAFE(r, &rtable, rt_link, tmp) {
while (r) {
next = r->rt_next;
if ((r->rt_timer += TIMER_INTERVAL) >= ROUTE_DISCARD_TIME) { if ((r->rt_timer += TIMER_INTERVAL) >= ROUTE_DISCARD_TIME) {
/* /*
* Time to garbage-collect the route entry. * Time to garbage-collect the route entry.
*/ */
del_table_entry(r, 0, DEL_ALL_ROUTES); del_table_entry(r, 0, DEL_ALL_ROUTES);
discard_route(r); discard_route(r);
} else if (r->rt_timer >= ROUTE_EXPIRE_TIME && } else if (r->rt_timer >= ROUTE_EXPIRE_TIME &&
r->rt_metric != UNREACHABLE) { r->rt_metric != UNREACHABLE) {
/* /*
* Time to expire the route entry. If the gateway is zero, * Time to expire the route entry. If the gateway is zero,
skipping to change at line 721 skipping to change at line 686
IF_DEBUG(DEBUG_ROUTE) { IF_DEBUG(DEBUG_ROUTE) {
logit(LOG_DEBUG, 0, "rt %s sub 0x%08x%08x subadv 0x%08x%08x m etric %d", logit(LOG_DEBUG, 0, "rt %s sub 0x%08x%08x subadv 0x%08x%08x m etric %d",
RT_FMT(r, s1), r->rt_subordinates.hi, r->rt_subordinate s.lo, RT_FMT(r, s1), r->rt_subordinates.hi, r->rt_subordinate s.lo,
r->rt_subordadv.hi, r->rt_subordadv.lo, r->rt_metric); r->rt_subordadv.hi, r->rt_subordadv.lo, r->rt_metric);
} }
NBRM_MASK(r->rt_subordinates, r->rt_subordadv); NBRM_MASK(r->rt_subordinates, r->rt_subordadv);
update_table_entry(r, r->rt_gateway); update_table_entry(r, r->rt_gateway);
} }
NBRM_CLRALL(r->rt_subordadv); NBRM_CLRALL(r->rt_subordadv);
} }
r = next;
} }
} }
/* /*
* Mark all routes as unreachable. This function is called only from * Mark all routes as unreachable. This function is called only from
* hup() in preparation for informing all neighbors that we are going * hup() in preparation for informing all neighbors that we are going
* off the air. For consistency, we ought also to delete all reachable * off the air. For consistency, we ought also to delete all reachable
* route entries from the kernel, but since we are about to exit we rely * route entries from the kernel, but since we are about to exit we rely
* on the kernel to do its own cleanup -- no point in making all those * on the kernel to do its own cleanup -- no point in making all those
* expensive kernel calls now. * expensive kernel calls now.
*/ */
void expire_all_routes(void) void expire_all_routes(void)
{ {
struct rtentry *r; struct rtentry *r;
for (r = routing_table; r; r = r->rt_next) { TAILQ_FOREACH(r, &rtable, rt_link) {
r->rt_metric = UNREACHABLE; r->rt_metric = UNREACHABLE;
r->rt_flags |= RTF_CHANGED; r->rt_flags |= RTF_CHANGED;
routes_changed = TRUE; routes_changed = TRUE;
} }
} }
/* /*
* Delete all the routes in the routing table. * Delete all the routes in the routing table.
*/ */
void free_all_routes(void) void free_all_routes(void)
{ {
struct rtentry *r, *next; struct rtentry *r, *tmp;
r = routing_table; TAILQ_FOREACH_SAFE(r, &rtable, rt_link, tmp)
while (r) {
next = r->rt_next;
discard_route(r); discard_route(r);
r = next;
}
} }
/* /*
* Process an incoming neighbor probe message. * Process an incoming neighbor probe message.
*/ */
void accept_probe(uint32_t src, uint32_t dst, char *p, size_t datalen, uint32_t level) void accept_probe(uint32_t src, uint32_t dst, char *p, size_t datalen, uint32_t level)
{ {
vifi_t vifi; vifi_t vifi;
vifi = find_vif_direct(src, dst); vifi = find_vif_direct(src, dst);
skipping to change at line 906 skipping to change at line 865
/* /*
* Process an incoming route report message. * Process an incoming route report message.
* If the report arrived on a vif marked as a "blaster", then just * If the report arrived on a vif marked as a "blaster", then just
* queue it and return; queue_blaster_report() will schedule it for * queue it and return; queue_blaster_report() will schedule it for
* processing later. If datalen is negative, then this is actually * processing later. If datalen is negative, then this is actually
* a queued report so actually process it instead of queueing it. * a queued report so actually process it instead of queueing it.
*/ */
void accept_report(uint32_t src, uint32_t dst, char *p, size_t datalen, uint32_t level) void accept_report(uint32_t src, uint32_t dst, char *p, size_t datalen, uint32_t level)
{ {
static struct newrt rt[MAX_NUM_RT]; /* Use heap instead of stack */ static struct newrt rt[MAX_NUM_RT]; /* Use heap instead of stack */ /* XXX: fixme */
struct listaddr *nbr; struct listaddr *nbr;
struct uvif *uv; struct uvif *uv;
uint32_t origin; uint32_t origin;
uint32_t mask; uint32_t mask;
size_t width, i; size_t width, i;
size_t nrt = 0; size_t nrt = 0;
vifi_t vifi; vifi_t vifi;
int metric; int metric;
/* /*
skipping to change at line 1048 skipping to change at line 1007
} }
update_route(rt[i].origin, rt[i].mask, rt[i].metric, src, vifi, nbr); update_route(rt[i].origin, rt[i].mask, rt[i].metric, src, vifi, nbr);
} }
if (routes_changed && !delay_change_reports) if (routes_changed && !delay_change_reports)
report_to_all_neighbors(CHANGED_ROUTES); report_to_all_neighbors(CHANGED_ROUTES);
} }
/* /*
* Send a route report message to destination 'dst', via virtual interface * Send a route report message to destination 'dst', via virtual interface
* 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. * 'vifi'. 'type' specifies ALL_ROUTES or CHANGED_ROUTES.
*/ */
void report(int which_routes, vifi_t vifi, uint32_t dst) void report(int type, vifi_t vifi, uint32_t dst)
{ {
struct rtentry *rt; struct rtentry *rt = TAILQ_LAST(&rtable, rthead);
int i; int dummy;
rt = rt_end; while (rt)
while (rt && rt != routing_table) { rt = report_chunk(type, rt, vifi, dst, &dummy);
i = report_chunk(which_routes, rt, vifi, dst);
while (i-- > 0)
rt = rt->rt_prev;
}
} }
/* /*
* Send a route report message to all neighboring routers. * Send a route report message to all neighboring routers.
* 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. * 'type' specifies ALL_ROUTES or CHANGED_ROUTES.
*/ */
void report_to_all_neighbors(int which_routes) void report_to_all_neighbors(int type)
{ {
int routes_changed_before; int routes_changed_before;
struct rtentry *r; struct rtentry *r;
struct uvif *uv; struct uvif *uv;
vifi_t vifi; vifi_t vifi;
/* /*
* Remember the state of the global routes_changed flag before * Remember the state of the global routes_changed flag before
* generating the reports, and clear the flag. * generating the reports, and clear the flag.
*/ */
routes_changed_before = routes_changed; routes_changed_before = routes_changed;
routes_changed = FALSE; routes_changed = FALSE;
UVIF_FOREACH(vifi, uv) { UVIF_FOREACH(vifi, uv) {
if (!NBRM_ISEMPTY(uv->uv_nbrmap)) if (!NBRM_ISEMPTY(uv->uv_nbrmap))
report(which_routes, vifi, uv->uv_dst_addr); report(type, vifi, uv->uv_dst_addr);
} }
/* /*
* If there were changed routes before we sent the reports AND * If there were changed routes before we sent the reports AND
* if no new changes occurred while sending the reports, clear * if no new changes occurred while sending the reports, clear
* the change flags in the individual route entries. If changes * the change flags in the individual route entries. If changes
* did occur while sending the reports, new reports will be * did occur while sending the reports, new reports will be
* generated at the next timer interrupt. * generated at the next timer interrupt.
*/ */
if (routes_changed_before && !routes_changed) { if (routes_changed_before && !routes_changed) {
for (r = routing_table; r; r = r->rt_next) TAILQ_FOREACH(r, &rtable, rt_link)
r->rt_flags &= ~RTF_CHANGED; r->rt_flags &= ~RTF_CHANGED;
} }
/* /*
* Set a flag to inhibit further reports of changed routes until the * Set a flag to inhibit further reports of changed routes until the
* next timer interrupt. This is to alleviate update storms. * next timer interrupt. This is to alleviate update storms.
*/ */
delay_change_reports = TRUE; delay_change_reports = TRUE;
} }
/* /*
* Send a route report message to destination 'dst', via virtual interface * Send a route report message to destination 'dst', via virtual interface
* 'vifi'. 'which_routes' specifies ALL_ROUTES or CHANGED_ROUTES. * 'vifi'. 'type' specifies ALL_ROUTES or CHANGED_ROUTES.
*/ */
static int report_chunk(int which_routes, struct rtentry *start_rt, vifi_t vifi, uint32_t dst) static struct rtentry *report_chunk(int type, struct rtentry *rt, vifi_t vifi, u int32_t dst, int *nrt)
{ {
struct rtentry *r; struct rtentry *r;
struct uvif *uv; struct uvif *uv;
uint32_t mask = 0; uint32_t mask = 0;
int datalen = 0; int datalen = 0;
size_t nrt = 0;
int width = 0; int width = 0;
int admetric; int admetric;
uint8_t *p; uint8_t *p;
int metric; int metric;
int i; int i;
*nrt = 0;
uv = find_uvif(vifi); uv = find_uvif(vifi);
if (!uv)
return NULL;
admetric = uv->uv_admetric; admetric = uv->uv_admetric;
p = send_buf + IP_HEADER_RAOPT_LEN + IGMP_MINLEN; p = send_buf + IP_HEADER_RAOPT_LEN + IGMP_MINLEN;
for (r = start_rt; r; r = r->rt_prev) { for (r = rt; r != TAILQ_END(&rtable); r = TAILQ_PREV(r, rthead, rt_link)) {
if (which_routes == CHANGED_ROUTES && !(r->rt_flags & RTF_CHANGED)) { if (type == CHANGED_ROUTES && !(r->rt_flags & RTF_CHANGED)) {
nrt++; (*nrt)++;
continue; continue;
} }
/* /*
* Do not poison-reverse a route for a directly-connected * Do not poison-reverse a route for a directly-connected
* subnetwork on that subnetwork. This can cause loops when * subnetwork on that subnetwork. This can cause loops when
* some router on the subnetwork is misconfigured. * some router on the subnetwork is misconfigured.
*/ */
if (r->rt_gateway == 0 && r->rt_parent == vifi) { if (r->rt_gateway == 0 && r->rt_parent == vifi) {
nrt++; (*nrt)++;
continue; continue;
} }
if (uv->uv_filter && uv->uv_filter->vf_flags & VFF_BIDIR) { if (uv->uv_filter && uv->uv_filter->vf_flags & VFF_BIDIR) {
struct vf_element *vfe; struct vf_element *vfe;
int match = 0; int match = 0;
for (vfe = uv->uv_filter->vf_filter; vfe; vfe = vfe->vfe_next) { for (vfe = uv->uv_filter->vf_filter; vfe; vfe = vfe->vfe_next) {
if (vfe->vfe_flags & VFEF_EXACT) { if (vfe->vfe_flags & VFEF_EXACT) {
if ((vfe->vfe_addr == r->rt_origin) && if ((vfe->vfe_addr == r->rt_origin) &&
skipping to change at line 1176 skipping to change at line 1133
IF_DEBUG(DEBUG_ROUTE) { IF_DEBUG(DEBUG_ROUTE) {
logit(LOG_DEBUG, 0, "%s not reported on vif %d because it %s %s", logit(LOG_DEBUG, 0, "%s not reported on vif %d because it %s %s",
RT_FMT(r, s1), vifi, RT_FMT(r, s1), vifi,
(match (match
? "matches" ? "matches"
: "doesn't match"), : "doesn't match"),
(match (match
? inet_fmts(vfe->vfe_addr, vfe->vfe_mask, s2, sizeof(s 2)) ? inet_fmts(vfe->vfe_addr, vfe->vfe_mask, s2, sizeof(s 2))
: "the filter")); : "the filter"));
} }
nrt++; (*nrt)++;
continue; continue;
} }
} }
/* /*
* If there is no room for this route in the current message, * If there is no room for this route in the current message,
* send it & return how many routes we sent. * send it & return how many routes we sent.
*/ */
if (datalen + ((r->rt_originmask == mask) if (datalen + ((r->rt_originmask == mask)
? (width + 1) ? (width + 1)
: (r->rt_originwidth + 4)) > MAX_DVMRP_DATA_LEN) { : (r->rt_originwidth + 4)) > MAX_DVMRP_DATA_LEN) {
*(p-1) |= 0x80; *(p-1) |= 0x80;
send_on_vif(uv, 0, DVMRP_REPORT, datalen); send_on_vif(uv, 0, DVMRP_REPORT, datalen);
return nrt; return r;
} }
if (r->rt_originmask != mask || datalen == 0) { if (r->rt_originmask != mask || datalen == 0) {
mask = r->rt_originmask; mask = r->rt_originmask;
width = r->rt_originwidth; width = r->rt_originwidth;
if (datalen != 0) if (datalen != 0)
*(p - 1) |= 0x80; *(p - 1) |= 0x80;
*p++ = ((char *)&mask)[1]; *p++ = ((char *)&mask)[1];
*p++ = ((char *)&mask)[2]; *p++ = ((char *)&mask)[2];
skipping to change at line 1219 skipping to change at line 1176
metric = r->rt_metric + admetric; metric = r->rt_metric + admetric;
if (metric > UNREACHABLE) if (metric > UNREACHABLE)
metric = UNREACHABLE; metric = UNREACHABLE;
if (r->rt_parent != vifi && AVOID_TRANSIT(vifi, uv, r)) if (r->rt_parent != vifi && AVOID_TRANSIT(vifi, uv, r))
metric = UNREACHABLE; metric = UNREACHABLE;
*p++ = (r->rt_parent == vifi && metric != UNREACHABLE) *p++ = (r->rt_parent == vifi && metric != UNREACHABLE)
? (char)(metric + UNREACHABLE) /* "poisoned reverse" */ ? (char)(metric + UNREACHABLE) /* "poisoned reverse" */
: (char)(metric); : (char)(metric);
++nrt; (*nrt)++;
datalen += width + 1; datalen += width + 1;
} }
if (datalen != 0) { if (datalen != 0) {
*(p-1) |= 0x80; *(p-1) |= 0x80;
send_on_vif(uv, 0, DVMRP_REPORT, datalen); send_on_vif(uv, 0, DVMRP_REPORT, datalen);
} }
return nrt; return r;
} }
/* /*
* send the next chunk of our routing table to all neighbors. * send the next chunk of our routing table to all neighbors.
* return the length of the smallest chunk we sent out. * return the length of the smallest chunk we sent out.
*/ */
int report_next_chunk(void) int report_next_chunk(void)
{ {
static int start_rt; static int start_rt = 0;
struct rtentry *sr; struct rtentry *sr;
struct uvif *uv; struct uvif *uv;
int min = 20000; int min = 20000;
vifi_t vifi; vifi_t vifi;
int n = 0; int n = 0;
int i; int i;
if (nroutes <= 0) if (nroutes <= 0)
return 0; return 0;
/* /*
* find this round's starting route. * find this round's starting route.
*/ */
for (sr = rt_end, i = start_rt; sr && --i >= 0; ) { i = start_rt;
sr = sr->rt_prev; TAILQ_FOREACH_REVERSE(sr, &rtable, rthead, rt_link) {
if (sr == routing_table) if (--i < 0)
sr = rt_end; break;
} }
/* /*
* send one chunk of routes starting at this round's start to * send one chunk of routes starting at this round's start to
* all our neighbors. * all our neighbors.
*/ */
UVIF_FOREACH(vifi, uv) { UVIF_FOREACH(vifi, uv) {
/* sr might turn up NULL above ... */ /* sr might turn up NULL above ... */
if (sr && !NBRM_ISEMPTY(uv->uv_nbrmap)) { if (sr && !NBRM_ISEMPTY(uv->uv_nbrmap)) {
n = report_chunk(ALL_ROUTES, sr, vifi, uv->uv_dst_addr); report_chunk(ALL_ROUTES, sr, vifi, uv->uv_dst_addr, &n);
if (n < min) if (n < min)
min = n; min = n;
} }
} }
if (min == 20000) if (min == 20000)
min = 0; /* Neighborless router didn't send any routes */ min = 0; /* Neighborless router didn't send any routes */
n = min; n = min;
IF_DEBUG(DEBUG_ROUTE) { IF_DEBUG(DEBUG_ROUTE) {
logit(LOG_INFO, 0, "update %d starting at %d of %d", logit(LOG_INFO, 0, "update %d starting at %d of %d",
skipping to change at line 1296 skipping to change at line 1253
void dump_routes(FILE *fp, int detail) void dump_routes(FILE *fp, int detail)
{ {
struct rtentry *r; struct rtentry *r;
struct uvif *uv; struct uvif *uv;
vifi_t vifi; vifi_t vifi;
if (detail) if (detail)
fprintf(fp, "Multicast Routing Table (%u entr%s)\n", nroutes, nroutes == 1 ? "y" : "ies"); fprintf(fp, "Multicast Routing Table (%u entr%s)\n", nroutes, nroutes == 1 ? "y" : "ies");
fputs(" Origin-Subnet From-Gateway Metric Tmr Fl In-Vif Out-Vifs=\n ", fp); fputs(" Origin-Subnet From-Gateway Metric Tmr Fl In-Vif Out-Vifs=\n ", fp);
for (r = routing_table; r; r = r->rt_next) { TAILQ_FOREACH(r, &rtable, rt_link) {
fprintf(fp, " %-18s %-15s ", fprintf(fp, " %-18s %-15s ",
inet_fmts(r->rt_origin, r->rt_originmask, s1, sizeof(s1)), inet_fmts(r->rt_origin, r->rt_originmask, s1, sizeof(s1)),
(r->rt_gateway == 0) ? "" : inet_fmt(r->rt_gateway, s2, sizeof(s2 ))); (r->rt_gateway == 0) ? "" : inet_fmt(r->rt_gateway, s2, sizeof(s2 )));
if (r->rt_metric == UNREACHABLE) if (r->rt_metric == UNREACHABLE)
fprintf(fp, " NR "); fprintf(fp, " NR ");
else else
fprintf(fp, "%4u ", r->rt_metric); fprintf(fp, "%4u ", r->rt_metric);
fprintf(fp, " %3u %c%c %3u ", r->rt_timer, fprintf(fp, " %3u %c%c %3u ", r->rt_timer,
skipping to change at line 1345 skipping to change at line 1302
} }
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
struct rtentry *determine_route(uint32_t src) struct rtentry *determine_route(uint32_t src)
{ {
struct rtentry *rt; struct rtentry *rt;
for (rt = routing_table; rt; rt = rt->rt_next) { TAILQ_FOREACH(rt, &rtable, rt_link) {
if (rt->rt_origin == (src & rt->rt_originmask) && if (rt->rt_origin == (src & rt->rt_originmask) &&
rt->rt_metric != UNREACHABLE) rt->rt_metric != UNREACHABLE)
break; break;
} }
return rt; return rt;
} }
struct rtentry *route_iter(struct rtentry **rt)
{
if (!*rt)
*rt = TAILQ_FIRST(&rtable);
else
*rt = TAILQ_NEXT(*rt, rt_link);
return *rt;
}
/** /**
* Local Variables: * Local Variables:
* indent-tabs-mode: t * indent-tabs-mode: t
* c-file-style: "ellemtel" * c-file-style: "cc-mode"
* c-basic-offset: 4
* End: * End:
*/ */
 End of changes. 53 change blocks. 
108 lines changed or deleted 74 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)