* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)input.c 5.1 (Berkeley) %G%";
* Routing Table Management Daemon
* Process a newly received packet.
register struct rt_entry
*rt
;
register struct netinfo
*n
;
register struct interface
*ifp
;
struct interface
*if_ifwithdstaddr();
register struct afswitch
*afp
;
TRACE_INPUT(ifp
, from
, size
);
if (from
->sa_family
>= AF_MAX
)
afp
= &afswitch
[from
->sa_family
];
size
-= 4 * sizeof (char);
if (size
< sizeof (struct netinfo
))
size
-= sizeof (struct netinfo
);
ntohs(n
->rip_dst
.sa_family
);
n
->rip_metric
= ntohl(n
->rip_metric
);
* 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) {
rt
= rtlookup(&n
->rip_dst
);
n
->rip_metric
= rt
== 0 ? HOPCNT_INFINITY
:
min(rt
->rt_metric
+1, HOPCNT_INFINITY
);
htons(n
->rip_dst
.sa_family
);
n
->rip_metric
= htonl(n
->rip_metric
);
n
++, newsize
+= sizeof (struct netinfo
);
msg
->rip_cmd
= RIPCMD_RESPONSE
;
(*afp
->af_output
)(s
, 0, from
, newsize
);
/* verify message came from a privileged port */
if ((*afp
->af_portcheck
)(from
) == 0)
if (msg
->rip_cmd
== RIPCMD_TRACEON
)
traceon(msg
->rip_tracefile
);
/* verify message came from a router */
if ((*afp
->af_portmatch
)(from
) == 0)
/* are we talking to ourselves? */
ifp
= if_ifwithaddr(from
);
if (rt
== 0 || (rt
->rt_state
& RTS_INTERFACE
) == 0)
* Update timer for interface on which the packet arrived.
* If from other end of a point-to-point link that isn't
* in the routing tables, (re-)add the route.
if ((rt
= rtfind(from
)) && (rt
->rt_state
& RTS_INTERFACE
))
else if (ifp
= if_ifwithdstaddr(from
))
size
-= 4 * sizeof (char);
for (; size
> 0; size
-= sizeof (struct netinfo
), n
++) {
if (size
< sizeof (struct netinfo
))
ntohs(n
->rip_dst
.sa_family
);
n
->rip_metric
= ntohl(n
->rip_metric
);
if ((unsigned) n
->rip_metric
> HOPCNT_INFINITY
)
if (n
->rip_dst
.sa_family
>= AF_MAX
)
afp
= &afswitch
[n
->rip_dst
.sa_family
];
if (((*afp
->af_checkhost
)(&n
->rip_dst
)) == 0)
rt
= rtlookup(&n
->rip_dst
);
if (n
->rip_metric
< HOPCNT_INFINITY
)
rtadd(&n
->rip_dst
, from
, n
->rip_metric
, 0);
* Update if from gateway and different,
* shorter, or getting stale and equivalent.
if (equal(from
, &rt
->rt_router
)) {
if (n
->rip_metric
== HOPCNT_INFINITY
) {
if (n
->rip_metric
!= rt
->rt_metric
)
rtchange(rt
, from
, n
->rip_metric
);
} else if ((unsigned) (n
->rip_metric
) < rt
->rt_metric
||
(rt
->rt_timer
> (EXPIRE_TIME
/2) &&
rt
->rt_metric
== n
->rip_metric
)) {
rtchange(rt
, from
, n
->rip_metric
);