📄 ipr.c
字号:
if (!oroute) { DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ", port_nr); writeIpAddr(dest); printf("but no route present\n")); return; } new_dist= oroute->ort_dist * 2; if (new_dist > IP_DEF_TTL) { new_dist= oroute->ort_dist+1; if (new_dist >= IP_DEF_TTL) { DBLOCK(1, printf("ip[%d]: got a ttl exceeded for ", port_nr); writeIpAddr(dest); printf(" but dist is %d\n", oroute->ort_dist)); return; } } result= ipr_add_oroute(port_nr, dest, netmask, oroute->ort_gateway, timeout, new_dist, oroute->ort_mtu, FALSE, 0, NULL); assert(result == NW_OK);}PUBLIC void ipr_mtu(port_nr, dest, mtu, timeout)int port_nr;ipaddr_t dest;u16_t mtu;time_t timeout;{ oroute_t *oroute; int result; oroute= oroute_find_ent(port_nr, dest); if (!oroute) { DBLOCK(1, printf("ip[%d]: got a mtu exceeded for ", port_nr); writeIpAddr(dest); printf("but no route present\n")); return; } if (mtu < IP_MIN_MTU) return; if (oroute->ort_mtu && mtu >= oroute->ort_mtu) return; /* Only decrease mtu */ result= ipr_add_oroute(port_nr, dest, HTONL(0xffffffff), oroute->ort_gateway, timeout, oroute->ort_dist, mtu, FALSE, 0, NULL); assert(result == NW_OK);}PUBLIC int ipr_get_oroute(ent_no, route_ent)int ent_no;nwio_route_t *route_ent;{ oroute_t *oroute; if (ent_no<0 || ent_no>= OROUTE_NR) return ENOENT; oroute= &oroute_table[ent_no]; if ((oroute->ort_flags & ORTF_INUSE) && oroute->ort_exp_tim && oroute->ort_exp_tim < get_time()) { oroute_del(oroute); oroute->ort_flags &= ~ORTF_INUSE; } route_ent->nwr_ent_no= ent_no; route_ent->nwr_ent_count= OROUTE_NR; route_ent->nwr_dest= oroute->ort_dest; route_ent->nwr_netmask= oroute->ort_subnetmask; route_ent->nwr_gateway= oroute->ort_gateway; route_ent->nwr_dist= oroute->ort_dist; route_ent->nwr_flags= NWRF_EMPTY; if (oroute->ort_flags & ORTF_INUSE) { route_ent->nwr_flags |= NWRF_INUSE; if (oroute->ort_flags & ORTF_STATIC) route_ent->nwr_flags |= NWRF_STATIC; } route_ent->nwr_pref= oroute->ort_pref; route_ent->nwr_mtu= oroute->ort_mtu; route_ent->nwr_ifaddr= ip_get_ifaddr(oroute->ort_port); return NW_OK;}PRIVATE oroute_t *oroute_find_ent(port_nr, dest)int port_nr;ipaddr_t dest;{ int hash; oroute_hash_t *oroute_hash; oroute_hash_t tmp_hash; oroute_t *oroute, *bestroute; time_t currtim; unsigned long hash_tmp; u32_t tmp_mask; currtim= get_time(); hash= hash_oroute(port_nr, dest, hash_tmp); oroute_hash= &oroute_hash_table[hash][0]; if (oroute_hash[0].orh_addr == dest) oroute= oroute_hash[0].orh_route; else if (oroute_hash[1].orh_addr == dest) { tmp_hash= oroute_hash[1]; oroute_hash[1]= oroute_hash[0]; oroute_hash[0]= tmp_hash; oroute= tmp_hash.orh_route; } else if (oroute_hash[2].orh_addr == dest) { tmp_hash= oroute_hash[2]; oroute_hash[2]= oroute_hash[1]; oroute_hash[1]= oroute_hash[0]; oroute_hash[0]= tmp_hash; oroute= tmp_hash.orh_route; } else if (oroute_hash[3].orh_addr == dest) { tmp_hash= oroute_hash[3]; oroute_hash[3]= oroute_hash[2]; oroute_hash[2]= oroute_hash[1]; oroute_hash[1]= oroute_hash[0]; oroute_hash[0]= tmp_hash; oroute= tmp_hash.orh_route; } else oroute= NULL; if (oroute) { assert(oroute->ort_port == port_nr); if (oroute->ort_exp_tim && oroute->ort_exp_tim<currtim) { oroute_del(oroute); oroute->ort_flags &= ~ORTF_INUSE; } else return oroute; } bestroute= NULL; for (oroute= oroute_head; oroute; oroute= oroute->ort_nextnw) { if (((dest ^ oroute->ort_dest) & oroute->ort_subnetmask) != 0) continue; if (oroute->ort_port != port_nr) continue; if (!bestroute) { bestroute= oroute; continue; } assert(oroute->ort_dest != bestroute->ort_dest); /* Using two ntohl macros in one expression * is not allowed (tmp_l is modified twice) */ tmp_mask= ntohl(oroute->ort_subnetmask); if (tmp_mask > ntohl(bestroute->ort_subnetmask)) { bestroute= oroute; continue; } } if (bestroute == NULL) return NULL; oroute_hash[3]= oroute_hash[2]; oroute_hash[2]= oroute_hash[1]; oroute_hash[1]= oroute_hash[0]; oroute_hash[0].orh_addr= dest; oroute_hash[0].orh_route= bestroute; return bestroute;}PRIVATE void oroute_del(oroute)oroute_t *oroute;{ oroute_t *prev, *nw_route, *gw_route, *dist_route, *prev_route; DBLOCK(0x10, printf("ip[%d]: deleting oroute to ", oroute->ort_port); writeIpAddr(oroute->ort_dest); printf("["); writeIpAddr(oroute->ort_subnetmask); printf("] through "); writeIpAddr(oroute->ort_gateway); printf( " timestamp %lds, timeout: %lds, distance %d pref %ld mtu %ld ", (long)oroute->ort_timestamp/HZ, (long)oroute->ort_exp_tim/HZ, oroute->ort_dist, (long)oroute->ort_pref, (long)oroute->ort_mtu); printf("flags 0x%x\n", oroute->ort_flags)); for (prev= NULL, nw_route= oroute_head; nw_route; prev= nw_route, nw_route= nw_route->ort_nextnw) { if (oroute->ort_port == nw_route->ort_port && oroute->ort_dest == nw_route->ort_dest && oroute->ort_subnetmask == nw_route->ort_subnetmask) { break; } } assert(nw_route); if (prev) prev->ort_nextnw= nw_route->ort_nextnw; else oroute_head= nw_route->ort_nextnw; prev_route= nw_route; for (prev= NULL, gw_route= nw_route; gw_route; prev= gw_route, gw_route= gw_route->ort_nextgw) { if (oroute->ort_gateway == gw_route->ort_gateway) break; } assert(gw_route); if (prev) prev->ort_nextgw= gw_route->ort_nextgw; else nw_route= gw_route->ort_nextgw; for (prev= NULL, dist_route= gw_route; dist_route; prev= dist_route, dist_route= dist_route->ort_nextdist) { if (oroute == dist_route) break; } assert(dist_route); if (prev) prev->ort_nextdist= dist_route->ort_nextdist; else gw_route= dist_route->ort_nextdist; gw_route= sort_dists(gw_route); if (gw_route != NULL) { gw_route->ort_nextgw= nw_route; nw_route= gw_route; } nw_route= sort_gws(nw_route); if (nw_route != NULL) { nw_route->ort_nextnw= oroute_head; oroute_head= nw_route; } if (nw_route != prev_route) { oroute_uncache_nw(prev_route->ort_dest, prev_route->ort_subnetmask); }}PRIVATE oroute_t *sort_dists(oroute)oroute_t *oroute;{ oroute_t *r, *prev, *best, *best_prev; int best_dist, best_pref; best= NULL; best_dist= best_pref= 0; best_prev= NULL; for (prev= NULL, r= oroute; r; prev= r, r= r->ort_nextdist) { if (best == NULL) ; /* Force assignment to best */ else if (r->ort_dist != best_dist) { if (r->ort_dist > best_dist) continue; } else { if (r->ort_pref <= best_pref) continue; } best= r; best_prev= prev; best_dist= r->ort_dist; best_pref= r->ort_pref; } if (!best) { assert(oroute == NULL); return oroute; } if (!best_prev) { assert(best == oroute); return oroute; } best_prev->ort_nextdist= best->ort_nextdist; best->ort_nextdist= oroute; return best;}PRIVATE oroute_t *sort_gws(oroute)oroute_t *oroute;{ oroute_t *r, *prev, *best, *best_prev; int best_dist, best_pref; best= NULL; best_dist= best_pref= 0; best_prev= NULL; for (prev= NULL, r= oroute; r; prev= r, r= r->ort_nextgw) { if (best == NULL) ; /* Force assignment to best */ else if (r->ort_dist != best_dist) { if (r->ort_dist > best_dist) continue; } else { if (r->ort_pref <= best_pref) continue; } best= r; best_prev= prev; best_dist= r->ort_dist; best_pref= r->ort_pref; } if (!best) { assert(oroute == NULL); return oroute; } if (!best_prev) { assert(best == oroute); return oroute; } best_prev->ort_nextgw= best->ort_nextgw; best->ort_nextgw= oroute; return best;}PRIVATE void oroute_uncache_nw(dest, netmask)ipaddr_t dest;ipaddr_t netmask;{ int i, j; oroute_hash_t *oroute_hash; for (i= 0, oroute_hash= &oroute_hash_table[0][0]; i<OROUTE_HASH_NR; i++, oroute_hash += OROUTE_HASH_ASS_NR) { for (j= 0; j<OROUTE_HASH_ASS_NR; j++) { if (((oroute_hash[j].orh_addr ^ dest) & netmask) == 0) { oroute_hash[j].orh_addr= 0; oroute_hash[j].orh_route= NULL; } } }}/* * Input routing */PUBLIC int ipr_get_iroute(ent_no, route_ent)int ent_no;nwio_route_t *route_ent;{ iroute_t *iroute; if (ent_no<0 || ent_no>= IROUTE_NR) return ENOENT; iroute= &iroute_table[ent_no]; route_ent->nwr_ent_no= ent_no; route_ent->nwr_ent_count= IROUTE_NR; route_ent->nwr_dest= iroute->irt_dest; route_ent->nwr_netmask= iroute->irt_subnetmask; route_ent->nwr_gateway= iroute->irt_gateway; route_ent->nwr_dist= iroute->irt_dist; route_ent->nwr_flags= NWRF_EMPTY; if (iroute->irt_flags & IRTF_INUSE) { route_ent->nwr_flags |= NWRF_INUSE; if (iroute->irt_flags & IRTF_STATIC) route_ent->nwr_flags |= NWRF_STATIC; if (iroute->irt_dist == IRTD_UNREACHABLE) route_ent->nwr_flags |= NWRF_UNREACHABLE; } route_ent->nwr_pref= 0; route_ent->nwr_mtu= iroute->irt_mtu; route_ent->nwr_ifaddr= ip_get_ifaddr(iroute->irt_port); return NW_OK;}PUBLIC int ipr_add_iroute(port_nr, dest, subnetmask, gateway, dist, mtu, static_route, iroute_p)int port_nr;ipaddr_t dest;ipaddr_t subnetmask;ipaddr_t gateway;int dist;int mtu;int static_route;iroute_t **iroute_p;{ int i; iroute_t *iroute, *unused_route; ip_port_t *ip_port; ip_port= &ip_port_table[port_nr]; /* Check gateway */ if (((gateway ^ ip_port->ip_ipaddr) & ip_port->ip_subnetmask) != 0 && gateway != 0) { DBLOCK(1, printf("ip[%d] (ipr_add_iroute): invalid gateway: ", port_nr); writeIpAddr(gateway); printf("\n")); return EINVAL; } unused_route= NULL; if (static_route) { /* Static routes are not reused automatically, so we look * for an unused entry. */ for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++) { if ((iroute->irt_flags & IRTF_INUSE) == 0) break; } if (i != IROUTE_NR) unused_route= iroute; } else { /* Try to track down any old routes, and look for an * unused one. */ for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++) { if ((iroute->irt_flags & IRTF_INUSE) == 0) { unused_route= iroute; continue; } if ((iroute->irt_flags & IRTF_STATIC) != 0) continue; if (iroute->irt_port != port_nr || iroute->irt_dest != dest || iroute->irt_subnetmask != subnetmask || iroute->irt_gateway != gateway) { continue; } break; } if (i != IROUTE_NR) unused_route= iroute; } if (unused_route == NULL) return ENOMEM; iroute= unused_route; iroute->irt_port= port_nr; iroute->irt_dest= dest; iroute->irt_subnetmask= subnetmask; iroute->irt_gateway= gateway; iroute->irt_dist= dist; iroute->irt_mtu= mtu; iroute->irt_flags= IRTF_INUSE; if (static_route) iroute->irt_flags |= IRTF_STATIC; iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask); if (iroute_p != NULL) *iroute_p= iroute; return NW_OK;}PUBLIC int ipr_del_iroute(port_nr, dest, subnetmask, gateway, static_route)int port_nr;ipaddr_t dest;ipaddr_t subnetmask;ipaddr_t gateway;int static_route;{ int i; iroute_t *iroute; /* Try to track down any old routes, and look for an * unused one. */ for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++) { if ((iroute->irt_flags & IRTF_INUSE) == 0) continue; if (iroute->irt_port != port_nr || iroute->irt_dest != dest || iroute->irt_subnetmask != subnetmask || iroute->irt_gateway != gateway) { continue; } if (!!(iroute->irt_flags & IRTF_STATIC) != static_route) continue; break; } if (i == IROUTE_NR) return ESRCH; iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask); iroute->irt_flags= IRTF_EMPTY; return NW_OK;}PUBLIC void ipr_chk_itab(port_nr, addr, mask)int port_nr;ipaddr_t addr;ipaddr_t mask;{ int i; iroute_t *iroute; DBLOCK(1, printf("ip[%d] (ipr_chk_itab): addr ", port_nr); writeIpAddr(addr); printf(" mask "); writeIpAddr(mask); printf("\n"); ); if (addr == 0) { /* Special hack to flush entries for an interface that * goes down. */ addr= mask= HTONL(0xffffffff); } for(i= 0, iroute= iroute_table; i<IROUTE_NR; i++, iroute++) { if ((iroute->irt_flags & IRTF_INUSE) == 0) continue; if (iroute->irt_port != port_nr) continue; if (iroute->irt_gateway == 0) { /* Special case: attached network. */ if (iroute->irt_subnetmask == mask && iroute->irt_dest == (addr & mask)) { /* Nothing changed. */ continue; } } if (((iroute->irt_gateway ^ addr) & mask) == 0) continue; DBLOCK(1, printf("ip[%d] (ipr_chk_itab): deleting route to ", port_nr); writeIpAddr(iroute->irt_dest); printf(" gw "); writeIpAddr(iroute->irt_gateway); printf("\n")); iroute_uncache_nw(iroute->irt_dest, iroute->irt_subnetmask); iroute->irt_flags &= ~IRTF_INUSE; }}PRIVATE void iroute_uncache_nw(dest, netmask)ipaddr_t dest;ipaddr_t netmask;{ int i, j; iroute_hash_t *iroute_hash; for (i= 0, iroute_hash= &iroute_hash_table[0][0]; i<IROUTE_HASH_NR; i++, iroute_hash += IROUTE_HASH_ASS_NR) { for (j= 0; j<IROUTE_HASH_ASS_NR; j++) { if (((iroute_hash[j].irh_addr ^ dest) & netmask) == 0) { iroute_hash[j].irh_addr= 0; iroute_hash[j].irh_route= NULL; } } }}/* * $PchId: ipr.c,v 1.23 2003/01/22 11:49:58 philip Exp $ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -