1*25202Skarels /* 2*25202Skarels $Log: rdp_input.c,v $ 3*25202Skarels * Revision 2.10 85/06/18 14:37:38 walsh 4*25202Skarels * check for version mismatch. 5*25202Skarels * 6*25202Skarels * Revision 2.9 85/04/08 14:35:11 root 7*25202Skarels * *** empty log message *** 8*25202Skarels * 9*25202Skarels * Revision 2.8 85/02/26 08:26:48 walsh 10*25202Skarels * First pass at using IP source routing information to establish connections 11*25202Skarels * (possibly with hosts not known by the Internet gateways.) The hooks with 12*25202Skarels * TCP could be better done - particularly dealing with IP addresses in the 13*25202Skarels * header for checksums and tcpdb lookups. 14*25202Skarels * 15*25202Skarels * Revision 2.7 84/11/15 09:55:52 walsh 16*25202Skarels * redid how we deal with compiler padding in the RDP header structure. 17*25202Skarels * 18*25202Skarels * Revision 2.6 84/11/08 16:11:17 walsh 19*25202Skarels * Added code to gather statistics on RDP traffic. This makes the RDPCB 20*25202Skarels * too big unles you make mbufs 512 bytes large. RDP_CS should be turned off 21*25202Skarels * unless you do. 22*25202Skarels * 23*25202Skarels * Revision 2.5 84/11/06 14:30:09 walsh 24*25202Skarels * intorduced RDP_HLSHIFT 25*25202Skarels * 26*25202Skarels * Revision 2.4 84/11/05 16:33:07 walsh 27*25202Skarels * fix coding error. 28*25202Skarels * 29*25202Skarels * Revision 2.3 84/11/05 10:51:53 walsh 30*25202Skarels * flush debugging log if new state is RDP_sCLOSED so that packet printer/ 31*25202Skarels * system analyst sees final transitions. 32*25202Skarels * 33*25202Skarels * Revision 2.2 84/11/02 15:28:19 walsh 34*25202Skarels * Allow for RDP header fields not on natural boundries. (Protocol 35*25202Skarels * specifiers say will be part of next version in 6-12 months). 36*25202Skarels * Until then, there goes the speed... Yucho modifications. 37*25202Skarels * 38*25202Skarels * Revision 2.1 84/11/02 10:12:58 walsh 39*25202Skarels * Fixed to include RCS comments in checked out source. 40*25202Skarels * 41*25202Skarels * 42*25202Skarels * description: 43*25202Skarels * Packet input processing for Reliable Datagram Protocol. 44*25202Skarels * 45*25202Skarels * revision 1.6 46*25202Skarels * date: 84/07/19 10:21:22; author: walsh; state: Exp; lines added/del: 2/1 47*25202Skarels * Organized macros and classified their definitions in rdp_macros.h. 48*25202Skarels * 49*25202Skarels * revision 1.5 50*25202Skarels * date: 84/07/10 09:59:38; author: walsh; state: Exp; lines added/del: 10/10 51*25202Skarels * declared some register variables. 52*25202Skarels * 53*25202Skarels * revision 1.4 54*25202Skarels * date: 84/07/06 14:43:19; author: wjacobso; state: Exp; lines added/del: 2/2 55*25202Skarels * *** empty log message *** 56*25202Skarels * 57*25202Skarels * revision 1.3 58*25202Skarels * date: 84/07/06 13:50:26; author: wjacobso; state: Exp; lines added/del: 6/3 59*25202Skarels * use RDP_ACTION macro instead of rdp_action 60*25202Skarels * 61*25202Skarels * revision 1.2 62*25202Skarels * date: 84/07/06 09:49:20; author: root; state: Exp; lines added/del: 27/45 63*25202Skarels * This version seems to run bug-free. 64*25202Skarels * 65*25202Skarels * revision 1.1 66*25202Skarels * date: 84/06/26 14:17:19; author: walsh; state: Exp; 67*25202Skarels * Initial revision 68*25202Skarels */ 69*25202Skarels 70*25202Skarels 71*25202Skarels #ifdef RDP 72*25202Skarels #ifdef RCSIDENT 73*25202Skarels static char rcsident[] = "$Header: rdp_input.c,v 2.10 85/06/18 14:37:38 walsh Exp $"; 74*25202Skarels #endif 75*25202Skarels 76*25202Skarels #include "../h/param.h" 77*25202Skarels #include "../h/dir.h" 78*25202Skarels #include "../h/user.h" 79*25202Skarels #include "../h/kernel.h" 80*25202Skarels #include "../h/inode.h" 81*25202Skarels #include "../h/mbuf.h" 82*25202Skarels #include "../h/socket.h" 83*25202Skarels #include "../h/socketvar.h" 84*25202Skarels #include "../h/syslog.h" 85*25202Skarels 86*25202Skarels #include "../net/if.h" 87*25202Skarels #include "../net/route.h" 88*25202Skarels 89*25202Skarels #include "../bbnnet/in.h" 90*25202Skarels #include "../bbnnet/in_var.h" 91*25202Skarels #include "../bbnnet/net.h" 92*25202Skarels #include "../bbnnet/in_pcb.h" 93*25202Skarels #include "../bbnnet/ip.h" 94*25202Skarels #include "../bbnnet/nopcb.h" 95*25202Skarels #include "../bbnnet/rdp.h" 96*25202Skarels #include "../bbnnet/rdp_macros.h" 97*25202Skarels #ifdef HMP 98*25202Skarels #include "../bbnnet/hmp_traps.h" 99*25202Skarels #endif 100*25202Skarels 101*25202Skarels extern int nosum; 102*25202Skarels 103*25202Skarels /* 104*25202Skarels * this is called from ip_input() upon reception of an RDP packet. 105*25202Skarels */ 106*25202Skarels rdp_input(mp) 107*25202Skarels register struct mbuf *mp; 108*25202Skarels { 109*25202Skarels register RDPHDR *pkt; 110*25202Skarels register struct ip *ip; 111*25202Skarels rdpchecksum pktcksum; 112*25202Skarels rdpchecksum cksum; 113*25202Skarels register int hlen; 114*25202Skarels register struct inpcb *inp; 115*25202Skarels 116*25202Skarels rdpstat.r_total++; 117*25202Skarels 118*25202Skarels /* 119*25202Skarels * see ip_input(). Get access to constant part of RDP header. 120*25202Skarels */ 121*25202Skarels #define SZ (RDPHDRSZ + sizeof(struct ip)) 122*25202Skarels if ((mp->m_off > MMAXOFF) || (mp->m_len < SZ)) 123*25202Skarels { 124*25202Skarels if ((mp = m_pullup(mp, SZ)) == NULL) 125*25202Skarels { 126*25202Skarels rdpstat.r_tooshort ++; 127*25202Skarels return; 128*25202Skarels } 129*25202Skarels } 130*25202Skarels #undef SZ 131*25202Skarels 132*25202Skarels ip = mtod(mp, struct ip *); 133*25202Skarels pkt = (RDPHDR *) (ip + 1); 134*25202Skarels 135*25202Skarels /* make sure header, incl. option region, does not overflow mbuf */ 136*25202Skarels 137*25202Skarels hlen = hdrlen(pkt) + sizeof(struct ip); 138*25202Skarels if (hlen > mp->m_len) 139*25202Skarels { 140*25202Skarels if ((mp = m_pullup(mp, hlen)) == NULL) 141*25202Skarels { 142*25202Skarels ip_log(ip, "rdp header overflow"); 143*25202Skarels #ifdef HMPTRAPS 144*25202Skarels /* hmp_trap(T_TCP_OVFLO, (caddr_t)0,0); */ 145*25202Skarels #else 146*25202Skarels /* netlog(mp); */ 147*25202Skarels #endif 148*25202Skarels return; 149*25202Skarels } 150*25202Skarels ip = mtod(mp, struct ip *); 151*25202Skarels pkt = (RDPHDR *) (ip + 1); 152*25202Skarels } 153*25202Skarels 154*25202Skarels if (pkt->rh_ver != RDP_VERSION) 155*25202Skarels { 156*25202Skarels ip_log (ip, "rdp version mismatch"); 157*25202Skarels netlog (mp); 158*25202Skarels return; 159*25202Skarels } 160*25202Skarels 161*25202Skarels /* 162*25202Skarels * do checksum calculation, drop packet if bad 163*25202Skarels * Checksum must be done on header in net form due to byte ordering 164*25202Skarels * and rotations. 165*25202Skarels */ 166*25202Skarels 167*25202Skarels pktcksum = RDP_CKSUM(pkt); 168*25202Skarels RDP_CKSUM(pkt) = 0; 169*25202Skarels cksum = rdp_cksum(mp); 170*25202Skarels if (cksum != pktcksum) 171*25202Skarels { 172*25202Skarels rdpstat.r_badsum++; 173*25202Skarels if (! nosum) 174*25202Skarels { 175*25202Skarels inet_cksum_err ("rdp", ip, (u_long) pktcksum, (u_long) cksum); 176*25202Skarels netlog(mp); 177*25202Skarels return; 178*25202Skarels } 179*25202Skarels } 180*25202Skarels 181*25202Skarels /* byte swap header */ 182*25202Skarels 183*25202Skarels pkt->rh_dlen = ntohs(pkt->rh_dlen); 184*25202Skarels RDP_SEQNO(pkt) = ntohl(RDP_SEQNO(pkt)); 185*25202Skarels RDP_ACKNO(pkt) = ntohl(RDP_ACKNO(pkt)); 186*25202Skarels 187*25202Skarels if (ip->ip_len != hdrlen(pkt) + pkt->rh_dlen) 188*25202Skarels { 189*25202Skarels ip_log(ip, "rdp length error"); 190*25202Skarels log(KERN_RECOV, "%d + %d != %d\n", hdrlen(pkt), pkt->rh_dlen, 191*25202Skarels ip->ip_len); 192*25202Skarels netlog(mp); 193*25202Skarels return; 194*25202Skarels } 195*25202Skarels 196*25202Skarels inp = in_pcblookup(&rdp, ip->ip_src.s_addr, (u_short)pkt->rh_sport, 197*25202Skarels ip->ip_dst.s_addr, (u_short)pkt->rh_dport, TRUE); 198*25202Skarels if (inp == NULL) 199*25202Skarels { 200*25202Skarels /* nobody wants it */ 201*25202Skarels rdpstat.r_drops ++; 202*25202Skarels rdp_uncon_rst (pkt); 203*25202Skarels } 204*25202Skarels else 205*25202Skarels { 206*25202Skarels register rdpstate newstate; 207*25202Skarels register RDPCB *rdpcb; 208*25202Skarels 209*25202Skarels rdpcb = (RDPCB *)inp->inp_ppcb; 210*25202Skarels 211*25202Skarels #ifdef RDP_CS 212*25202Skarels rdpcb->r_rcvd.r_total ++; 213*25202Skarels if (pkt->rh_flags & (RDP_fNULL|RDP_fRST|RDP_fSYN)) 214*25202Skarels { 215*25202Skarels if (pkt->rh_flags & RDP_fNULL) 216*25202Skarels rdpcb->r_rcvd.r_nullpkts ++; 217*25202Skarels if (pkt->rh_flags & RDP_fRST) 218*25202Skarels rdpcb->r_rcvd.r_rstpkts ++; 219*25202Skarels if (pkt->rh_flags & RDP_fSYN) 220*25202Skarels rdpcb->r_rcvd.r_synpkts ++; 221*25202Skarels } 222*25202Skarels #endif 223*25202Skarels /* found a protocol control block for the message */ 224*25202Skarels RDP_ACTION(RDP_iNETR, rdpcb, ((int) pkt), newstate); 225*25202Skarels } 226*25202Skarels } 227*25202Skarels 228*25202Skarels 229*25202Skarels /* 230*25202Skarels * Call a subroutine specifically tailored to deal with this state 231*25202Skarels * transition. 232*25202Skarels */ 233*25202Skarels rdpaction (input, rdpcb, arg) 234*25202Skarels register RDPCB *rdpcb; 235*25202Skarels { 236*25202Skarels register rdpstate newstate; 237*25202Skarels 238*25202Skarels RDP_ACTION (input, rdpcb, arg, newstate) 239*25202Skarels } 240*25202Skarels 241*25202Skarels rdp_uncon_rst (pkt) 242*25202Skarels register RDPHDR *pkt; 243*25202Skarels { 244*25202Skarels register struct ip *ip; 245*25202Skarels register struct mbuf *mp; 246*25202Skarels struct in_addr tempinaddr; 247*25202Skarels rdpportnum tempport; 248*25202Skarels long his_seqno; 249*25202Skarels int error; 250*25202Skarels 251*25202Skarels mp = dtom(pkt); 252*25202Skarels 253*25202Skarels /* make sure we don't send a RST in response to an RST */ 254*25202Skarels 255*25202Skarels if (pkt->rh_flags & RDP_fRST) 256*25202Skarels { 257*25202Skarels m_freem(mp); 258*25202Skarels return; 259*25202Skarels } 260*25202Skarels ip = (struct ip *) (((caddr_t) pkt) - sizeof(struct ip)); 261*25202Skarels 262*25202Skarels /* free everything but the header */ 263*25202Skarels 264*25202Skarels m_freem(mp->m_next); 265*25202Skarels mp->m_next = NULL; 266*25202Skarels mp->m_len = sizeof(struct ip) + RDPHDRSZ; 267*25202Skarels 268*25202Skarels /* direct the packet back to the originator */ 269*25202Skarels 270*25202Skarels tempinaddr = ip->ip_dst; 271*25202Skarels ip->ip_dst = ip->ip_src; 272*25202Skarels ip->ip_src = tempinaddr; 273*25202Skarels 274*25202Skarels tempport = pkt->rh_sport; 275*25202Skarels pkt->rh_sport = pkt->rh_dport; 276*25202Skarels pkt->rh_dport = tempport; 277*25202Skarels 278*25202Skarels /* 279*25202Skarels * and initialize (seqno, ackno, flags) so that it's "in window" 280*25202Skarels * and resets him independent of his state (is acceptable to all 281*25202Skarels * net reception subroutines.) 282*25202Skarels */ 283*25202Skarels his_seqno = RDP_SEQNO(pkt); 284*25202Skarels RDP_SEQNO(pkt) = htonl(RDP_ACKNO(pkt) + 1); 285*25202Skarels RDP_ACKNO(pkt) = htonl(his_seqno); 286*25202Skarels if (pkt->rh_flags & RDP_fSYN) 287*25202Skarels pkt->rh_flags = RDP_fRST|RDP_fACK; 288*25202Skarels else 289*25202Skarels pkt->rh_flags = RDP_fRST; 290*25202Skarels 291*25202Skarels /* and send it */ 292*25202Skarels 293*25202Skarels pkt->rh_hdrlen = RDPHDRSZ >> RDP_HLSHIFT; 294*25202Skarels pkt->rh_dlen = 0; 295*25202Skarels RDP_CKSUM(pkt) = 0; 296*25202Skarels 297*25202Skarels RDP_CKSUM(pkt) = rdp_cksum(mp); 298*25202Skarels 299*25202Skarels NOPCB_IPSEND (mp, RDPHDRSZ, FALSE, error); 300*25202Skarels #ifdef lint 301*25202Skarels error = error; 302*25202Skarels #endif 303*25202Skarels } 304*25202Skarels 305*25202Skarels struct mbuf *rdpdebuf; 306*25202Skarels #ifdef RDPDEBUG 307*25202Skarels int rdprint; 308*25202Skarels #endif 309*25202Skarels 310*25202Skarels /* 311*25202Skarels * Write a record in the rdp debugging log 312*25202Skarels */ 313*25202Skarels rdp_debug(rdpcb, arg, input, newstate) 314*25202Skarels register RDPCB *rdpcb; 315*25202Skarels rdpstate newstate; 316*25202Skarels { 317*25202Skarels register struct r_debug *dp; 318*25202Skarels register struct mbuf *m; 319*25202Skarels 320*25202Skarels #ifdef RDPDEBUG 321*25202Skarels if (rdprint) 322*25202Skarels { 323*25202Skarels /* 324*25202Skarels * Print debugging info directly on the console (use this for 325*25202Skarels * intial testing only). 326*25202Skarels */ 327*25202Skarels printf("RDP(0x%x) %s X %s", rdpcb, rdpstates[rdpcb->r_state], 328*25202Skarels (input < 0 ? "send pkt" : rdpinputs[input]) ); 329*25202Skarels 330*25202Skarels if (input == RDP_iTIMER) 331*25202Skarels printf("(%s)", rdptimers[arg]); 332*25202Skarels 333*25202Skarels printf(" --> %s\n", 334*25202Skarels rdpstates[newstate==RDP_sSAME ? rdpcb->r_state : newstate]; 335*25202Skarels } 336*25202Skarels #endif 337*25202Skarels 338*25202Skarels /* 339*25202Skarels * Get an mbuf to write the debugging record into. If we don't already 340*25202Skarels * have one, allocate a new one. 341*25202Skarels */ 342*25202Skarels if ((m = rdpdebuf) == NULL) 343*25202Skarels { 344*25202Skarels register struct mbuf *c; 345*25202Skarels 346*25202Skarels if ((rdpdebuf = m = m_get(M_DONTWAIT, MT_DATA)) == NULL) 347*25202Skarels return; 348*25202Skarels /* 349*25202Skarels * If possible, use a cluster so that we need to wake up the 350*25202Skarels * raw listener less often and reduce likelihood he misses 351*25202Skarels * some information. 352*25202Skarels */ 353*25202Skarels MCLGET(c, 1); 354*25202Skarels if (c) 355*25202Skarels { 356*25202Skarels m->m_off = ((int) c) - ((int) m); 357*25202Skarels m->m_act = (struct mbuf *) RCDBLEN; 358*25202Skarels } 359*25202Skarels else 360*25202Skarels m->m_act = (struct mbuf *) RDBLEN; 361*25202Skarels m->m_len = 0; 362*25202Skarels } 363*25202Skarels 364*25202Skarels dp = (R_DEBUG *) (mtod(m, char *) + m->m_len); 365*25202Skarels /* 366*25202Skarels * Set up the debugging record. 367*25202Skarels */ 368*25202Skarels dp->rd_iptime = iptime(); 369*25202Skarels dp->rd_input = input; 370*25202Skarels dp->rd_newstate = newstate; 371*25202Skarels dp->rd_rdpcb = (*rdpcb); /* structure copy */ 372*25202Skarels 373*25202Skarels /* 374*25202Skarels * input == RDP_iNETR incoming packet 375*25202Skarels * == -1 monitor outgoing packet. Not a true 376*25202Skarels * transition CAUSING event, but useful. 377*25202Skarels */ 378*25202Skarels if ((input == RDP_iNETR) || (input < 0)) 379*25202Skarels { 380*25202Skarels register struct ip *ip; 381*25202Skarels register RDPHDR *pkt; 382*25202Skarels 383*25202Skarels ip = (struct ip *) arg; 384*25202Skarels pkt = (RDPHDR *) (ip + 1); 385*25202Skarels dp->rd_iphdr = (*ip); /* structure copy */ 386*25202Skarels dp->rd_rdphdr = (*pkt); /* structure copy */ 387*25202Skarels } 388*25202Skarels else if (input == RDP_iTIMER) 389*25202Skarels dp->rd_timer = arg; 390*25202Skarels 391*25202Skarels /* 392*25202Skarels * If the mbuf is full, dispatch it to a raw listener. 393*25202Skarels * Also for transition to closed state so oberver sees all and 394*25202Skarels * can debug stuff more easily. 395*25202Skarels */ 396*25202Skarels m->m_len += sizeof(struct r_debug); 397*25202Skarels if ((m->m_len >= ((int) m->m_act)) || (newstate == RDP_sCLOSED)) 398*25202Skarels { 399*25202Skarels m->m_act = 0; 400*25202Skarels rdpdebuglog(m); 401*25202Skarels rdpdebuf = NULL; 402*25202Skarels } 403*25202Skarels } 404*25202Skarels #endif 405