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