124328Ssklower /*
2*61474Sbostic * Copyright (c) 1985, 1993
3*61474Sbostic * The Regents of the University of California. All rights reserved.
424328Ssklower *
535551Sbostic * This file includes significant work done at Cornell University by
635551Sbostic * Bill Nesheim. That work included by permission.
735551Sbostic *
842698Sbostic * %sccs.include.redist.c%
924328Ssklower */
1024328Ssklower
1124307Ssklower #ifndef lint
12*61474Sbostic static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 06/05/93";
1335551Sbostic #endif /* not lint */
1424307Ssklower
1524307Ssklower /*
1624307Ssklower * XNS Routing Table Management Daemon
1724307Ssklower */
1824307Ssklower #include "defs.h"
1924307Ssklower
2024307Ssklower struct sockaddr *
xns_nettosa(net)2124307Ssklower xns_nettosa(net)
2226170Ssklower union ns_net net;
2324307Ssklower {
2424317Ssklower static struct sockaddr_ns sxn;
2524317Ssklower extern char ether_broadcast_addr[6];
2624307Ssklower
2724317Ssklower bzero(&sxn, sizeof (struct sockaddr_ns));
2824317Ssklower sxn.sns_family = AF_NS;
2938687Ssklower sxn.sns_len = sizeof (sxn);
3026170Ssklower sxn.sns_addr.x_net = net;
3124317Ssklower sxn.sns_addr.x_host = *(union ns_host *)ether_broadcast_addr;
3224307Ssklower return( (struct sockaddr *)&sxn);
3324307Ssklower
3424307Ssklower }
3524307Ssklower
3624307Ssklower /*
3724307Ssklower * Process a newly received packet.
3824307Ssklower */
3924307Ssklower rip_input(from, size)
4024307Ssklower struct sockaddr *from;
4124307Ssklower int size;
4224307Ssklower {
4324307Ssklower struct rt_entry *rt;
4424307Ssklower struct netinfo *n;
4524307Ssklower struct interface *ifp;
4624307Ssklower int newsize;
4724307Ssklower struct afswitch *afp;
4824307Ssklower
4924307Ssklower
5024317Ssklower ifp = 0;
5124307Ssklower TRACE_INPUT(ifp, from, size);
5224307Ssklower if (from->sa_family >= AF_MAX)
5324307Ssklower return;
5424307Ssklower afp = &afswitch[from->sa_family];
5524307Ssklower
5624307Ssklower size -= sizeof (u_short) /* command */;
5724307Ssklower n = msg->rip_nets;
5824307Ssklower
5924307Ssklower switch (ntohs(msg->rip_cmd)) {
6024307Ssklower
6124307Ssklower case RIPCMD_REQUEST:
6224307Ssklower newsize = 0;
6324307Ssklower while (size > 0) {
6424307Ssklower if (size < sizeof (struct netinfo))
6524307Ssklower break;
6624307Ssklower size -= sizeof (struct netinfo);
6724307Ssklower
6824307Ssklower /*
6924307Ssklower * A single entry with rip_dst == DSTNETS_ALL and
7024307Ssklower * metric ``infinity'' means ``all routes''.
7124307Ssklower */
7226170Ssklower if (ns_neteqnn(n->rip_dst, ns_anynet) &&
7324317Ssklower ntohs(n->rip_metric) == HOPCNT_INFINITY &&
7424317Ssklower size == 0) {
7524317Ssklower ifp = if_ifwithnet(from);
7624317Ssklower supply(from, 0, ifp);
7724307Ssklower return;
7824307Ssklower }
7924307Ssklower /*
8024307Ssklower * request for specific nets
8124307Ssklower */
8224307Ssklower rt = rtlookup(xns_nettosa(n->rip_dst));
8324875Ssklower if (ftrace) {
8424328Ssklower fprintf(ftrace,
8526170Ssklower "specific request for %s",
8626170Ssklower xns_nettoa(n->rip_dst));
8724328Ssklower fprintf(ftrace,
8826170Ssklower " yields route %x\n",
8924328Ssklower rt);
9024328Ssklower }
9124307Ssklower n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
9224307Ssklower min(rt->rt_metric+1, HOPCNT_INFINITY));
9326170Ssklower n++;
9426170Ssklower newsize += sizeof (struct netinfo);
9524307Ssklower }
9624307Ssklower if (newsize > 0) {
9724307Ssklower msg->rip_cmd = htons(RIPCMD_RESPONSE);
9824307Ssklower newsize += sizeof (u_short);
9924307Ssklower /* should check for if with dstaddr(from) first */
10024875Ssklower (*afp->af_output)(0, from, newsize);
10126170Ssklower ifp = if_ifwithnet(from);
10226170Ssklower TRACE_OUTPUT(ifp, from, newsize);
10324875Ssklower if (ftrace) {
10424328Ssklower fprintf(ftrace,
10526170Ssklower "request arrived on interface %s\n",
10626170Ssklower ifp->int_name);
10724328Ssklower }
10824307Ssklower }
10924307Ssklower return;
11024307Ssklower
11124307Ssklower case RIPCMD_RESPONSE:
11224307Ssklower /* verify message came from a router */
11324307Ssklower if ((*afp->af_portmatch)(from) == 0)
11424307Ssklower return;
11524317Ssklower (*afp->af_canon)(from);
11624317Ssklower /* are we talking to ourselves? */
11724317Ssklower if (ifp = if_ifwithaddr(from)) {
11824317Ssklower rt = rtfind(from);
11924317Ssklower if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
12024317Ssklower addrouteforif(ifp);
12124317Ssklower else
12224317Ssklower rt->rt_timer = 0;
12324317Ssklower return;
12424317Ssklower }
12524328Ssklower /* Update timer for interface on which the packet arrived.
12624328Ssklower * If from other end of a point-to-point link that isn't
12724328Ssklower * in the routing tables, (re-)add the route.
12824328Ssklower */
12924328Ssklower if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
13024875Ssklower if(ftrace) fprintf(ftrace, "Got route\n");
13124307Ssklower rt->rt_timer = 0;
13224328Ssklower } else if (ifp = if_ifwithdstaddr(from)) {
13324875Ssklower if(ftrace) fprintf(ftrace, "Got partner\n");
13424328Ssklower addrouteforif(ifp);
13524328Ssklower }
13624307Ssklower for (; size > 0; size -= sizeof (struct netinfo), n++) {
13724328Ssklower struct sockaddr *sa;
13824307Ssklower if (size < sizeof (struct netinfo))
13924307Ssklower break;
14025507Ssklower if ((unsigned) ntohs(n->rip_metric) >= HOPCNT_INFINITY)
14124307Ssklower continue;
14224328Ssklower rt = rtfind(sa = xns_nettosa(n->rip_dst));
14324307Ssklower if (rt == 0) {
14424328Ssklower rtadd(sa, from, ntohs(n->rip_metric), 0);
14524307Ssklower continue;
14624307Ssklower }
14724307Ssklower
14824307Ssklower /*
14924307Ssklower * Update if from gateway and different,
15024307Ssklower * from anywhere and shorter, or getting stale and equivalent.
15124307Ssklower */
15224307Ssklower if ((equal(from, &rt->rt_router) &&
15324307Ssklower ntohs(n->rip_metric) != rt->rt_metric ) ||
15424307Ssklower (unsigned) ntohs(n->rip_metric) < rt->rt_metric ||
15524307Ssklower (rt->rt_timer > (EXPIRE_TIME/2) &&
15624307Ssklower rt->rt_metric == ntohs(n->rip_metric))) {
15724307Ssklower rtchange(rt, from, ntohs(n->rip_metric));
15824307Ssklower rt->rt_timer = 0;
15924307Ssklower }
16024307Ssklower }
16124307Ssklower return;
16224307Ssklower }
16324307Ssklower }
164