--- /dev/null
+#ifndef lint
+static char sccsid[] = "@(#)input.c 4.1 %G%";
+#endif
+
+/*
+ * Routing Table Management Daemon
+ */
+#include "router.h"
+
+/*
+ * Process a newly received packet.
+ */
+rip_input(from, size)
+ struct sockaddr *from;
+ int size;
+{
+ struct rt_entry *rt;
+ struct netinfo *n;
+ struct interface *ifp;
+ int newsize;
+ struct afswitch *afp;
+
+ ifp = 0;
+ TRACE_INPUT(ifp, from, size);
+ if (from->sa_family >= AF_MAX)
+ return;
+ afp = &afswitch[from->sa_family];
+ switch (msg->rip_cmd) {
+
+ case RIPCMD_REQUEST:
+ newsize = 0;
+ size -= 4 * sizeof (char);
+ n = msg->rip_nets;
+ while (size > 0) {
+ if (size < sizeof (struct netinfo))
+ break;
+ 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, ifp);
+ return;
+ }
+ rt = rtlookup(&n->rip_dst);
+ n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
+ min(rt->rt_metric+1, HOPCNT_INFINITY);
+ n++, newsize += sizeof (struct netinfo);
+ }
+ if (newsize > 0) {
+ msg->rip_cmd = RIPCMD_RESPONSE;
+ newsize += sizeof (int);
+ (*afp->af_output)(s, from, newsize);
+ }
+ return;
+
+ case RIPCMD_TRACEON:
+ case RIPCMD_TRACEOFF:
+ /* verify message came from a priviledged port */
+ if ((*afp->af_portcheck)(from) == 0)
+ return;
+ packet[size] = '\0';
+ if (msg->rip_cmd == RIPCMD_TRACEON)
+ traceon(msg->rip_tracefile);
+ else
+ traceoff();
+ return;
+
+ case RIPCMD_RESPONSE:
+ /* verify message came from a router */
+ if ((*afp->af_portmatch)(from) == 0)
+ return;
+ (*afp->af_canon)(from);
+ /* are we talking to ourselves? */
+ ifp = if_ifwithaddr(from);
+ if (ifp) {
+ rt = rtfind(from);
+ if (rt == 0)
+ addrouteforif(ifp);
+ else
+ rt->rt_timer = 0;
+ return;
+ }
+ size -= 4 * sizeof (char);
+ n = msg->rip_nets;
+ for (; size > 0; size -= sizeof (struct netinfo), n++) {
+ if (size < sizeof (struct netinfo))
+ break;
+ if (n->rip_metric >= HOPCNT_INFINITY)
+ continue;
+ rt = rtlookup(&n->rip_dst);
+ if (rt == 0) {
+ rtadd(&n->rip_dst, from, n->rip_metric, 0);
+ continue;
+ }
+
+ /*
+ * Update if from gateway, shorter, or getting
+ * stale and equivalent.
+ */
+ 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);
+ rt->rt_timer = 0;
+ }
+ }
+ return;
+ }
+}