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