LOCAL void routeTableShow(int routeType, int af) { int type, s; struct radix_node_head *rnh; /* Setup locals */ type = routeType; rnh = rt_tables[af]; /* If head dont exists */ if (rnh == NULL) return; /* Get processor level */ s = splnet(); /* Show routes */ rn_walktree(rnh, routeNodeShow, &type); /* Restore processor level */ splx(s); }
/* Supply dst with the contents of the routing tables. * If this won't fit in one packet, chop it up into several. */ void supply(struct sockaddr_in *dst, struct interface *ifp, /* output interface */ enum output_type type, int flash, /* 1=flash update */ int vers, /* RIP version */ int passwd_ok) /* OK to include cleartext password */ { struct rt_entry *rt; int def_metric; ws.state = 0; ws.gen_limit = 1024; ws.to = *dst; ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr); ws.to_std_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_std_mask; if (ifp != NULL) { ws.to_mask = ifp->int_mask; ws.to_net = ifp->int_net; if (on_net(ws.to.sin_addr.s_addr, ws.to_net, ws.to_mask)) ws.state |= WS_ST_TO_ON_NET; } else { ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0); ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask; rt = rtfind(dst->sin_addr.s_addr); if (rt) ifp = rt->rt_ifp; } ws.npackets = 0; if (flash) ws.state |= WS_ST_FLASH; if ((ws.ifp = ifp) == NULL) { ws.metric = 1; } else { /* Adjust the advertised metric by the outgoing interface * metric. */ ws.metric = ifp->int_metric+1; } ripv12_buf.rip.rip_vers = vers; switch (type) { case OUT_MULTICAST: if (ifp->int_if_flags & IFF_MULTICAST) v2buf.type = OUT_MULTICAST; else v2buf.type = NO_OUT_MULTICAST; v12buf.type = OUT_BROADCAST; break; case OUT_QUERY: ws.state |= WS_ST_QUERY; /* fall through */ case OUT_BROADCAST: case OUT_UNICAST: v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2; v12buf.type = type; break; case NO_OUT_MULTICAST: case NO_OUT_RIPV2: break; /* no output */ } if (vers == RIPv2) { /* full RIPv2 only if cannot be heard by RIPv1 listeners */ if (type != OUT_BROADCAST) ws.state |= WS_ST_RIP2_ALL; if ((ws.state & WS_ST_QUERY) || !(ws.state & WS_ST_TO_ON_NET)) { ws.state |= (WS_ST_AG | WS_ST_SUPER_AG); } else if (ifp == NULL || !(ifp->int_state & IS_NO_AG)) { ws.state |= WS_ST_AG; if (type != OUT_BROADCAST && (ifp == NULL || !(ifp->int_state & IS_NO_SUPER_AG))) ws.state |= WS_ST_SUPER_AG; } } ws.a = (vers == RIPv2) ? find_auth(ifp) : 0; if (!passwd_ok && ws.a != NULL && ws.a->type == RIP_AUTH_PW) ws.a = NULL; clr_ws_buf(&v12buf,ws.a); clr_ws_buf(&v2buf,ws.a); /* Fake a default route if asked and if there is not already * a better, real default route. */ if (supplier && (def_metric = ifp->int_d_metric) != 0) { if (NULL == (rt = rtget(RIP_DEFAULT, 0)) || rt->rt_metric+ws.metric >= def_metric) { ws.state |= WS_ST_DEFAULT; ag_check(0, 0, 0, 0, def_metric, def_metric, 0, 0, 0, supply_out); } else { def_metric = rt->rt_metric+ws.metric; } /* If both RIPv2 and the poor-man's router discovery * kludge are on, arrange to advertise an extra * default route via RIPv1. */ if ((ws.state & WS_ST_RIP2_ALL) && (ifp->int_state & IS_PM_RDISC)) { ripv12_buf.rip.rip_vers = RIPv1; v12buf.n->n_family = RIP_AF_INET; v12buf.n->n_dst = htonl(RIP_DEFAULT); v12buf.n->n_metric = htonl(def_metric); v12buf.n++; } } rn_walktree(rhead, walk_supply, 0); ag_flush(0,0,supply_out); /* Flush the packet buffers, provided they are not empty and * do not contain only the password. */ if (v12buf.n != v12buf.base && (v12buf.n > v12buf.base+1 || v12buf.base->n_family != RIP_AF_AUTH)) supply_write(&v12buf); if (v2buf.n != v2buf.base && (v2buf.n > v2buf.base+1 || v2buf.base->n_family != RIP_AF_AUTH)) supply_write(&v2buf); /* If we sent nothing and this is an answer to a query, send * an empty buffer. */ if (ws.npackets == 0 && (ws.state & WS_ST_QUERY)) supply_write(&v12buf); }
int ifAllRoutesDelete ( char *ifName, /* name of the interface */ int unit /* unit number for this interface */ ) { FAST struct ifnet *ifp; FAST struct ifaddr *ifa; FAST struct in_ifaddr *ia = 0; int deleted; int args[3]; struct radix_node_head * rnh; if (ifName == NULL) return (ERROR); deleted = 0; #ifdef VIRTUAL_STACK for (ifp = _ifnet; ifp; ifp = ifp->if_next) #else for (ifp = ifnet; ifp; ifp = ifp->if_next) #endif /* VIRTUAL_STACK */ { if (ifp->if_unit != unit || strcmp(ifName, ifp->if_name)) continue; /* * Find address for this interface, if it exists. */ #ifdef VIRTUAL_STACK for (ia = _in_ifaddr; ia; ia = ia->ia_next) #else for (ia = in_ifaddr; ia; ia = ia->ia_next) #endif /* VIRTUAL_STACK */ if (ia->ia_ifp == ifp) break; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { /* skip if address family does not belong to AF_INET */ if (ifa->ifa_addr->sa_family != AF_INET) continue; /* * Walk through the entire table and delete routes associated * with the interface. */ /* First delete the ARP entries */ args[0] = (int)ifp; args[1] = RT_ARP; args[2] = (int)&deleted; rnh = rt_tables[AF_INET]; if (rnh) rn_walktree(rnh, routeNodeDelete, (void *)args); /* Next delete the non-ARP routes */ args[0] = (int)ifp; args[1] = ~RT_ARP; args[2] = (int)&deleted; if (rnh) rn_walktree(rnh, routeNodeDelete, (void *)args); break; } } return (deleted); }