Deleted Added
sdiff udiff text old ( 54221 ) new ( 55009 )
full compact
1/*
2 * Copyright (c) 1982, 1986, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 17 unchanged lines hidden (view full) ---

26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
34 * $FreeBSD: head/sys/netinet/ip_input.c 54221 1999-12-06 20:36:50Z guido $
35 */
36
37#define _IP_VHL
38
39#include "opt_bootp.h"
40#include "opt_ipfw.h"
41#include "opt_ipdn.h"
42#include "opt_ipdivert.h"
43#include "opt_ipfilter.h"
44#include "opt_ipstealth.h"
45
46#include <stddef.h>
47
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/mbuf.h>
51#include <sys/malloc.h>
52#include <sys/domain.h>

--- 14 unchanged lines hidden (view full) ---

67#include <netinet/in_systm.h>
68#include <netinet/in_var.h>
69#include <netinet/ip.h>
70#include <netinet/in_pcb.h>
71#include <netinet/ip_var.h>
72#include <netinet/ip_icmp.h>
73#include <machine/in_cksum.h>
74
75#include <sys/socketvar.h>
76
77#include <netinet/ip_fw.h>
78
79#ifdef DUMMYNET
80#include <netinet/ip_dummynet.h>
81#endif
82
83int rsvp_on = 0;
84static int ip_rsvp_on;
85struct socket *ip_rsvpd;
86

--- 12 unchanged lines hidden (view full) ---

99static int ip_dosourceroute = 0;
100SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW,
101 &ip_dosourceroute, 0, "Enable forwarding source routed IP packets");
102
103static int ip_acceptsourceroute = 0;
104SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute,
105 CTLFLAG_RW, &ip_acceptsourceroute, 0,
106 "Enable accepting source routed IP packets");
107#ifdef DIAGNOSTIC
108static int ipprintfs = 0;
109#endif
110
111extern struct domain inetdomain;
112extern struct protosw inetsw[];
113u_char ip_protox[IPPROTO_MAX];
114static int ipqmaxlen = IFQ_MAXLEN;
115struct in_ifaddrhead in_ifaddrhead; /* first inet address */
116struct ifqueue ipintrq;
117SYSCTL_INT(_net_inet_ip, IPCTL_INTRQMAXLEN, intr_queue_maxlen, CTLFLAG_RW,
118 &ipintrq.ifq_maxlen, 0, "Maximum size of the IP input queue");
119SYSCTL_INT(_net_inet_ip, IPCTL_INTRQDROPS, intr_queue_drops, CTLFLAG_RD,
120 &ipintrq.ifq_drops, 0, "Number of packets dropped from the IP input queue");

--- 55 unchanged lines hidden (view full) ---

176
177struct sockaddr_in *ip_fw_fwd_addr;
178
179static void save_rte __P((u_char *, struct in_addr));
180static int ip_dooptions __P((struct mbuf *));
181static void ip_forward __P((struct mbuf *, int));
182static void ip_freef __P((struct ipq *));
183#ifdef IPDIVERT
184static struct ip *ip_reass __P((struct mbuf *,
185 struct ipq *, struct ipq *, u_int32_t *, u_int16_t *));
186#else
187static struct ip *ip_reass __P((struct mbuf *, struct ipq *, struct ipq *));
188#endif
189static struct in_ifaddr *ip_rtaddr __P((struct in_addr));
190static void ipintr __P((void));
191
192/*
193 * IP initialization: fill in IP protocol switch table.
194 * All protocols not implemented in kernel go to raw IP protocol handler.
195 */
196void
197ip_init()
198{
199 register struct protosw *pr;
200 register int i;
201
202 TAILQ_INIT(&in_ifaddrhead);
203 pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
204 if (pr == 0)
205 panic("ip_init");
206 for (i = 0; i < IPPROTO_MAX; i++)
207 ip_protox[i] = pr - inetsw;
208 for (pr = inetdomain.dom_protosw;
209 pr < inetdomain.dom_protoswNPROTOSW; pr++)
210 if (pr->pr_domain->dom_family == PF_INET &&
211 pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
212 ip_protox[pr->pr_protocol] = pr - inetsw;
213
214 for (i = 0; i < IPREASS_NHASH; i++)
215 ipq[i].next = ipq[i].prev = &ipq[i];
216
217 maxnipq = nmbclusters/4;

--- 164 unchanged lines hidden (view full) ---

382 hlen, NULL, &divert_cookie, &m, &rule, &ip_fw_fwd_addr);
383 if (m == NULL) /* Packet discarded by firewall */
384 return;
385 if (i == 0 && ip_fw_fwd_addr == NULL) /* common case */
386 goto pass;
387#ifdef DUMMYNET
388 if ((i & IP_FW_PORT_DYNT_FLAG) != 0) {
389 /* Send packet to the appropriate pipe */
390 dummynet_io(i&0xffff,DN_TO_IP_IN,m,NULL,NULL,0, rule);
391 return;
392 }
393#endif
394#ifdef IPDIVERT
395 if (i != 0 && (i & IP_FW_PORT_DYNT_FLAG) == 0) {
396 /* Divert or tee packet */
397 divert_info = i;
398 goto ours;

--- 119 unchanged lines hidden (view full) ---

518 }
519 goto ours;
520 }
521 if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST)
522 goto ours;
523 if (ip->ip_dst.s_addr == INADDR_ANY)
524 goto ours;
525
526 /*
527 * Not for us; forward if possible and desirable.
528 */
529 if (ipforwarding == 0) {
530 ipstat.ips_cantforward++;
531 m_freem(m);
532 } else
533 ip_forward(m, 0);
534#ifdef IPFIREWALL_FORWARD

--- 6 unchanged lines hidden (view full) ---

541 /*
542 * If offset or IP_MF are set, must reassemble.
543 * Otherwise, nothing need be done.
544 * (We could look in the reassembly queue to see
545 * if the packet was previously fragmented,
546 * but it's not worth the time; just let them time out.)
547 */
548 if (ip->ip_off & (IP_MF | IP_OFFMASK | IP_RF)) {
549 if (m->m_flags & M_EXT) { /* XXX */
550 if ((m = m_pullup(m, hlen)) == 0) {
551 ipstat.ips_toosmall++;
552#ifdef IPFIREWALL_FORWARD
553 ip_fw_fwd_addr = NULL;
554#endif
555 return;
556 }
557 ip = mtod(m, struct ip *);
558 }
559 sum = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
560 /*
561 * Look for queue of fragments
562 * of this datagram.
563 */
564 for (fp = ipq[sum].next; fp != &ipq[sum]; fp = fp->next)
565 if (ip->ip_id == fp->ipq_id &&
566 ip->ip_src.s_addr == fp->ipq_src.s_addr &&

--- 44 unchanged lines hidden (view full) ---

611 * If datagram marked as having more fragments
612 * or if this is not the first fragment,
613 * attempt reassembly; if it succeeds, proceed.
614 */
615 if (mff || ip->ip_off) {
616 ipstat.ips_fragments++;
617 m->m_pkthdr.header = ip;
618#ifdef IPDIVERT
619 ip = ip_reass(m,
620 fp, &ipq[sum], &divert_info, &divert_cookie);
621#else
622 ip = ip_reass(m, fp, &ipq[sum]);
623#endif
624 if (ip == 0) {
625#ifdef IPFIREWALL_FORWARD
626 ip_fw_fwd_addr = NULL;
627#endif
628 return;
629 }
630 /* Get the length of the reassembled packets header */
631 hlen = IP_VHL_HL(ip->ip_vhl) << 2;
632 ipstat.ips_reassembled++;
633 m = dtom(ip);
634#ifdef IPDIVERT
635 /* Restore original checksum before diverting packet */
636 if (divert_info != 0) {
637 ip->ip_len += hlen;
638 HTONS(ip->ip_len);
639 HTONS(ip->ip_off);
640 HTONS(ip->ip_id);
641 ip->ip_sum = 0;

--- 42 unchanged lines hidden (view full) ---

684 ip = mtod(m, struct ip *);
685 }
686#endif
687
688 /*
689 * Switch out to protocol's input routine.
690 */
691 ipstat.ips_delivered++;
692 (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
693#ifdef IPFIREWALL_FORWARD
694 ip_fw_fwd_addr = NULL; /* tcp needed it */
695#endif
696 return;
697bad:
698#ifdef IPFIREWALL_FORWARD
699 ip_fw_fwd_addr = NULL;
700#endif
701 m_freem(m);
702}
703
704/*

--- 21 unchanged lines hidden (view full) ---

726 * Take incoming datagram fragment and try to reassemble it into
727 * whole datagram. If a chain for reassembly of this datagram already
728 * exists, then it is given as fp; otherwise have to make a chain.
729 *
730 * When IPDIVERT enabled, keep additional state with each packet that
731 * tells us if we need to divert or tee the packet we're building.
732 */
733
734static struct ip *
735#ifdef IPDIVERT
736ip_reass(m, fp, where, divinfo, divcookie)
737#else
738ip_reass(m, fp, where)
739#endif
740 register struct mbuf *m;
741 register struct ipq *fp;
742 struct ipq *where;

--- 53 unchanged lines hidden (view full) ---

796 * segment. If it provides all of our data, drop us, otherwise
797 * stick new segment in the proper place.
798 */
799 if (p) {
800 i = GETIP(p)->ip_off + GETIP(p)->ip_len - ip->ip_off;
801 if (i > 0) {
802 if (i >= ip->ip_len)
803 goto dropfrag;
804 m_adj(dtom(ip), i);
805 ip->ip_off += i;
806 ip->ip_len -= i;
807 }
808 m->m_nextpkt = p->m_nextpkt;
809 p->m_nextpkt = m;
810 } else {
811 m->m_nextpkt = fp->ipq_frags;
812 fp->ipq_frags = m;

--- 90 unchanged lines hidden (view full) ---

903 remque(fp);
904 nipq--;
905 (void) m_free(dtom(fp));
906 m->m_len += (IP_VHL_HL(ip->ip_vhl) << 2);
907 m->m_data -= (IP_VHL_HL(ip->ip_vhl) << 2);
908 /* some debugging cruft by sklower, below, will go away soon */
909 if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
910 register int plen = 0;
911 for (t = m; m; m = m->m_next)
912 plen += m->m_len;
913 t->m_pkthdr.len = plen;
914 }
915 return (ip);
916
917dropfrag:
918#ifdef IPDIVERT
919 *divinfo = 0;
920 *divcookie = 0;
921#endif
922 ipstat.ips_fragdropped++;
923 m_freem(m);

--- 470 unchanged lines hidden (view full) ---

1394{
1395 register struct ip *ip = mtod(m, struct ip *);
1396 register struct sockaddr_in *sin;
1397 register struct rtentry *rt;
1398 int error, type = 0, code = 0;
1399 struct mbuf *mcopy;
1400 n_long dest;
1401 struct ifnet *destifp;
1402
1403 dest = 0;
1404#ifdef DIAGNOSTIC
1405 if (ipprintfs)
1406 printf("forward: src %lx dst %lx ttl %x\n",
1407 (u_long)ip->ip_src.s_addr, (u_long)ip->ip_dst.s_addr,
1408 ip->ip_ttl);
1409#endif

--- 108 unchanged lines hidden (view full) ---

1518 default:
1519 type = ICMP_UNREACH;
1520 code = ICMP_UNREACH_HOST;
1521 break;
1522
1523 case EMSGSIZE:
1524 type = ICMP_UNREACH;
1525 code = ICMP_UNREACH_NEEDFRAG;
1526 if (ipforward_rt.ro_rt)
1527 destifp = ipforward_rt.ro_rt->rt_ifp;
1528 ipstat.ips_cantfrag++;
1529 break;
1530
1531 case ENOBUFS:
1532 type = ICMP_SOURCEQUENCH;
1533 code = 0;
1534 break;
1535 }

--- 118 unchanged lines hidden ---