1 /* ip_input.c 1.2 81/10/14 */ 2 #include "../h/param.h" 3 #include "../bbnnet/net.h" 4 #include "../bbnnet/tcp.h" 5 #include "../bbnnet/ip.h" 6 #include "../bbnnet/ucb.h" 7 8 /***************************************************************************** 9 * * 10 * ip level input routine: called from 1822 level upon receipt * 11 * of an internet datagram or fragment. this routine does * 12 * fragment reassembly, if necessary, and passes completed * 13 * datagrams to higher level protocol processing routines on * 14 * the basis of the ip header protocol field. it is passed a * 15 * pointer to an mbuf chain containing the datagram/fragment. * 16 * the mbuf offset/length are set to point at the ip header. * 17 * * 18 *****************************************************************************/ 19 20 int nosum = 0; 21 22 ip_input(mp) 23 struct mbuf *mp; 24 { 25 register struct ip *ip, *q; 26 register struct ipq *fp; 27 register struct mbuf *m; 28 register i; 29 struct mbuf *n; 30 int hlen; 31 struct ip *p, *savq; 32 struct ipq *ip_findf(); 33 34 COUNT(IP_INPUT); 35 ip = (struct ip *)((int)mp + mp->m_off); /* ->ip hdr */ 36 37 /* make sure header does not overflow mbuf */ 38 39 if ((hlen = ip->ip_hl << 2) > mp->m_len) { 40 printf("ip header overflow\n"); 41 m_freem(mp); 42 return; 43 } 44 45 i = (unsigned short)ip->ip_sum; 46 ip->ip_sum = 0; 47 48 if (i != (unsigned short)cksum(mp, hlen)) { /* verify checksum */ 49 netstat.ip_badsum++; 50 if (!nosum) { 51 m_freem(mp); 52 return; 53 } 54 } 55 56 ip_bswap(ip); /* byte-swap header */ 57 58 netcb.n_ip_lock++; /* lock frag reass.q */ 59 fp = ip_findf(ip); /* look for chain on reass.q with this hdr */ 60 61 /* adjust message length to remove any padding */ 62 63 for (i=0, m=mp; m != NULL; m = m->m_next) { 64 i += m->m_len; 65 n = m; 66 } 67 i -= ip->ip_len; 68 69 if (i != 0) 70 if (i > (int)n->m_len) 71 m_adj(mp, -i); 72 else 73 n->m_len -= i; 74 75 ip->ip_len -= hlen; /* length of data */ 76 ip->ip_mff = ((ip->ip_off & ip_mf) ? TRUE : FALSE); 77 ip->ip_off <<= 3; 78 if (!ip->ip_mff && ip->ip_off == 0) { /* not fragmented */ 79 80 if (fp != NULL) { /* free existing reass.q chain */ 81 82 q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */ 83 while (q != (struct ip *)fp) { 84 m_freem(dtom(q)); 85 q = q->ip_next; 86 } 87 ip_freef(fp); /* free header */ 88 } 89 netcb.n_ip_lock = 0; 90 91 ip_opt(ip, hlen); /* option processing */ 92 i = ip->ip_p; 93 94 /* pass to next level */ 95 96 if (i == TCPROTO) 97 tcp_input(mp); 98 else 99 raw_input(mp, i, UIP); 100 101 } else { /* fragmented */ 102 103 /* -> msg buf beyond ip hdr if not first fragment */ 104 105 if (ip->ip_off != 0) { 106 mp->m_off += hlen; 107 mp->m_len -= hlen; 108 } 109 110 if (fp == NULL) { /* first fragment of datagram in */ 111 112 /* set up reass.q header: enq it, set up as head of frag 113 chain, set a timer value, and move in ip header */ 114 115 if ((m = m_get(1)) == NULL) { /* allocate an mbuf */ 116 m_freem(mp); 117 return; 118 } 119 120 fp = (struct ipq *)((int)m + MHEAD); 121 fp->iqx.ip_next = fp->iqx.ip_prev = (struct ip *)fp; 122 bcopy(ip, &fp->iqh, min(MLEN-28, hlen)); 123 fp->iqh.ip_ttl = MAXTTL; 124 fp->iq_next = NULL; 125 fp->iq_prev = netcb.n_ip_tail; 126 if (netcb.n_ip_head != NULL) 127 netcb.n_ip_tail->iq_next = fp; 128 else 129 netcb.n_ip_head = fp; 130 netcb.n_ip_tail = fp; 131 } 132 133 /*********************************************************** 134 * * 135 * merge fragment into reass.q * 136 * algorithm: match start and end bytes of new * 137 * fragment with fragments on the queue. if no * 138 * overlaps are found, add new frag. to the queue. * 139 * otherwise, adjust start and end of new frag. so no * 140 * overlap and add remainder to queue. if any * 141 * fragments are completely covered by the new one, or * 142 * if the new one is completely duplicated, free the * 143 * fragments. * 144 * * 145 ***********************************************************/ 146 147 q = fp->iqx.ip_next; /* -> top of reass. chain */ 148 ip->ip_end = ip->ip_off + ip->ip_len - 1; 149 150 /* skip frags which new doesn't overlap at end */ 151 152 while ((q != (struct ip *)fp) && (ip->ip_off > q->ip_end)) 153 q = q->ip_next; 154 155 if (q == (struct ip *)fp) /* frag at end of chain */ 156 ip_enq(ip, fp->iqx.ip_prev); 157 158 else { 159 if (ip->ip_end < q->ip_off) /* frag doesn't overlap any on chain */ 160 ip_enq(ip, q->ip_prev); 161 162 /* new overlaps beginning of next frag only */ 163 164 else if (ip->ip_end < q->ip_end) { 165 if ((i = ip->ip_end - q->ip_off + 1) < ip->ip_len) { 166 ip->ip_len -= i; 167 ip->ip_end -= i; 168 m_adj(mp, -i); 169 ip_enq(ip, q->ip_prev); 170 } else 171 m_freem(mp); 172 173 /* new overlaps end of previous frag */ 174 175 } else { 176 177 savq = q; 178 if (ip->ip_off <= q->ip_off) { /* complete cover */ 179 savq = q->ip_prev; 180 ip_deq(q); 181 m_freem(dtom(q)); 182 183 } else { /* overlap */ 184 if ((i = q->ip_end - ip->ip_off + 1) < ip->ip_len) { 185 ip->ip_off += i; 186 ip->ip_len -= i; 187 m_adj(mp, i); 188 } else 189 ip->ip_len = 0; 190 } 191 192 /* new overlaps at beginning of successor frags */ 193 194 q = savq->ip_next; 195 while ((q != (struct ip *)fp) && (ip->ip_len != 0) && 196 (q->ip_off < ip->ip_end)) 197 198 /* complete cover */ 199 200 if (q->ip_end <= ip->ip_end) { 201 p = q->ip_next; 202 ip_deq(q); 203 m_freem(dtom(q)); 204 q = p; 205 206 } else { /* overlap */ 207 208 if ((i = ip->ip_end - q->ip_off + 1) < ip->ip_len) { 209 ip->ip_len -= i; 210 ip->ip_end -= i; 211 m_adj(mp, -i); 212 } else 213 ip->ip_len = 0; 214 break; 215 } 216 217 /* enqueue whatever is left of new before successors */ 218 219 if (ip->ip_len != 0) 220 ip_enq(ip, savq); 221 else 222 m_freem(mp); 223 } 224 } 225 226 /* check for completed fragment reassembly */ 227 228 if ((i = ip_done(fp)) > 0) { 229 230 p = fp->iqx.ip_next; /* -> top mbuf */ 231 m = dtom(p); 232 p->ip_len = i; /* total data length */ 233 ip_opt(p, p->ip_hl << 2); /* option processing */ 234 ip_mergef(fp); /* cleanup frag chain */ 235 236 /* copy src/dst internet address to header mbuf */ 237 238 bcopy(&fp->iqh.ip_src, &p->ip_src, 2*sizeof(struct socket)); 239 ip_freef(fp); /* dequeue header */ 240 netcb.n_ip_lock = 0; 241 242 /* call next level with completed datagram */ 243 244 i = p->ip_p; 245 if (i == TCPROTO) 246 tcp_input(m); 247 else 248 raw_input(m, i, UIP); 249 } else 250 netcb.n_ip_lock = 0; 251 } 252 } 253 254 255 ip_done(p) /* check to see if fragment reassembly is complete */ 256 register struct ip *p; 257 { 258 register struct ip *q; 259 register next; 260 261 COUNT(IP_DONE); 262 q = p->ip_next; 263 264 if (q->ip_off != 0) 265 return(0); 266 do { 267 next = q->ip_end + 1; 268 q = q->ip_next; 269 } while ((q != p) && (q->ip_off == next)); 270 271 if ((q == p) && !(q->ip_prev->ip_mff)) /* all fragments in */ 272 return(next); /* total data length */ 273 else 274 return(0); 275 } 276 277 ip_mergef(p) /* merge mbufs of fragments of completed datagram */ 278 register struct ip *p; 279 { 280 register struct mbuf *m, *n; 281 register struct ip *q; 282 int dummy; 283 284 COUNT(IP_MERGEF); 285 q = p->ip_next; /* -> bottom of reass chain */ 286 n = (struct mbuf *)&dummy; /* dummy for init assignment */ 287 288 while (q != p) { /* through chain */ 289 290 n->m_next = m = dtom(q); 291 while (m != NULL) 292 if (m->m_len != 0) { 293 n = m; 294 m = m->m_next; 295 } else /* free null mbufs */ 296 n->m_next = m = m_free(m); 297 q = q->ip_next; 298 } 299 } 300 301 302 ip_freef(fp) /* deq and free reass.q header */ 303 register struct ipq *fp; 304 { 305 COUNT(IP_FREEF); 306 if (fp->iq_prev != NULL) 307 (fp->iq_prev)->iq_next = fp->iq_next; 308 else 309 netcb.n_ip_head = fp->iq_next; 310 if (fp->iq_next != NULL) 311 (fp->iq_next)->iq_prev = fp->iq_prev; 312 else 313 netcb.n_ip_tail = fp->iq_prev; 314 m_free(dtom(fp)); 315 } 316 317 struct ipq *ip_findf(p) /* does fragment reass chain w/this hdr exist? */ 318 register struct ip *p; 319 { 320 register struct ipq *fp; 321 322 COUNT(IP_FINDF); 323 for (fp = netcb.n_ip_head; (fp != NULL && ( 324 p->ip_src.s_addr != fp->iqh.ip_src.s_addr || 325 p->ip_dst.s_addr != fp->iqh.ip_dst.s_addr || 326 p->ip_id != fp->iqh.ip_id || 327 p->ip_p != fp->iqh.ip_p)); fp = fp->iq_next); 328 return(fp); 329 } 330 331 ip_opt(ip, hlen) /* process ip options */ 332 struct ip *ip; 333 int hlen; 334 { 335 register char *p, *q; 336 register i, len; 337 register struct mbuf *m; 338 339 COUNT(IP_OPT); 340 p = q = (char *)((int)ip + sizeof(struct ip)); /* -> at options */ 341 342 if ((i = hlen - sizeof(struct ip)) > 0) { /* any options */ 343 344 /* *** IP OPTION PROCESSING *** 345 346 while (i > 0) 347 348 switch (*q++) { 349 case 0: 350 case 1: 351 i--; 352 break; 353 354 default: 355 i -= *q; 356 q += *q; 357 } 358 */ q += i; 359 m = dtom(q); 360 len = (int)m + m->m_off + m->m_len - (int)q; 361 bcopy((caddr_t)q, (caddr_t)p, len); /* remove options */ 362 m->m_len -= i; 363 } 364 } 365 366 ip_enq(p, prev) 367 register struct ip *p; 368 register struct ip *prev; 369 { 370 COUNT(IP_ENQ); 371 p->ip_prev = prev; 372 p->ip_next = prev->ip_next; 373 prev->ip_next->ip_prev = p; 374 prev->ip_next = p; 375 } 376 377 ip_deq(p) 378 register struct ip *p; 379 { 380 COUNT(IP_DEQ); 381 p->ip_prev->ip_next = p->ip_next; 382 p->ip_next->ip_prev = p->ip_prev; 383 } 384 385 ip_timeo() /* frag reass.q timeout routine */ 386 { 387 register struct ip *q; 388 register struct ipq *fp; 389 390 COUNT(IP_TIMEO); 391 timeout(ip_timeo, 0, 60); /* reschedule every second */ 392 393 if (netcb.n_ip_lock) /* reass.q must not be in use */ 394 return; 395 396 /* search through reass.q */ 397 398 for (fp = netcb.n_ip_head; fp != NULL; fp = fp->iq_next) 399 400 if (--(fp->iqx.ip_ttl) == 0) { /* time to die */ 401 402 q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */ 403 while (q != (struct ip *)fp) { 404 m_freem(dtom(q)); 405 q = q->ip_next; 406 } 407 ip_freef(fp); /* free header */ 408 } 409 } 410