diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-02-17 23:51:13 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1999-02-17 23:51:13 +0000 |
commit | 800232291df6681bd7168bfc03e7f7f9ccab92c0 (patch) | |
tree | 65119e5da5fb75f740a18ca6634096c8afbecd26 /sys | |
parent | cd7ab9190045396b86218b18a8148c785a49784c (diff) |
add fragment flood protection; configureable using sysctl ip.maxqueue
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/in.h | 6 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 71 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 3 |
3 files changed, 57 insertions, 23 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 2855c5246d1..abcd39ae79d 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -1,4 +1,4 @@ -/* $OpenBSD: in.h,v 1.17 1999/01/10 02:37:33 deraadt Exp $ */ +/* $OpenBSD: in.h,v 1.18 1999/02/17 23:51:12 deraadt Exp $ */ /* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */ /* @@ -336,7 +336,8 @@ struct ip_mreq { #define IPCTL_IPPORT_LASTAUTO 8 #define IPCTL_IPPORT_HIFIRSTAUTO 9 #define IPCTL_IPPORT_HILASTAUTO 10 -#define IPCTL_MAXID 11 +#define IPCTL_IPPORT_MAXQUEUE 11 +#define IPCTL_MAXID 12 #define IPCTL_NAMES { \ { 0, 0 }, \ @@ -350,6 +351,7 @@ struct ip_mreq { { "portlast", CTLTYPE_INT }, \ { "porthifirst", CTLTYPE_INT }, \ { "porthilast", CTLTYPE_INT }, \ + { "maxqueue", CTLTYPE_INT }, \ } #ifndef _KERNEL diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 8c893c4ee2c..238685a5561 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.34 1998/12/28 23:54:57 deraadt Exp $ */ +/* $OpenBSD: ip_input.c,v 1.35 1999/02/17 23:51:12 deraadt Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -99,6 +99,10 @@ int ipsec_auth_default_level = IPSEC_AUTH_LEVEL_DEFAULT; int ipsec_esp_trans_default_level = IPSEC_ESP_TRANS_LEVEL_DEFAULT; int ipsec_esp_network_default_level = IPSEC_ESP_NETWORK_LEVEL_DEFAULT; +/* Keep track of memory used for reassembly */ +int ip_maxqueue = 300; +int ip_frags = 0; + /* from in_pcb.c */ extern int ipport_firstauto; extern int ipport_lastauto; @@ -117,7 +121,6 @@ int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); #endif - char * inet_ntoa(ina) struct in_addr ina; @@ -278,10 +281,10 @@ next: } #if defined(IPFILTER) || defined(IPFILTER_LKM) - /* - * Check if we want to allow this packet to be processed. - * Consider it to be bad if not. - */ + /* + * Check if we want to allow this packet to be processed. + * Consider it to be bad if not. + */ { struct mbuf *m0 = m; if (fr_checkp && (*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m0)) @@ -432,12 +435,19 @@ found: */ if (mff || ip->ip_off) { ipstat.ips_fragments++; + if (ip_frags + 1 > ip_maxqueue) { + ip_flush(); + ipstat.ips_rcvmemdrop++; + goto bad; + } + MALLOC(ipqe, struct ipqent *, sizeof (struct ipqent), M_IPQ, M_NOWAIT); if (ipqe == NULL) { ipstat.ips_rcvmemdrop++; goto bad; } + ip_frags++; ipqe->ipqe_mff = mff; ipqe->ipqe_ip = ip; ip = ip_reass(ipqe, fp); @@ -580,6 +590,7 @@ ip_reass(ipqe, fp) m_freem(dtom(q->ipqe_ip)); LIST_REMOVE(q, ipqe_q); FREE(q, M_IPQ); + ip_frags--; } insert: @@ -619,10 +630,12 @@ insert: m_cat(m, t); nq = q->ipqe_q.le_next; FREE(q, M_IPQ); + ip_frags--; for (q = nq; q != NULL; q = nq) { t = dtom(q->ipqe_ip); nq = q->ipqe_q.le_next; FREE(q, M_IPQ); + ip_frags--; m_cat(m, t); } @@ -652,6 +665,7 @@ dropfrag: ipstat.ips_fragdropped++; m_freem(m); FREE(ipqe, M_IPQ); + ip_frags--; return (0); } @@ -670,6 +684,7 @@ ip_freef(fp) m_freem(dtom(q->ipqe_ip)); LIST_REMOVE(q, ipqe_q); FREE(q, M_IPQ); + ip_frags--; } LIST_REMOVE(fp, ipq_q); (void) m_free(dtom(fp)); @@ -710,6 +725,19 @@ ip_drain() } /* + * Flush a bunch of datagram fragments, till we are down to 75%. + */ +void +ip_flush() +{ + + while (ipq.lh_first != NULL && ip_frags > ip_maxqueue * 3 / 4) { + ipstat.ips_fragdropped++; + ip_freef(ipq.lh_first); + } +} + +/* * Do option processing on a datagram, * possibly discarding it if bad options are encountered, * or forwarding it if source-routed. @@ -976,9 +1004,9 @@ save_rte(option, dst) */ static int ip_weadvertise(addr) - u_int32_t addr; + u_int32_t addr; { - register struct rtentry *rt; + register struct rtentry *rt; register struct ifnet *ifp; register struct ifaddr *ifa; struct sockaddr_inarp sin; @@ -993,21 +1021,21 @@ ip_weadvertise(addr) RTFREE(rt); - if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 - || rt->rt_gateway->sa_family != AF_LINK) + if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 || + rt->rt_gateway->sa_family != AF_LINK) return 0; for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) - for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) - { - if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family) - continue; - - if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr), - LLADDR((struct sockaddr_dl *)rt->rt_gateway), - ETHER_ADDR_LEN)) - return 1; - } + for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; + ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != rt->rt_gateway->sa_family) + continue; + + if (!bcmp(LLADDR((struct sockaddr_dl *)ifa->ifa_addr), + LLADDR((struct sockaddr_dl *)rt->rt_gateway), + ETHER_ADDR_LEN)) + return 1; + } return 0; } @@ -1325,6 +1353,9 @@ ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen) case IPCTL_IPPORT_HILASTAUTO: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipport_hilastauto)); + case IPCTL_IPPORT_MAXQUEUE: + return (sysctl_int(oldp, oldlenp, newp, newlen, + &ip_maxqueue)); default: return (EOPNOTSUPP); } diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 1583d199f98..ccf7e9d2b92 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.10 1999/01/11 02:01:34 deraadt Exp $ */ +/* $OpenBSD: ip_var.h,v 1.11 1999/02/17 23:51:12 deraadt Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -165,6 +165,7 @@ int ip_defttl; /* default IP ttl */ int ip_ctloutput __P((int, struct socket *, int, int, struct mbuf **)); int ip_dooptions __P((struct mbuf *)); void ip_drain __P((void)); +void ip_flush __P((void)); void ip_forward __P((struct mbuf *, int)); void ip_freef __P((struct ipq *)); void ip_freemoptions __P((struct ip_moptions *)); |