diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/in_pcb.c | 6 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 126 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 4 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 6 |
4 files changed, 94 insertions, 48 deletions
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index ba9a0b6382f..c9981fcc442 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in_pcb.c,v 1.115 2011/04/14 08:15:26 claudio Exp $ */ +/* $OpenBSD: in_pcb.c,v 1.116 2011/04/19 03:47:29 dlg Exp $ */ /* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */ /* @@ -276,8 +276,8 @@ in_pcbbind(v, nam, p) } else if (sin->sin_addr.s_addr != INADDR_ANY) { sin->sin_port = 0; /* yech... */ if (!(so->so_options & SO_BINDANY) && - in_iawithaddr(sin->sin_addr, NULL, - inp->inp_rtableid) == 0) + in_iawithaddr(sin->sin_addr, + inp->inp_rtableid) == NULL) return (EADDRNOTAVAIL); } if (lport) { diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 72f8227047e..0d71e404e78 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.190 2011/04/14 08:15:26 claudio Exp $ */ +/* $OpenBSD: ip_input.c,v 1.191 2011/04/19 03:47:29 dlg Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -144,6 +144,8 @@ struct pool ipq_pool; struct ipstat ipstat; +int in_ouraddr(struct in_addr, struct mbuf *); + char * inet_ntoa(ina) struct in_addr ina; @@ -259,7 +261,6 @@ ipv4_input(m) { struct ip *ip; struct ipq *fp; - struct in_ifaddr *ia; struct ipqent *ipqe; int hlen, mff, len; in_addr_t pfrdr = 0; @@ -387,25 +388,9 @@ ipv4_input(m) return; } - if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) + if (in_ouraddr(ip->ip_dst, m)) goto ours; -#if NPF > 0 - if (m->m_pkthdr.pf.statekey && - ((struct pf_state_key *)m->m_pkthdr.pf.statekey)->inp) - goto ours; - - /* - * Check our list of addresses, to see if the packet is for us. - * if we have linked state keys it is certainly to be forwarded. - */ - if (!m->m_pkthdr.pf.statekey || - !((struct pf_state_key *)m->m_pkthdr.pf.statekey)->reverse) -#endif - if ((ia = in_iawithaddr(ip->ip_dst, m, m->m_pkthdr.rdomain)) != - NULL && (ia->ia_ifp->if_flags & IFF_UP)) - goto ours; - if (IN_MULTICAST(ip->ip_dst.s_addr)) { struct in_multi *inm; #ifdef MROUTING @@ -679,33 +664,94 @@ bad: m_freem(m); } -struct in_ifaddr * -in_iawithaddr(struct in_addr ina, struct mbuf *m, u_int rdomain) +int +in_ouraddr(struct in_addr ina, struct mbuf *m) { - struct in_ifaddr *ia; + struct in_ifaddr *ia; + struct sockaddr_in sin; +#if NPF > 0 + struct pf_state_key *key; - rdomain = rtable_l2(rdomain); - TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { - if (ia->ia_ifp->if_rdomain != rdomain) - continue; - if (ina.s_addr == ia->ia_addr.sin_addr.s_addr) - return ia; - /* check ancient classful too, e. g. for rarp-based netboot */ - if (((ip_directedbcast == 0) || (m && ip_directedbcast && - ia->ia_ifp == m->m_pkthdr.rcvif)) && - (ia->ia_ifp->if_flags & IFF_BROADCAST)) { - if (ina.s_addr == ia->ia_broadaddr.sin_addr.s_addr || + if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) + return (1); + + key = (struct pf_state_key *)m->m_pkthdr.pf.statekey; + if (key != NULL) { + if (key->inp != NULL) + return (1); + + /* If we have linked state keys it is certainly forwarded. */ + if (key->reverse != NULL) + return (0); + } +#endif + + bzero(&sin, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr = ina; + ia = (struct in_ifaddr *)ifa_ifwithaddr(sintosa(&sin), + m->m_pkthdr.rdomain); + + if (ia == NULL) { + /* + * No local address or broadcast address found, so check for + * ancient classful broadcast addresses. + * It must have been broadcast on the link layer, and for an + * address on the interface it was received on. + */ + if (!ISSET(m->m_flags, M_BCAST) || + !IN_CLASSFULBROADCAST(ina.s_addr, ina.s_addr)) + return (0); + + /* + * The check in the loop assumes you only rx a packet on an UP + * interface, and that M_BCAST will only be set on a BROADCAST + * interface. + */ + TAILQ_FOREACH(ia, &in_ifaddr, ia_list) { + if (ia->ia_ifp == m->m_pkthdr.rcvif && + ia->ia_ifp->if_rdomain == m->m_pkthdr.rdomain && IN_CLASSFULBROADCAST(ina.s_addr, - ia->ia_addr.sin_addr.s_addr)) { - /* Make sure M_BCAST is set */ - if (m) - m->m_flags |= M_BCAST; - return ia; - } + ia->ia_addr.sin_addr.s_addr)) + return (1); } + + return (0); + } + + if (ina.s_addr != ia->ia_addr.sin_addr.s_addr) { + /* + * This matches a broadcast address on one of our interfaces. + * If directedbcast is enabled we only consider it local if it + * is received on the interface with that address. + */ + if (ip_directedbcast && ia->ia_ifp != m->m_pkthdr.rcvif) + return (0); + + /* Make sure M_BCAST is set */ + if (m) + m->m_flags |= M_BCAST; } - return NULL; + return (ISSET(ia->ia_ifp->if_flags, IFF_UP)); +} + +struct in_ifaddr * +in_iawithaddr(struct in_addr ina, u_int rdomain) +{ + struct in_ifaddr *ia; + struct sockaddr_in sin; + + bzero(&sin, sizeof(sin)); + sin.sin_len = sizeof(sin); + sin.sin_family = AF_INET; + sin.sin_addr = ina; + ia = (struct in_ifaddr *)ifa_ifwithaddr(sintosa(&sin), rdomain); + if (ia == NULL || ina.s_addr == ia->ia_addr.sin_addr.s_addr) + return (ia); + + return (NULL); } /* diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index adacedc2d96..045304469bd 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.41 2011/04/14 08:15:26 claudio Exp $ */ +/* $OpenBSD: ip_var.h,v 1.42 2011/04/19 03:47:29 dlg Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -172,7 +172,7 @@ int ip_pcbopts(struct mbuf **, struct mbuf *); struct mbuf * ip_reass(struct ipqent *, struct ipq *); struct in_ifaddr * - in_iawithaddr(struct in_addr, struct mbuf *, u_int); + in_iawithaddr(struct in_addr, u_int); struct in_ifaddr * ip_rtaddr(struct in_addr, u_int); u_int16_t diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 951023bbaed..db470c84bb2 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip.c,v 1.53 2011/04/14 08:15:26 claudio Exp $ */ +/* $OpenBSD: raw_ip.c,v 1.54 2011/04/19 03:47:29 dlg Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* @@ -424,8 +424,8 @@ rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, (addr->sin_family != AF_IMPLINK)) || (addr->sin_addr.s_addr && (!(so->so_options & SO_BINDANY) && - in_iawithaddr(addr->sin_addr, NULL, inp->inp_rtableid) == - 0))) { + in_iawithaddr(addr->sin_addr, inp->inp_rtableid) == + NULL))) { error = EADDRNOTAVAIL; break; } |