1*25202Skarels #ifdef RCSIDENT 2*25202Skarels static char rcsident[] = "$Header: ip_input.c,v 1.39 85/07/31 09:31:26 walsh Exp $"; 3*25202Skarels #endif 4*25202Skarels 5*25202Skarels #include "../h/param.h" 6*25202Skarels #include "../h/mbuf.h" 7*25202Skarels #include "../h/socket.h" 8*25202Skarels #include "../h/socketvar.h" 9*25202Skarels #include "../h/errno.h" 10*25202Skarels #include "../h/protosw.h" 11*25202Skarels #include "../h/domain.h" 12*25202Skarels #include "../h/syslog.h" 13*25202Skarels 14*25202Skarels #include "../net/if.h" 15*25202Skarels #include "../net/route.h" 16*25202Skarels #include "../net/raw_cb.h" 17*25202Skarels 18*25202Skarels #include "../bbnnet/in.h" 19*25202Skarels #include "../bbnnet/net.h" 20*25202Skarels #include "../bbnnet/in_pcb.h" 21*25202Skarels #include "../bbnnet/in_var.h" 22*25202Skarels #include "../bbnnet/ip.h" 23*25202Skarels #include "../bbnnet/icmp.h" 24*25202Skarels #ifdef HMP 25*25202Skarels #include "../bbnnet/hmp_traps.h" 26*25202Skarels #endif 27*25202Skarels 28*25202Skarels #ifdef RCSIDENT 29*25202Skarels static char rcsiphdr[] = RCSIPHDR; 30*25202Skarels #endif 31*25202Skarels 32*25202Skarels #define rawreaders(r) ((r)->rcb_next != (r)) 33*25202Skarels #define any_rawreaders() rawreaders(&rawcb) 34*25202Skarels 35*25202Skarels #define FIELD_OFF(fld, type) (((char *) (&(((type *) 0)->fld))) - ((char *) 0)) 36*25202Skarels 37*25202Skarels struct in_stat otherstat; 38*25202Skarels struct ip_stat ipstat; 39*25202Skarels struct { 40*25202Skarels struct ipq *n_ip_head; /* -> top of ip reass. queue */ 41*25202Skarels struct ipq *n_ip_tail; /* -> end of ip reass. queue */ 42*25202Skarels } ipfrags; 43*25202Skarels 44*25202Skarels 45*25202Skarels /* 46*25202Skarels * The protocol layers above IP assume the IP header and the protocol 47*25202Skarels * header are contiguous. However, need to save the options in case 48*25202Skarels * a connection oriented protocol (RDP/TCP) wants to respond to an 49*25202Skarels * incoming packet (SYN) over the same route if the packet got here 50*25202Skarels * using IP source routing. This allows connection establishment and 51*25202Skarels * maintenance when the remote end is on a network that is not known 52*25202Skarels * to our gateways. Only applicable options are Loose/Strict source 53*25202Skarels * routing, so rather than saving them in ip_stripopt() and reinterpreting 54*25202Skarels * them, we'll set up something specific and appropriate here. 55*25202Skarels */ 56*25202Skarels 57*25202Skarels int nosum = 0; 58*25202Skarels int ip_nhops = 0; 59*25202Skarels struct in_addr ip_hops[MAX_IPOPTLEN / sizeof(struct in_addr)]; 60*25202Skarels 61*25202Skarels /* use a dispatch table for protocol dispatching */ 62*25202Skarels struct ipswitch ipsw[IPPROTO_MAX]; 63*25202Skarels 64*25202Skarels extern struct ip *ip_reass(); 65*25202Skarels 66*25202Skarels 67*25202Skarels ip_init() 68*25202Skarels { 69*25202Skarels register struct protosw *pr; 70*25202Skarels register int i; 71*25202Skarels 72*25202Skarels pr = pffindproto(PF_INET, IPPROTO_IP, SOCK_RAW); 73*25202Skarels 74*25202Skarels /* build our internal switch table */ 75*25202Skarels for(i=0; i < IPPROTO_MAX; i++) 76*25202Skarels { 77*25202Skarels ipsw[i].ipsw_raw = pr; 78*25202Skarels ipsw[i].ipsw_user = 0; 79*25202Skarels ipsw[i].ipsw_hlen = sizeof(struct ip); 80*25202Skarels } 81*25202Skarels 82*25202Skarels for(pr = inetdomain.dom_protosw; pr < inetdomain.dom_protoswNPROTOSW; pr++) 83*25202Skarels { 84*25202Skarels if (pr->pr_protocol >= IPPROTO_MAX) 85*25202Skarels panic("ip_init"); 86*25202Skarels 87*25202Skarels if (pr->pr_type == SOCK_RAW) 88*25202Skarels ipsw[pr->pr_protocol].ipsw_raw = pr; 89*25202Skarels else 90*25202Skarels ipsw[pr->pr_protocol].ipsw_user = pr; 91*25202Skarels } 92*25202Skarels 93*25202Skarels ipintrq.ifq_maxlen = IFQ_MAXLEN; /* got a better number? */ 94*25202Skarels } 95*25202Skarels 96*25202Skarels /* 97*25202Skarels * Being global might be a little gross, but we just got the interface pointer 98*25202Skarels * passed up the week before 4.3 release. 99*25202Skarels */ 100*25202Skarels struct ifnet *inetifp; 101*25202Skarels 102*25202Skarels /* 103*25202Skarels * IP network software interrupt service routine. Dequeue a message from the 104*25202Skarels * ip input queue, and pass to internal ip input processor (ip_input). 105*25202Skarels */ 106*25202Skarels ipintr() 107*25202Skarels { 108*25202Skarels extern char *panicstr; 109*25202Skarels register struct mbuf *m; 110*25202Skarels register int s; 111*25202Skarels 112*25202Skarels /* 113*25202Skarels * Half-hearted attempt to prevent recursive panics due to network 114*25202Skarels * bugs since panic calls boot, which lowers spl. Note that the 115*25202Skarels * drivers will still store packets in mbufs and that some processing 116*25202Skarels * (ARP, Chaosnet) that occurs at splimp() will still proceed. At 117*25202Skarels * least this should preserve state information for post-mortem. 118*25202Skarels */ 119*25202Skarels if (panicstr == NULL) 120*25202Skarels { 121*25202Skarels for (;;) 122*25202Skarels { 123*25202Skarels /* for 4.3, Berkeley finally changed imp code to queue up messages 124*25202Skarels * for ctlinput path, so don't need to check for them here with our 125*25202Skarels * old queueing mechanism 126*25202Skarels */ 127*25202Skarels 128*25202Skarels s = splimp(); 129*25202Skarels IF_DEQUEUEIF (&ipintrq, m, inetifp); 130*25202Skarels splx(s); 131*25202Skarels if (m == NULL) 132*25202Skarels return; 133*25202Skarels 134*25202Skarels ip_input(m); 135*25202Skarels } 136*25202Skarels } 137*25202Skarels } 138*25202Skarels 139*25202Skarels /* 140*25202Skarels * IP level input routine 141*25202Skarels * 142*25202Skarels * Called from local net level upon recpt of an internet datagram or fragment. 143*25202Skarels * This routine does fragment reassembly, if necessary, and passes completed 144*25202Skarels * datagrams to higher level protocol processing routines on the basis of the 145*25202Skarels * ip header protocol field. It is passed a pointer to an mbuf chain 146*25202Skarels * containing the datagram/fragment. The mbuf offset+length are set to point 147*25202Skarels * at the ip header. 148*25202Skarels */ 149*25202Skarels ip_input(mp) 150*25202Skarels register struct mbuf *mp; 151*25202Skarels { 152*25202Skarels register struct ip *ip; 153*25202Skarels register int hlen; 154*25202Skarels register int i; 155*25202Skarels register struct mbuf *m; 156*25202Skarels register struct ipq *fp; 157*25202Skarels int fragsize = 0; 158*25202Skarels struct in_ifaddr *ia; 159*25202Skarels int j; 160*25202Skarels struct inpcb fwdinp; 161*25202Skarels 162*25202Skarels ipstat.ip_total ++; 163*25202Skarels /* 164*25202Skarels * make sure dtom() macro works by getting header out of mbufs using 165*25202Skarels * pages, also make sure header contiguous in first mbuf. 166*25202Skarels */ 167*25202Skarels if ((mp->m_off > MMAXOFF) || (mp->m_len < sizeof(struct ip))) 168*25202Skarels { 169*25202Skarels /* 170*25202Skarels * Might as well avoid doing m_pullup twice. 171*25202Skarels * Common case is using cluster for large chunk of data. 172*25202Skarels */ 173*25202Skarels if (mp->m_len < FIELD_OFF(ip_p, struct ip) + sizeof(ip->ip_p)) 174*25202Skarels i = sizeof(struct ip); 175*25202Skarels else 176*25202Skarels { 177*25202Skarels ip = mtod(mp, struct ip *); 178*25202Skarels i = ipsw[ip->ip_p].ipsw_hlen; 179*25202Skarels } 180*25202Skarels 181*25202Skarels if ((mp = m_pullup(mp, i)) == NULL) 182*25202Skarels { 183*25202Skarels ipstat.ip_tooshort ++; 184*25202Skarels return; 185*25202Skarels } 186*25202Skarels } 187*25202Skarels 188*25202Skarels ip = mtod(mp, struct ip *); 189*25202Skarels 190*25202Skarels /* 191*25202Skarels * make sure header does not overflow mbuf (is contiguous) 192*25202Skarels */ 193*25202Skarels hlen = ip->ip_hl << IP_HLSHIFT; 194*25202Skarels if (hlen > mp->m_len) 195*25202Skarels { 196*25202Skarels if ((mp = m_pullup(mp, hlen)) == NULL) 197*25202Skarels { 198*25202Skarels ip_log(ip, "ip header overflow"); 199*25202Skarels #ifdef HMPTRAPS 200*25202Skarels /* hmp_trap(T_IP_OVFLO, (caddr_t)0,0); */ 201*25202Skarels #else 202*25202Skarels /* netlog(mp); no longer have mbuf list */ 203*25202Skarels #endif 204*25202Skarels return; 205*25202Skarels } 206*25202Skarels ip = mtod(mp, struct ip *); 207*25202Skarels } 208*25202Skarels 209*25202Skarels /* 210*25202Skarels * Adjust msg length to remove any driver padding. Make sure that 211*25202Skarels * message length matches ip length. 212*25202Skarels */ 213*25202Skarels for (i = 0, m = mp; m->m_next != NULL; m = m->m_next) 214*25202Skarels i += m->m_len; 215*25202Skarels i -= ntohs((u_short)ip->ip_len) - m->m_len; 216*25202Skarels if (i != 0) 217*25202Skarels { 218*25202Skarels if (i > (int)m->m_len) 219*25202Skarels m_adj(mp, -i); 220*25202Skarels else if (i < 0) 221*25202Skarels { 222*25202Skarels ip_log(ip, "truncated ip packet"); 223*25202Skarels #ifdef HMPTRAPS 224*25202Skarels /* hmp_trap(T_IP_TRUNC, (caddr_t)0, 0); */ 225*25202Skarels #else 226*25202Skarels netlog(mp); 227*25202Skarels #endif 228*25202Skarels return; 229*25202Skarels } 230*25202Skarels else 231*25202Skarels m->m_len -= i; 232*25202Skarels } 233*25202Skarels 234*25202Skarels i = (u_short)ip->ip_sum; 235*25202Skarels ip->ip_sum = 0; 236*25202Skarels 237*25202Skarels /* used to do inline cksum here via sed */ 238*25202Skarels if (i != (j = (u_short)in_cksum(dtom(ip), hlen))) 239*25202Skarels { 240*25202Skarels ipstat.ip_badsum++; 241*25202Skarels if (!nosum) 242*25202Skarels { 243*25202Skarels #ifdef HMPTRAPS 244*25202Skarels /* hmp_trap(T_IP_CKSUM, (caddr_t)0,0); */ 245*25202Skarels #endif 246*25202Skarels inet_cksum_err ("ip", ip, (u_long) i, (u_long) j); 247*25202Skarels 248*25202Skarels ip->ip_sum = i; 249*25202Skarels ic_errmsg (icmp_addr(ip), ip->ip_src, 250*25202Skarels ICMP_PARM, 0, FIELD_OFF(ip_sum, struct ip), 251*25202Skarels hlen + ICMP_ERRLEN, (char *) ip); 252*25202Skarels 253*25202Skarels netlog(mp); 254*25202Skarels return; 255*25202Skarels } 256*25202Skarels } 257*25202Skarels 258*25202Skarels /* 259*25202Skarels * Make sure this packet is addressed to us before we put fields 260*25202Skarels * in host order and do reassembly (fragments may reach destination 261*25202Skarels * by separate routes.) 262*25202Skarels * Remember that IP source routing option can change ip_dst, so have 263*25202Skarels * to do option processing for all incoming packets with options. 264*25202Skarels * Even if the packet turns out to be for us and we strip them. 265*25202Skarels */ 266*25202Skarels fwdinp.inp_route.ro_rt = NULL; /* in case fwd, but no options */ 267*25202Skarels ip_nhops = 0; /* for source routed TCP/RDP... connections */ 268*25202Skarels if (hlen > sizeof(struct ip)) 269*25202Skarels /* 270*25202Skarels * Any route allocated by ip_opt() 1. will be used by 271*25202Skarels * ip_forward(), and 2. will only be needed by ip_forward() 272*25202Skarels */ 273*25202Skarels if (! ip_opt (ip, hlen, &fwdinp)) 274*25202Skarels { 275*25202Skarels ip_log (ip, "ip option error"); 276*25202Skarels netlog (mp); 277*25202Skarels return; 278*25202Skarels } 279*25202Skarels 280*25202Skarels /* 281*25202Skarels * if packet is not for us then forward 282*25202Skarels */ 283*25202Skarels if ((ia = in_iawithaddr(ip->ip_dst, TRUE)) == NULL) 284*25202Skarels { 285*25202Skarels ip_forward (&fwdinp, ip, mp, hlen); 286*25202Skarels return; 287*25202Skarels } 288*25202Skarels 289*25202Skarels ip->ip_len = ntohs((u_short)ip->ip_len); 290*25202Skarels if ((int)(ip->ip_len -= hlen) < 0) 291*25202Skarels { /* length of data */ 292*25202Skarels ip_log(ip, "ip header length error"); 293*25202Skarels #ifdef HMPTRAPS 294*25202Skarels /* hmp_trap(T_IP_HLEN, (caddr_t)0,0); */ 295*25202Skarels #else 296*25202Skarels netlog(mp); 297*25202Skarels #endif 298*25202Skarels return; 299*25202Skarels } 300*25202Skarels ip->ip_off = ntohs((u_short)ip->ip_off); 301*25202Skarels ip->ip_mff = ((ip->ip_off & ip_mf) ? TRUE : FALSE); 302*25202Skarels ip->ip_off <<= IP_OFFSHIFT; 303*25202Skarels 304*25202Skarels /* look for chain on reassembly queue with this header */ 305*25202Skarels 306*25202Skarels for (fp = ipfrags.n_ip_head; (fp != NULL && ( 307*25202Skarels ip->ip_src.s_addr != fp->iqh.ip_src.s_addr || 308*25202Skarels ip->ip_dst.s_addr != fp->iqh.ip_dst.s_addr || 309*25202Skarels ip->ip_id != fp->iqh.ip_id || 310*25202Skarels ip->ip_p != fp->iqh.ip_p)); fp = fp->iq_next); 311*25202Skarels 312*25202Skarels if (!ip->ip_mff && ip->ip_off == 0) 313*25202Skarels { /* not fragmented */ 314*25202Skarels 315*25202Skarels if (fp != NULL) 316*25202Skarels { /* free existing reass chain */ 317*25202Skarels struct ip *q; 318*25202Skarels struct ip *p; 319*25202Skarels 320*25202Skarels q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */ 321*25202Skarels while (q != (struct ip *)fp) 322*25202Skarels { 323*25202Skarels p = q->ip_next; 324*25202Skarels m_freem(dtom(q)); 325*25202Skarels q = p; 326*25202Skarels } 327*25202Skarels ip_freef(fp); /* free header */ 328*25202Skarels } 329*25202Skarels 330*25202Skarels /* 331*25202Skarels * The options aren't of any use to higher level 332*25202Skarels * protocols or of any concern to the user process. 333*25202Skarels */ 334*25202Skarels if (hlen > sizeof(struct ip)) 335*25202Skarels ip_stripopt (ip, hlen); 336*25202Skarels 337*25202Skarels } 338*25202Skarels else 339*25202Skarels { 340*25202Skarels ip = ip_reass(ip, fp, &fragsize); 341*25202Skarels if (ip == NULL) 342*25202Skarels return; 343*25202Skarels mp = dtom(ip); 344*25202Skarels } 345*25202Skarels 346*25202Skarels /* call next level with completed datagram */ 347*25202Skarels 348*25202Skarels /* any raw readers?? */ 349*25202Skarels /* if (rawreaders((struct rawcb *)ipsw[ip->ip_p].ipsw_raw->pr_ppcbq)) */ 350*25202Skarels if (any_rawreaders()) 351*25202Skarels { 352*25202Skarels otherstat.in_total++; 353*25202Skarels if (m = m_copy(mp, 0, M_COPYALL)) 354*25202Skarels ipsw[ip->ip_p].ipsw_raw->pr_input(m); 355*25202Skarels } 356*25202Skarels 357*25202Skarels if (ip->ip_p == IPPROTO_TCP) 358*25202Skarels /* wish I didn't need this special case for fragsize */ 359*25202Skarels tcp_input(mp, fragsize); 360*25202Skarels else if (ipsw[ip->ip_p].ipsw_user != 0) 361*25202Skarels /* There's a protocol implementation for these packets */ 362*25202Skarels ipsw[ip->ip_p].ipsw_user->pr_input(mp); 363*25202Skarels else if (ip->ip_p == IPPROTO_ICMP) 364*25202Skarels /* 365*25202Skarels * Since don't want user to get a non-raw ICMP socket, did not make 366*25202Skarels * an entry in the protocol jump table; also wanted to be able to 367*25202Skarels * make raw ICMP socket. 368*25202Skarels */ 369*25202Skarels icmp (mp); 370*25202Skarels else 371*25202Skarels { 372*25202Skarels /* 373*25202Skarels * Don't bother everyone on the net, and remember some other 374*25202Skarels * host may support the protocol. 375*25202Skarels */ 376*25202Skarels if ((!in_broadcast(ip->ip_src)) && (!in_broadcast(ip->ip_dst))) 377*25202Skarels ic_errmsg (icmp_addr(ip), ip->ip_src, 378*25202Skarels ICMP_UNRCH, ICMP_UNRCH_PR, FIELD_OFF(ip_p, struct ip), 379*25202Skarels sizeof(struct ip) + ICMP_ERRLEN, (char *) ip); 380*25202Skarels 381*25202Skarels /* get rid of the packet */ 382*25202Skarels ipstat.ip_drops++; 383*25202Skarels m_freem(mp); 384*25202Skarels } 385*25202Skarels } 386*25202Skarels 387*25202Skarels 388*25202Skarels /* 389*25202Skarels * We've received an IP fragment. Try to perform IP reassembly. 390*25202Skarels */ 391*25202Skarels struct ip *ip_reass(ip, fp, fragsize) 392*25202Skarels register struct ip *ip; 393*25202Skarels register struct ipq *fp; 394*25202Skarels int *fragsize; 395*25202Skarels { 396*25202Skarels register struct ip *q, *savq; 397*25202Skarels register struct mbuf *mp; 398*25202Skarels int hlen; 399*25202Skarels int i; 400*25202Skarels 401*25202Skarels mp = dtom(ip); 402*25202Skarels hlen = ip->ip_hl << IP_HLSHIFT; 403*25202Skarels 404*25202Skarels if (ip->ip_off != 0) 405*25202Skarels { 406*25202Skarels /* 407*25202Skarels * Only the first fragment retains the IP header. 408*25202Skarels */ 409*25202Skarels mp->m_off += hlen; 410*25202Skarels mp->m_len -= hlen; 411*25202Skarels } 412*25202Skarels 413*25202Skarels if (fp == NULL) 414*25202Skarels { 415*25202Skarels /* 416*25202Skarels * This is the first fragment of the IP datagram that we've 417*25202Skarels * received. Set up reassembly q header. 418*25202Skarels */ 419*25202Skarels struct mbuf *m; 420*25202Skarels 421*25202Skarels if ((m = m_get(M_WAIT, MT_FTABLE)) == NULL) 422*25202Skarels { 423*25202Skarels m_freem(mp); 424*25202Skarels return(NULL); 425*25202Skarels } 426*25202Skarels 427*25202Skarels fp = mtod(m, struct ipq *); 428*25202Skarels fp->iqx.ip_next = fp->iqx.ip_prev = (struct ip *)fp; 429*25202Skarels bcopy((caddr_t)ip, (caddr_t)&fp->iqh, sizeof(struct ip)); 430*25202Skarels fp->iqx.ip_ttl = MAXTTL; 431*25202Skarels fp->iq_size = 0; 432*25202Skarels /* 433*25202Skarels * and enter this into the list of fragmented IP datagrams 434*25202Skarels */ 435*25202Skarels fp->iq_next = NULL; 436*25202Skarels fp->iq_prev = ipfrags.n_ip_tail; 437*25202Skarels if (ipfrags.n_ip_head != NULL) 438*25202Skarels ipfrags.n_ip_tail->iq_next = fp; 439*25202Skarels else 440*25202Skarels ipfrags.n_ip_head = fp; 441*25202Skarels ipfrags.n_ip_tail = fp; 442*25202Skarels } 443*25202Skarels 444*25202Skarels /* 445*25202Skarels * Merge fragment into reass.q 446*25202Skarels * 447*25202Skarels * Algorithm: Match start and end bytes of new 448*25202Skarels * fragment with fragments on the queue. If no 449*25202Skarels * overlaps are found, add new frag. to the queue. 450*25202Skarels * Otherwise, adjust start and end of new frag. so no 451*25202Skarels * overlap and add remainder to queue. If any 452*25202Skarels * fragments are completely covered by the new one, or 453*25202Skarels * if the new one is completely duplicated, free the 454*25202Skarels * fragments. 455*25202Skarels */ 456*25202Skarels q = fp->iqx.ip_next; /* -> top of reass. chain */ 457*25202Skarels ip->ip_end = ip->ip_off + ip->ip_len - 1; 458*25202Skarels 459*25202Skarels /* record the maximum fragment size for TCP */ 460*25202Skarels 461*25202Skarels fp->iq_size = MAX(ip->ip_len, fp->iq_size); 462*25202Skarels 463*25202Skarels /* skip frags which new doesn't overlap at end */ 464*25202Skarels 465*25202Skarels while ((q != (struct ip *)fp) && (ip->ip_off > q->ip_end)) 466*25202Skarels q = q->ip_next; 467*25202Skarels 468*25202Skarels if (q == (struct ip *)fp) 469*25202Skarels { /* frag at end of chain */ 470*25202Skarels ip_enq(ip, fp->iqx.ip_prev); 471*25202Skarels } 472*25202Skarels else 473*25202Skarels { /* frag doesn't overlap any */ 474*25202Skarels if (ip->ip_end < q->ip_off) 475*25202Skarels { 476*25202Skarels ip_enq(ip, q->ip_prev); 477*25202Skarels 478*25202Skarels /* new overlaps beginning of next frag only */ 479*25202Skarels 480*25202Skarels } 481*25202Skarels else if (ip->ip_end < q->ip_end) 482*25202Skarels { 483*25202Skarels if ((i = ip->ip_end-q->ip_off+1) < ip->ip_len) 484*25202Skarels { 485*25202Skarels ip->ip_len -= i; 486*25202Skarels ip->ip_end -= i; 487*25202Skarels m_adj(mp, -i); 488*25202Skarels ip_enq(ip, q->ip_prev); 489*25202Skarels } 490*25202Skarels else 491*25202Skarels m_freem(mp); 492*25202Skarels 493*25202Skarels /* new overlaps end of previous frag */ 494*25202Skarels 495*25202Skarels } 496*25202Skarels else 497*25202Skarels { 498*25202Skarels savq = q; 499*25202Skarels if (ip->ip_off <= q->ip_off) 500*25202Skarels { 501*25202Skarels 502*25202Skarels /* complete cover */ 503*25202Skarels 504*25202Skarels savq = q->ip_prev; 505*25202Skarels ip_deq(q); 506*25202Skarels m_freem(dtom(q)); 507*25202Skarels 508*25202Skarels } 509*25202Skarels else 510*25202Skarels { /* overlap */ 511*25202Skarels if ((i = q->ip_end-ip->ip_off+1) 512*25202Skarels < ip->ip_len) 513*25202Skarels { 514*25202Skarels ip->ip_off += i; 515*25202Skarels ip->ip_len -= i; 516*25202Skarels m_adj(mp, i); 517*25202Skarels } 518*25202Skarels else 519*25202Skarels ip->ip_len = 0; 520*25202Skarels } 521*25202Skarels 522*25202Skarels /* new overlaps at beginning of successor frags */ 523*25202Skarels 524*25202Skarels q = savq->ip_next; 525*25202Skarels while ((q != (struct ip *)fp) && 526*25202Skarels (ip->ip_len != 0) && 527*25202Skarels (q->ip_off <= ip->ip_end)) 528*25202Skarels 529*25202Skarels /* complete cover */ 530*25202Skarels 531*25202Skarels if (q->ip_end <= ip->ip_end) 532*25202Skarels { 533*25202Skarels struct ip *next; 534*25202Skarels 535*25202Skarels next = q->ip_next; 536*25202Skarels ip_deq(q); 537*25202Skarels m_freem(dtom(q)); 538*25202Skarels q = next; 539*25202Skarels } 540*25202Skarels else 541*25202Skarels { /* overlap */ 542*25202Skarels if ((i = ip->ip_end-q->ip_off+1) < ip->ip_len) 543*25202Skarels { 544*25202Skarels ip->ip_len -= i; 545*25202Skarels ip->ip_end -= i; 546*25202Skarels m_adj(mp, -i); 547*25202Skarels } 548*25202Skarels else 549*25202Skarels ip->ip_len = 0; 550*25202Skarels break; 551*25202Skarels } 552*25202Skarels 553*25202Skarels /* enqueue whatever is left of new before successors */ 554*25202Skarels 555*25202Skarels if (ip->ip_len != 0) 556*25202Skarels { 557*25202Skarels ip_enq(ip, savq); 558*25202Skarels } 559*25202Skarels else 560*25202Skarels m_freem(mp); 561*25202Skarels } 562*25202Skarels } 563*25202Skarels 564*25202Skarels /* check for completed fragment reassembly */ 565*25202Skarels 566*25202Skarels if ((i = ip_done(&fp->iqx)) == 0) 567*25202Skarels return(NULL); 568*25202Skarels 569*25202Skarels ip = fp->iqx.ip_next; /* -> top mbuf */ 570*25202Skarels ip->ip_len = i; /* total data length */ 571*25202Skarels *fragsize = fp->iq_size; /* remember for TCP */ 572*25202Skarels /* option processing */ 573*25202Skarels 574*25202Skarels if ((hlen = ip->ip_hl<<IP_HLSHIFT) > sizeof(struct ip)) 575*25202Skarels ip_stripopt (ip, hlen); 576*25202Skarels 577*25202Skarels ip_mergef(&fp->iqx); /* clean frag chain */ 578*25202Skarels 579*25202Skarels /* copy src/dst internet address to header mbuf */ 580*25202Skarels 581*25202Skarels ip->ip_src = fp->iqh.ip_src; 582*25202Skarels ip->ip_dst = fp->iqh.ip_dst; 583*25202Skarels 584*25202Skarels ip_freef(fp); /* dequeue header */ 585*25202Skarels return(ip); 586*25202Skarels } 587*25202Skarels 588*25202Skarels /* 589*25202Skarels * Let people control gateway action by patching this: 590*25202Skarels */ 591*25202Skarels int ip_forwarding = FALSE; 592*25202Skarels 593*25202Skarels /* 594*25202Skarels * Try to forward the packet. Act like a gateway. 595*25202Skarels */ 596*25202Skarels ip_forward (fwdinp, ip, mp, hlen) 597*25202Skarels struct inpcb *fwdinp; 598*25202Skarels register struct ip *ip; 599*25202Skarels struct mbuf *mp; 600*25202Skarels int hlen; 601*25202Skarels { 602*25202Skarels register int type, code; 603*25202Skarels register u_short len; 604*25202Skarels register struct mbuf *mcopy; 605*25202Skarels register unsigned icmplen; 606*25202Skarels int error; 607*25202Skarels 608*25202Skarels /* 609*25202Skarels * Also copy forwarded packets, just like copy TCP/UDP/RDP... 610*25202Skarels * packets sent to us so that can debug gateway action problems. 611*25202Skarels * It's easy enough for the user-level program to filter these 612*25202Skarels * out. 613*25202Skarels */ 614*25202Skarels if (any_rawreaders()) 615*25202Skarels if (mcopy = m_copy(mp, 0, M_COPYALL)) 616*25202Skarels raw_ip_input (mcopy); 617*25202Skarels 618*25202Skarels if (ip->ip_ttl) 619*25202Skarels ip->ip_ttl --; 620*25202Skarels 621*25202Skarels len = ntohs(ip->ip_len); 622*25202Skarels icmplen = MIN(len, hlen + ICMP_ERRLEN); 623*25202Skarels 624*25202Skarels if (ip_forwarding && ip->ip_ttl) 625*25202Skarels { 626*25202Skarels /* 627*25202Skarels * Save chunk of ip packet in case there is an error 628*25202Skarels */ 629*25202Skarels mcopy = m_copy (mp, 0, (int)icmplen); 630*25202Skarels 631*25202Skarels /* 632*25202Skarels * The packet is not sourced by the local machine, so 633*25202Skarels * save ourselves a useless call to ip_route in ip_send(). 634*25202Skarels * Also, don't want ip_send to work if sending from 635*25202Skarels * 8.7.0.2 to 192.1.11.1 via 8.0.0.16, and 8.0.0.16 636*25202Skarels * knows about a default gateway on net 8. This can 637*25202Skarels * cause an ENETUNREACH if 192.1.11 is not a network 638*25202Skarels * that default gateway knows about. [8.0.0.16 is on 639*25202Skarels * 192.1.11 and ip_route uses default gateway on net 8 640*25202Skarels * while rtalloc uses local interface] 641*25202Skarels * 642*25202Skarels * This route should be found by rtalloc, so let's do 643*25202Skarels * it here. 644*25202Skarels */ 645*25202Skarels if (fwdinp->inp_route.ro_rt == NULL) 646*25202Skarels { 647*25202Skarels /* Isn't a source routed packet */ 648*25202Skarels struct rtentry *rt; 649*25202Skarels struct sockaddr_in *sin; 650*25202Skarels 651*25202Skarels bzero ((caddr_t) fwdinp, sizeof(*fwdinp)); 652*25202Skarels sin = (struct sockaddr_in *) &fwdinp->inp_route.ro_dst; 653*25202Skarels sin->sin_family = AF_INET; 654*25202Skarels sin->sin_addr = ip->ip_dst; 655*25202Skarels rtalloc (&fwdinp->inp_route); 656*25202Skarels 657*25202Skarels /* 658*25202Skarels * Check to see if should send ICMP redirect. Don't 659*25202Skarels * send redirect if source routing was used. 660*25202Skarels */ 661*25202Skarels if ((rt = fwdinp->inp_route.ro_rt) != NULL) 662*25202Skarels { 663*25202Skarels sin = (struct sockaddr_in *) &rt->rt_gateway; 664*25202Skarels if (! (rt->rt_flags & (RTF_GATEWAY|RTF_HOST))) 665*25202Skarels send_redirect (ip, ip->ip_dst, ICMP_REDIR_HOST, icmplen); 666*25202Skarels else if (iptonet(ip->ip_src) == iptonet(sin->sin_addr)) 667*25202Skarels send_redirect (ip, sin->sin_addr, ICMP_REDIR_NET, icmplen); 668*25202Skarels } 669*25202Skarels } 670*25202Skarels 671*25202Skarels if (fwdinp->inp_route.ro_rt == NULL) 672*25202Skarels { 673*25202Skarels /* no way to get there from here */ 674*25202Skarels m_freem(mp); 675*25202Skarels type = ICMP_UNRCH; 676*25202Skarels code = ICMP_UNRCH_NET; 677*25202Skarels } 678*25202Skarels else 679*25202Skarels { 680*25202Skarels error = ip_send (fwdinp, mp, (int)len, TRUE); 681*25202Skarels rtfree(fwdinp->inp_route.ro_rt); 682*25202Skarels fwdinp->inp_route.ro_rt = NULL; 683*25202Skarels 684*25202Skarels if (! error) 685*25202Skarels { 686*25202Skarels ipstat.ip_forwarded ++; 687*25202Skarels if (mcopy) 688*25202Skarels m_freem(mcopy); 689*25202Skarels return; 690*25202Skarels } 691*25202Skarels 692*25202Skarels type = ICMP_UNRCH; 693*25202Skarels switch (error) 694*25202Skarels { 695*25202Skarels case ENETUNREACH: 696*25202Skarels case ENETDOWN: 697*25202Skarels code = ICMP_UNRCH_NET; 698*25202Skarels break; 699*25202Skarels case EMSGSIZE: 700*25202Skarels code = ICMP_UNRCH_FRAG; 701*25202Skarels break; 702*25202Skarels case EHOSTDOWN: 703*25202Skarels case EHOSTUNREACH: 704*25202Skarels code = ICMP_UNRCH_HOST; 705*25202Skarels break; 706*25202Skarels 707*25202Skarels case ENOBUFS: 708*25202Skarels type = ICMP_SRCQ; 709*25202Skarels break; 710*25202Skarels 711*25202Skarels default: 712*25202Skarels log(KERN_RECOV, "ip_forward: error %d\n", error); 713*25202Skarels } 714*25202Skarels } 715*25202Skarels } 716*25202Skarels else 717*25202Skarels { 718*25202Skarels if (ip->ip_ttl == 0) 719*25202Skarels { 720*25202Skarels type = ICMP_TIMEX; 721*25202Skarels code = ICMP_TIMEX_XMT; 722*25202Skarels } 723*25202Skarels else 724*25202Skarels { 725*25202Skarels type = ICMP_UNRCH; 726*25202Skarels code = ICMP_UNRCH_NET; 727*25202Skarels } 728*25202Skarels mcopy = mp; 729*25202Skarels if (fwdinp->inp_route.ro_rt) 730*25202Skarels { 731*25202Skarels /* was source routed by IP option */ 732*25202Skarels rtfree (fwdinp->inp_route.ro_rt); 733*25202Skarels fwdinp->inp_route.ro_rt = NULL; 734*25202Skarels } 735*25202Skarels } 736*25202Skarels 737*25202Skarels if (mcopy) 738*25202Skarels { 739*25202Skarels ip = mtod(mcopy, struct ip *); 740*25202Skarels ic_errmsg (redir_addr(ip), ip->ip_src, type, code, 0, icmplen, (char *) ip); 741*25202Skarels #ifdef HMPTRAPS 742*25202Skarels /* hmp_trap(T_IP_ADDRS, (caddr_t) 0, 0); */ 743*25202Skarels #else 744*25202Skarels if (ip_forwarding) 745*25202Skarels /* 746*25202Skarels * If not acting as a gateway, don't want some one else's 747*25202Skarels * misconception to flood our console or logfile. This error 748*25202Skarels * can be found through netstat an ip_drops. 749*25202Skarels */ 750*25202Skarels ip_log(ip, "ip forwarding error"); 751*25202Skarels netlog(mcopy); 752*25202Skarels #endif 753*25202Skarels } 754*25202Skarels 755*25202Skarels ipstat.ip_drops++; 756*25202Skarels } 757*25202Skarels 758*25202Skarels 759*25202Skarels /* 760*25202Skarels * Check to see if fragment reassembly is complete 761*25202Skarels */ 762*25202Skarels ip_done(p) 763*25202Skarels register struct ip *p; 764*25202Skarels { 765*25202Skarels register struct ip *q; 766*25202Skarels register next; 767*25202Skarels 768*25202Skarels q = p->ip_next; 769*25202Skarels 770*25202Skarels if (q->ip_off != 0) 771*25202Skarels return(0); 772*25202Skarels do 773*25202Skarels { 774*25202Skarels next = q->ip_end + 1; 775*25202Skarels q = q->ip_next; 776*25202Skarels } 777*25202Skarels while ((q != p) && (q->ip_off == next)); 778*25202Skarels 779*25202Skarels if ((q == p) && !(q->ip_prev->ip_mff)) /* all fragments in */ 780*25202Skarels return(next); /* total data length */ 781*25202Skarels else 782*25202Skarels return(0); 783*25202Skarels } 784*25202Skarels 785*25202Skarels /* 786*25202Skarels * Merge mbufs of fragments of completed datagram 787*25202Skarels */ 788*25202Skarels ip_mergef(p) 789*25202Skarels register struct ip *p; 790*25202Skarels { 791*25202Skarels register struct mbuf *m, *n; 792*25202Skarels register struct ip *q; 793*25202Skarels int dummy; 794*25202Skarels 795*25202Skarels q = p->ip_next; /* -> bottom of reass chain */ 796*25202Skarels n = (struct mbuf *)&dummy; /* dummy for init assignment */ 797*25202Skarels 798*25202Skarels while (q != p) 799*25202Skarels { /* through chain */ 800*25202Skarels /* 801*25202Skarels * If free mbuf holding q, cannot access q->ip_next in case 802*25202Skarels * that mbuf is used by device code for an incoming packet. 803*25202Skarels */ 804*25202Skarels register struct ip *next; 805*25202Skarels 806*25202Skarels next = q->ip_next; 807*25202Skarels n->m_next = m = dtom(q); 808*25202Skarels while (m != NULL) 809*25202Skarels { 810*25202Skarels if (m->m_len != 0) 811*25202Skarels { 812*25202Skarels n = m; 813*25202Skarels m = m->m_next; 814*25202Skarels } 815*25202Skarels else /* free null mbufs */ 816*25202Skarels n->m_next = m = m_free(m); 817*25202Skarels } 818*25202Skarels q = next; 819*25202Skarels } 820*25202Skarels } 821*25202Skarels 822*25202Skarels /* 823*25202Skarels * Dequeue and free reass.q header 824*25202Skarels */ 825*25202Skarels ip_freef(fp) 826*25202Skarels register struct ipq *fp; 827*25202Skarels { 828*25202Skarels if (fp->iq_prev != NULL) 829*25202Skarels (fp->iq_prev)->iq_next = fp->iq_next; 830*25202Skarels else 831*25202Skarels ipfrags.n_ip_head = fp->iq_next; 832*25202Skarels 833*25202Skarels if (fp->iq_next != NULL) 834*25202Skarels (fp->iq_next)->iq_prev = fp->iq_prev; 835*25202Skarels else 836*25202Skarels ipfrags.n_ip_tail = fp->iq_prev; 837*25202Skarels 838*25202Skarels m_free(dtom(fp)); 839*25202Skarels } 840*25202Skarels 841*25202Skarels ip_stripopt (ip, hlen) 842*25202Skarels struct ip *ip; 843*25202Skarels int hlen; 844*25202Skarels { 845*25202Skarels int optlen; 846*25202Skarels 847*25202Skarels if ((optlen = (hlen - sizeof(struct ip))) > 0) 848*25202Skarels { 849*25202Skarels struct mbuf *m; 850*25202Skarels caddr_t end_of_ip, end_of_opt; 851*25202Skarels unsigned len; 852*25202Skarels 853*25202Skarels m = dtom(ip); 854*25202Skarels end_of_ip = (char *) (ip +1); 855*25202Skarels end_of_opt = end_of_ip + optlen; 856*25202Skarels len = m->m_len - hlen; 857*25202Skarels bcopy (end_of_opt, end_of_ip, len); 858*25202Skarels m->m_len -= optlen; 859*25202Skarels } 860*25202Skarels } 861*25202Skarels 862*25202Skarels /* 863*25202Skarels * Process ip options 864*25202Skarels * FALSE -> options were in error, and an icmp message has been sent 865*25202Skarels */ 866*25202Skarels #define OFF_OLEN 1 867*25202Skarels #define OFF_OFFSET 2 868*25202Skarels #define MIN_OFF 4 /* since option is a 1, not 0, based array */ 869*25202Skarels 870*25202Skarels /* 871*25202Skarels * Record route in same form as ip_setopt() 872*25202Skarels */ 873*25202Skarels save_rte (option, dst) 874*25202Skarels u_char *option; 875*25202Skarels struct in_addr dst; 876*25202Skarels { 877*25202Skarels int olen; 878*25202Skarels int off; 879*25202Skarels u_char *x; 880*25202Skarels struct in_addr *p, *q; 881*25202Skarels 882*25202Skarels if (ip_nhops != 0) 883*25202Skarels { 884*25202Skarels /* Use both loose and strict source routing? */ 885*25202Skarels log(KERN_RECOV, "ip_nhops %d\n", ip_nhops); 886*25202Skarels ip_nhops = 0; 887*25202Skarels return; 888*25202Skarels } 889*25202Skarels olen = option[OFF_OLEN]; 890*25202Skarels if (olen > sizeof(ip_hops)) 891*25202Skarels { 892*25202Skarels log(KERN_RECOV, "save_rte: olen %d\n", olen); 893*25202Skarels return; 894*25202Skarels } 895*25202Skarels off = option[OFF_OFFSET]; 896*25202Skarels p = (struct in_addr *) (&option[off - 1]); 897*25202Skarels q = (struct in_addr *) (&option[MIN_OFF -1]); 898*25202Skarels 899*25202Skarels x = (u_char *) ip_hops; 900*25202Skarels x[0] = IP_NOP_OPT; 901*25202Skarels x[1] = option[0]; /* loose/strict source routing */ 902*25202Skarels x[2] = (p - q) * sizeof(struct in_addr) + 3; 903*25202Skarels x[3] = MIN_OFF; 904*25202Skarels ip_nhops ++; /* = 1 (1 long for opt hdr) */ 905*25202Skarels p--; /* p points at first hop for return route */ 906*25202Skarels 907*25202Skarels ip_hops[p-q+2] = (*p); /* save first hop after return route option */ 908*25202Skarels p--; /* it is in what will be ip_hops[ip_nhops] */ 909*25202Skarels 910*25202Skarels /* record return path as an IP source route */ 911*25202Skarels while (p >= q) 912*25202Skarels { 913*25202Skarels ip_hops[ip_nhops] = (*p); 914*25202Skarels p--; 915*25202Skarels ip_nhops ++; 916*25202Skarels } 917*25202Skarels /* remember eventual destination is in the option field */ 918*25202Skarels ip_hops[ip_nhops] = dst; 919*25202Skarels ip_nhops ++; 920*25202Skarels } 921*25202Skarels 922*25202Skarels ip_opt (ip, hlen, fwdinp) 923*25202Skarels register struct ip *ip; 924*25202Skarels struct inpcb *fwdinp; 925*25202Skarels { 926*25202Skarels register u_char *endopt; 927*25202Skarels register u_char *option; 928*25202Skarels register int olen; 929*25202Skarels register int off; 930*25202Skarels int type; 931*25202Skarels int code; 932*25202Skarels struct in_addr nexthop; 933*25202Skarels struct in_ifaddr *ia; 934*25202Skarels 935*25202Skarels endopt = ((u_char *) ip) + hlen; 936*25202Skarels option = (u_char *) (ip +1); 937*25202Skarels 938*25202Skarels while (option < endopt) 939*25202Skarels { 940*25202Skarels switch (*option) 941*25202Skarels { 942*25202Skarels case IP_END_OPT: 943*25202Skarels return (TRUE); 944*25202Skarels 945*25202Skarels case IP_NOP_OPT: 946*25202Skarels olen = sizeof(u_char); 947*25202Skarels break; 948*25202Skarels 949*25202Skarels case IP_SEC_OPT: 950*25202Skarels olen = option[OFF_OLEN]; 951*25202Skarels /* so much for security */ 952*25202Skarels break; 953*25202Skarels 954*25202Skarels case IP_LRTE_OPT: 955*25202Skarels olen = option[OFF_OLEN]; 956*25202Skarels off = option[OFF_OFFSET]; 957*25202Skarels if (off < MIN_OFF) 958*25202Skarels { 959*25202Skarels type = ICMP_PARM; 960*25202Skarels code = &option[OFF_OFFSET] - ((u_char *) ip); 961*25202Skarels goto err; 962*25202Skarels } 963*25202Skarels off--; /* adjust for use by C */ 964*25202Skarels if (in_iawithaddr(ip->ip_dst, TRUE) == NULL) 965*25202Skarels /* 966*25202Skarels * With loose routing, may take a few hops 967*25202Skarels * to get to current nexthop. 968*25202Skarels */ 969*25202Skarels break; 970*25202Skarels 971*25202Skarels if (off > (olen - sizeof(struct in_addr))) 972*25202Skarels { 973*25202Skarels /* hints all used up. pkt for us */ 974*25202Skarels save_rte (option, ip->ip_src); 975*25202Skarels break; 976*25202Skarels } 977*25202Skarels 978*25202Skarels nexthop = *((struct in_addr *) (option + off)); 979*25202Skarels 980*25202Skarels /* 981*25202Skarels * record outgoing interface 982*25202Skarels */ 983*25202Skarels if (! ip_opt_route(fwdinp, nexthop)) 984*25202Skarels { 985*25202Skarels type = ICMP_UNRCH; 986*25202Skarels /* net? frag? host? */ 987*25202Skarels code = ICMP_UNRCH_SRC; 988*25202Skarels goto err; 989*25202Skarels } 990*25202Skarels ip->ip_dst = nexthop; 991*25202Skarels option[OFF_OFFSET] += sizeof(struct in_addr); 992*25202Skarels if (fwdinp->inp_route.ro_rt == NULL) 993*25202Skarels /* 994*25202Skarels * Destined for ourselves, and we're 995*25202Skarels * just going to strip the options off 996*25202Skarels */ 997*25202Skarels break; 998*25202Skarels *((struct in_addr *) (option + off)) = 999*25202Skarels IA_INADDR(in_iafromif (fwdinp->inp_route.ro_rt->rt_ifp)); 1000*25202Skarels break; 1001*25202Skarels 1002*25202Skarels case IP_SRTE_OPT: 1003*25202Skarels olen = option[OFF_OLEN]; 1004*25202Skarels off = option[OFF_OFFSET]; 1005*25202Skarels if (off < MIN_OFF) 1006*25202Skarels { 1007*25202Skarels type = ICMP_PARM; 1008*25202Skarels code = &option[OFF_OFFSET] - ((u_char *) ip); 1009*25202Skarels goto err; 1010*25202Skarels } 1011*25202Skarels off--; /* adjust for use by C */ 1012*25202Skarels if (in_iawithaddr(ip->ip_dst, TRUE) == NULL) 1013*25202Skarels { 1014*25202Skarels /* strict path -> someone goofed */ 1015*25202Skarels /* should have come in on us for us */ 1016*25202Skarels type = ICMP_UNRCH; 1017*25202Skarels code = ICMP_UNRCH_SRC; 1018*25202Skarels goto err; 1019*25202Skarels } 1020*25202Skarels 1021*25202Skarels if (off > (olen - sizeof(struct in_addr))) 1022*25202Skarels { 1023*25202Skarels /* hints all used up */ 1024*25202Skarels save_rte (option, ip->ip_src); 1025*25202Skarels break; 1026*25202Skarels } 1027*25202Skarels 1028*25202Skarels nexthop = *((struct in_addr *) (option + off)); 1029*25202Skarels 1030*25202Skarels if ((ia = in_iawithnet(nexthop)) == NULL) 1031*25202Skarels { 1032*25202Skarels /* strict path -> someone goofed 1033*25202Skarels * we should be directly connected to 1034*25202Skarels * next hop 1035*25202Skarels */ 1036*25202Skarels type = ICMP_UNRCH; 1037*25202Skarels code = ICMP_UNRCH_SRC; 1038*25202Skarels goto err; 1039*25202Skarels } 1040*25202Skarels *((struct in_addr *) (option + off)) = IA_INADDR(ia); 1041*25202Skarels 1042*25202Skarels ip->ip_dst = nexthop; 1043*25202Skarels 1044*25202Skarels option[OFF_OFFSET] += sizeof(struct in_addr); 1045*25202Skarels break; 1046*25202Skarels 1047*25202Skarels case IP_TIME_OPT: 1048*25202Skarels olen = option[OFF_OLEN]; 1049*25202Skarels off = option[OFF_OFFSET]; 1050*25202Skarels if (off < MIN_OFF) 1051*25202Skarels { 1052*25202Skarels type = ICMP_PARM; 1053*25202Skarels code = &option[OFF_OFFSET] - ((u_char *) ip); 1054*25202Skarels goto err; 1055*25202Skarels } 1056*25202Skarels off--; /* adjust for use by C */ 1057*25202Skarels if (off > (olen - sizeof(u_long))) 1058*25202Skarels { 1059*25202Skarels /* increment overflow count */ 1060*25202Skarels if ((option[3] & 0xf0) == 0xf0) 1061*25202Skarels { 1062*25202Skarels /* overflow overflowed */ 1063*25202Skarels type = ICMP_PARM; 1064*25202Skarels code = &option[OFF_OLEN] - ((u_char *) ip); 1065*25202Skarels goto err; 1066*25202Skarels } 1067*25202Skarels option[3] += 0x10; 1068*25202Skarels break; 1069*25202Skarels } 1070*25202Skarels 1071*25202Skarels if (option[3] & 2) 1072*25202Skarels { 1073*25202Skarels /* want specific host to stamp */ 1074*25202Skarels ia = in_iawithaddr(*((struct in_addr *) (option + off)), FALSE); 1075*25202Skarels if (ia == NULL) 1076*25202Skarels break; 1077*25202Skarels } 1078*25202Skarels else 1079*25202Skarels ia = in_ifaddr; 1080*25202Skarels 1081*25202Skarels if (option[3] & 1) 1082*25202Skarels { 1083*25202Skarels /* record stamping host */ 1084*25202Skarels *((struct in_addr *) (option + off)) = IA_INADDR (ia); 1085*25202Skarels off += sizeof(struct in_addr); 1086*25202Skarels option[OFF_OFFSET] += sizeof(struct in_addr); 1087*25202Skarels } 1088*25202Skarels if (off > (olen - sizeof(u_long))) 1089*25202Skarels { 1090*25202Skarels option[3] += 0x10; 1091*25202Skarels break; 1092*25202Skarels } 1093*25202Skarels *((u_long *) (option + off)) = iptime(); 1094*25202Skarels option[OFF_OFFSET] += sizeof(u_long); 1095*25202Skarels break; 1096*25202Skarels 1097*25202Skarels case IP_STRID_OPT: 1098*25202Skarels olen = option[OFF_OLEN]; 1099*25202Skarels break; 1100*25202Skarels 1101*25202Skarels case IP_RRTE_OPT: 1102*25202Skarels olen = option[OFF_OLEN]; 1103*25202Skarels off = option[OFF_OFFSET]; 1104*25202Skarels if (off < MIN_OFF) 1105*25202Skarels { 1106*25202Skarels type = ICMP_PARM; 1107*25202Skarels code = &option[OFF_OFFSET] - ((u_char *) ip); 1108*25202Skarels goto err; 1109*25202Skarels } 1110*25202Skarels off--; /* adjust for use by C */ 1111*25202Skarels if (off > (olen - sizeof(u_long))) 1112*25202Skarels /* no space left for recording route */ 1113*25202Skarels break; 1114*25202Skarels 1115*25202Skarels /* record outgoing interface */ 1116*25202Skarels if (! ip_opt_route(fwdinp, ip->ip_dst)) 1117*25202Skarels { 1118*25202Skarels type = ICMP_UNRCH; 1119*25202Skarels code = ICMP_UNRCH_NET; 1120*25202Skarels goto err; 1121*25202Skarels } 1122*25202Skarels option[OFF_OFFSET] += sizeof(struct in_addr); 1123*25202Skarels if (fwdinp->inp_route.ro_rt == NULL) 1124*25202Skarels /* 1125*25202Skarels * Destined for us, and we're just 1126*25202Skarels * going to strip options off 1127*25202Skarels */ 1128*25202Skarels break; 1129*25202Skarels *((struct in_addr *) (option + off)) = 1130*25202Skarels IA_INADDR(in_iafromif (fwdinp->inp_route.ro_rt->rt_ifp)); 1131*25202Skarels break; 1132*25202Skarels } 1133*25202Skarels 1134*25202Skarels option += olen; 1135*25202Skarels } 1136*25202Skarels return (TRUE); 1137*25202Skarels 1138*25202Skarels err : 1139*25202Skarels ic_errmsg (icmp_addr(ip), ip->ip_src, 1140*25202Skarels type, code, option - ((u_char *) ip), hlen, (char *) ip); 1141*25202Skarels return (FALSE); 1142*25202Skarels } 1143*25202Skarels #undef OFF_OLEN 1144*25202Skarels #undef OFF_OFFSET 1145*25202Skarels #undef MIN_OFF 1146*25202Skarels 1147*25202Skarels 1148*25202Skarels ip_opt_route (fwdinp, dst) 1149*25202Skarels register struct inpcb *fwdinp; 1150*25202Skarels struct in_addr dst; 1151*25202Skarels { 1152*25202Skarels register struct sockaddr_in *sin; 1153*25202Skarels 1154*25202Skarels /* in case they use several options involving routing */ 1155*25202Skarels if (fwdinp->inp_route.ro_rt) 1156*25202Skarels return (TRUE); 1157*25202Skarels 1158*25202Skarels bzero ((caddr_t) fwdinp, sizeof(*fwdinp)); 1159*25202Skarels 1160*25202Skarels sin = (struct sockaddr_in *) &fwdinp->inp_route.ro_dst; 1161*25202Skarels 1162*25202Skarels /* not sure ip_send cares about this stuff ... */ 1163*25202Skarels sin->sin_family = AF_INET; 1164*25202Skarels sin->sin_addr = dst; 1165*25202Skarels 1166*25202Skarels /* Don't allocate route if not forwarding packet. 1167*25202Skarels * This saves us from doing a check in ip_input() to see 1168*25202Skarels * if we should do a rtfree() for an uncommon occurrence. 1169*25202Skarels */ 1170*25202Skarels 1171*25202Skarels if (in_iawithaddr(dst, TRUE) != NULL) 1172*25202Skarels return (TRUE); 1173*25202Skarels 1174*25202Skarels rtalloc (&fwdinp->inp_route); 1175*25202Skarels return (fwdinp->inp_route.ro_rt != NULL); 1176*25202Skarels } 1177*25202Skarels 1178*25202Skarels 1179*25202Skarels /* 1180*25202Skarels * IP fragment reassembly timeout routine. 1181*25202Skarels */ 1182*25202Skarels ip_timeo() 1183*25202Skarels { 1184*25202Skarels register struct ip *p, *q; 1185*25202Skarels register struct ipq *fp, *next; 1186*25202Skarels register int s; 1187*25202Skarels 1188*25202Skarels static int timflag; 1189*25202Skarels 1190*25202Skarels /* check once per sec */ 1191*25202Skarels 1192*25202Skarels if (timflag = !timflag) /* looks strange, doesn't it? */ 1193*25202Skarels return; 1194*25202Skarels 1195*25202Skarels 1196*25202Skarels /* search through reass.q */ 1197*25202Skarels s = splnet(); 1198*25202Skarels for (fp = ipfrags.n_ip_head; fp != NULL; fp = next) 1199*25202Skarels { 1200*25202Skarels /* 1201*25202Skarels * If fragment times out, mbufs are freed, and can't 1202*25202Skarels * use next pointer since mbuf may be grabbed by 1203*25202Skarels * an interface at splimp 1204*25202Skarels */ 1205*25202Skarels next = fp->iq_next; 1206*25202Skarels 1207*25202Skarels if (--(fp->iqx.ip_ttl) == 0) 1208*25202Skarels { /* time to die */ 1209*25202Skarels 1210*25202Skarels q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */ 1211*25202Skarels while (q != (struct ip *)fp) 1212*25202Skarels { 1213*25202Skarels p = q->ip_next; 1214*25202Skarels /* ### generate timed out in reassembly msg */ 1215*25202Skarels #ifdef HMPTRAPS 1216*25202Skarels /* hmp_trap(T_IP_FDROP, (caddr_t)0,0); */ 1217*25202Skarels #else 1218*25202Skarels m_freem(dtom(q)); 1219*25202Skarels #endif 1220*25202Skarels q = p; 1221*25202Skarels } 1222*25202Skarels ip_freef(fp); /* free header */ 1223*25202Skarels } 1224*25202Skarels } 1225*25202Skarels splx(s); 1226*25202Skarels } 1227*25202Skarels 1228*25202Skarels /* 1229*25202Skarels * Called at splimp from uipc_mbuf.c 1230*25202Skarels * Network code needs to free up space! IP fragments dropped. 1231*25202Skarels */ 1232*25202Skarels ip_drain() 1233*25202Skarels { 1234*25202Skarels register struct ip *p, *q; 1235*25202Skarels register struct ipq *fp; 1236*25202Skarels 1237*25202Skarels while (fp = ipfrags.n_ip_head) 1238*25202Skarels { 1239*25202Skarels q = fp->iqx.ip_next; /* free mbufs assoc w/chain */ 1240*25202Skarels while (q != (struct ip *)fp) 1241*25202Skarels { 1242*25202Skarels p = q->ip_next; 1243*25202Skarels m_freem(dtom(q)); 1244*25202Skarels q = p; 1245*25202Skarels } 1246*25202Skarels ip_freef(fp); /* free header */ 1247*25202Skarels } 1248*25202Skarels } 1249*25202Skarels 1250*25202Skarels #include "../h/syslog.h" 1251*25202Skarels 1252*25202Skarels inet_cksum_err (protoname, ip, was, should_be) 1253*25202Skarels char *protoname; 1254*25202Skarels struct ip *ip; 1255*25202Skarels u_long was; 1256*25202Skarels u_long should_be; 1257*25202Skarels { 1258*25202Skarels union { u_long ul; u_char c[4]; } s, d; 1259*25202Skarels 1260*25202Skarels s.ul = ip->ip_src.s_addr; 1261*25202Skarels d.ul = ip->ip_dst.s_addr; 1262*25202Skarels log (KERN_RECOV, 1263*25202Skarels "%s checksum was 0x%x not 0x%x src %d.%d.%d.%d dst %d.%d.%d.%d\n", 1264*25202Skarels protoname, was, should_be, 1265*25202Skarels s.c[0], s.c[1], s.c[2], s.c[3], 1266*25202Skarels d.c[0], d.c[1], d.c[2], d.c[3]); 1267*25202Skarels } 1268*25202Skarels 1269*25202Skarels ip_log(ip, emsg) 1270*25202Skarels struct ip *ip; 1271*25202Skarels char *emsg; 1272*25202Skarels { 1273*25202Skarels union { u_long ul; u_char c[4]; } s, d; 1274*25202Skarels 1275*25202Skarels s.ul = ip->ip_src.s_addr; 1276*25202Skarels d.ul = ip->ip_dst.s_addr; 1277*25202Skarels log(KERN_RECOV, "%s: src %d.%d.%d.%d dst %d.%d.%d.%d\n", 1278*25202Skarels emsg, 1279*25202Skarels s.c[0], s.c[1], s.c[2], s.c[3], 1280*25202Skarels d.c[0], d.c[1], d.c[2], d.c[3]); 1281*25202Skarels } 1282*25202Skarels 1283*25202Skarels no_route (msg, from, to) 1284*25202Skarels char *msg; 1285*25202Skarels struct in_addr from; 1286*25202Skarels struct in_addr to; 1287*25202Skarels { 1288*25202Skarels union { u_long ul; u_char c[4]; } f, t; 1289*25202Skarels 1290*25202Skarels f.ul = from.s_addr; 1291*25202Skarels t.ul = to.s_addr; 1292*25202Skarels log(KERN_RECOV, "%s: no route %d.%d.%d.%d -> %d.%d.%d.%d\n", 1293*25202Skarels msg, 1294*25202Skarels f.c[0], f.c[1], f.c[2], f.c[3], 1295*25202Skarels t.c[0], t.c[1], t.c[2], t.c[3]); 1296*25202Skarels } 1297