1 /* ip_input.c 1.16 81/11/20 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/clock.h" 6 #include "../h/mbuf.h" 7 #include "../h/protosw.h" 8 #include "../h/socket.h" 9 #include "../net/inet.h" 10 #include "../net/inet_systm.h" 11 #include "../net/if.h" 12 #include "../net/imp.h" 13 #include "../net/ip.h" /* belongs before inet.h */ 14 #include "../net/ip_var.h" 15 #include "../net/ip_icmp.h" 16 #include "../net/tcp.h" 17 18 u_char ip_protox[IPPROTO_MAX]; 19 20 /* 21 * Ip initialization. 22 */ 23 ip_init() 24 { 25 register struct protosw *pr; 26 register int i; 27 28 COUNT(IP_INIT); 29 pr = pffindproto(PF_INET, IPPROTO_RAW); 30 if (pr == 0) 31 panic("ip_init"); 32 for (i = 0; i < IPPROTO_MAX; i++) 33 ip_protox[i] = pr - protosw; 34 for (pr = protosw; pr <= protoswLAST; pr++) 35 if (pr->pr_family == PF_INET && 36 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) 37 ip_protox[pr->pr_protocol] = pr - protosw; 38 ipq.next = ipq.prev = &ipq; 39 ip_id = time & 0xffff; 40 } 41 42 u_char ipcksum = 1; 43 struct ip *ip_reass(); 44 45 /* 46 * Ip input routines. 47 */ 48 49 /* 50 * Ip input routine. Checksum and byte swap header. If fragmented 51 * try to reassamble. If complete and fragment queue exists, discard. 52 * Process options. Pass to next level. 53 */ 54 ip_input(m0) 55 struct mbuf *m0; 56 { 57 register struct ip *ip; 58 register struct mbuf *m = m0; 59 register int i; 60 register struct ipq *fp; 61 int hlen; 62 63 COUNT(IP_INPUT); 64 /* 65 * Check header and byteswap. 66 */ 67 ip = mtod(m, struct ip *); 68 if ((hlen = ip->ip_hl << 2) > m->m_len) { 69 printf("ip hdr ovflo\n"); 70 goto bad; 71 } 72 if (ipcksum) 73 if (ip->ip_sum = inet_cksum(m, hlen)) { 74 printf("ip_sum %x\n", ip->ip_sum); 75 ipstat.ips_badsum++; 76 goto bad; 77 } 78 79 /* 80 * Convert fields to host representation. 81 */ 82 ip->ip_len = ntohs((u_short)ip->ip_len); 83 ip->ip_id = ntohs(ip->ip_id); 84 ip->ip_off = ntohs((u_short)ip->ip_off); 85 86 /* 87 * Check that the amount of data in the buffers 88 * is as at least much as the IP header would have us expect. 89 * Trim mbufs if longer than we expect. 90 * Drop packet if shorter than we expect. 91 */ 92 i = 0; 93 for (; m != NULL; m = m->m_next) 94 i += m->m_len; 95 m = m0; 96 if (i != ip->ip_len) { 97 if (i < ip->ip_len) { 98 printf("ip_input: short packet\n"); 99 goto bad; 100 } 101 m_adj(m, ip->ip_len - i); 102 } 103 104 /* 105 * Process options and, if not destined for us, 106 * ship it on. 107 */ 108 if (hlen > sizeof (struct ip)) 109 ip_dooptions(ip); 110 if (ip->ip_dst.s_addr != n_lhost.s_addr) { 111 if (--ip->ip_ttl == 0) { 112 icmp_error(ip, ICMP_TIMXCEED, 0); 113 return; 114 } 115 ip_output(dtom(ip)); 116 return; 117 } 118 119 /* 120 * Look for queue of fragments 121 * of this datagram. 122 */ 123 for (fp = ipq.next; fp != &ipq; fp = fp->next) 124 if (ip->ip_id == fp->ipq_id && 125 ip->ip_src.s_addr == fp->ipq_src.s_addr && 126 ip->ip_dst.s_addr == fp->ipq_dst.s_addr && 127 ip->ip_p == fp->ipq_p) 128 goto found; 129 fp = 0; 130 found: 131 132 /* 133 * Adjust ip_len to not reflect header, 134 * set ip_mff if more fragments are expected, 135 * convert offset of this to bytes. 136 */ 137 ip->ip_len -= hlen; 138 ((struct ipasfrag *)ip)->ipf_mff = 0; 139 if (ip->ip_off & IP_MF) 140 ((struct ipasfrag *)ip)->ipf_mff = 1; 141 ip->ip_off <<= 3; 142 143 /* 144 * If datagram marked as having more fragments 145 * or if this is not the first fragment, 146 * attempt reassembly; if it succeeds, proceed. 147 */ 148 if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) { 149 ip = ip_reass((struct ipasfrag *)ip, fp); 150 if (ip == 0) 151 return; 152 hlen = ip->ip_hl << 2; 153 m = dtom(ip); 154 } else 155 if (fp) 156 (void) ip_freef(fp); 157 158 /* 159 * Switch out to protocol's input routine. 160 */ 161 (*protosw[ip_protox[ip->ip_p]].pr_input)(m); 162 return; 163 bad: 164 m_freem(m); 165 } 166 167 /* 168 * Take incoming datagram fragment and try to 169 * reassemble it into whole datagram. If a chain for 170 * reassembly of this datagram already exists, then it 171 * is given as fp; otherwise have to make a chain. 172 */ 173 struct ip * 174 ip_reass(ip, fp) 175 register struct ipasfrag *ip; 176 register struct ipq *fp; 177 { 178 register struct mbuf *m = dtom(ip); 179 register struct ipasfrag *q; 180 struct mbuf *t; 181 int hlen = ip->ip_hl << 2; 182 int i, next; 183 COUNT(IP_REASS); 184 185 /* 186 * Presence of header sizes in mbufs 187 * would confuse code below. 188 */ 189 m->m_off += hlen; 190 m->m_len -= hlen; 191 192 /* 193 * If first fragment to arrive, create a reassembly queue. 194 */ 195 if (fp == 0) { 196 if ((t = m_get(1)) == NULL) 197 goto dropfrag; 198 t->m_off = MMINOFF; 199 fp = mtod(t, struct ipq *); 200 insque(fp, &ipq); 201 fp->ipq_ttl = IPFRAGTTL; 202 fp->ipq_p = ip->ip_p; 203 fp->ipq_id = ip->ip_id; 204 fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp; 205 fp->ipq_src = ((struct ip *)ip)->ip_src; 206 fp->ipq_dst = ((struct ip *)ip)->ip_dst; 207 } 208 209 /* 210 * Find a segment which begins after this one does. 211 */ 212 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) 213 if (q->ip_off > ip->ip_off) 214 break; 215 216 /* 217 * If there is a preceding segment, it may provide some of 218 * our data already. If so, drop the data from the incoming 219 * segment. If it provides all of our data, drop us. 220 */ 221 if (q->ipf_prev != (struct ipasfrag *)fp) { 222 i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off; 223 if (i > 0) { 224 if (i >= ip->ip_len) 225 goto dropfrag; 226 m_adj(dtom(ip), i); 227 ip->ip_off += i; 228 ip->ip_len -= i; 229 } 230 } 231 232 /* 233 * While we overlap succeeding segments trim them or, 234 * if they are completely covered, dequeue them. 235 */ 236 while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { 237 i = (ip->ip_off + ip->ip_len) - q->ip_off; 238 if (i < q->ip_len) { 239 q->ip_len -= i; 240 m_adj(dtom(q), i); 241 break; 242 } 243 q = q->ipf_next; 244 m_freem(dtom(q->ipf_prev)); 245 ip_deq(q->ipf_prev); 246 } 247 248 /* 249 * Stick new segment in its place; 250 * check for complete reassembly. 251 */ 252 ip_enq(ip, q->ipf_prev); 253 next = 0; 254 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { 255 if (q->ip_off != next) 256 return (0); 257 next += q->ip_len; 258 } 259 if (q->ipf_prev->ipf_mff) 260 return (0); 261 262 /* 263 * Reassembly is complete; concatenate fragments. 264 */ 265 q = fp->ipq_next; 266 m = dtom(q); 267 t = m->m_next; 268 m->m_next = 0; 269 m_cat(m, t); 270 while ((q = q->ipf_next) != (struct ipasfrag *)fp) 271 m_cat(m, dtom(q)); 272 273 /* 274 * Create header for new ip packet by 275 * modifying header of first packet; 276 * dequeue and discard fragment reassembly header. 277 * Make header visible. 278 */ 279 ip = fp->ipq_next; 280 ip->ip_len = next; 281 ((struct ip *)ip)->ip_src = fp->ipq_src; 282 ((struct ip *)ip)->ip_dst = fp->ipq_dst; 283 remque(fp); 284 (void) m_free(dtom(fp)); 285 m = dtom(ip); 286 m->m_len += sizeof (struct ipasfrag); 287 m->m_off -= sizeof (struct ipasfrag); 288 return ((struct ip *)ip); 289 290 dropfrag: 291 m_freem(m); 292 return (0); 293 } 294 295 /* 296 * Free a fragment reassembly header and all 297 * associated datagrams. 298 */ 299 struct ipq * 300 ip_freef(fp) 301 struct ipq *fp; 302 { 303 register struct ipasfrag *q; 304 struct mbuf *m; 305 COUNT(IP_FREEF); 306 307 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) 308 m_freem(dtom(q)); 309 m = dtom(fp); 310 fp = fp->next; 311 remque(fp->prev); 312 (void) m_free(m); 313 return (fp); 314 } 315 316 /* 317 * Put an ip fragment on a reassembly chain. 318 * Like insque, but pointers in middle of structure. 319 */ 320 ip_enq(p, prev) 321 register struct ipasfrag *p, *prev; 322 { 323 324 COUNT(IP_ENQ); 325 p->ipf_prev = prev; 326 p->ipf_next = prev->ipf_next; 327 prev->ipf_next->ipf_prev = p; 328 prev->ipf_next = p; 329 } 330 331 /* 332 * To ip_enq as remque is to insque. 333 */ 334 ip_deq(p) 335 register struct ipasfrag *p; 336 { 337 338 COUNT(IP_DEQ); 339 p->ipf_prev->ipf_next = p->ipf_next; 340 p->ipf_next->ipf_prev = p->ipf_prev; 341 } 342 343 /* 344 * IP timer processing; 345 * if a timer expires on a reassembly 346 * queue, discard it. 347 */ 348 ip_slowtimo() 349 { 350 register struct ipq *fp; 351 int s = splnet(); 352 353 COUNT(IP_SLOWTIMO); 354 for (fp = ipq.next; fp != &ipq; ) 355 if (--fp->ipq_ttl == 0) 356 fp = ip_freef(fp); 357 else 358 fp = fp->next; 359 splx(s); 360 } 361 362 /* 363 * Drain off all datagram fragments. 364 */ 365 ip_drain() 366 { 367 368 COUNT(IP_DRAIN); 369 while (ipq.next != &ipq) 370 (void) ip_freef(ipq.next); 371 } 372 373 /* 374 * Do option processing on a datagram, 375 * possibly discarding it if bad options 376 * are encountered. 377 */ 378 ip_dooptions(ip) 379 struct ip *ip; 380 { 381 register u_char *cp; 382 int opt, optlen, cnt; 383 struct in_addr *sin; 384 register struct ip_timestamp *ipt; 385 register struct ifnet *ifp; 386 struct in_addr t; 387 388 COUNT(IP_DOOPTIONS); 389 cp = (u_char *)(ip + 1); 390 cnt = (ip->ip_hl << 2) - sizeof (struct ip); 391 for (; cnt > 0; cnt -= optlen, cp += optlen) { 392 opt = cp[0]; 393 if (opt == IPOPT_EOL) 394 break; 395 if (opt == IPOPT_NOP) 396 optlen = 1; 397 else 398 optlen = cp[1]; 399 switch (opt) { 400 401 default: 402 break; 403 404 /* 405 * Source routing with record. 406 * Find interface with current destination address. 407 * If none on this machine then drop if strictly routed, 408 * or do nothing if loosely routed. 409 * Record interface address and bring up next address 410 * component. If strictly routed make sure next 411 * address on directly accessible net. 412 */ 413 case IPOPT_LSRR: 414 if (cp[2] < 4 || cp[2] > optlen - (sizeof (long) - 1)) 415 break; 416 sin = (struct in_addr *)(cp + cp[2]); 417 ifp = if_ifwithaddr(*sin); 418 if (ifp == 0) { 419 if (opt == IPOPT_SSRR) 420 goto bad; 421 break; 422 } 423 t = ip->ip_dst; ip->ip_dst = *sin; *sin = t; 424 cp[2] += 4; 425 if (cp[2] > optlen - (sizeof (long) - 1)) 426 break; 427 ip->ip_dst = sin[1]; 428 if (opt == IPOPT_SSRR && if_ifonnetof(ip->ip_dst)==0) 429 goto bad; 430 break; 431 432 case IPOPT_TS: 433 ipt = (struct ip_timestamp *)cp; 434 if (ipt->ipt_len < 5) 435 goto bad; 436 if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) { 437 if (++ipt->ipt_oflw == 0) 438 goto bad; 439 break; 440 } 441 sin = (struct in_addr *)(cp+cp[2]); 442 switch (ipt->ipt_flg) { 443 444 case IPOPT_TS_TSONLY: 445 break; 446 447 case IPOPT_TS_TSANDADDR: 448 if (ipt->ipt_ptr + 8 > ipt->ipt_len) 449 goto bad; 450 /* stamp with ``first'' interface address */ 451 *sin++ = ifnet->if_addr; 452 break; 453 454 case IPOPT_TS_PRESPEC: 455 if (if_ifwithaddr(*sin) == 0) 456 continue; 457 if (ipt->ipt_ptr + 8 > ipt->ipt_len) 458 goto bad; 459 ipt->ipt_ptr += 4; 460 break; 461 462 default: 463 goto bad; 464 } 465 *(n_time *)sin = iptime(); 466 ipt->ipt_ptr += 4; 467 } 468 } 469 return; 470 bad: 471 /* SHOULD FORCE ICMP MESSAGE */ 472 return; 473 } 474 475 /* 476 * Strip out IP options, at higher 477 * level protocol in the kernel. 478 * Second argument is buffer to which options 479 * will be moved, and return value is their length. 480 */ 481 ip_stripoptions(ip, cp) 482 struct ip *ip; 483 char *cp; 484 { 485 register int i; 486 register struct mbuf *m; 487 int olen; 488 COUNT(IP_STRIPOPTIONS); 489 490 olen = (ip->ip_hl<<2) - sizeof (struct ip); 491 m = dtom(ip); 492 ip++; 493 if (cp) 494 bcopy((caddr_t)ip, cp, (unsigned)olen); 495 i = m->m_len - (sizeof (struct ip) + olen); 496 bcopy((caddr_t)ip+olen, (caddr_t)ip, (unsigned)i); 497 m->m_len -= i; 498 } 499