static char sccsid
[] = "@(#)routed.c 4.15 82/06/09";
* Routing Table Management Daemon
/* casts to keep lint happy */
#define insque(q,p) _insque((caddr_t)q,(caddr_t)p)
#define remque(q) _remque((caddr_t)q)
(bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0)
#define min(a,b) ((a)>(b)?(b):(a))
struct sockaddr_in routingaddr
= { AF_INET
, IPPORT_ROUTESERVER
};
struct sockaddr_in noroutingaddr
= { AF_INET
, IPPORT_ROUTESERVER
+1 };
int snoroute
; /* socket with no routing */
int supplier
= -1; /* process should supply updates */
int install
= 1; /* if 1 call kernel */
int timeval
= -TIMER_RATE
;
#define tprintf if (trace) printf
char packet
[MAXPACKETSIZE
+1];
struct rip
*msg
= (struct rip
*)packet
;
struct in_addr
if_makeaddr();
struct ifnet
*if_ifwithaddr(), *if_ifwithnet();
extern int errno
, exit();
for (cc
= 0; cc
< 10; cc
++)
{ int t
= open("/dev/tty", 2);
ioctl(t
, TIOCNOTTY
, (char *)0);
ftrace
= fopen("/etc/routerlog", "w");
routingaddr
.sin_port
= htons(routingaddr
.sin_port
);
noroutingaddr
.sin_port
= htons(noroutingaddr
.sin_port
);
s
= socket(SOCK_DGRAM
, 0, &routingaddr
, 0);
snoroute
= socket(SOCK_DGRAM
, 0, &noroutingaddr
, SO_DONTROUTE
);
while (argc
> 0 && **argv
== '-') {
if (!strcmp(*argv
, "-s") == 0) {
if (!strcmp(*argv
, "-q") == 0) {
fprintf(stderr
, "usage: routed [ -s ]\n");
msg
->rip_cmd
= RIPCMD_REQUEST
;
msg
->rip_nets
[0].rip_dst
.sa_family
= AF_UNSPEC
;
msg
->rip_nets
[0].rip_metric
= HOPCNT_INFINITY
;
cc
= receive(s
, &from
, packet
, sizeof (packet
));
if (cc
< 0 && errno
!= EINTR
)
register struct rthash
*rh
;
for (rh
= nethash
; rh
< &nethash
[ROUTEHASHSIZ
]; rh
++)
rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
for (rh
= hosthash
; rh
< &hosthash
[ROUTEHASHSIZ
]; rh
++)
rh
->rt_forw
= rh
->rt_back
= (struct rt_entry
*)rh
;
struct ifnet
*ifp
, *next
;
int uniquemultihostinterfaces
= 0;
if (nl
[N_IFNET
].n_value
== 0) {
printf("ifnet: not in namelist\n");
kmem
= open("/dev/kmem", 0);
if (lseek(kmem
, (long)nl
[N_IFNET
].n_value
, 0) == -1 ||
read(kmem
, (char *)&next
, sizeof (next
)) != sizeof (next
)) {
printf("ifnet: error reading kmem\n");
ifp
= (struct ifnet
*)malloc(sizeof (struct ifnet
));
printf("routed: out of memory\n");
if (lseek(kmem
, (long)next
, 0) == -1 ||
read(kmem
, (char *)ifp
, sizeof (*ifp
)) != sizeof (*ifp
)) {
if (ifp
->if_addr
.sa_family
!= AF_INET
)
if (ifp
->if_net
== LOOPBACKNET
)
if ((ifp
->if_flags
& IFF_POINTOPOINT
) == 0 ||
if_ifwithaddr(&ifp
->if_dstaddr
) == 0)
uniquemultihostinterfaces
++;
if (uniquemultihostinterfaces
> 1 && supplier
< 0)
execv("/etc/routed", argv0
);
if (ifp
->if_flags
& IFF_POINTOPOINT
)
bzero((char *)&net
, sizeof (net
));
net
.sin_family
= AF_INET
;
net
.sin_addr
= if_makeaddr(ifp
->if_net
, INADDR_ANY
);
dst
= (struct sockaddr
*)&net
;
rtadd(dst
, &ifp
->if_addr
, 0, RTS_DONTDELETE
|RTS_DONTROUTE
);
struct sockaddr_in dst
, gate
;
fp
= fopen("/etc/gateways", "r");
bzero((char *)&dst
, sizeof (dst
));
bzero((char *)&gate
, sizeof (gate
));
dst
.sin_family
= AF_INET
;
gate
.sin_family
= AF_INET
;
/* format is: dst XX gateway XX [passive]\n */
if (fscanf(fp
, "dst %x gateway %x %s\n", &dst
.sin_addr
.s_addr
,
&gate
.sin_addr
.s_addr
, buf
) == EOF
)
rtadd((struct sockaddr
*)&dst
, (struct sockaddr
*)&gate
, 1,
strcmp(buf
, "passive") == 0 ? RTS_PASSIVE
: RTS_DONTDELETE
);
register struct rthash
*rh
;
register struct rt_entry
*rt
;
struct rthash
*base
= hosthash
;
int doinghost
= 1, state
;
tprintf(">>> time %d >>>\n", timeval
);
for (rh
= base
; rh
< &base
[ROUTEHASHSIZ
]; rh
++) {
for (; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
if (!(rt
->rt_state
& RTS_PASSIVE
)) {
rt
->rt_timer
+= TIMER_RATE
;
if (rt
->rt_state
& RTS_HIDDEN
)
if (rt
->rt_timer
>= EXPIRE_TIME
)
rt
->rt_metric
= HOPCNT_INFINITY
;
if ((rt
->rt_state
& RTS_DELRT
) ||
rt
->rt_timer
>= GARBAGE_TIME
) {
if (rt
->rt_state
& RTS_ADDRT
) {
if (ioctl(s
, SIOCADDRT
,(char *)&rt
->rt_rt
) < 0)
rt
->rt_state
&= ~RTS_ADDRT
;
if (rt
->rt_state
& RTS_CHGRT
) {
oldroute
.rt_gateway
= rt
->rt_oldrouter
;
ioctl(s
, SIOCADDRT
,(char *)&rt
->rt_rt
) < 0)
ioctl(s
, SIOCDELRT
, (char *)&oldroute
) < 0)
rt
->rt_state
&= ~RTS_CHGRT
;
if (supplier
&& (state
& (RTS_CHGRT
|RTS_ADDRT
))) {
msg
->rip_cmd
= RIPCMD_RESPONSE
;
msg
->rip_nets
[0].rip_dst
= rt
->rt_dst
;
msg
->rip_nets
[0].rip_metric
=
min(rt
->rt_metric
+1, HOPCNT_INFINITY
);
if (supplier
&& (timeval
% SUPPLY_INTERVAL
) == 0)
tprintf("<<< time %d <<<\n", timeval
);
register struct rthash
*rh
;
register struct rt_entry
*rt
;
register struct sockaddr
*dst
;
struct rthash
*base
= hosthash
;
for (rh
= base
; rh
< &base
[ROUTEHASHSIZ
]; rh
++)
for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
if ((rt
->rt_state
& RTS_PASSIVE
) || rt
->rt_metric
> 0)
if (rt
->rt_ifp
&& (rt
->rt_ifp
->if_flags
& IFF_BROADCAST
))
dst
= &rt
->rt_ifp
->if_broadaddr
;
(*f
)(dst
, rt
->rt_state
& RTS_DONTROUTE
);
(*afswitch
[dst
->sa_family
].af_output
)(s
, dst
, sizeof (struct rip
));
register struct rt_entry
*rt
;
struct netinfo
*n
= msg
->rip_nets
;
register struct rthash
*rh
;
struct rthash
*base
= hosthash
;
int (*output
)() = afswitch
[dst
->sa_family
].af_output
;
int sto
= dontroute
? snoroute
: s
;
for (rh
= base
; rh
< &base
[ROUTEHASHSIZ
]; rh
++)
for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
if (rt
->rt_state
& RTS_HIDDEN
)
size
= (char *)n
- packet
;
if (size
> MAXPACKETSIZE
- sizeof (struct netinfo
)) {
(*output
)(sto
, dst
, size
);
n
->rip_metric
= min(rt
->rt_metric
+ 1, HOPCNT_INFINITY
);
(*output
)(sto
, dst
, (char *)n
- packet
);
* Handle an incoming routing packet.
if (msg
->rip_cmd
< RIPCMD_MAX
)
printf("%s from %x\n", ripcmds
[msg
->rip_cmd
],
((struct sockaddr_in
*)from
)->sin_addr
);
printf("%x from %x\n", msg
->rip_cmd
,
((struct sockaddr_in
*)from
)->sin_addr
);
if (from
->sa_family
>= AF_MAX
)
afp
= &afswitch
[from
->sa_family
];
size
-= 4 * sizeof (char);
if (size
< sizeof (struct netinfo
))
size
-= sizeof (struct netinfo
);
* A single entry with sa_family == AF_UNSPEC and
* metric ``infinity'' means ``all routes''.
if (n
->rip_dst
.sa_family
== AF_UNSPEC
&&
n
->rip_metric
== HOPCNT_INFINITY
&& size
== 0) {
supply(from
, 0); /* don't route */
rt
= rtlookup(&n
->rip_dst
);
n
->rip_metric
= rt
== 0 ? HOPCNT_INFINITY
:
min(rt
->rt_metric
+1, HOPCNT_INFINITY
);
n
++, newsize
+= sizeof (struct netinfo
);
msg
->rip_cmd
= RIPCMD_RESPONSE
;
(*afp
->af_output
)(s
, from
, newsize
);
if ((*afp
->af_portcheck
)(from
) == 0)
ftrace
= fopen(msg
->rip_tracefile
, "a");
(void) dup2(fileno(ftrace
), 1);
(void) dup2(fileno(ftrace
), 2);
printf("*** Tracing turned on at %.24s ***\n", ctime(&t
));
/* verify message came from a priviledged port */
if ((*afp
->af_portcheck
)(from
) == 0)
printf("*** Tracing turned off at %.24s ***\n", ctime(&t
));
fflush(stdout
), fflush(stderr
);
(void) close(1), (void) close(2);
/* verify message came from a router */
if ((*afp
->af_portmatch
)(from
) == 0)
/* are we talking to ourselves? */
ifp
= if_ifwithaddr(from
);
/* interface previously thought down? */
struct rt_entry
*downrt
= rtfind(from
, 1);
/* unhide old route and delete other */
downrt
->rt_state
&= ~RTS_HIDDEN
;
downrt
->rt_state
|= RTS_ADDRT
;
rt
->rt_state
|= RTS_DELRT
;
size
-= 4 * sizeof (char);
for (; size
> 0; size
-= sizeof (struct netinfo
), n
++) {
if (size
< sizeof (struct netinfo
))
if (n
->rip_metric
>= HOPCNT_INFINITY
)
tprintf("dst %x hc %d...",
((struct sockaddr_in
*)&n
->rip_dst
)->sin_addr
,
rt
= rtlookup(&n
->rip_dst
);
rtadd(&n
->rip_dst
, from
, n
->rip_metric
, 0);
tprintf("ours: gate %x hc %d timer %d\n",
((struct sockaddr_in
*)&rt
->rt_router
)->sin_addr
,
rt
->rt_metric
, rt
->rt_timer
);
* update if from gateway, shorter, or getting
if (equal(from
, &rt
->rt_router
) ||
n
->rip_metric
< rt
->rt_metric
||
(rt
->rt_timer
> (EXPIRE_TIME
/2) &&
rt
->rt_metric
== n
->rip_metric
)) {
rtchange(rt
, from
, n
->rip_metric
);
printf("bad packet, cmd=%x\n", msg
->rip_cmd
);
register struct rt_entry
*rt
;
register struct rthash
*rh
;
if (dst
->sa_family
>= AF_MAX
)
(*afswitch
[dst
->sa_family
].af_hash
)(dst
, &h
);
rh
= &hosthash
[hash
% ROUTEHASHSIZ
];
for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
if (rt
->rt_hash
!= hash
|| (rt
->rt_state
& RTS_HIDDEN
))
if (equal(&rt
->rt_dst
, dst
))
rh
= &nethash
[hash
% ROUTEHASHSIZ
];
rtfind(dst
, lookfordownif
)
register struct rt_entry
*rt
;
register struct rthash
*rh
;
int doinghost
= 1, (*match
)();
(*afswitch
[af
].af_hash
)(dst
, &h
);
rh
= &hosthash
[hash
% ROUTEHASHSIZ
];
for (rt
= rh
->rt_forw
; rt
!= (struct rt_entry
*)rh
; rt
= rt
->rt_forw
) {
if (lookfordownif
^ (rt
->rt_state
& RTS_HIDDEN
))
if (equal(&rt
->rt_dst
, dst
))
if (rt
->rt_dst
.sa_family
== af
&&
(*match
)(&rt
->rt_dst
, dst
))
rh
= &nethash
[hash
% ROUTEHASHSIZ
];
match
= afswitch
[af
].af_netmatch
;
rtadd(dst
, gate
, metric
, state
)
struct sockaddr
*dst
, *gate
;
register struct rt_entry
*rt
;
int af
= dst
->sa_family
, flags
, hash
;
(*afswitch
[af
].af_hash
)(dst
, &h
);
flags
= (*afswitch
[af
].af_checkhost
)(dst
) ? RTF_HOST
: 0;
rh
= &hosthash
[hash
% ROUTEHASHSIZ
];
rh
= &nethash
[hash
% ROUTEHASHSIZ
];
rt
= (struct rt_entry
*)malloc(sizeof (*rt
));
rt
->rt_flags
= RTF_UP
| flags
;
rt
->rt_ifp
= if_ifwithnet(&rt
->rt_router
);
rt
->rt_flags
|= RTF_GATEWAY
;
rt
->rt_state
|= RTS_ADDRT
;
rtchange(rt
, gate
, metric
)
int doioctl
= 0, metricchanged
= 0;
if (!equal(&rt
->rt_router
, gate
)) {
if (rt
->rt_state
& RTS_DONTDELETE
) {
rtadd(&rt
->rt_dst
, gate
, metric
,
rt
->rt_state
&~ (RTS_DONTDELETE
|RTS_DONTROUTE
));
rt
->rt_state
|= RTS_DELRT
;
if (metric
!= rt
->rt_metric
) {
if ((rt
->rt_state
& RTS_CHGRT
) == 0)
rt
->rt_oldrouter
= rt
->rt_router
;
rt
->rt_state
|= RTS_CHGRT
;
if (doioctl
|| metricchanged
)
if (install
&& ioctl(s
, SIOCDELRT
, (char *)&rt
->rt_rt
))
if (rt
->rt_state
& RTS_DONTDELETE
) {
rt
->rt_state
|= RTS_HIDDEN
;
struct sockaddr_in
*dst
, *gate
;
{ RTF_GATEWAY
, "GATEWAY" },
{ RTS_PASSIVE
, "PASSIVE" },
{ RTS_DONTDELETE
,"DONTDELETE" },
{ RTS_DONTROUTE
,"DONTROUTE" },
{ RTS_HIDDEN
, "HIDDEN" },
printf("%s ", operation
);
dst
= (struct sockaddr_in
*)&rt
->rt_dst
;
gate
= (struct sockaddr_in
*)&rt
->rt_router
;
printf("dst %x, router %x", dst
->sin_addr
, gate
->sin_addr
);
if (rt
->rt_state
& RTS_CHGRT
)
((struct sockaddr_in
*)&rt
->rt_oldrouter
)->sin_addr
);
printf(", metric %d, flags", rt
->rt_metric
);
for (first
= 1, p
= flagbits
; p
->t_bits
> 0; p
++) {
if ((rt
->rt_flags
& p
->t_bits
) == 0)
for (first
= 1, p
= statebits
; p
->t_bits
> 0; p
++) {
if ((rt
->rt_state
& p
->t_bits
) == 0)
register struct ifnet
*ifp
;
(bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0)
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
) {
if (ifp
->if_addr
.sa_family
!= addr
->sa_family
)
if (same(&ifp
->if_addr
, addr
))
if ((ifp
->if_flags
& IFF_BROADCAST
) &&
same(&ifp
->if_broadaddr
, addr
))
register struct sockaddr
*addr
;
register struct ifnet
*ifp
;
register int af
= addr
->sa_family
;
register int (*netmatch
)();
netmatch
= afswitch
[af
].af_netmatch
;
for (ifp
= ifnet
; ifp
; ifp
= ifp
->if_next
) {
if (af
!= ifp
->if_addr
.sa_family
)
if ((*netmatch
)(addr
, &ifp
->if_addr
))
addr
= (net
<< 24) | host
;
addr
= (net
<< 16) | host
;
addr
= (net
<< 8) | host
;
return (*(struct in_addr
*)&addr
);