void check_replace(struct route_node *np2, struct rib *rib2, struct route_node **np, struct rib **rib) { int proto, proto2; if (!*np) { *np = np2; *rib = rib2; return; } if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0) return; if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0) { *np = np2; *rib = rib2; return; } proto = proto_trans((*rib)->type); proto2 = proto_trans(rib2->type); if (proto2 > proto) return; if (proto2 < proto) { *np = np2; *rib = rib2; return; } #if 0 if (in_addr_cmp((u_char *)&(*rib)->u.gate4, (u_char *)&rib2->u.gate4) <= 0) return; #endif /* 0 */ *np = np2; *rib = rib2; return; }
void get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len, int exact, struct route_node **np, struct rib **rib) { struct in_addr dest; struct route_table *table; struct route_node *np2; struct rib *rib2; int proto; int policy; struct in_addr nexthop; u_char *pnt; int i; /* Init index variables */ pnt = (u_char *) &dest; for (i = 0; i < 4; i++) *pnt++ = 0; pnt = (u_char *) &nexthop; for (i = 0; i < 4; i++) *pnt++ = 0; proto = 0; policy = 0; /* Init return variables */ *np = NULL; *rib = NULL; /* Short circuit exact matches of wrong length */ if (exact && (*objid_len != (unsigned) v->namelen + 10)) return; table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) return; /* Get INDEX information out of OID. * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop */ if (*objid_len > v->namelen) oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest); if (*objid_len > (unsigned) v->namelen + 4) proto = objid[v->namelen + 4]; if (*objid_len > (unsigned) v->namelen + 5) policy = objid[v->namelen + 5]; if (*objid_len > (unsigned) v->namelen + 6) oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6), &nexthop); /* Apply GETNEXT on not exact search */ if (!exact && (*objid_len >= (unsigned) v->namelen + 10)) { if (! in_addr_add((u_char *) &nexthop, 1)) return; } /* For exact: search matching entry in rib table. */ if (exact) { if (policy) /* Not supported (yet?) */ return; for (*np = route_top (table); *np; *np = route_next (*np)) { if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest)) { for (*rib = (*np)->info; *rib; *rib = (*rib)->next) { if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4, (u_char *)&nexthop)) if (proto == proto_trans((*rib)->type)) return; } } } return; } /* Search next best entry */ for (np2 = route_top (table); np2; np2 = route_next (np2)) { /* Check destination first */ if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0) for (rib2 = np2->info; rib2; rib2 = rib2->next) check_replace(np2, rib2, np, rib); if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0) { /* have to look at each rib individually */ for (rib2 = np2->info; rib2; rib2 = rib2->next) { int proto2, policy2; proto2 = proto_trans(rib2->type); policy2 = 0; if ((policy < policy2) || ((policy == policy2) && (proto < proto2)) || ((policy == policy2) && (proto == proto2) && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4, (u_char *) &nexthop) >= 0) )) check_replace(np2, rib2, np, rib); } } } if (!*rib) return; policy = 0; proto = proto_trans((*rib)->type); *objid_len = v->namelen + 10; pnt = (u_char *) &(*np)->p.u.prefix; for (i = 0; i < 4; i++) objid[v->namelen + i] = *pnt++; objid[v->namelen + 4] = proto; objid[v->namelen + 5] = policy; { struct nexthop *nexthop; nexthop = (*rib)->nexthop; if (nexthop) { pnt = (u_char *) &nexthop->gate.ipv4; for (i = 0; i < 4; i++) objid[i + v->namelen + 6] = *pnt++; } } return; }