125202Skarels /*
225202Skarels $Log: rdp_input.c,v $
325202Skarels * Revision 2.10 85/06/18 14:37:38 walsh
425202Skarels * check for version mismatch.
525202Skarels *
625202Skarels * Revision 2.9 85/04/08 14:35:11 root
725202Skarels * *** empty log message ***
825202Skarels *
925202Skarels * Revision 2.8 85/02/26 08:26:48 walsh
1025202Skarels * First pass at using IP source routing information to establish connections
1125202Skarels * (possibly with hosts not known by the Internet gateways.) The hooks with
1225202Skarels * TCP could be better done - particularly dealing with IP addresses in the
1325202Skarels * header for checksums and tcpdb lookups.
1425202Skarels *
1525202Skarels * Revision 2.7 84/11/15 09:55:52 walsh
1625202Skarels * redid how we deal with compiler padding in the RDP header structure.
1725202Skarels *
1825202Skarels * Revision 2.6 84/11/08 16:11:17 walsh
1925202Skarels * Added code to gather statistics on RDP traffic. This makes the RDPCB
2025202Skarels * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off
2125202Skarels * unless you do.
2225202Skarels *
2325202Skarels * Revision 2.5 84/11/06 14:30:09 walsh
2425202Skarels * intorduced RDP_HLSHIFT
2525202Skarels *
2625202Skarels * Revision 2.4 84/11/05 16:33:07 walsh
2725202Skarels * fix coding error.
2825202Skarels *
2925202Skarels * Revision 2.3 84/11/05 10:51:53 walsh
3025202Skarels * flush debugging log if new state is RDP_sCLOSED so that packet printer/
3125202Skarels * system analyst sees final transitions.
3225202Skarels *
3325202Skarels * Revision 2.2 84/11/02 15:28:19 walsh
3425202Skarels * Allow for RDP header fields not on natural boundries. (Protocol
3525202Skarels * specifiers say will be part of next version in 6-12 months).
3625202Skarels * Until then, there goes the speed... Yucho modifications.
3725202Skarels *
3825202Skarels * Revision 2.1 84/11/02 10:12:58 walsh
3925202Skarels * Fixed to include RCS comments in checked out source.
4025202Skarels *
4125202Skarels *
4225202Skarels * description:
4325202Skarels * Packet input processing for Reliable Datagram Protocol.
4425202Skarels *
4525202Skarels * revision 1.6
4625202Skarels * date: 84/07/19 10:21:22; author: walsh; state: Exp; lines added/del: 2/1
4725202Skarels * Organized macros and classified their definitions in rdp_macros.h.
4825202Skarels *
4925202Skarels * revision 1.5
5025202Skarels * date: 84/07/10 09:59:38; author: walsh; state: Exp; lines added/del: 10/10
5125202Skarels * declared some register variables.
5225202Skarels *
5325202Skarels * revision 1.4
5425202Skarels * date: 84/07/06 14:43:19; author: wjacobso; state: Exp; lines added/del: 2/2
5525202Skarels * *** empty log message ***
5625202Skarels *
5725202Skarels * revision 1.3
5825202Skarels * date: 84/07/06 13:50:26; author: wjacobso; state: Exp; lines added/del: 6/3
5925202Skarels * use RDP_ACTION macro instead of rdp_action
6025202Skarels *
6125202Skarels * revision 1.2
6225202Skarels * date: 84/07/06 09:49:20; author: root; state: Exp; lines added/del: 27/45
6325202Skarels * This version seems to run bug-free.
6425202Skarels *
6525202Skarels * revision 1.1
6625202Skarels * date: 84/06/26 14:17:19; author: walsh; state: Exp;
6725202Skarels * Initial revision
6825202Skarels */
6925202Skarels
7025202Skarels
7125202Skarels #ifdef RDP
7225202Skarels #ifdef RCSIDENT
7325202Skarels static char rcsident[] = "$Header: rdp_input.c,v 2.10 85/06/18 14:37:38 walsh Exp $";
7425202Skarels #endif
7525202Skarels
7625202Skarels #include "../h/param.h"
7725202Skarels #include "../h/dir.h"
7825202Skarels #include "../h/user.h"
7925202Skarels #include "../h/kernel.h"
8025202Skarels #include "../h/inode.h"
8125202Skarels #include "../h/mbuf.h"
8225202Skarels #include "../h/socket.h"
8325202Skarels #include "../h/socketvar.h"
8425202Skarels #include "../h/syslog.h"
8525202Skarels
8625202Skarels #include "../net/if.h"
8725202Skarels #include "../net/route.h"
8825202Skarels
8925202Skarels #include "../bbnnet/in.h"
9025202Skarels #include "../bbnnet/in_var.h"
9125202Skarels #include "../bbnnet/net.h"
9225202Skarels #include "../bbnnet/in_pcb.h"
9325202Skarels #include "../bbnnet/ip.h"
9425202Skarels #include "../bbnnet/nopcb.h"
9525202Skarels #include "../bbnnet/rdp.h"
9625202Skarels #include "../bbnnet/rdp_macros.h"
9725202Skarels #ifdef HMP
9825202Skarels #include "../bbnnet/hmp_traps.h"
9925202Skarels #endif
10025202Skarels
10125202Skarels extern int nosum;
10225202Skarels
10325202Skarels /*
10425202Skarels * this is called from ip_input() upon reception of an RDP packet.
10525202Skarels */
rdp_input(mp)10625202Skarels rdp_input(mp)
10725202Skarels register struct mbuf *mp;
10825202Skarels {
10925202Skarels register RDPHDR *pkt;
11025202Skarels register struct ip *ip;
11125202Skarels rdpchecksum pktcksum;
11225202Skarels rdpchecksum cksum;
11325202Skarels register int hlen;
11425202Skarels register struct inpcb *inp;
11525202Skarels
11625202Skarels rdpstat.r_total++;
11725202Skarels
11825202Skarels /*
11925202Skarels * see ip_input(). Get access to constant part of RDP header.
12025202Skarels */
12125202Skarels #define SZ (RDPHDRSZ + sizeof(struct ip))
12225202Skarels if ((mp->m_off > MMAXOFF) || (mp->m_len < SZ))
12325202Skarels {
12425202Skarels if ((mp = m_pullup(mp, SZ)) == NULL)
12525202Skarels {
12625202Skarels rdpstat.r_tooshort ++;
12725202Skarels return;
12825202Skarels }
12925202Skarels }
13025202Skarels #undef SZ
13125202Skarels
13225202Skarels ip = mtod(mp, struct ip *);
13325202Skarels pkt = (RDPHDR *) (ip + 1);
13425202Skarels
13525202Skarels /* make sure header, incl. option region, does not overflow mbuf */
13625202Skarels
13725202Skarels hlen = hdrlen(pkt) + sizeof(struct ip);
13825202Skarels if (hlen > mp->m_len)
13925202Skarels {
14025202Skarels if ((mp = m_pullup(mp, hlen)) == NULL)
14125202Skarels {
14225202Skarels ip_log(ip, "rdp header overflow");
14325202Skarels #ifdef HMPTRAPS
14425202Skarels /* hmp_trap(T_TCP_OVFLO, (caddr_t)0,0); */
14525202Skarels #else
14625202Skarels /* netlog(mp); */
14725202Skarels #endif
14825202Skarels return;
14925202Skarels }
15025202Skarels ip = mtod(mp, struct ip *);
15125202Skarels pkt = (RDPHDR *) (ip + 1);
15225202Skarels }
15325202Skarels
15425202Skarels if (pkt->rh_ver != RDP_VERSION)
15525202Skarels {
15625202Skarels ip_log (ip, "rdp version mismatch");
15725202Skarels netlog (mp);
15825202Skarels return;
15925202Skarels }
16025202Skarels
16125202Skarels /*
16225202Skarels * do checksum calculation, drop packet if bad
16325202Skarels * Checksum must be done on header in net form due to byte ordering
16425202Skarels * and rotations.
16525202Skarels */
16625202Skarels
16725202Skarels pktcksum = RDP_CKSUM(pkt);
16825202Skarels RDP_CKSUM(pkt) = 0;
16925202Skarels cksum = rdp_cksum(mp);
17025202Skarels if (cksum != pktcksum)
17125202Skarels {
17225202Skarels rdpstat.r_badsum++;
17325202Skarels if (! nosum)
17425202Skarels {
17525202Skarels inet_cksum_err ("rdp", ip, (u_long) pktcksum, (u_long) cksum);
17625202Skarels netlog(mp);
17725202Skarels return;
17825202Skarels }
17925202Skarels }
18025202Skarels
18125202Skarels /* byte swap header */
18225202Skarels
18325202Skarels pkt->rh_dlen = ntohs(pkt->rh_dlen);
18425202Skarels RDP_SEQNO(pkt) = ntohl(RDP_SEQNO(pkt));
18525202Skarels RDP_ACKNO(pkt) = ntohl(RDP_ACKNO(pkt));
18625202Skarels
18725202Skarels if (ip->ip_len != hdrlen(pkt) + pkt->rh_dlen)
18825202Skarels {
18925202Skarels ip_log(ip, "rdp length error");
190*25208Skarels log(LOG_INFO, "%d + %d != %d\n", hdrlen(pkt), pkt->rh_dlen,
19125202Skarels ip->ip_len);
19225202Skarels netlog(mp);
19325202Skarels return;
19425202Skarels }
19525202Skarels
19625202Skarels inp = in_pcblookup(&rdp, ip->ip_src.s_addr, (u_short)pkt->rh_sport,
19725202Skarels ip->ip_dst.s_addr, (u_short)pkt->rh_dport, TRUE);
19825202Skarels if (inp == NULL)
19925202Skarels {
20025202Skarels /* nobody wants it */
20125202Skarels rdpstat.r_drops ++;
20225202Skarels rdp_uncon_rst (pkt);
20325202Skarels }
20425202Skarels else
20525202Skarels {
20625202Skarels register rdpstate newstate;
20725202Skarels register RDPCB *rdpcb;
20825202Skarels
20925202Skarels rdpcb = (RDPCB *)inp->inp_ppcb;
21025202Skarels
21125202Skarels #ifdef RDP_CS
21225202Skarels rdpcb->r_rcvd.r_total ++;
21325202Skarels if (pkt->rh_flags & (RDP_fNULL|RDP_fRST|RDP_fSYN))
21425202Skarels {
21525202Skarels if (pkt->rh_flags & RDP_fNULL)
21625202Skarels rdpcb->r_rcvd.r_nullpkts ++;
21725202Skarels if (pkt->rh_flags & RDP_fRST)
21825202Skarels rdpcb->r_rcvd.r_rstpkts ++;
21925202Skarels if (pkt->rh_flags & RDP_fSYN)
22025202Skarels rdpcb->r_rcvd.r_synpkts ++;
22125202Skarels }
22225202Skarels #endif
22325202Skarels /* found a protocol control block for the message */
22425202Skarels RDP_ACTION(RDP_iNETR, rdpcb, ((int) pkt), newstate);
22525202Skarels }
22625202Skarels }
22725202Skarels
22825202Skarels
22925202Skarels /*
23025202Skarels * Call a subroutine specifically tailored to deal with this state
23125202Skarels * transition.
23225202Skarels */
rdpaction(input,rdpcb,arg)23325202Skarels rdpaction (input, rdpcb, arg)
23425202Skarels register RDPCB *rdpcb;
23525202Skarels {
23625202Skarels register rdpstate newstate;
23725202Skarels
23825202Skarels RDP_ACTION (input, rdpcb, arg, newstate)
23925202Skarels }
24025202Skarels
rdp_uncon_rst(pkt)24125202Skarels rdp_uncon_rst (pkt)
24225202Skarels register RDPHDR *pkt;
24325202Skarels {
24425202Skarels register struct ip *ip;
24525202Skarels register struct mbuf *mp;
24625202Skarels struct in_addr tempinaddr;
24725202Skarels rdpportnum tempport;
24825202Skarels long his_seqno;
24925202Skarels int error;
25025202Skarels
25125202Skarels mp = dtom(pkt);
25225202Skarels
25325202Skarels /* make sure we don't send a RST in response to an RST */
25425202Skarels
25525202Skarels if (pkt->rh_flags & RDP_fRST)
25625202Skarels {
25725202Skarels m_freem(mp);
25825202Skarels return;
25925202Skarels }
26025202Skarels ip = (struct ip *) (((caddr_t) pkt) - sizeof(struct ip));
26125202Skarels
26225202Skarels /* free everything but the header */
26325202Skarels
26425202Skarels m_freem(mp->m_next);
26525202Skarels mp->m_next = NULL;
26625202Skarels mp->m_len = sizeof(struct ip) + RDPHDRSZ;
26725202Skarels
26825202Skarels /* direct the packet back to the originator */
26925202Skarels
27025202Skarels tempinaddr = ip->ip_dst;
27125202Skarels ip->ip_dst = ip->ip_src;
27225202Skarels ip->ip_src = tempinaddr;
27325202Skarels
27425202Skarels tempport = pkt->rh_sport;
27525202Skarels pkt->rh_sport = pkt->rh_dport;
27625202Skarels pkt->rh_dport = tempport;
27725202Skarels
27825202Skarels /*
27925202Skarels * and initialize (seqno, ackno, flags) so that it's "in window"
28025202Skarels * and resets him independent of his state (is acceptable to all
28125202Skarels * net reception subroutines.)
28225202Skarels */
28325202Skarels his_seqno = RDP_SEQNO(pkt);
28425202Skarels RDP_SEQNO(pkt) = htonl(RDP_ACKNO(pkt) + 1);
28525202Skarels RDP_ACKNO(pkt) = htonl(his_seqno);
28625202Skarels if (pkt->rh_flags & RDP_fSYN)
28725202Skarels pkt->rh_flags = RDP_fRST|RDP_fACK;
28825202Skarels else
28925202Skarels pkt->rh_flags = RDP_fRST;
29025202Skarels
29125202Skarels /* and send it */
29225202Skarels
29325202Skarels pkt->rh_hdrlen = RDPHDRSZ >> RDP_HLSHIFT;
29425202Skarels pkt->rh_dlen = 0;
29525202Skarels RDP_CKSUM(pkt) = 0;
29625202Skarels
29725202Skarels RDP_CKSUM(pkt) = rdp_cksum(mp);
29825202Skarels
29925202Skarels NOPCB_IPSEND (mp, RDPHDRSZ, FALSE, error);
30025202Skarels #ifdef lint
30125202Skarels error = error;
30225202Skarels #endif
30325202Skarels }
30425202Skarels
30525202Skarels struct mbuf *rdpdebuf;
30625202Skarels #ifdef RDPDEBUG
30725202Skarels int rdprint;
30825202Skarels #endif
30925202Skarels
31025202Skarels /*
31125202Skarels * Write a record in the rdp debugging log
31225202Skarels */
rdp_debug(rdpcb,arg,input,newstate)31325202Skarels rdp_debug(rdpcb, arg, input, newstate)
31425202Skarels register RDPCB *rdpcb;
31525202Skarels rdpstate newstate;
31625202Skarels {
31725202Skarels register struct r_debug *dp;
31825202Skarels register struct mbuf *m;
31925202Skarels
32025202Skarels #ifdef RDPDEBUG
32125202Skarels if (rdprint)
32225202Skarels {
32325202Skarels /*
32425202Skarels * Print debugging info directly on the console (use this for
32525202Skarels * intial testing only).
32625202Skarels */
32725202Skarels printf("RDP(0x%x) %s X %s", rdpcb, rdpstates[rdpcb->r_state],
32825202Skarels (input < 0 ? "send pkt" : rdpinputs[input]) );
32925202Skarels
33025202Skarels if (input == RDP_iTIMER)
33125202Skarels printf("(%s)", rdptimers[arg]);
33225202Skarels
33325202Skarels printf(" --> %s\n",
33425202Skarels rdpstates[newstate==RDP_sSAME ? rdpcb->r_state : newstate];
33525202Skarels }
33625202Skarels #endif
33725202Skarels
33825202Skarels /*
33925202Skarels * Get an mbuf to write the debugging record into. If we don't already
34025202Skarels * have one, allocate a new one.
34125202Skarels */
34225202Skarels if ((m = rdpdebuf) == NULL)
34325202Skarels {
34425202Skarels register struct mbuf *c;
34525202Skarels
34625202Skarels if ((rdpdebuf = m = m_get(M_DONTWAIT, MT_DATA)) == NULL)
34725202Skarels return;
34825202Skarels /*
34925202Skarels * If possible, use a cluster so that we need to wake up the
35025202Skarels * raw listener less often and reduce likelihood he misses
35125202Skarels * some information.
35225202Skarels */
35325202Skarels MCLGET(c, 1);
35425202Skarels if (c)
35525202Skarels {
35625202Skarels m->m_off = ((int) c) - ((int) m);
35725202Skarels m->m_act = (struct mbuf *) RCDBLEN;
35825202Skarels }
35925202Skarels else
36025202Skarels m->m_act = (struct mbuf *) RDBLEN;
36125202Skarels m->m_len = 0;
36225202Skarels }
36325202Skarels
36425202Skarels dp = (R_DEBUG *) (mtod(m, char *) + m->m_len);
36525202Skarels /*
36625202Skarels * Set up the debugging record.
36725202Skarels */
36825202Skarels dp->rd_iptime = iptime();
36925202Skarels dp->rd_input = input;
37025202Skarels dp->rd_newstate = newstate;
37125202Skarels dp->rd_rdpcb = (*rdpcb); /* structure copy */
37225202Skarels
37325202Skarels /*
37425202Skarels * input == RDP_iNETR incoming packet
37525202Skarels * == -1 monitor outgoing packet. Not a true
37625202Skarels * transition CAUSING event, but useful.
37725202Skarels */
37825202Skarels if ((input == RDP_iNETR) || (input < 0))
37925202Skarels {
38025202Skarels register struct ip *ip;
38125202Skarels register RDPHDR *pkt;
38225202Skarels
38325202Skarels ip = (struct ip *) arg;
38425202Skarels pkt = (RDPHDR *) (ip + 1);
38525202Skarels dp->rd_iphdr = (*ip); /* structure copy */
38625202Skarels dp->rd_rdphdr = (*pkt); /* structure copy */
38725202Skarels }
38825202Skarels else if (input == RDP_iTIMER)
38925202Skarels dp->rd_timer = arg;
39025202Skarels
39125202Skarels /*
39225202Skarels * If the mbuf is full, dispatch it to a raw listener.
39325202Skarels * Also for transition to closed state so oberver sees all and
39425202Skarels * can debug stuff more easily.
39525202Skarels */
39625202Skarels m->m_len += sizeof(struct r_debug);
39725202Skarels if ((m->m_len >= ((int) m->m_act)) || (newstate == RDP_sCLOSED))
39825202Skarels {
39925202Skarels m->m_act = 0;
40025202Skarels rdpdebuglog(m);
40125202Skarels rdpdebuf = NULL;
40225202Skarels }
40325202Skarels }
40425202Skarels #endif
405