1 /* ip_input.c 1.13 81/11/15 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/clock.h" 6 #include "../h/mbuf.h" 7 #include "../h/protocol.h" 8 #include "../h/protosw.h" 9 #include "../net/inet_cksum.h" 10 #include "../net/inet.h" 11 #include "../net/inet_systm.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 int raw; 28 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; /* known to be r11 in CKSUM below */ 58 register struct mbuf *m = m0; 59 register int i; 60 register struct ipq *q; 61 register struct ipq *fp; 62 int hlen; 63 64 COUNT(IP_INPUT); 65 /* 66 * Check header and byteswap. 67 */ 68 ip = mtod(m, struct ip *); 69 if ((hlen = ip->ip_hl << 2) > m->m_len) { 70 printf("ip hdr ovflo\n"); 71 m_freem(m); 72 return; 73 } 74 CKSUM_IPCHK(m, ip, r11, hlen); 75 if (ip->ip_sum) { 76 printf("ip_sum %x\n", ip->ip_sum); 77 netstat.ip_badsum++; 78 if (ipcksum) { 79 m_freem(m); 80 return; 81 } 82 } 83 ip->ip_len = ntohs(ip->ip_len); 84 ip->ip_id = ntohs(ip->ip_id); 85 ip->ip_off = ntohs(ip->ip_off); 86 87 /* 88 * Check that the amount of data in the buffers 89 * is as at least much as the IP header would have us expect. 90 * Trim mbufs if longer than we expect. 91 * Drop packet if shorter than we expect. 92 */ 93 i = 0; 94 for (; m != NULL; m = m->m_next) 95 i += m->m_len; 96 m = m0; 97 if (i != ip->ip_len) { 98 if (i < ip->ip_len) { 99 printf("ip_input: short packet\n"); 100 m_freem(m); 101 return; 102 } 103 m_adj(m, ip->ip_len - i); 104 } 105 106 /* 107 * Process options and, if not destined for us, 108 * ship it on. 109 */ 110 if (hlen > sizeof (struct ip)) 111 ip_dooptions(ip, hlen); 112 if (ip->ip_dst.s_addr != n_lhost.s_addr) { 113 if (--ip->ip_ttl == 0) { 114 icmp_error(ip, ICMP_TIMXCEED); 115 return; 116 } 117 ip_output(dtom(ip)); 118 return; 119 } 120 121 /* 122 * Look for queue of fragments 123 * of this datagram. 124 */ 125 for (fp = ipq.next; fp != &ipq; fp = fp->next) 126 if (ip->ip_id == fp->ipq_id && 127 ip->ip_src.s_addr == fp->ipq_src.s_addr && 128 ip->ip_dst.s_addr == fp->ipq_dst.s_addr && 129 ip->ip_p == fp->ipq_p) 130 goto found; 131 fp = 0; 132 found: 133 134 /* 135 * Adjust ip_len to not reflect header, 136 * set ip_mff if more fragments are expected, 137 * convert offset of this to bytes. 138 */ 139 ip->ip_len -= hlen; 140 ((struct ipasfrag *)ip)->ipf_mff = 0; 141 if (ip->ip_off & IP_MF) 142 ((struct ipasfrag *)ip)->ipf_mff = 1; 143 ip->ip_off <<= 3; 144 145 /* 146 * If datagram marked as having more fragments 147 * or if this is not the first fragment, 148 * attempt reassembly; if it succeeds, proceed. 149 */ 150 if (((struct ipasfrag *)ip)->ipf_mff || ip->ip_off) { 151 ip = ip_reass((struct ipasfrag *)ip, fp); 152 if (ip == 0) 153 return; 154 hlen = ip->ip_hl << 2; 155 m = dtom(ip); 156 } else 157 if (fp) 158 (void) ip_freef(fp); 159 (*protosw[ip_protox[ip->ip_p]].pr_input)(m); 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 ipasfrag *ip; 171 register struct ipq *fp; 172 { 173 register struct mbuf *m = dtom(ip); 174 register struct ipasfrag *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 ipasfrag *)fp; 199 fp->ipq_src = ((struct ip *)ip)->ip_src; 200 fp->ipq_dst = ((struct ip *)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 ipasfrag *)fp; q = q->ipf_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->ipf_prev != (struct ipasfrag *)fp) { 216 i = q->ipf_prev->ip_off + q->ipf_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 ipasfrag *)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->ipf_next; 238 m_freem(dtom(q->ipf_prev)); 239 ip_deq(q->ipf_prev); 240 } 241 242 /* 243 * Stick new segment in its place; 244 * check for complete reassembly. 245 */ 246 ip_enq(ip, q->ipf_prev); 247 next = 0; 248 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { 249 if (q->ip_off != next) 250 return (0); 251 next += q->ip_len; 252 } 253 if (q->ipf_prev->ipf_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->ipf_next) != (struct ipasfrag *)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 ((struct ip *)ip)->ip_src = fp->ipq_src; 276 ((struct ip *)ip)->ip_dst = fp->ipq_dst; 277 remque(fp); 278 m_free(dtom(fp)); 279 m = dtom(ip); 280 m->m_len += sizeof (struct ipasfrag); 281 m->m_off -= sizeof (struct ipasfrag); 282 return ((struct ip *)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 ipasfrag *q; 298 struct mbuf *m; 299 300 for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_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 ipasfrag *p, *prev; 315 { 316 COUNT(IP_ENQ); 317 318 p->ipf_prev = prev; 319 p->ipf_next = prev->ipf_next; 320 prev->ipf_next->ipf_prev = p; 321 prev->ipf_next = p; 322 } 323 324 /* 325 * To ip_enq as remque is to insque. 326 */ 327 ip_deq(p) 328 register struct ipasfrag *p; 329 { 330 COUNT(IP_DEQ); 331 332 p->ipf_prev->ipf_next = p->ipf_next; 333 p->ipf_next->ipf_prev = p->ipf_prev; 334 } 335 336 /* 337 * IP timer processing; 338 * if a timer expires on a reassembly 339 * queue, discard it. 340 */ 341 ip_slowtimo() 342 { 343 register struct ipq *fp; 344 int s = splnet(); 345 COUNT(IP_SLOWTIMO); 346 347 for (fp = ipq.next; fp != &ipq; ) 348 if (--fp->ipq_ttl == 0) 349 fp = ip_freef(fp); 350 else 351 fp = fp->next; 352 splx(s); 353 } 354 355 ip_drain() 356 { 357 358 } 359 /* 360 * Do option processing on a datagram, 361 * possibly discarding it if bad options 362 * are encountered. 363 */ 364 ip_dooptions(ip) 365 struct ip *ip; 366 { 367 register u_char *cp; 368 int opt, optlen, cnt, s; 369 struct ip_addr *sp; 370 register struct ip_timestamp *ipt; 371 int x; 372 373 cp = (u_char *)(ip + 1); 374 cnt = (ip->ip_hl << 2) - sizeof (struct ip); 375 for (; cnt > 0; cnt -= optlen, cp += optlen) { 376 opt = cp[0]; 377 if (opt == IPOPT_EOL) 378 break; 379 if (opt == IPOPT_NOP) 380 optlen = 1; 381 else 382 optlen = cp[1]; 383 switch (opt) { 384 385 default: 386 break; 387 388 case IPOPT_LSRR: 389 case IPOPT_SSRR: 390 if (cp[2] < 4 || cp[2] > optlen - (sizeof (long) - 1)) 391 break; 392 sp = (struct ip_addr *)(cp + cp[2]); 393 if (n_lhost.s_addr == *(u_long *)sp) { 394 if (opt == IPOPT_SSRR) { 395 /* MAKE SURE *SP DIRECTLY ACCESSIBLE */ 396 } 397 ip->ip_dst = *sp; 398 *sp = n_lhost; 399 cp[2] += 4; 400 } 401 break; 402 403 case IPOPT_TS: 404 ipt = (struct ip_timestamp *)cp; 405 if (ipt->ipt_len < 5) 406 goto bad; 407 if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) { 408 if (++ipt->ipt_oflw == 0) 409 goto bad; 410 break; 411 } 412 sp = (struct ip_addr *)(cp+cp[2]); 413 switch (ipt->ipt_flg) { 414 415 case IPOPT_TS_TSONLY: 416 break; 417 418 case IPOPT_TS_TSANDADDR: 419 if (ipt->ipt_ptr + 8 > ipt->ipt_len) 420 goto bad; 421 *(struct ip_addr *)sp++ = n_lhost; 422 break; 423 424 case IPOPT_TS_PRESPEC: 425 if (*(u_long *)sp != n_lhost.s_addr) 426 break; 427 if (ipt->ipt_ptr + 8 > ipt->ipt_len) 428 goto bad; 429 ipt->ipt_ptr += 4; 430 break; 431 432 default: 433 goto bad; 434 } 435 *(n_time *)sp = ip_time(); 436 ipt->ipt_ptr += 4; 437 } 438 } 439 return (0); 440 bad: 441 /* SHOULD FORCE ICMP MESSAGE */ 442 return (-1); 443 } 444 445 /* 446 * Strip out IP options, e.g. before passing 447 * to higher level protocol in the kernel. 448 */ 449 ip_stripoptions(ip) 450 struct ip *ip; 451 { 452 register int i; 453 register struct mbuf *m; 454 char *op; 455 int olen; 456 COUNT(IP_OPT); 457 458 olen = (ip->ip_hl<<2) - sizeof (struct ip); 459 op = (caddr_t)ip + olen; 460 m = dtom(++ip); 461 i = m->m_len - (sizeof (struct ip) + olen); 462 bcopy((caddr_t)ip+olen, (caddr_t)ip, i); 463 m->m_len -= i; 464 } 465