1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that this notice is preserved and that due credit is given
   7:  * to the University of California at Berkeley. The name of the University
   8:  * may not be used to endorse or promote products derived from this
   9:  * software without specific prior written permission. This software
  10:  * is provided ``as is'' without express or implied warranty.
  11:  *
  12:  *	@(#)ip_input.c	7.9.2 (2.11BSD GTE) 1995/10/09
  13:  */
  14: 
  15: #include "param.h"
  16: #include "systm.h"
  17: #include "mbuf.h"
  18: #include "domain.h"
  19: #include "protosw.h"
  20: #include "socket.h"
  21: #include "errno.h"
  22: #include "time.h"
  23: #include "kernel.h"
  24: 
  25: #include "../net/if.h"
  26: #include "../net/route.h"
  27: 
  28: #include "in.h"
  29: #include "in_pcb.h"
  30: #include "in_systm.h"
  31: #include "in_var.h"
  32: #include "ip.h"
  33: #include "ip_var.h"
  34: #include "ip_icmp.h"
  35: #include "tcp.h"
  36: 
  37: extern  int ipforwarding, ipsendredirects, ipforward_srcrt, ip_defttl;
  38: u_char  ip_protox[IPPROTO_MAX];
  39: int ipqmaxlen = IFQ_MAXLEN;
  40: int ipprintfs = 0;
  41: struct  in_ifaddr *in_ifaddr;           /* first inet address */
  42: 
  43: /*
  44:  * We need to save the IP options in case a protocol wants to respond
  45:  * to an incoming packet over the same route if the packet got here
  46:  * using IP source routing.  This allows connection establishment and
  47:  * maintenance when the remote end is on a network that is not known
  48:  * to us.
  49:  */
  50: int ip_nhops = 0;
  51: static  struct ip_srcrt {
  52:     char    nop;                /* one NOP to align */
  53:     char    srcopt[IPOPT_OFFSET + 1];   /* OPTVAL, OLEN and OFFSET */
  54:     struct  in_addr route[MAX_IPOPTLEN];
  55: } ip_srcrt;
  56: 
  57: /*
  58:  * IP initialization: fill in IP protocol switch table.
  59:  * All protocols not implemented in kernel go to raw IP protocol handler.
  60:  */
  61: ip_init()
  62: {
  63:     register struct protosw *pr;
  64:     register int i;
  65: extern  struct  timeval time;
  66:     struct  timeval nettime;
  67: 
  68:     pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
  69:     if (pr == 0)
  70:         panic("ip_init");
  71:     for (i = 0; i < IPPROTO_MAX; i++)
  72:         ip_protox[i] = pr - inetsw;
  73:     for (pr = inetdomain.dom_protosw;
  74:         pr < inetdomain.dom_protoswNPROTOSW; pr++)
  75:         if (pr->pr_domain->dom_family == PF_INET &&
  76:             pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
  77:             ip_protox[pr->pr_protocol] = pr - inetsw;
  78:     ipq.next = ipq.prev = &ipq;
  79:     cpfromkern(&time, &nettime, sizeof (struct timeval));
  80:     ip_id = nettime.tv_sec & 0xffffL;
  81:     ipintrq.ifq_maxlen = ipqmaxlen;
  82: }
  83: 
  84: u_char  ipcksum = 1;
  85: struct  ip *ip_reass();
  86: struct  sockaddr_in ipaddr = { AF_INET };
  87: struct  route ipforward_rt;
  88: 
  89: /*
  90:  * Ip input routine.  Checksum and byte swap header.  If fragmented
  91:  * try to reassamble.  If complete and fragment queue exists, discard.
  92:  * Process options.  Pass to next level.
  93:  */
  94: ipintr()
  95: {
  96:     register struct ip *ip;
  97:     register struct mbuf *m;
  98:     struct mbuf *m0;
  99:     register int i;
 100:     register struct ipq *fp;
 101:     register struct in_ifaddr *ia;
 102:     struct ifnet *ifp;
 103:     int hlen, s;
 104: 
 105: next:
 106:     /*
 107: 	 * Get next datagram off input queue and get IP header
 108: 	 * in first mbuf.
 109: 	 */
 110:     s = splimp();
 111:     IF_DEQUEUEIF(&ipintrq, m, ifp);
 112:     splx(s);
 113:     if (m == 0)
 114:         return;
 115:     /*
 116: 	 * If no IP addresses have been set yet but the interfaces
 117: 	 * are receiving, can't do anything with incoming packets yet.
 118: 	 */
 119:     if (in_ifaddr == NULL)
 120:         goto bad;
 121:     ipstat.ips_total++;
 122:     if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct ip)) &&
 123:         (m = m_pullup(m, sizeof (struct ip))) == 0) {
 124:         ipstat.ips_toosmall++;
 125:         goto next;
 126:     }
 127:     ip = mtod(m, struct ip *);
 128:     hlen = ip->ip_hl << 2;
 129:     if (hlen < sizeof(struct ip)) { /* minimum header length */
 130:         ipstat.ips_badhlen++;
 131:         goto bad;
 132:     }
 133:     if (hlen > m->m_len) {
 134:         if ((m = m_pullup(m, hlen)) == 0) {
 135:             ipstat.ips_badhlen++;
 136:             goto next;
 137:         }
 138:         ip = mtod(m, struct ip *);
 139:     }
 140:     if (ipcksum)
 141:         if (ip->ip_sum = in_cksum(m, hlen)) {
 142:             ipstat.ips_badsum++;
 143:             goto bad;
 144:         }
 145: 
 146:     /*
 147: 	 * Convert fields to host representation.
 148: 	 */
 149:     ip->ip_len = ntohs((u_short)ip->ip_len);
 150:     if (ip->ip_len < hlen) {
 151:         ipstat.ips_badlen++;
 152:         goto bad;
 153:     }
 154:     ip->ip_id = ntohs(ip->ip_id);
 155:     ip->ip_off = ntohs((u_short)ip->ip_off);
 156: 
 157:     /*
 158: 	 * Check that the amount of data in the buffers
 159: 	 * is as at least much as the IP header would have us expect.
 160: 	 * Trim mbufs if longer than we expect.
 161: 	 * Drop packet if shorter than we expect.
 162: 	 */
 163:     i = -(u_short)ip->ip_len;
 164:     m0 = m;
 165:     for (;;) {
 166:         i += m->m_len;
 167:         if (m->m_next == 0)
 168:             break;
 169:         m = m->m_next;
 170:     }
 171:     if (i != 0) {
 172:         if (i < 0) {
 173:             ipstat.ips_tooshort++;
 174:             m = m0;
 175:             goto bad;
 176:         }
 177:         if (i <= m->m_len)
 178:             m->m_len -= i;
 179:         else
 180:             m_adj(m0, -i);
 181:     }
 182:     m = m0;
 183: 
 184:     /*
 185: 	 * Process options and, if not destined for us,
 186: 	 * ship it on.  ip_dooptions returns 1 when an
 187: 	 * error was detected (causing an icmp message
 188: 	 * to be sent and the original packet to be freed).
 189: 	 */
 190:     ip_nhops = 0;       /* for source routed packets */
 191:     if (hlen > sizeof (struct ip) && ip_dooptions(ip, ifp))
 192:         goto next;
 193: 
 194:     /*
 195: 	 * Check our list of addresses, to see if the packet is for us.
 196: 	 */
 197:     for (ia = in_ifaddr; ia; ia = ia->ia_next) {
 198: #define satosin(sa) ((struct sockaddr_in *)(sa))
 199: 
 200:         if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr)
 201:             goto ours;
 202:         if (
 203: #ifdef  DIRECTED_BROADCAST
 204:             ia->ia_ifp == ifp &&
 205: #endif
 206:             (ia->ia_ifp->if_flags & IFF_BROADCAST)) {
 207:             u_long t;
 208: 
 209:             if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
 210:                 ip->ip_dst.s_addr)
 211:                 goto ours;
 212:             if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr)
 213:                 goto ours;
 214:             /*
 215: 			 * Look for all-0's host part (old broadcast addr),
 216: 			 * either for subnet or net.
 217: 			 */
 218:             t = ntohl(ip->ip_dst.s_addr);
 219:             if (t == ia->ia_subnet)
 220:                 goto ours;
 221:             if (t == ia->ia_net)
 222:                 goto ours;
 223:         }
 224:     }
 225:     if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST)
 226:         goto ours;
 227:     if (ip->ip_dst.s_addr == INADDR_ANY)
 228:         goto ours;
 229: 
 230:     /*
 231: 	 * Not for us; forward if possible and desirable.
 232: 	 */
 233:     if (ipforwarding == 0) {
 234:         ipstat.ips_cantforward++;
 235:         m_freem(m);
 236:     } else
 237:         ip_forward(ip, ifp, 0);
 238:     goto next;
 239: 
 240: ours:
 241:     /*
 242: 	 * If offset or IP_MF are set, must reassemble.
 243: 	 * Otherwise, nothing need be done.
 244: 	 * (We could look in the reassembly queue to see
 245: 	 * if the packet was previously fragmented,
 246: 	 * but it's not worth the time; just let them time out.)
 247: 	 */
 248:     if (ip->ip_off &~ IP_DF) {
 249:         /*
 250: 		 * Look for queue of fragments
 251: 		 * of this datagram.
 252: 		 */
 253:         for (fp = ipq.next; fp != &ipq; fp = fp->next)
 254:             if (ip->ip_id == fp->ipq_id &&
 255:                 ip->ip_src.s_addr == fp->ipq_src.s_addr &&
 256:                 ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&
 257:                 ip->ip_p == fp->ipq_p)
 258:                 goto found;
 259:         fp = 0;
 260: found:
 261: 
 262:         /*
 263: 		 * Adjust ip_len to not reflect header,
 264: 		 * set ip_mff if more fragments are expected,
 265: 		 * convert offset of this to bytes.
 266: 		 */
 267:         ip->ip_len -= hlen;
 268:         ((struct ipasfrag *)ip)->ipf_mff = 0;
 269:         if (ip->ip_off & IP_MF)
 270:             ((struct ipasfrag *)ip)->ipf_mff = 1;
 271:         ip->ip_off <<= 3;
 272: 
 273:         /*
 274: 		 * If datagram marked as having more fragments
 275: 		 * or if this is not the first fragment,
 276: 		 * attempt reassembly; if it succeeds, proceed.
 277: 		 */
 278:         if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) {
 279:             ipstat.ips_fragments++;
 280:             ip = ip_reass((struct ipasfrag *)ip, fp);
 281:             if (ip == 0)
 282:                 goto next;
 283:             m = dtom(ip);
 284:         } else
 285:             if (fp)
 286:                 ip_freef(fp);
 287:     } else
 288:         ip->ip_len -= hlen;
 289: 
 290:     /*
 291: 	 * Switch out to protocol's input routine.
 292: 	 */
 293:     (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, ifp);
 294:     goto next;
 295: bad:
 296:     m_freem(m);
 297:     goto next;
 298: }
 299: 
 300: /*
 301:  * Take incoming datagram fragment and try to
 302:  * reassemble it into whole datagram.  If a chain for
 303:  * reassembly of this datagram already exists, then it
 304:  * is given as fp; otherwise have to make a chain.
 305:  */
 306: struct ip *
 307: ip_reass(ip, fp)
 308:     register struct ipasfrag *ip;
 309:     register struct ipq *fp;
 310: {
 311:     register struct mbuf *m = dtom(ip);
 312:     register struct ipasfrag *q;
 313:     struct mbuf *t;
 314:     int hlen = ip->ip_hl << 2;
 315:     int i, next;
 316: 
 317:     /*
 318: 	 * Presence of header sizes in mbufs
 319: 	 * would confuse code below.
 320: 	 */
 321:     m->m_off += hlen;
 322:     m->m_len -= hlen;
 323: 
 324:     /*
 325: 	 * If first fragment to arrive, create a reassembly queue.
 326: 	 */
 327:     if (fp == 0) {
 328:         if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
 329:             goto dropfrag;
 330:         fp = mtod(t, struct ipq *);
 331:         insque(fp, &ipq);
 332:         fp->ipq_ttl = IPFRAGTTL;
 333:         fp->ipq_p = ip->ip_p;
 334:         fp->ipq_id = ip->ip_id;
 335:         fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp;
 336:         fp->ipq_src = ((struct ip *)ip)->ip_src;
 337:         fp->ipq_dst = ((struct ip *)ip)->ip_dst;
 338:         q = (struct ipasfrag *)fp;
 339:         goto insert;
 340:     }
 341: 
 342:     /*
 343: 	 * Find a segment which begins after this one does.
 344: 	 */
 345:     for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next)
 346:         if (q->ip_off > ip->ip_off)
 347:             break;
 348: 
 349:     /*
 350: 	 * If there is a preceding segment, it may provide some of
 351: 	 * our data already.  If so, drop the data from the incoming
 352: 	 * segment.  If it provides all of our data, drop us.
 353: 	 */
 354:     if (q->ipf_prev != (struct ipasfrag *)fp) {
 355:         i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off;
 356:         if (i > 0) {
 357:             if (i >= ip->ip_len)
 358:                 goto dropfrag;
 359:             m_adj(dtom(ip), i);
 360:             ip->ip_off += i;
 361:             ip->ip_len -= i;
 362:         }
 363:     }
 364: 
 365:     /*
 366: 	 * While we overlap succeeding segments trim them or,
 367: 	 * if they are completely covered, dequeue them.
 368: 	 */
 369:     while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) {
 370:         i = (ip->ip_off + ip->ip_len) - q->ip_off;
 371:         if (i < q->ip_len) {
 372:             q->ip_len -= i;
 373:             q->ip_off += i;
 374:             m_adj(dtom(q), i);
 375:             break;
 376:         }
 377:         q = q->ipf_next;
 378:         m_freem(dtom(q->ipf_prev));
 379:         ip_deq(q->ipf_prev);
 380:     }
 381: 
 382: insert:
 383:     /*
 384: 	 * Stick new segment in its place;
 385: 	 * check for complete reassembly.
 386: 	 */
 387:     ip_enq(ip, q->ipf_prev);
 388:     next = 0;
 389:     for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) {
 390:         if (q->ip_off != next)
 391:             return (0);
 392:         next += q->ip_len;
 393:     }
 394:     if (q->ipf_prev->ipf_mff)
 395:         return (0);
 396: 
 397:     /*
 398: 	 * Reassembly is complete; concatenate fragments.
 399: 	 */
 400:     q = fp->ipq_next;
 401:     m = dtom(q);
 402:     t = m->m_next;
 403:     m->m_next = 0;
 404:     m_cat(m, t);
 405:     q = q->ipf_next;
 406:     while (q != (struct ipasfrag *)fp) {
 407:         t = dtom(q);
 408:         q = q->ipf_next;
 409:         m_cat(m, t);
 410:     }
 411: 
 412:     /*
 413: 	 * Create header for new ip packet by
 414: 	 * modifying header of first packet;
 415: 	 * dequeue and discard fragment reassembly header.
 416: 	 * Make header visible.
 417: 	 */
 418:     ip = fp->ipq_next;
 419:     ip->ip_len = next;
 420:     ((struct ip *)ip)->ip_src = fp->ipq_src;
 421:     ((struct ip *)ip)->ip_dst = fp->ipq_dst;
 422:     remque(fp);
 423:     (void) m_free(dtom(fp));
 424:     m = dtom(ip);
 425:     m->m_len += (ip->ip_hl << 2);
 426:     m->m_off -= (ip->ip_hl << 2);
 427:     return ((struct ip *)ip);
 428: 
 429: dropfrag:
 430:     ipstat.ips_fragdropped++;
 431:     m_freem(m);
 432:     return (0);
 433: }
 434: 
 435: /*
 436:  * Free a fragment reassembly header and all
 437:  * associated datagrams.
 438:  */
 439: ip_freef(fp)
 440:     struct ipq *fp;
 441: {
 442:     register struct ipasfrag *q, *p;
 443: 
 444:     for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) {
 445:         p = q->ipf_next;
 446:         ip_deq(q);
 447:         m_freem(dtom(q));
 448:     }
 449:     remque(fp);
 450:     (void) m_free(dtom(fp));
 451: }
 452: 
 453: /*
 454:  * Put an ip fragment on a reassembly chain.
 455:  * Like insque, but pointers in middle of structure.
 456:  */
 457: ip_enq(p, prev)
 458:     register struct ipasfrag *p, *prev;
 459: {
 460: 
 461:     p->ipf_prev = prev;
 462:     p->ipf_next = prev->ipf_next;
 463:     prev->ipf_next->ipf_prev = p;
 464:     prev->ipf_next = p;
 465: }
 466: 
 467: /*
 468:  * To ip_enq as remque is to insque.
 469:  */
 470: ip_deq(p)
 471:     register struct ipasfrag *p;
 472: {
 473: 
 474:     p->ipf_prev->ipf_next = p->ipf_next;
 475:     p->ipf_next->ipf_prev = p->ipf_prev;
 476: }
 477: 
 478: /*
 479:  * IP timer processing;
 480:  * if a timer expires on a reassembly
 481:  * queue, discard it.
 482:  */
 483: ip_slowtimo()
 484: {
 485:     register struct ipq *fp;
 486:     int s = splnet();
 487: 
 488:     fp = ipq.next;
 489:     if (fp == 0) {
 490:         splx(s);
 491:         return;
 492:     }
 493:     while (fp != &ipq) {
 494:         --fp->ipq_ttl;
 495:         fp = fp->next;
 496:         if (fp->prev->ipq_ttl == 0) {
 497:             ipstat.ips_fragtimeout++;
 498:             ip_freef(fp->prev);
 499:         }
 500:     }
 501:     splx(s);
 502: }
 503: 
 504: /*
 505:  * Drain off all datagram fragments.
 506:  */
 507: ip_drain()
 508: {
 509: 
 510:     while (ipq.next != &ipq) {
 511:         ipstat.ips_fragdropped++;
 512:         ip_freef(ipq.next);
 513:     }
 514: }
 515: 
 516: extern struct in_ifaddr *ifptoia();
 517: struct in_ifaddr *ip_rtaddr();
 518: 
 519: /*
 520:  * Do option processing on a datagram,
 521:  * possibly discarding it if bad options
 522:  * are encountered.
 523:  */
 524: ip_dooptions(ip, ifp)
 525:     register struct ip *ip;
 526:     struct ifnet *ifp;
 527: {
 528:     register u_char *cp;
 529:     int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
 530:     register struct ip_timestamp *ipt;
 531:     register struct in_ifaddr *ia;
 532:     struct in_addr *sin;
 533:     n_time ntime, iptime();
 534: 
 535:     cp = (u_char *)(ip + 1);
 536:     cnt = (ip->ip_hl << 2) - sizeof (struct ip);
 537:     for (; cnt > 0; cnt -= optlen, cp += optlen) {
 538:         opt = UCHAR(cp[IPOPT_OPTVAL]);
 539:         if (opt == IPOPT_EOL)
 540:             break;
 541:         if (opt == IPOPT_NOP)
 542:             optlen = 1;
 543:         else {
 544:             optlen = UCHAR(cp[IPOPT_OLEN]);
 545:             if (optlen <= 0 || optlen > cnt) {
 546:                 code = &cp[IPOPT_OLEN] - (u_char *)ip;
 547:                 goto bad;
 548:             }
 549:         }
 550:         switch (opt) {
 551: 
 552:         default:
 553:             break;
 554: 
 555:         /*
 556: 		 * Source routing with record.
 557: 		 * Find interface with current destination address.
 558: 		 * If none on this machine then drop if strictly routed,
 559: 		 * or do nothing if loosely routed.
 560: 		 * Record interface address and bring up next address
 561: 		 * component.  If strictly routed make sure next
 562: 		 * address on directly accessible net.
 563: 		 */
 564:         case IPOPT_LSRR:
 565:         case IPOPT_SSRR:
 566:             if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
 567:                 code = &cp[IPOPT_OFFSET] - (u_char *)ip;
 568:                 goto bad;
 569:             }
 570:             ipaddr.sin_addr = ip->ip_dst;
 571:             ia = (struct in_ifaddr *)
 572:                 ifa_ifwithaddr((struct sockaddr *)&ipaddr);
 573:             if (ia == 0) {
 574:                 if (opt == IPOPT_SSRR) {
 575:                     type = ICMP_UNREACH;
 576:                     code = ICMP_UNREACH_SRCFAIL;
 577:                     goto bad;
 578:                 }
 579:                 /*
 580: 				 * Loose routing, and not at next destination
 581: 				 * yet; nothing to do except forward.
 582: 				 */
 583:                 break;
 584:             }
 585:             off--;          /* 0 origin */
 586:             if (off > optlen - sizeof(struct in_addr)) {
 587:                 /*
 588: 				 * End of source route.  Should be for us.
 589: 				 */
 590:                 save_rte(cp, ip->ip_src);
 591:                 break;
 592:             }
 593:             /*
 594: 			 * locate outgoing interface
 595: 			 */
 596:             bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr,
 597:                 sizeof(ipaddr.sin_addr));
 598:             if ((opt == IPOPT_SSRR &&
 599:                 in_iaonnetof(in_netof(ipaddr.sin_addr)) == 0) ||
 600:                 (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
 601:                 type = ICMP_UNREACH;
 602:                 code = ICMP_UNREACH_SRCFAIL;
 603:                 goto bad;
 604:             }
 605:             ip->ip_dst = ipaddr.sin_addr;
 606:             bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
 607:                 (caddr_t)(cp + off), sizeof(struct in_addr));
 608:             cp[IPOPT_OFFSET] += sizeof(struct in_addr);
 609: /*
 610:  * Since 2.11 will never have multicasting so the following line from 4.4
 611:  * is effectively always 1.
 612: */
 613:             forward = !IN_MULTICAST(ip->ip_dst.s_addr);
 614:             break;
 615: 
 616:         case IPOPT_RR:
 617:             if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
 618:                 code = &cp[IPOPT_OFFSET] - (u_char *)ip;
 619:                 goto bad;
 620:             }
 621:             /*
 622: 			 * If no space remains, ignore.
 623: 			 */
 624:             off--;          /* 0 origin */
 625:             if (off > optlen - sizeof(struct in_addr))
 626:                 break;
 627:             bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr,
 628:                 sizeof(ipaddr.sin_addr));
 629:             /*
 630: 			 * locate outgoing interface
 631: 			 */
 632:             if ((ia = ip_rtaddr(ipaddr.sin_addr)) == 0) {
 633:                 type = ICMP_UNREACH;
 634:                 code = ICMP_UNREACH_HOST;
 635:                 goto bad;
 636:             }
 637:             bcopy((caddr_t)&(IA_SIN(ia)->sin_addr),
 638:                 (caddr_t)(cp + off), sizeof(struct in_addr));
 639:             cp[IPOPT_OFFSET] += sizeof(struct in_addr);
 640:             break;
 641: 
 642:         case IPOPT_TS:
 643:             code = cp - (u_char *)ip;
 644:             ipt = (struct ip_timestamp *)cp;
 645:             if (ipt->ipt_len < 5)
 646:                 goto bad;
 647:             if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {
 648:                 if (++ipt->ipt_oflw == 0)
 649:                     goto bad;
 650:                 break;
 651:             }
 652:             sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1);
 653:             switch (ipt->ipt_flg) {
 654: 
 655:             case IPOPT_TS_TSONLY:
 656:                 break;
 657: 
 658:             case IPOPT_TS_TSANDADDR:
 659:                 if (ipt->ipt_ptr + sizeof(n_time) +
 660:                     sizeof(struct in_addr) > ipt->ipt_len)
 661:                     goto bad;
 662:                 ia = ifptoia(ifp);
 663:                 bcopy((caddr_t)&IA_SIN(ia)->sin_addr,
 664:                     (caddr_t)sin, sizeof(struct in_addr));
 665:                 ipt->ipt_ptr += sizeof(struct in_addr);
 666:                 break;
 667: 
 668:             case IPOPT_TS_PRESPEC:
 669:                 if (ipt->ipt_ptr + sizeof(n_time) +
 670:                     sizeof(struct in_addr) > ipt->ipt_len)
 671:                     goto bad;
 672:                 bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr,
 673:                     sizeof(struct in_addr));
 674:                 if (ifa_ifwithaddr((struct sockaddr *)&ipaddr) == 0)
 675:                     continue;
 676:                 ipt->ipt_ptr += sizeof(struct in_addr);
 677:                 break;
 678: 
 679:             default:
 680:                 goto bad;
 681:             }
 682:             ntime = iptime();
 683:             bcopy((caddr_t)&ntime, (caddr_t)cp + ipt->ipt_ptr - 1,
 684:                 sizeof(n_time));
 685:             ipt->ipt_ptr += sizeof(n_time);
 686:         }
 687:     }
 688:     if (forward) {
 689:         if (ipforward_srcrt == 0) {
 690:             type = ICMP_UNREACH;
 691:             code = ICMP_UNREACH_SRCFAIL;
 692:             goto bad;
 693:         }
 694:         ip_forward(ip, ifp, 1);
 695:         return(1);
 696:     }
 697:     return (0);
 698: bad:
 699:     ip->ip_len -= ip->ip_hl << 2;   /* XXX icmp_error adds in hdr length */
 700:     icmp_error(ip, type, code, ifp);
 701:     return (1);
 702: }
 703: 
 704: /*
 705:  * Given address of next destination (final or next hop),
 706:  * return internet address info of interface to be used to get there.
 707:  */
 708: struct in_ifaddr *
 709: ip_rtaddr(dst)
 710:      struct in_addr dst;
 711: {
 712:     register struct sockaddr_in *sin;
 713:     register struct in_ifaddr *ia;
 714: 
 715:     sin = (struct sockaddr_in *) &ipforward_rt.ro_dst;
 716: 
 717:     if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {
 718:         if (ipforward_rt.ro_rt) {
 719:             RTFREE(ipforward_rt.ro_rt);
 720:             ipforward_rt.ro_rt = 0;
 721:         }
 722:         sin->sin_family = AF_INET;
 723:         sin->sin_addr = dst;
 724: 
 725:         rtalloc(&ipforward_rt);
 726:     }
 727:     if (ipforward_rt.ro_rt == 0)
 728:         return ((struct in_ifaddr *)0);
 729:     /*
 730: 	 * Find address associated with outgoing interface.
 731: 	 */
 732:     for (ia = in_ifaddr; ia; ia = ia->ia_next)
 733:         if (ia->ia_ifp == ipforward_rt.ro_rt->rt_ifp)
 734:             break;
 735:     return (ia);
 736: }
 737: 
 738: /*
 739:  * Save incoming source route for use in replies,
 740:  * to be picked up later by ip_srcroute if the receiver is interested.
 741:  */
 742: save_rte(option, dst)
 743:     u_char *option;
 744:     struct in_addr dst;
 745: {
 746:     unsigned olen;
 747: 
 748:     olen = option[IPOPT_OLEN];
 749:     if (olen > sizeof(ip_srcrt) - 1) {
 750:         if (ipprintfs)
 751:             printf("save_rte: olen %d\n", olen);
 752:         return;
 753:     }
 754:     bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
 755:     ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
 756:     ip_srcrt.route[ip_nhops++] = dst;
 757: }
 758: 
 759: /*
 760:  * Retrieve incoming source route for use in replies,
 761:  * in the same form used by setsockopt.
 762:  * The first hop is placed before the options, will be removed later.
 763:  */
 764: struct mbuf *
 765: ip_srcroute()
 766: {
 767:     register struct in_addr *p, *q;
 768:     register struct mbuf *m;
 769: 
 770:     if (ip_nhops == 0)
 771:         return ((struct mbuf *)0);
 772:     m = m_get(M_DONTWAIT, MT_SOOPTS);
 773:     if (m == 0)
 774:         return ((struct mbuf *)0);
 775:     m->m_len = ip_nhops * sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1;
 776: 
 777:     /*
 778: 	 * First save first hop for return route
 779: 	 */
 780:     p = &ip_srcrt.route[ip_nhops - 1];
 781:     *(mtod(m, struct in_addr *)) = *p--;
 782: 
 783:     /*
 784: 	 * Copy option fields and padding (nop) to mbuf.
 785: 	 */
 786:     ip_srcrt.nop = IPOPT_NOP;
 787:     bcopy((caddr_t)&ip_srcrt, mtod(m, caddr_t) + sizeof(struct in_addr),
 788:         IPOPT_OFFSET + 1 + 1);
 789:     q = (struct in_addr *)(mtod(m, caddr_t) +
 790:         sizeof(struct in_addr) + IPOPT_OFFSET + 1 + 1);
 791:     /*
 792: 	 * Record return path as an IP source route,
 793: 	 * reversing the path (pointers are now aligned).
 794: 	 */
 795:     while (p >= ip_srcrt.route)
 796:         *q++ = *p--;
 797:     return (m);
 798: }
 799: 
 800: /*
 801:  * Strip out IP options, at higher
 802:  * level protocol in the kernel.
 803:  * Second argument is buffer to which options
 804:  * will be moved, and return value is their length.
 805:  */
 806: ip_stripoptions(ip, mopt)
 807:     struct ip *ip;
 808:     struct mbuf *mopt;
 809: {
 810:     register int i;
 811:     register struct mbuf *m;
 812:     register caddr_t opts;
 813:     int olen;
 814: 
 815:     olen = (ip->ip_hl<<2) - sizeof (struct ip);
 816:     m = dtom(ip);
 817:     opts = (caddr_t)(ip + 1);
 818:     if (mopt) {
 819:         mopt->m_len = olen;
 820:         mopt->m_off = MMINOFF;
 821:         bcopy(opts, mtod(mopt, caddr_t), (unsigned)olen);
 822:     }
 823:     i = m->m_len - (sizeof (struct ip) + olen);
 824:     bcopy(opts  + olen, opts, (unsigned)i);
 825:     m->m_len -= olen;
 826:     ip->ip_hl = sizeof(struct ip) >> 2;
 827: }
 828: 
 829: u_char inetctlerrmap[PRC_NCMDS] = {
 830:     0,      0,      0,      0,
 831:     0,      0,      EHOSTDOWN,  EHOSTUNREACH,
 832:     ENETUNREACH,    EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
 833:     EMSGSIZE,   EHOSTUNREACH,   0,      0,
 834:     0,      0,      0,      0,
 835:     ENOPROTOOPT
 836: };
 837: 
 838: extern  int in_interfaces;
 839: 
 840: /*
 841:  * Forward a packet.  If some error occurs return the sender
 842:  * an icmp packet.  Note we can't always generate a meaningful
 843:  * icmp message because icmp doesn't have a large enough repertoire
 844:  * of codes and types.
 845:  *
 846:  * If not forwarding (possibly because we have only a single external
 847:  * network), just drop the packet.  This could be confusing if ipforwarding
 848:  * was zero but some routing protocol was advancing us as a gateway
 849:  * to somewhere.  However, we must let the routing protocol deal with that.
 850:  *
 851:  * The srcrt parameter indicates whether the packet is being forwarded
 852:  * via a source route.
 853:  */
 854: ip_forward(ip, ifp, srcrt)
 855:     register struct ip *ip;
 856:     struct ifnet *ifp;
 857:     int srcrt;
 858: {
 859:     register int error, type = 0, code;
 860:     register struct sockaddr_in *sin;
 861:     struct mbuf *mcopy;
 862:     struct in_addr dest;
 863: 
 864:     dest.s_addr = 0;
 865:     if (ipprintfs)
 866:         printf("forward: src %X dst %X ttl %x\n", ntohl(ip->ip_src),
 867:             ntohl(ip->ip_dst), ip->ip_ttl);
 868:     ip->ip_id = htons(ip->ip_id);
 869:     if (in_canforward(ip->ip_dst) == 0) {
 870:         ipstat.ips_cantforward++;
 871:         m_freem(dtom(ip));
 872:         return;
 873:     }
 874:     if (ip->ip_ttl < IPTTLDEC) {
 875:         type = ICMP_TIMXCEED, code = ICMP_TIMXCEED_INTRANS;
 876:         goto sendicmp;
 877:     }
 878:     ip->ip_ttl -= IPTTLDEC;
 879: 
 880:     sin = (struct sockaddr_in *)&ipforward_rt.ro_dst;
 881:     if (ipforward_rt.ro_rt == 0 ||
 882:         ip->ip_dst.s_addr != sin->sin_addr.s_addr) {
 883:         if (ipforward_rt.ro_rt) {
 884:             RTFREE(ipforward_rt.ro_rt);
 885:             ipforward_rt.ro_rt = 0;
 886:         }
 887:         sin->sin_family = AF_INET;
 888:         sin->sin_addr = ip->ip_dst;
 889: 
 890:         rtalloc(&ipforward_rt);
 891:         if (ipforward_rt.ro_rt == 0) {
 892:             ip->ip_len -= ip->ip_hl << 2;   /* icmp_error assumes this */
 893:             icmp_error(ip,ICMP_UNREACH,ICMP_UNREACH_HOST,ifp,dest);
 894:             return;
 895:         }
 896:     }
 897: 
 898:     /*
 899: 	 * Save at most 64 bytes of the packet in case
 900: 	 * we need to generate an ICMP message to the src.
 901: 	 */
 902:     mcopy = m_copy(dtom(ip), 0, MIN((int)ip->ip_len, 64));
 903: 
 904:     /*
 905: 	 * If forwarding packet using same interface that it came in on,
 906: 	 * perhaps should send a redirect to sender to shortcut a hop.
 907: 	 * Only send redirect if source is sending directly to us,
 908: 	 * and if packet was not source routed (or has any options).
 909: 	 * Also, don't send redirect if forwarding using a default route
 910: 	 * or a route modfied by a redirect.
 911: 	 */
 912: #define satosin(sa) ((struct sockaddr_in *)(sa))
 913:     if (ipforward_rt.ro_rt && ipforward_rt.ro_rt->rt_ifp == ifp &&
 914:         (ipforward_rt.ro_rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
 915:         satosin(&ipforward_rt.ro_rt->rt_dst)->sin_addr.s_addr != 0 &&
 916:         ipsendredirects && !srcrt && ip->ip_hl == (sizeof(struct ip) >> 2)){
 917:         struct in_ifaddr *ia;
 918:         u_long src = ntohl(ip->ip_src.s_addr);
 919:         u_long dst = ntohl(ip->ip_dst.s_addr);
 920: 
 921:         if ((ia = ifptoia(ifp)) &&
 922:            (src & ia->ia_subnetmask) == ia->ia_subnet) {
 923:             if (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY)
 924:             dest = satosin(&ipforward_rt.ro_rt->rt_gateway)->sin_addr;
 925:             else
 926:             dest = ip->ip_dst;
 927:             /*
 928: 		     * If the destination is reached by a route to host,
 929: 		     * is on a subnet of a local net, or is directly
 930: 		     * on the attached net (!), use host redirect.
 931: 		     * (We may be the correct first hop for other subnets.)
 932: 		     */
 933:             type = ICMP_REDIRECT;
 934:             code = ICMP_REDIRECT_NET;
 935:             if ((ipforward_rt.ro_rt->rt_flags & RTF_HOST) ||
 936:                (ipforward_rt.ro_rt->rt_flags & RTF_GATEWAY) == 0)
 937:             code = ICMP_REDIRECT_HOST;
 938:             else for (ia = in_ifaddr; ia = ia->ia_next; )
 939:             if ((dst & ia->ia_netmask) == ia->ia_net) {
 940:                 if (ia->ia_subnetmask != ia->ia_netmask)
 941:                     code = ICMP_REDIRECT_HOST;
 942:                 break;
 943:             }
 944:             if (ipprintfs)
 945:                 printf("redirect (%d) to %x\n", code, dest);
 946:         }
 947:     }
 948: 
 949:     error = ip_output(dtom(ip), (struct mbuf *)0, &ipforward_rt,
 950:         IP_FORWARDING);
 951:     if (error)
 952:         ipstat.ips_cantforward++;
 953:     else if (type)
 954:         ipstat.ips_redirectsent++;
 955:     else {
 956:         if (mcopy)
 957:             m_freem(mcopy);
 958:         ipstat.ips_forward++;
 959:         return;
 960:     }
 961:     if (mcopy == NULL)
 962:         return;
 963:     ip = mtod(mcopy, struct ip *);
 964:     type = ICMP_UNREACH;
 965:     switch (error) {
 966: 
 967:     case 0:             /* forwarded, but need redirect */
 968:         type = ICMP_REDIRECT;
 969:         /* code set above */
 970:         break;
 971: 
 972:     case ENETUNREACH:
 973:     case ENETDOWN:
 974:         if (in_localaddr(ip->ip_dst))
 975:             code = ICMP_UNREACH_HOST;
 976:         else
 977:             code = ICMP_UNREACH_NET;
 978:         break;
 979: 
 980:     case EMSGSIZE:
 981:         code = ICMP_UNREACH_NEEDFRAG;
 982:         break;
 983: 
 984:     case EPERM:
 985:         code = ICMP_UNREACH_PORT;
 986:         break;
 987: 
 988:     case ENOBUFS:
 989:         type = ICMP_SOURCEQUENCH;
 990:         break;
 991: 
 992:     case EHOSTDOWN:
 993:     case EHOSTUNREACH:
 994:         code = ICMP_UNREACH_HOST;
 995:         break;
 996:     }
 997: sendicmp:
 998:     ip->ip_len -= ip->ip_hl << 2;   /* icmp_error assumes this */
 999:     icmp_error(ip, type, code, ifp, dest);
1000: }
1001: 
1002: int
1003: ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1004:     int *name;
1005:     u_int namelen;
1006:     void *oldp;
1007:     size_t *oldlenp;
1008:     void *newp;
1009:     size_t newlen;
1010: {
1011:     /* All sysctl names at this level are terminal. */
1012:     if (namelen != 1)
1013:         return (ENOTDIR);
1014: 
1015:     switch (name[0]) {
1016:     case IPCTL_FORWARDING:
1017:         return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding));
1018:     case IPCTL_SENDREDIRECTS:
1019:         return (sysctl_int(oldp, oldlenp, newp, newlen,
1020:             &ipsendredirects));
1021:     case IPCTL_DEFTTL:
1022:         return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl));
1023: #ifdef notyet
1024:     case IPCTL_DEFMTU:
1025:         return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
1026: #endif
1027:     case IPCTL_FORWSRCRT:
1028:         return (sysctl_int(oldp, oldlenp, newp, newlen,
1029:             &ipforward_srcrt));
1030:     default:
1031:         return (EOPNOTSUPP);
1032:     }
1033:     /* NOTREACHED */
1034: }

Defined functions

ip_deq defined in line 470; used 2 times
ip_dooptions defined in line 524; used 1 times
ip_drain defined in line 507; never used
ip_enq defined in line 457; used 1 times
ip_forward defined in line 854; used 2 times
ip_freef defined in line 439; used 3 times
ip_init defined in line 61; never used
ip_reass defined in line 306; used 2 times
ip_rtaddr defined in line 708; used 3 times
ip_slowtimo defined in line 483; never used
ip_srcroute defined in line 764; never used
ip_stripoptions defined in line 806; never used
ip_sysctl defined in line 1002; never used
ipintr defined in line 94; never used
save_rte defined in line 742; used 1 times

Defined variables

in_ifaddr defined in line 41; used 4 times
inetctlerrmap defined in line 829; never used
ip_nhops defined in line 50; used 6 times
ip_protox defined in line 38; used 3 times
ip_srcrt defined in line 55; used 7 times
ipaddr defined in line 86; used 12 times
ipcksum defined in line 84; used 1 times
ipforward_rt defined in line 87; used 24 times
ipprintfs defined in line 40; used 3 times
ipqmaxlen defined in line 39; used 1 times
  • in line 81

Defined struct's

ip_srcrt defined in line 51; never used

Defined macros

satosin defined in line 912; used 3 times
Last modified: 1995-10-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6327
Valid CSS Valid XHTML 1.0 Strict