diff options
author | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2016-03-20 01:26:31 +0000 |
---|---|---|
committer | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2016-03-20 01:26:31 +0000 |
commit | 16d49d4a1ee59fdd9dc5d65774ad633dba6d1da2 (patch) | |
tree | 7679d1ebe1d4f385c14df6dcefc29327d8fafb56 | |
parent | 276cbad1f829d62d4f85498a058f5ea0cc61557f (diff) |
Revert, missing decl for in6_pcbaddrisavail() breaks kernel build.
Spotted by deraadt@
-rw-r--r-- | sys/netinet6/in6_pcb.c | 193 | ||||
-rw-r--r-- | sys/netinet6/udp6_output.c | 25 |
2 files changed, 107 insertions, 111 deletions
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 4abefb38354..2c093a852a4 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: in6_pcb.c,v 1.86 2016/03/19 23:59:49 vgross Exp $ */ +/* $OpenBSD: in6_pcb.c,v 1.87 2016/03/20 01:26:30 jca Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -158,9 +158,10 @@ in6_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) { struct socket *so = inp->inp_socket; + struct inpcbtable *head = inp->inp_table; struct sockaddr_in6 *sin6; u_short lport = 0; - int wild = INPLOOKUP_IPV6; + int wild = INPLOOKUP_IPV6, reuseport = (so->so_options & SO_REUSEPORT); int error; /* @@ -193,10 +194,95 @@ in6_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) if (sin6->sin6_family != AF_INET6) return EAFNOSUPPORT; - if ((error = in6_pcbaddrisavail(inp, sin6, wild, p))) - return (error); - inp->inp_laddr6 = sin6->sin6_addr; + /* KAME hack: embed scopeid */ + if (in6_embedscope(&sin6->sin6_addr, sin6, inp) != 0) + return EINVAL; + /* this must be cleared for ifa_ifwithaddr() */ + sin6->sin6_scope_id = 0; + lport = sin6->sin6_port; + + /* reject IPv4 mapped address, we have no support for it */ + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + return EADDRNOTAVAIL; + + if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { + /* + * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; + * allow complete duplication of binding if + * SO_REUSEPORT is set, or if SO_REUSEADDR is set + * and a multicast address is bound on both + * new and duplicated sockets. + */ + if (so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) + reuseport = SO_REUSEADDR | SO_REUSEPORT; + } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { + struct ifaddr *ifa = NULL; + + sin6->sin6_port = 0; /* + * Yechhhh, because of upcoming + * call to ifa_ifwithaddr(), which + * does bcmp's over the PORTS as + * well. (What about flow?) + */ + sin6->sin6_flowinfo = 0; + if (!(so->so_options & SO_BINDANY) && + (ifa = ifa_ifwithaddr(sin6tosa(sin6), + inp->inp_rtableid)) == NULL) + return EADDRNOTAVAIL; + + /* + * bind to an anycast address might accidentally + * cause sending a packet with an anycast source + * address, so we forbid it. + * + * We should allow to bind to a deprecated address, + * since the application dare to use it. + * But, can we assume that they are careful enough + * to check if the address is deprecated or not? + * Maybe, as a safeguard, we should have a setsockopt + * flag to control the bind(2) behavior against + * deprecated addresses (default: forbid bind(2)). + */ + if (ifa && + ifatoia6(ifa)->ia6_flags & + (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) + return (EADDRNOTAVAIL); + } + if (lport) { + struct inpcb *t; + + /* + * Question: Do we wish to continue the Berkeley + * tradition of ports < IPPORT_RESERVED be only for + * root? + * Answer: For now yes, but IMHO, it should be REMOVED! + * OUCH: One other thing, is there no better way of + * finding a process for a socket instead of using + * curproc? (Marked with BSD's {in,}famous XXX ? + */ + if (ntohs(lport) < IPPORT_RESERVED && + (error = suser(p, 0))) + return error; + if (so->so_euid) { + t = in_pcblookup(head, + (struct in_addr *)&zeroin6_addr, 0, + (struct in_addr *)&sin6->sin6_addr, lport, + INPLOOKUP_WILDCARD | INPLOOKUP_IPV6, + inp->inp_rtableid); + if (t && + (so->so_euid != t->inp_socket->so_euid)) + return EADDRINUSE; + } + t = in_pcblookup(head, + (struct in_addr *)&zeroin6_addr, 0, + (struct in_addr *)&sin6->sin6_addr, lport, + wild, inp->inp_rtableid); + + if (t && (reuseport & t->inp_socket->so_options) == 0) + return EADDRINUSE; + } + inp->inp_laddr6 = sin6->sin6_addr; } if (lport == 0) @@ -207,103 +293,6 @@ in6_pcbbind(struct inpcb *inp, struct mbuf *nam, struct proc *p) return 0; } -int -in6_pcbaddrisavail(struct inpcb *inp, struct sockaddr_in6 *sin6, int wild, - struct proc *p) -{ - struct socket *so = inp->inp_socket; - struct inpcbtable *table = inp->inp_table; - u_short lport = sin6->sin6_port; - int reuseport = (so->so_options & SO_REUSEPORT); - int error; - - wild |= INPLOOKUP_IPV6; - /* KAME hack: embed scopeid */ - if (in6_embedscope(&sin6->sin6_addr, sin6, inp) != 0) - return (EINVAL); - /* this must be cleared for ifa_ifwithaddr() */ - sin6->sin6_scope_id = 0; - /* reject IPv4 mapped address, we have no support for it */ - if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) - return (EADDRNOTAVAIL); - - if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { - /* - * Treat SO_REUSEADDR as SO_REUSEPORT for multicast; - * allow complete duplication of binding if - * SO_REUSEPORT is set, or if SO_REUSEADDR is set - * and a multicast address is bound on both - * new and duplicated sockets. - */ - if (so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) - reuseport = SO_REUSEADDR | SO_REUSEPORT; - } else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { - struct ifaddr *ifa = NULL; - - sin6->sin6_port = 0; /* - * Yechhhh, because of upcoming - * call to ifa_ifwithaddr(), which - * does bcmp's over the PORTS as - * well. (What about flow?) - */ - sin6->sin6_flowinfo = 0; - if (!(so->so_options & SO_BINDANY) && - (ifa = ifa_ifwithaddr(sin6tosa(sin6), - inp->inp_rtableid)) == NULL) - return (EADDRNOTAVAIL); - sin6->sin6_port = lport; - - /* - * bind to an anycast address might accidentally - * cause sending a packet with an anycast source - * address, so we forbid it. - * - * We should allow to bind to a deprecated address, - * since the application dare to use it. - * But, can we assume that they are careful enough - * to check if the address is deprecated or not? - * Maybe, as a safeguard, we should have a setsockopt - * flag to control the bind(2) behavior against - * deprecated addresses (default: forbid bind(2)). - */ - if (ifa && - ifatoia6(ifa)->ia6_flags & - (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) - return (EADDRNOTAVAIL); - } - if (lport) { - struct inpcb *t; - - /* - * Question: Do we wish to continue the Berkeley - * tradition of ports < IPPORT_RESERVED be only for - * root? - * Answer: For now yes, but IMHO, it should be REMOVED! - * OUCH: One other thing, is there no better way of - * finding a process for a socket instead of using - * curproc? (Marked with BSD's {in,}famous XXX ? - */ - if (ntohs(lport) < IPPORT_RESERVED && (error = suser(p, 0))) - return error; - if (so->so_euid) { - t = in_pcblookup(table, - (struct in_addr *)&zeroin6_addr, 0, - (struct in_addr *)&sin6->sin6_addr, lport, - INPLOOKUP_WILDCARD | INPLOOKUP_IPV6, - inp->inp_rtableid); - if (t && (so->so_euid != t->inp_socket->so_euid)) - return (EADDRINUSE); - } - t = in_pcblookup(table, - (struct in_addr *)&zeroin6_addr, 0, - (struct in_addr *)&sin6->sin6_addr, lport, - wild, inp->inp_rtableid); - if (t && (reuseport & t->inp_socket->so_options) == 0) - return (EADDRINUSE); - } - return (0); -} - /* * Connect from a socket to a specified address. * Both address and port must be specified in argument sin6. diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c index a55667163d0..7717b056aab 100644 --- a/sys/netinet6/udp6_output.c +++ b/sys/netinet6/udp6_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp6_output.c,v 1.43 2016/03/19 23:59:49 vgross Exp $ */ +/* $OpenBSD: udp6_output.c,v 1.44 2016/03/20 01:26:30 jca Exp $ */ /* $KAME: udp6_output.c,v 1.21 2001/02/07 11:51:54 itojun Exp $ */ /* @@ -102,7 +102,7 @@ udp6_output(struct inpcb *in6p, struct mbuf *m, struct mbuf *addr6, struct udphdr *udp6; struct in6_addr *laddr, *faddr; struct ip6_pktopts *optp, opt; - struct sockaddr_in6 tmp, valid; + struct sockaddr_in6 tmp; struct proc *p = curproc; /* XXX */ u_short fport; @@ -168,14 +168,21 @@ udp6_output(struct inpcb *in6p, struct mbuf *m, struct mbuf *addr6, goto release; } - if (!IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, laddr)) { - valid.sin6_addr = *laddr; - valid.sin6_port = in6p->inp_lport; - valid.sin6_family = AF_INET6; - valid.sin6_len = sizeof(valid); - error = in6_pcbaddrisavail(in6p, &valid, 0, p); - if (error) + if (!IN6_ARE_ADDR_EQUAL(&in6p->inp_laddr6, laddr) && + (in6p->inp_socket->so_euid != 0)) { + struct inpcb *t; + + t = in_pcblookup(in6p->inp_table, + (struct in_addr *)&zeroin6_addr, 0, + (struct in_addr *)laddr, in6p->inp_lport, + (INPLOOKUP_WILDCARD | INPLOOKUP_IPV6), + in6p->inp_rtableid); + if (t && + (t->inp_socket->so_euid != + in6p->inp_socket->so_euid)) { + error = EADDRINUSE; goto release; + } } } else { if (IN6_IS_ADDR_UNSPECIFIED(&in6p->inp_faddr6)) { |