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