📄 ipr.c
字号:
/*
ipr.c
*/
#include "inet.h"
#include "clock.h"
#include "assert.h"
#include "io.h"
#include "ipr.h"
INIT_PANIC();
#define ROUTE_NR 32
#define DIST_UNREACHABLE 512
PRIVATE route_t route_table[ROUTE_NR];
PRIVATE int fixed_routes;
FORWARD route_t *get_route_ent ARGS(( ipaddr_t dest ));
PUBLIC void ipr_init()
{
int i;
route_t *route_ind;
for (i= 0, route_ind= route_table; i<ROUTE_NR; i++, route_ind++)
route_ind->rt_flags= RTF_EMPTY;
fixed_routes= 0;
}
PUBLIC int iproute_frag(dest, ttl, nexthop, port)
ipaddr_t dest;
int ttl;
ipaddr_t *nexthop;
int *port;
{
route_t *route_ent;
route_ent= get_route_ent(dest);
if (!route_ent || route_ent->rt_dist > ttl)
return EDSTNOTRCH;
*nexthop= route_ent->rt_gateway;
*port= route_ent->rt_port;
return 1;
}
PRIVATE route_t *get_route_ent(dest)
ipaddr_t dest;
{
route_t *route_ind, *route_hi;
route_t *bestroute, *sec_bestroute, tmproute;
time_t currtim;
currtim= get_time();
route_hi= &route_table[ROUTE_NR];
bestroute= 0;
for (route_ind= route_table; route_ind<route_hi; route_ind++)
{
if (!(route_ind->rt_flags & RTF_INUSE))
continue;
if (route_ind->rt_exp_tim && route_ind->rt_exp_tim<currtim)
{
route_ind->rt_flags &= ~RTF_INUSE;
continue;
}
if ((dest ^ route_ind->rt_dest) & route_ind->rt_netmask)
continue;
if (!bestroute)
{
bestroute= route_ind;
continue;
}
if (bestroute->rt_netmask != route_ind->rt_netmask)
{
if (route_ind->rt_dist > bestroute->rt_dist ||
(route_ind->rt_dist == bestroute->
rt_dist && ntohl(route_ind->rt_netmask)>
ntohl(bestroute->rt_netmask)))
bestroute= route_ind;
continue;
}
sec_bestroute= bestroute;
if (bestroute->rt_gateway == route_ind->rt_gateway)
{
if (route_ind->rt_timestamp >
bestroute->rt_timestamp)
bestroute= route_ind;
}
else
{
if (route_ind->rt_dist < bestroute->rt_dist)
bestroute= route_ind;
}
if (bestroute->rt_dist > sec_bestroute->rt_dist)
{
tmproute= *bestroute;
*bestroute= *sec_bestroute;
*sec_bestroute= tmproute;
route_ind= bestroute= sec_bestroute;
}
}
#if DEBUG & 256
{ where(); if (!bestroute){ printf("no route to "); writeIpAddr(dest);
printf("\n"); } else { printf ("route to ");
writeIpAddr(bestroute->rt_dest); printf(" via ");
writeIpAddr(bestroute->rt_gateway); printf(" at distance %d\n",
bestroute->rt_dist); } }
#endif
return bestroute;
}
PUBLIC route_t *ipr_add_route(dest, netmask, gateway, port, timeout, dist,
fixed, preference)
ipaddr_t dest;
ipaddr_t netmask;
ipaddr_t gateway;
int port;
time_t timeout;
int dist;
int fixed;
i32_t preference;
{
int i;
route_t *route_ind;
route_t *oldest_route;
time_t currtim;
#if DEBUG & 256
{ where(); printf("ipr_add_route(dest= "); writeIpAddr(dest);
printf(", netmask= "); writeIpAddr(netmask);
printf(", gateway= "); writeIpAddr(gateway);
printf(", port= %d, timeout= %ld, dist= %d, fixed= %d, pref= %d\n",
port, timeout, dist, fixed, preference); }
#endif
if (fixed)
{
if (fixed_routes >= IPR_MAX_FIXED_ROUTES)
return 0;
fixed_routes++;
}
oldest_route= 0;
currtim= get_time();
for (i= 0, route_ind= route_table; i<ROUTE_NR; i++, route_ind++)
{
if (!(route_ind->rt_flags & RTF_INUSE))
{
oldest_route= route_ind;
break;
}
if (route_ind->rt_exp_tim && route_ind->rt_exp_tim < currtim)
{
oldest_route= route_ind;
break;
}
if (route_ind->rt_dest == dest &&
route_ind->rt_netmask == netmask &&
route_ind->rt_gateway == gateway)
{
if (!fixed && (route_ind->rt_flags & RTF_FIXED))
continue;
oldest_route= route_ind;
break;
}
if (route_ind->rt_flags & RTF_FIXED)
continue;
if (!oldest_route)
{
oldest_route= route_ind;
continue;
}
if (route_ind->rt_timestamp < oldest_route->rt_timestamp)
oldest_route= route_ind;
}
assert (oldest_route);
oldest_route->rt_dest= dest;
oldest_route->rt_gateway= gateway;
oldest_route->rt_netmask= netmask;
if (timeout)
oldest_route->rt_exp_tim= currtim + timeout;
else
oldest_route->rt_exp_tim= 0;
oldest_route->rt_timestamp= currtim;
oldest_route->rt_dist= dist;
oldest_route->rt_port= port;
oldest_route->rt_flags= RTF_INUSE;
oldest_route->rt_pref= preference;
if (fixed)
oldest_route->rt_flags |= RTF_FIXED;
return oldest_route;
}
PUBLIC void ipr_gateway_down(gateway, timeout)
ipaddr_t gateway;
time_t timeout;
{
route_t *route_ind, *route;
time_t currtim;
int i;
currtim= get_time();
for (i= 0, route_ind= route_table; i<ROUTE_NR; i++, route_ind++)
{
if (!(route_ind->rt_flags & RTF_INUSE))
continue;
if (route_ind->rt_gateway != gateway)
continue;
if (route_ind->rt_exp_tim && route_ind->rt_exp_tim < currtim)
{
route_ind->rt_flags &= ~RTF_INUSE;
continue;
}
if (!(route_ind->rt_flags & RTF_FIXED))
{
route_ind->rt_timestamp= currtim;
if (timeout)
route_ind->rt_exp_tim= currtim+timeout;
else
route_ind->rt_exp_tim= 0;
route_ind->rt_dist= DIST_UNREACHABLE;
continue;
}
#if DEBUG
{ where(); printf("adding route\n"); }
#endif
route= ipr_add_route(route_ind->rt_dest, route_ind->rt_netmask,
gateway, route_ind->rt_port, timeout, DIST_UNREACHABLE,
FALSE, 0);
assert (route);
}
}
PUBLIC void ipr_destunrch(dest, netmask, timeout)
ipaddr_t dest;
ipaddr_t netmask;
time_t timeout;
{
route_t *route;
route= get_route_ent(dest);
if (!route)
{
#if DEBUG
{ where(); printf("got a dest unreachable for "); writeIpAddr(dest);
printf("but no route present\n"); }
#endif
return;
}
#if DEBUG
{ where(); printf("adding route\n"); }
#endif
route= ipr_add_route(dest, netmask, route->rt_gateway, route->rt_port,
timeout, DIST_UNREACHABLE, FALSE, 0);
assert (route);
}
PUBLIC void ipr_redirect(dest, netmask, old_gateway, new_gateway, new_port,
timeout)
ipaddr_t dest;
ipaddr_t netmask;
ipaddr_t old_gateway;
ipaddr_t new_gateway;
int new_port;
time_t timeout;
{
route_t *route;
route= get_route_ent(dest);
if (!route)
{
#if DEBUG
{ where(); printf("got a redirect for "); writeIpAddr(dest);
printf("but no route present\n"); }
#endif
return;
}
if (route->rt_gateway != old_gateway)
{
#if DEBUG
{ where(); printf("got a redirect from "); writeIpAddr(old_gateway);
printf(" for "); writeIpAddr(dest); printf(" but curr gateway is ");
writeIpAddr(route->rt_gateway); printf("\n"); }
#endif
return;
}
if (route->rt_flags & RTF_FIXED)
{
if ( route->rt_dest == dest)
{
#if DEBUG
{ where(); printf("got a redirect for "); writeIpAddr(dest);
printf("but route is fixed\n"); }
#endif
return;
}
}
else
{
#if DEBUG
{ where(); printf("adding route\n"); }
#endif
route= ipr_add_route(dest, netmask, route->rt_gateway,
route->rt_port, timeout, DIST_UNREACHABLE, FALSE, 0);
assert(route);
}
#if DEBUG
{ where(); printf("adding route\n"); }
#endif
route= ipr_add_route(dest, netmask, new_gateway, new_port,
timeout, 1, FALSE, 0);
assert (route);
}
PUBLIC void ipr_ttl_exc(dest, netmask, timeout)
ipaddr_t dest;
ipaddr_t netmask;
time_t timeout;
{
route_t *route;
int new_dist;
route= get_route_ent(dest);
if (!route)
{
#if DEBUG
{ where(); printf("got a ttl exceeded for "); writeIpAddr(dest);
printf("but no route present\n"); }
#endif
return;
}
new_dist= route->rt_dist * 2;
if (new_dist>IP_MAX_TTL)
{
new_dist= route->rt_dist+1;
if (new_dist>IP_MAX_TTL)
{
#if DEBUG
{ where(); printf("got a ttl exceeded for "); writeIpAddr(dest);
printf(" but dist is %d\n", route->rt_dist); }
#endif
return;
}
}
#if DEBUG
{ where(); printf("adding route\n"); }
#endif
route= ipr_add_route(dest, netmask, route->rt_gateway, route->rt_port,
timeout, new_dist, FALSE, 0);
assert (route);
}
int ipr_get_route(ent_no, route_ent)
int ent_no;
nwio_route_t *route_ent;
{
route_t *route;
if (ent_no<0 || ent_no>= ROUTE_NR)
return ENOENT;
route= &route_table[ent_no];
if (route->rt_exp_tim && route->rt_exp_tim < get_time())
route->rt_flags &= ~RTF_INUSE;
route_ent->nwr_ent_count= ROUTE_NR;
route_ent->nwr_dest= route->rt_dest;
route_ent->nwr_netmask= route->rt_netmask;
route_ent->nwr_gateway= route->rt_gateway;
route_ent->nwr_dist= route->rt_dist;
route_ent->nwr_flags= NWRF_EMPTY;
if (route->rt_flags & RTF_INUSE)
{
route_ent->nwr_flags |= NWRF_INUSE;
if (route->rt_flags & RTF_FIXED)
route_ent->nwr_flags |= NWRF_FIXED;
}
route_ent->nwr_pref= route->rt_pref;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -