1 #ifdef RCSIDENT
2 static char rcsident[] = "$Header: ip_input.c,v 1.39 85/07/31 09:31:26 walsh Exp $";
3 #endif
4
5 #include "../h/param.h"
6 #include "../h/mbuf.h"
7 #include "../h/socket.h"
8 #include "../h/socketvar.h"
9 #include "../h/errno.h"
10 #include "../h/protosw.h"
11 #include "../h/domain.h"
12 #include "../h/syslog.h"
13
14 #include "../net/if.h"
15 #include "../net/route.h"
16 #include "../net/raw_cb.h"
17
18 #include "../bbnnet/in.h"
19 #include "../bbnnet/net.h"
20 #include "../bbnnet/in_pcb.h"
21 #include "../bbnnet/in_var.h"
22 #include "../bbnnet/ip.h"
23 #include "../bbnnet/icmp.h"
24 #ifdef HMP
25 #include "../bbnnet/hmp_traps.h"
26 #endif
27
28 #ifdef RCSIDENT
29 static char rcsiphdr[] = RCSIPHDR;
30 #endif
31
32 #define rawreaders(r) ((r)->rcb_next != (r))
33 #define any_rawreaders() rawreaders(&rawcb)
34
35 #define FIELD_OFF(fld, type) (((char *) (&(((type *) 0)->fld))) - ((char *) 0))
36
37 struct in_stat otherstat;
38 struct ip_stat ipstat;
39 struct {
40 struct ipq *n_ip_head; /* -> top of ip reass. queue */
41 struct ipq *n_ip_tail; /* -> end of ip reass. queue */
42 } ipfrags;
43
44
45 /*
46 * The protocol layers above IP assume the IP header and the protocol
47 * header are contiguous. However, need to save the options in case
48 * a connection oriented protocol (RDP/TCP) wants to respond to an
49 * incoming packet (SYN) over the same route if the packet got here
50 * using IP source routing. This allows connection establishment and
51 * maintenance when the remote end is on a network that is not known
52 * to our gateways. Only applicable options are Loose/Strict source
53 * routing, so rather than saving them in ip_stripopt() and reinterpreting
54 * them, we'll set up something specific and appropriate here.
55 */
56
57 int nosum = 0;
58 int ip_nhops = 0;
59 struct in_addr ip_hops[MAX_IPOPTLEN / sizeof(struct in_addr)];
60
61 /* use a dispatch table for protocol dispatching */
62 struct ipswitch ipsw[IPPROTO_MAX];
63
64 extern struct ip *ip_reass();
65
66
ip_init()67 ip_init()
68 {
69 register struct protosw *pr;
70 register int i;
71
72 pr = pffindproto(PF_INET, IPPROTO_IP, SOCK_RAW);
73
74 /* build our internal switch table */
75 for(i=0; i < IPPROTO_MAX; i++)
76 {
77 ipsw[i].ipsw_raw = pr;
78 ipsw[i].ipsw_user = 0;
79 ipsw[i].ipsw_hlen = sizeof(struct ip);
80 }
81
82 for(pr = inetdomain.dom_protosw; pr < inetdomain.dom_protoswNPROTOSW; pr++)
83 {
84 if (pr->pr_protocol >= IPPROTO_MAX)
85 panic("ip_init");
86
87 if (pr->pr_type == SOCK_RAW)
88 ipsw[pr->pr_protocol].ipsw_raw = pr;
89 else
90 ipsw[pr->pr_protocol].ipsw_user = pr;
91 }
92
93 ipintrq.ifq_maxlen = IFQ_MAXLEN; /* got a better number? */
94 }
95
96 /*
97 * Being global might be a little gross, but we just got the interface pointer
98 * passed up the week before 4.3 release.
99 */
100 struct ifnet *inetifp;
101
102 /*
103 * IP network software interrupt service routine. Dequeue a message from the
104 * ip input queue, and pass to internal ip input processor (ip_input).
105 */
ipintr()106 ipintr()
107 {
108 extern char *panicstr;
109 register struct mbuf *m;
110 register int s;
111
112 /*
113 * Half-hearted attempt to prevent recursive panics due to network
114 * bugs since panic calls boot, which lowers spl. Note that the
115 * drivers will still store packets in mbufs and that some processing
116 * (ARP, Chaosnet) that occurs at splimp() will still proceed. At
117 * least this should preserve state information for post-mortem.
118 */
119 if (panicstr == NULL)
120 {
121 for (;;)
122 {
123 /* for 4.3, Berkeley finally changed imp code to queue up messages
124 * for ctlinput path, so don't need to check for them here with our
125 * old queueing mechanism
126 */
127
128 s = splimp();
129 IF_DEQUEUEIF (&ipintrq, m, inetifp);
130 splx(s);
131 if (m == NULL)
132 return;
133
134 ip_input(m);
135 }
136 }
137 }
138
139 /*
140 * IP level input routine
141 *
142 * Called from local net level upon recpt of an internet datagram or fragment.
143 * This routine does fragment reassembly, if necessary, and passes completed
144 * datagrams to higher level protocol processing routines on the basis of the
145 * ip header protocol field. It is passed a pointer to an mbuf chain
146 * containing the datagram/fragment. The mbuf offset+length are set to point
147 * at the ip header.
148 */
ip_input(mp)149 ip_input(mp)
150 register struct mbuf *mp;
151 {
152 register struct ip *ip;
153 register int hlen;
154 register int i;
155 register struct mbuf *m;
156 register struct ipq *fp;
157 int fragsize = 0;
158 struct in_ifaddr *ia;
159 int j;
160 struct inpcb fwdinp;
161
162 ipstat.ip_total ++;
163 /*
164 * make sure dtom() macro works by getting header out of mbufs using
165 * pages, also make sure header contiguous in first mbuf.
166 */
167 if ((mp->m_off > MMAXOFF) || (mp->m_len < sizeof(struct ip)))
168 {
169 /*
170 * Might as well avoid doing m_pullup twice.
171 * Common case is using cluster for large chunk of data.
172 */
173 if (mp->m_len < FIELD_OFF(ip_p, struct ip) + sizeof(ip->ip_p))
174 i = sizeof(struct ip);
175 else
176 {
177 ip = mtod(mp, struct ip *);
178 i = ipsw[ip->ip_p].ipsw_hlen;
179 }
180
181 if ((mp = m_pullup(mp, i)) == NULL)
182 {
183 ipstat.ip_tooshort ++;
184 return;
185 }
186 }
187
188 ip = mtod(mp, struct ip *);
189
190 /*
191 * make sure header does not overflow mbuf (is contiguous)
192 */
193 hlen = ip->ip_hl << IP_HLSHIFT;
194 if (hlen > mp->m_len)
195 {
196 if ((mp = m_pullup(mp, hlen)) == NULL)
197 {
198 ip_log(ip, "ip header overflow");
199 #ifdef HMPTRAPS
200 /* hmp_trap(T_IP_OVFLO, (caddr_t)0,0); */
201 #else
202 /* netlog(mp); no longer have mbuf list */
203 #endif
204 return;
205 }
206 ip = mtod(mp, struct ip *);
207 }
208
209 /*
210 * Adjust msg length to remove any driver padding. Make sure that
211 * message length matches ip length.
212 */
213 for (i = 0, m = mp; m->m_next != NULL; m = m->m_next)
214 i += m->m_len;
215 i -= ntohs((u_short)ip->ip_len) - m->m_len;
216 if (i != 0)
217 {
218 if (i > (int)m->m_len)
219 m_adj(mp, -i);
220 else if (i < 0)
221 {
222 ip_log(ip, "truncated ip packet");
223 #ifdef HMPTRAPS
224 /* hmp_trap(T_IP_TRUNC, (caddr_t)0, 0); */
225 #else
226 netlog(mp);
227 #endif
228 return;
229 }
230 else
231 m->m_len -= i;
232 }
233
234 i = (u_short)ip->ip_sum;
235 ip->ip_sum = 0;
236
237 /* used to do inline cksum here via sed */
238 if (i != (j = (u_short)in_cksum(dtom(ip), hlen)))
239 {
240 ipstat.ip_badsum++;
241 if (!nosum)
242 {
243 #ifdef HMPTRAPS
244 /* hmp_trap(T_IP_CKSUM, (caddr_t)0,0); */
245 #endif
246 inet_cksum_err ("ip", ip, (u_long) i, (u_long) j);
247
248 ip->ip_sum = i;
249 ic_errmsg (icmp_addr(ip), ip->ip_src,
250 ICMP_PARM, 0, FIELD_OFF(ip_sum, struct ip),
251 hlen + ICMP_ERRLEN, (char *) ip);
252
253 netlog(mp);
254 return;
255 }
256 }
257
258 /*
259 * Make sure this packet is addressed to us before we put fields
260 * in host order and do reassembly (fragments may reach destination
261 * by separate routes.)
262 * Remember that IP source routing option can change ip_dst, so have
263 * to do option processing for all incoming packets with options.
264 * Even if the packet turns out to be for us and we strip them.
265 */
266 fwdinp.inp_route.ro_rt = NULL; /* in case fwd, but no options */
267 ip_nhops = 0; /* for source routed TCP/RDP... connections */
268 if (hlen > sizeof(struct ip))
269 /*
270 * Any route allocated by ip_opt() 1. will be used by
271 * ip_forward(), and 2. will only be needed by ip_forward()
272 */
273 if (! ip_opt (ip, hlen, &fwdinp))
274 {
275 ip_log (ip, "ip option error");
276 netlog (mp);
277 return;
278 }
279
280 /*
281 * if packet is not for us then forward
282 */
283 if ((ia = in_iawithaddr(ip->ip_dst, TRUE)) == NULL)
284 {
285 ip_forward (&fwdinp, ip, mp, hlen);
286 return;
287 }
288
289 ip->ip_len = ntohs((u_short)ip->ip_len);
290 if ((int)(ip->ip_len -= hlen) < 0)
291 { /* length of data */
292 ip_log(ip, "ip header length error");
293 #ifdef HMPTRAPS
294 /* hmp_trap(T_IP_HLEN, (caddr_t)0,0); */
295 #else
296 netlog(mp);
297 #endif
298 return;
299 }
300 ip->ip_off = ntohs((u_short)ip->ip_off);
301 ip->ip_mff = ((ip->ip_off & ip_mf) ? TRUE : FALSE);
302 ip->ip_off <<= IP_OFFSHIFT;
303
304 /* look for chain on reassembly queue with this header */
305
306 for (fp = ipfrags.n_ip_head; (fp != NULL && (
307 ip->ip_src.s_addr != fp->iqh.ip_src.s_addr ||
308 ip->ip_dst.s_addr != fp->iqh.ip_dst.s_addr ||
309 ip->ip_id != fp->iqh.ip_id ||
310 ip->ip_p != fp->iqh.ip_p)); fp = fp->iq_next);
311
312 if (!ip->ip_mff && ip->ip_off == 0)
313 { /* not fragmented */
314
315 if (fp != NULL)
316 { /* free existing reass chain */
317 struct ip *q;
318 struct ip *p;
319
320 q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */
321 while (q != (struct ip *)fp)
322 {
323 p = q->ip_next;
324 m_freem(dtom(q));
325 q = p;
326 }
327 ip_freef(fp); /* free header */
328 }
329
330 /*
331 * The options aren't of any use to higher level
332 * protocols or of any concern to the user process.
333 */
334 if (hlen > sizeof(struct ip))
335 ip_stripopt (ip, hlen);
336
337 }
338 else
339 {
340 ip = ip_reass(ip, fp, &fragsize);
341 if (ip == NULL)
342 return;
343 mp = dtom(ip);
344 }
345
346 /* call next level with completed datagram */
347
348 /* any raw readers?? */
349 /* if (rawreaders((struct rawcb *)ipsw[ip->ip_p].ipsw_raw->pr_ppcbq)) */
350 if (any_rawreaders())
351 {
352 otherstat.in_total++;
353 if (m = m_copy(mp, 0, M_COPYALL))
354 ipsw[ip->ip_p].ipsw_raw->pr_input(m);
355 }
356
357 if (ip->ip_p == IPPROTO_TCP)
358 /* wish I didn't need this special case for fragsize */
359 tcp_input(mp, fragsize);
360 else if (ipsw[ip->ip_p].ipsw_user != 0)
361 /* There's a protocol implementation for these packets */
362 ipsw[ip->ip_p].ipsw_user->pr_input(mp);
363 else if (ip->ip_p == IPPROTO_ICMP)
364 /*
365 * Since don't want user to get a non-raw ICMP socket, did not make
366 * an entry in the protocol jump table; also wanted to be able to
367 * make raw ICMP socket.
368 */
369 icmp (mp);
370 else
371 {
372 /*
373 * Don't bother everyone on the net, and remember some other
374 * host may support the protocol.
375 */
376 if ((!in_broadcast(ip->ip_src)) && (!in_broadcast(ip->ip_dst)))
377 ic_errmsg (icmp_addr(ip), ip->ip_src,
378 ICMP_UNRCH, ICMP_UNRCH_PR, FIELD_OFF(ip_p, struct ip),
379 sizeof(struct ip) + ICMP_ERRLEN, (char *) ip);
380
381 /* get rid of the packet */
382 ipstat.ip_drops++;
383 m_freem(mp);
384 }
385 }
386
387
388 /*
389 * We've received an IP fragment. Try to perform IP reassembly.
390 */
ip_reass(ip,fp,fragsize)391 struct ip *ip_reass(ip, fp, fragsize)
392 register struct ip *ip;
393 register struct ipq *fp;
394 int *fragsize;
395 {
396 register struct ip *q, *savq;
397 register struct mbuf *mp;
398 int hlen;
399 int i;
400
401 mp = dtom(ip);
402 hlen = ip->ip_hl << IP_HLSHIFT;
403
404 if (ip->ip_off != 0)
405 {
406 /*
407 * Only the first fragment retains the IP header.
408 */
409 mp->m_off += hlen;
410 mp->m_len -= hlen;
411 }
412
413 if (fp == NULL)
414 {
415 /*
416 * This is the first fragment of the IP datagram that we've
417 * received. Set up reassembly q header.
418 */
419 struct mbuf *m;
420
421 if ((m = m_get(M_WAIT, MT_FTABLE)) == NULL)
422 {
423 m_freem(mp);
424 return(NULL);
425 }
426
427 fp = mtod(m, struct ipq *);
428 fp->iqx.ip_next = fp->iqx.ip_prev = (struct ip *)fp;
429 bcopy((caddr_t)ip, (caddr_t)&fp->iqh, sizeof(struct ip));
430 fp->iqx.ip_ttl = MAXTTL;
431 fp->iq_size = 0;
432 /*
433 * and enter this into the list of fragmented IP datagrams
434 */
435 fp->iq_next = NULL;
436 fp->iq_prev = ipfrags.n_ip_tail;
437 if (ipfrags.n_ip_head != NULL)
438 ipfrags.n_ip_tail->iq_next = fp;
439 else
440 ipfrags.n_ip_head = fp;
441 ipfrags.n_ip_tail = fp;
442 }
443
444 /*
445 * Merge fragment into reass.q
446 *
447 * Algorithm: Match start and end bytes of new
448 * fragment with fragments on the queue. If no
449 * overlaps are found, add new frag. to the queue.
450 * Otherwise, adjust start and end of new frag. so no
451 * overlap and add remainder to queue. If any
452 * fragments are completely covered by the new one, or
453 * if the new one is completely duplicated, free the
454 * fragments.
455 */
456 q = fp->iqx.ip_next; /* -> top of reass. chain */
457 ip->ip_end = ip->ip_off + ip->ip_len - 1;
458
459 /* record the maximum fragment size for TCP */
460
461 fp->iq_size = MAX(ip->ip_len, fp->iq_size);
462
463 /* skip frags which new doesn't overlap at end */
464
465 while ((q != (struct ip *)fp) && (ip->ip_off > q->ip_end))
466 q = q->ip_next;
467
468 if (q == (struct ip *)fp)
469 { /* frag at end of chain */
470 ip_enq(ip, fp->iqx.ip_prev);
471 }
472 else
473 { /* frag doesn't overlap any */
474 if (ip->ip_end < q->ip_off)
475 {
476 ip_enq(ip, q->ip_prev);
477
478 /* new overlaps beginning of next frag only */
479
480 }
481 else if (ip->ip_end < q->ip_end)
482 {
483 if ((i = ip->ip_end-q->ip_off+1) < ip->ip_len)
484 {
485 ip->ip_len -= i;
486 ip->ip_end -= i;
487 m_adj(mp, -i);
488 ip_enq(ip, q->ip_prev);
489 }
490 else
491 m_freem(mp);
492
493 /* new overlaps end of previous frag */
494
495 }
496 else
497 {
498 savq = q;
499 if (ip->ip_off <= q->ip_off)
500 {
501
502 /* complete cover */
503
504 savq = q->ip_prev;
505 ip_deq(q);
506 m_freem(dtom(q));
507
508 }
509 else
510 { /* overlap */
511 if ((i = q->ip_end-ip->ip_off+1)
512 < ip->ip_len)
513 {
514 ip->ip_off += i;
515 ip->ip_len -= i;
516 m_adj(mp, i);
517 }
518 else
519 ip->ip_len = 0;
520 }
521
522 /* new overlaps at beginning of successor frags */
523
524 q = savq->ip_next;
525 while ((q != (struct ip *)fp) &&
526 (ip->ip_len != 0) &&
527 (q->ip_off <= ip->ip_end))
528
529 /* complete cover */
530
531 if (q->ip_end <= ip->ip_end)
532 {
533 struct ip *next;
534
535 next = q->ip_next;
536 ip_deq(q);
537 m_freem(dtom(q));
538 q = next;
539 }
540 else
541 { /* overlap */
542 if ((i = ip->ip_end-q->ip_off+1) < ip->ip_len)
543 {
544 ip->ip_len -= i;
545 ip->ip_end -= i;
546 m_adj(mp, -i);
547 }
548 else
549 ip->ip_len = 0;
550 break;
551 }
552
553 /* enqueue whatever is left of new before successors */
554
555 if (ip->ip_len != 0)
556 {
557 ip_enq(ip, savq);
558 }
559 else
560 m_freem(mp);
561 }
562 }
563
564 /* check for completed fragment reassembly */
565
566 if ((i = ip_done(&fp->iqx)) == 0)
567 return(NULL);
568
569 ip = fp->iqx.ip_next; /* -> top mbuf */
570 ip->ip_len = i; /* total data length */
571 *fragsize = fp->iq_size; /* remember for TCP */
572 /* option processing */
573
574 if ((hlen = ip->ip_hl<<IP_HLSHIFT) > sizeof(struct ip))
575 ip_stripopt (ip, hlen);
576
577 ip_mergef(&fp->iqx); /* clean frag chain */
578
579 /* copy src/dst internet address to header mbuf */
580
581 ip->ip_src = fp->iqh.ip_src;
582 ip->ip_dst = fp->iqh.ip_dst;
583
584 ip_freef(fp); /* dequeue header */
585 return(ip);
586 }
587
588 /*
589 * Let people control gateway action by patching this:
590 */
591 int ip_forwarding = FALSE;
592
593 /*
594 * Try to forward the packet. Act like a gateway.
595 */
596 ip_forward (fwdinp, ip, mp, hlen)
597 struct inpcb *fwdinp;
598 register struct ip *ip;
599 struct mbuf *mp;
600 int hlen;
601 {
602 register int type, code;
603 register u_short len;
604 register struct mbuf *mcopy;
605 register unsigned icmplen;
606 int error;
607
608 /*
609 * Also copy forwarded packets, just like copy TCP/UDP/RDP...
610 * packets sent to us so that can debug gateway action problems.
611 * It's easy enough for the user-level program to filter these
612 * out.
613 */
614 if (any_rawreaders())
615 if (mcopy = m_copy(mp, 0, M_COPYALL))
616 raw_ip_input (mcopy);
617
618 if (ip->ip_ttl)
619 ip->ip_ttl --;
620
621 len = ntohs(ip->ip_len);
622 icmplen = MIN(len, hlen + ICMP_ERRLEN);
623
624 if (ip_forwarding && ip->ip_ttl)
625 {
626 /*
627 * Save chunk of ip packet in case there is an error
628 */
629 mcopy = m_copy (mp, 0, (int)icmplen);
630
631 /*
632 * The packet is not sourced by the local machine, so
633 * save ourselves a useless call to ip_route in ip_send().
634 * Also, don't want ip_send to work if sending from
635 * 8.7.0.2 to 192.1.11.1 via 8.0.0.16, and 8.0.0.16
636 * knows about a default gateway on net 8. This can
637 * cause an ENETUNREACH if 192.1.11 is not a network
638 * that default gateway knows about. [8.0.0.16 is on
639 * 192.1.11 and ip_route uses default gateway on net 8
640 * while rtalloc uses local interface]
641 *
642 * This route should be found by rtalloc, so let's do
643 * it here.
644 */
645 if (fwdinp->inp_route.ro_rt == NULL)
646 {
647 /* Isn't a source routed packet */
648 struct rtentry *rt;
649 struct sockaddr_in *sin;
650
651 bzero ((caddr_t) fwdinp, sizeof(*fwdinp));
652 sin = (struct sockaddr_in *) &fwdinp->inp_route.ro_dst;
653 sin->sin_family = AF_INET;
654 sin->sin_addr = ip->ip_dst;
655 rtalloc (&fwdinp->inp_route);
656
657 /*
658 * Check to see if should send ICMP redirect. Don't
659 * send redirect if source routing was used.
660 */
661 if ((rt = fwdinp->inp_route.ro_rt) != NULL)
662 {
663 sin = (struct sockaddr_in *) &rt->rt_gateway;
664 if (! (rt->rt_flags & (RTF_GATEWAY|RTF_HOST)))
665 send_redirect (ip, ip->ip_dst, ICMP_REDIR_HOST, icmplen);
666 else if (iptonet(ip->ip_src) == iptonet(sin->sin_addr))
667 send_redirect (ip, sin->sin_addr, ICMP_REDIR_NET, icmplen);
668 }
669 }
670
671 if (fwdinp->inp_route.ro_rt == NULL)
672 {
673 /* no way to get there from here */
674 m_freem(mp);
675 type = ICMP_UNRCH;
676 code = ICMP_UNRCH_NET;
677 }
678 else
679 {
680 error = ip_send (fwdinp, mp, (int)len, TRUE);
681 rtfree(fwdinp->inp_route.ro_rt);
682 fwdinp->inp_route.ro_rt = NULL;
683
684 if (! error)
685 {
686 ipstat.ip_forwarded ++;
687 if (mcopy)
688 m_freem(mcopy);
689 return;
690 }
691
692 type = ICMP_UNRCH;
693 switch (error)
694 {
695 case ENETUNREACH:
696 case ENETDOWN:
697 code = ICMP_UNRCH_NET;
698 break;
699 case EMSGSIZE:
700 code = ICMP_UNRCH_FRAG;
701 break;
702 case EHOSTDOWN:
703 case EHOSTUNREACH:
704 code = ICMP_UNRCH_HOST;
705 break;
706
707 case ENOBUFS:
708 type = ICMP_SRCQ;
709 break;
710
711 default:
712 log(LOG_INFO, "ip_forward: error %d\n", error);
713 }
714 }
715 }
716 else
717 {
718 if (ip->ip_ttl == 0)
719 {
720 type = ICMP_TIMEX;
721 code = ICMP_TIMEX_XMT;
722 }
723 else
724 {
725 type = ICMP_UNRCH;
726 code = ICMP_UNRCH_NET;
727 }
728 mcopy = mp;
729 if (fwdinp->inp_route.ro_rt)
730 {
731 /* was source routed by IP option */
732 rtfree (fwdinp->inp_route.ro_rt);
733 fwdinp->inp_route.ro_rt = NULL;
734 }
735 }
736
737 if (mcopy)
738 {
739 ip = mtod(mcopy, struct ip *);
740 ic_errmsg (redir_addr(ip), ip->ip_src, type, code, 0, icmplen, (char *) ip);
741 #ifdef HMPTRAPS
742 /* hmp_trap(T_IP_ADDRS, (caddr_t) 0, 0); */
743 #else
744 if (ip_forwarding)
745 /*
746 * If not acting as a gateway, don't want some one else's
747 * misconception to flood our console or logfile. This error
748 * can be found through netstat an ip_drops.
749 */
750 ip_log(ip, "ip forwarding error");
751 netlog(mcopy);
752 #endif
753 }
754
755 ipstat.ip_drops++;
756 }
757
758
759 /*
760 * Check to see if fragment reassembly is complete
761 */
ip_done(p)762 ip_done(p)
763 register struct ip *p;
764 {
765 register struct ip *q;
766 register next;
767
768 q = p->ip_next;
769
770 if (q->ip_off != 0)
771 return(0);
772 do
773 {
774 next = q->ip_end + 1;
775 q = q->ip_next;
776 }
777 while ((q != p) && (q->ip_off == next));
778
779 if ((q == p) && !(q->ip_prev->ip_mff)) /* all fragments in */
780 return(next); /* total data length */
781 else
782 return(0);
783 }
784
785 /*
786 * Merge mbufs of fragments of completed datagram
787 */
ip_mergef(p)788 ip_mergef(p)
789 register struct ip *p;
790 {
791 register struct mbuf *m, *n;
792 register struct ip *q;
793 int dummy;
794
795 q = p->ip_next; /* -> bottom of reass chain */
796 n = (struct mbuf *)&dummy; /* dummy for init assignment */
797
798 while (q != p)
799 { /* through chain */
800 /*
801 * If free mbuf holding q, cannot access q->ip_next in case
802 * that mbuf is used by device code for an incoming packet.
803 */
804 register struct ip *next;
805
806 next = q->ip_next;
807 n->m_next = m = dtom(q);
808 while (m != NULL)
809 {
810 if (m->m_len != 0)
811 {
812 n = m;
813 m = m->m_next;
814 }
815 else /* free null mbufs */
816 n->m_next = m = m_free(m);
817 }
818 q = next;
819 }
820 }
821
822 /*
823 * Dequeue and free reass.q header
824 */
ip_freef(fp)825 ip_freef(fp)
826 register struct ipq *fp;
827 {
828 if (fp->iq_prev != NULL)
829 (fp->iq_prev)->iq_next = fp->iq_next;
830 else
831 ipfrags.n_ip_head = fp->iq_next;
832
833 if (fp->iq_next != NULL)
834 (fp->iq_next)->iq_prev = fp->iq_prev;
835 else
836 ipfrags.n_ip_tail = fp->iq_prev;
837
838 m_free(dtom(fp));
839 }
840
841 ip_stripopt (ip, hlen)
842 struct ip *ip;
843 int hlen;
844 {
845 int optlen;
846
847 if ((optlen = (hlen - sizeof(struct ip))) > 0)
848 {
849 struct mbuf *m;
850 caddr_t end_of_ip, end_of_opt;
851 unsigned len;
852
853 m = dtom(ip);
854 end_of_ip = (char *) (ip +1);
855 end_of_opt = end_of_ip + optlen;
856 len = m->m_len - hlen;
857 bcopy (end_of_opt, end_of_ip, len);
858 m->m_len -= optlen;
859 }
860 }
861
862 /*
863 * Process ip options
864 * FALSE -> options were in error, and an icmp message has been sent
865 */
866 #define OFF_OLEN 1
867 #define OFF_OFFSET 2
868 #define MIN_OFF 4 /* since option is a 1, not 0, based array */
869
870 /*
871 * Record route in same form as ip_setopt()
872 */
save_rte(option,dst)873 save_rte (option, dst)
874 u_char *option;
875 struct in_addr dst;
876 {
877 int olen;
878 int off;
879 u_char *x;
880 struct in_addr *p, *q;
881
882 if (ip_nhops != 0)
883 {
884 /* Use both loose and strict source routing? */
885 log(LOG_INFO, "ip_nhops %d\n", ip_nhops);
886 ip_nhops = 0;
887 return;
888 }
889 olen = option[OFF_OLEN];
890 if (olen > sizeof(ip_hops))
891 {
892 log(LOG_INFO, "save_rte: olen %d\n", olen);
893 return;
894 }
895 off = option[OFF_OFFSET];
896 p = (struct in_addr *) (&option[off - 1]);
897 q = (struct in_addr *) (&option[MIN_OFF -1]);
898
899 x = (u_char *) ip_hops;
900 x[0] = IP_NOP_OPT;
901 x[1] = option[0]; /* loose/strict source routing */
902 x[2] = (p - q) * sizeof(struct in_addr) + 3;
903 x[3] = MIN_OFF;
904 ip_nhops ++; /* = 1 (1 long for opt hdr) */
905 p--; /* p points at first hop for return route */
906
907 ip_hops[p-q+2] = (*p); /* save first hop after return route option */
908 p--; /* it is in what will be ip_hops[ip_nhops] */
909
910 /* record return path as an IP source route */
911 while (p >= q)
912 {
913 ip_hops[ip_nhops] = (*p);
914 p--;
915 ip_nhops ++;
916 }
917 /* remember eventual destination is in the option field */
918 ip_hops[ip_nhops] = dst;
919 ip_nhops ++;
920 }
921
ip_opt(ip,hlen,fwdinp)922 ip_opt (ip, hlen, fwdinp)
923 register struct ip *ip;
924 struct inpcb *fwdinp;
925 {
926 register u_char *endopt;
927 register u_char *option;
928 register int olen;
929 register int off;
930 int type;
931 int code;
932 struct in_addr nexthop;
933 struct in_ifaddr *ia;
934
935 endopt = ((u_char *) ip) + hlen;
936 option = (u_char *) (ip +1);
937
938 while (option < endopt)
939 {
940 switch (*option)
941 {
942 case IP_END_OPT:
943 return (TRUE);
944
945 case IP_NOP_OPT:
946 olen = sizeof(u_char);
947 break;
948
949 case IP_SEC_OPT:
950 olen = option[OFF_OLEN];
951 /* so much for security */
952 break;
953
954 case IP_LRTE_OPT:
955 olen = option[OFF_OLEN];
956 off = option[OFF_OFFSET];
957 if (off < MIN_OFF)
958 {
959 type = ICMP_PARM;
960 code = &option[OFF_OFFSET] - ((u_char *) ip);
961 goto err;
962 }
963 off--; /* adjust for use by C */
964 if (in_iawithaddr(ip->ip_dst, TRUE) == NULL)
965 /*
966 * With loose routing, may take a few hops
967 * to get to current nexthop.
968 */
969 break;
970
971 if (off > (olen - sizeof(struct in_addr)))
972 {
973 /* hints all used up. pkt for us */
974 save_rte (option, ip->ip_src);
975 break;
976 }
977
978 nexthop = *((struct in_addr *) (option + off));
979
980 /*
981 * record outgoing interface
982 */
983 if (! ip_opt_route(fwdinp, nexthop))
984 {
985 type = ICMP_UNRCH;
986 /* net? frag? host? */
987 code = ICMP_UNRCH_SRC;
988 goto err;
989 }
990 ip->ip_dst = nexthop;
991 option[OFF_OFFSET] += sizeof(struct in_addr);
992 if (fwdinp->inp_route.ro_rt == NULL)
993 /*
994 * Destined for ourselves, and we're
995 * just going to strip the options off
996 */
997 break;
998 *((struct in_addr *) (option + off)) =
999 IA_INADDR(in_iafromif (fwdinp->inp_route.ro_rt->rt_ifp));
1000 break;
1001
1002 case IP_SRTE_OPT:
1003 olen = option[OFF_OLEN];
1004 off = option[OFF_OFFSET];
1005 if (off < MIN_OFF)
1006 {
1007 type = ICMP_PARM;
1008 code = &option[OFF_OFFSET] - ((u_char *) ip);
1009 goto err;
1010 }
1011 off--; /* adjust for use by C */
1012 if (in_iawithaddr(ip->ip_dst, TRUE) == NULL)
1013 {
1014 /* strict path -> someone goofed */
1015 /* should have come in on us for us */
1016 type = ICMP_UNRCH;
1017 code = ICMP_UNRCH_SRC;
1018 goto err;
1019 }
1020
1021 if (off > (olen - sizeof(struct in_addr)))
1022 {
1023 /* hints all used up */
1024 save_rte (option, ip->ip_src);
1025 break;
1026 }
1027
1028 nexthop = *((struct in_addr *) (option + off));
1029
1030 if ((ia = in_iawithnet(nexthop)) == NULL)
1031 {
1032 /* strict path -> someone goofed
1033 * we should be directly connected to
1034 * next hop
1035 */
1036 type = ICMP_UNRCH;
1037 code = ICMP_UNRCH_SRC;
1038 goto err;
1039 }
1040 *((struct in_addr *) (option + off)) = IA_INADDR(ia);
1041
1042 ip->ip_dst = nexthop;
1043
1044 option[OFF_OFFSET] += sizeof(struct in_addr);
1045 break;
1046
1047 case IP_TIME_OPT:
1048 olen = option[OFF_OLEN];
1049 off = option[OFF_OFFSET];
1050 if (off < MIN_OFF)
1051 {
1052 type = ICMP_PARM;
1053 code = &option[OFF_OFFSET] - ((u_char *) ip);
1054 goto err;
1055 }
1056 off--; /* adjust for use by C */
1057 if (off > (olen - sizeof(u_long)))
1058 {
1059 /* increment overflow count */
1060 if ((option[3] & 0xf0) == 0xf0)
1061 {
1062 /* overflow overflowed */
1063 type = ICMP_PARM;
1064 code = &option[OFF_OLEN] - ((u_char *) ip);
1065 goto err;
1066 }
1067 option[3] += 0x10;
1068 break;
1069 }
1070
1071 if (option[3] & 2)
1072 {
1073 /* want specific host to stamp */
1074 ia = in_iawithaddr(*((struct in_addr *) (option + off)), FALSE);
1075 if (ia == NULL)
1076 break;
1077 }
1078 else
1079 ia = in_ifaddr;
1080
1081 if (option[3] & 1)
1082 {
1083 /* record stamping host */
1084 *((struct in_addr *) (option + off)) = IA_INADDR (ia);
1085 off += sizeof(struct in_addr);
1086 option[OFF_OFFSET] += sizeof(struct in_addr);
1087 }
1088 if (off > (olen - sizeof(u_long)))
1089 {
1090 option[3] += 0x10;
1091 break;
1092 }
1093 *((u_long *) (option + off)) = iptime();
1094 option[OFF_OFFSET] += sizeof(u_long);
1095 break;
1096
1097 case IP_STRID_OPT:
1098 olen = option[OFF_OLEN];
1099 break;
1100
1101 case IP_RRTE_OPT:
1102 olen = option[OFF_OLEN];
1103 off = option[OFF_OFFSET];
1104 if (off < MIN_OFF)
1105 {
1106 type = ICMP_PARM;
1107 code = &option[OFF_OFFSET] - ((u_char *) ip);
1108 goto err;
1109 }
1110 off--; /* adjust for use by C */
1111 if (off > (olen - sizeof(u_long)))
1112 /* no space left for recording route */
1113 break;
1114
1115 /* record outgoing interface */
1116 if (! ip_opt_route(fwdinp, ip->ip_dst))
1117 {
1118 type = ICMP_UNRCH;
1119 code = ICMP_UNRCH_NET;
1120 goto err;
1121 }
1122 option[OFF_OFFSET] += sizeof(struct in_addr);
1123 if (fwdinp->inp_route.ro_rt == NULL)
1124 /*
1125 * Destined for us, and we're just
1126 * going to strip options off
1127 */
1128 break;
1129 *((struct in_addr *) (option + off)) =
1130 IA_INADDR(in_iafromif (fwdinp->inp_route.ro_rt->rt_ifp));
1131 break;
1132 }
1133
1134 option += olen;
1135 }
1136 return (TRUE);
1137
1138 err :
1139 ic_errmsg (icmp_addr(ip), ip->ip_src,
1140 type, code, option - ((u_char *) ip), hlen, (char *) ip);
1141 return (FALSE);
1142 }
1143 #undef OFF_OLEN
1144 #undef OFF_OFFSET
1145 #undef MIN_OFF
1146
1147
ip_opt_route(fwdinp,dst)1148 ip_opt_route (fwdinp, dst)
1149 register struct inpcb *fwdinp;
1150 struct in_addr dst;
1151 {
1152 register struct sockaddr_in *sin;
1153
1154 /* in case they use several options involving routing */
1155 if (fwdinp->inp_route.ro_rt)
1156 return (TRUE);
1157
1158 bzero ((caddr_t) fwdinp, sizeof(*fwdinp));
1159
1160 sin = (struct sockaddr_in *) &fwdinp->inp_route.ro_dst;
1161
1162 /* not sure ip_send cares about this stuff ... */
1163 sin->sin_family = AF_INET;
1164 sin->sin_addr = dst;
1165
1166 /* Don't allocate route if not forwarding packet.
1167 * This saves us from doing a check in ip_input() to see
1168 * if we should do a rtfree() for an uncommon occurrence.
1169 */
1170
1171 if (in_iawithaddr(dst, TRUE) != NULL)
1172 return (TRUE);
1173
1174 rtalloc (&fwdinp->inp_route);
1175 return (fwdinp->inp_route.ro_rt != NULL);
1176 }
1177
1178
1179 /*
1180 * IP fragment reassembly timeout routine.
1181 */
ip_timeo()1182 ip_timeo()
1183 {
1184 register struct ip *p, *q;
1185 register struct ipq *fp, *next;
1186 register int s;
1187
1188 static int timflag;
1189
1190 /* check once per sec */
1191
1192 if (timflag = !timflag) /* looks strange, doesn't it? */
1193 return;
1194
1195
1196 /* search through reass.q */
1197 s = splnet();
1198 for (fp = ipfrags.n_ip_head; fp != NULL; fp = next)
1199 {
1200 /*
1201 * If fragment times out, mbufs are freed, and can't
1202 * use next pointer since mbuf may be grabbed by
1203 * an interface at splimp
1204 */
1205 next = fp->iq_next;
1206
1207 if (--(fp->iqx.ip_ttl) == 0)
1208 { /* time to die */
1209
1210 q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */
1211 while (q != (struct ip *)fp)
1212 {
1213 p = q->ip_next;
1214 /* ### generate timed out in reassembly msg */
1215 #ifdef HMPTRAPS
1216 /* hmp_trap(T_IP_FDROP, (caddr_t)0,0); */
1217 #else
1218 m_freem(dtom(q));
1219 #endif
1220 q = p;
1221 }
1222 ip_freef(fp); /* free header */
1223 }
1224 }
1225 splx(s);
1226 }
1227
1228 /*
1229 * Called at splimp from uipc_mbuf.c
1230 * Network code needs to free up space! IP fragments dropped.
1231 */
ip_drain()1232 ip_drain()
1233 {
1234 register struct ip *p, *q;
1235 register struct ipq *fp;
1236
1237 while (fp = ipfrags.n_ip_head)
1238 {
1239 q = fp->iqx.ip_next; /* free mbufs assoc w/chain */
1240 while (q != (struct ip *)fp)
1241 {
1242 p = q->ip_next;
1243 m_freem(dtom(q));
1244 q = p;
1245 }
1246 ip_freef(fp); /* free header */
1247 }
1248 }
1249
1250 #include "../h/syslog.h"
1251
inet_cksum_err(protoname,ip,was,should_be)1252 inet_cksum_err (protoname, ip, was, should_be)
1253 char *protoname;
1254 struct ip *ip;
1255 u_long was;
1256 u_long should_be;
1257 {
1258 union { u_long ul; u_char c[4]; } s, d;
1259
1260 s.ul = ip->ip_src.s_addr;
1261 d.ul = ip->ip_dst.s_addr;
1262 log (LOG_INFO,
1263 "%s checksum was 0x%x not 0x%x src %d.%d.%d.%d dst %d.%d.%d.%d\n",
1264 protoname, was, should_be,
1265 s.c[0], s.c[1], s.c[2], s.c[3],
1266 d.c[0], d.c[1], d.c[2], d.c[3]);
1267 }
1268
1269 ip_log(ip, emsg)
1270 struct ip *ip;
1271 char *emsg;
1272 {
1273 union { u_long ul; u_char c[4]; } s, d;
1274
1275 s.ul = ip->ip_src.s_addr;
1276 d.ul = ip->ip_dst.s_addr;
1277 log(LOG_INFO, "%s: src %d.%d.%d.%d dst %d.%d.%d.%d\n",
1278 emsg,
1279 s.c[0], s.c[1], s.c[2], s.c[3],
1280 d.c[0], d.c[1], d.c[2], d.c[3]);
1281 }
1282
no_route(msg,from,to)1283 no_route (msg, from, to)
1284 char *msg;
1285 struct in_addr from;
1286 struct in_addr to;
1287 {
1288 union { u_long ul; u_char c[4]; } f, t;
1289
1290 f.ul = from.s_addr;
1291 t.ul = to.s_addr;
1292 log(LOG_INFO, "%s: no route %d.%d.%d.%d -> %d.%d.%d.%d\n",
1293 msg,
1294 f.c[0], f.c[1], f.c[2], f.c[3],
1295 t.c[0], t.c[1], t.c[2], t.c[3]);
1296 }
1297