Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netinet6/udp6_usrreq.c
Show First 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
/* | /* | ||||
* Construct sockaddr format source address. | * Construct sockaddr format source address. | ||||
*/ | */ | ||||
init_sin6(&fromsa, m); | init_sin6(&fromsa, m); | ||||
fromsa.sin6_port = uh->uh_sport; | fromsa.sin6_port = uh->uh_sport; | ||||
pcbinfo = get_inpcbinfo(nxt); | pcbinfo = udp_get_inpcbinfo(nxt); | ||||
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | ||||
struct inpcb *last; | struct inpcb *last; | ||||
struct inpcbhead *pcblist; | struct inpcbhead *pcblist; | ||||
struct ip6_moptions *imo; | struct ip6_moptions *imo; | ||||
INP_INFO_RLOCK(pcbinfo); | INP_INFO_RLOCK(pcbinfo); | ||||
/* | /* | ||||
* In the event that laddr should be set to the link-local | * In the event that laddr should be set to the link-local | ||||
* address (this happens in RIPng), the multicast address | * address (this happens in RIPng), the multicast address | ||||
* specified in the received packet will not match laddr. To | * specified in the received packet will not match laddr. To | ||||
* handle this situation, matching is relaxed if the | * handle this situation, matching is relaxed if the | ||||
* receiving interface is the same as one specified in the | * receiving interface is the same as one specified in the | ||||
* socket and if the destination multicast address matches | * socket and if the destination multicast address matches | ||||
* one of the multicast groups specified in the socket. | * one of the multicast groups specified in the socket. | ||||
*/ | */ | ||||
/* | /* | ||||
* KAME note: traditionally we dropped udpiphdr from mbuf | * KAME note: traditionally we dropped udpiphdr from mbuf | ||||
* here. We need udphdr for IPsec processing so we do that | * here. We need udphdr for IPsec processing so we do that | ||||
* later. | * later. | ||||
*/ | */ | ||||
pcblist = get_pcblist(nxt); | pcblist = udp_get_pcblist(nxt); | ||||
last = NULL; | last = NULL; | ||||
LIST_FOREACH(inp, pcblist, inp_list) { | LIST_FOREACH(inp, pcblist, inp_list) { | ||||
if ((inp->inp_vflag & INP_IPV6) == 0) | if ((inp->inp_vflag & INP_IPV6) == 0) | ||||
continue; | continue; | ||||
if (inp->inp_lport != uh->uh_dport) | if (inp->inp_lport != uh->uh_dport) | ||||
continue; | continue; | ||||
if (inp->inp_fport != 0 && | if (inp->inp_fport != 0 && | ||||
inp->inp_fport != uh->uh_sport) | inp->inp_fport != uh->uh_sport) | ||||
▲ Show 20 Lines • Show All 587 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static void | static void | ||||
udp6_abort(struct socket *so) | udp6_abort(struct socket *so) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("udp6_abort: inp == NULL")); | KASSERT(inp != NULL, ("udp6_abort: inp == NULL")); | ||||
#ifdef INET | #ifdef INET | ||||
if (inp->inp_vflag & INP_IPV4) { | if (inp->inp_vflag & INP_IPV4) { | ||||
struct pr_usrreqs *pru; | struct pr_usrreqs *pru; | ||||
pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; | pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; | ||||
Show All 15 Lines | |||||
static int | static int | ||||
udp6_attach(struct socket *so, int proto, struct thread *td) | udp6_attach(struct socket *so, int proto, struct thread *td) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
int error; | int error; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp == NULL, ("udp6_attach: inp != NULL")); | KASSERT(inp == NULL, ("udp6_attach: inp != NULL")); | ||||
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { | if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { | ||||
error = soreserve(so, udp_sendspace, udp_recvspace); | error = soreserve(so, udp_sendspace, udp_recvspace); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
} | } | ||||
Show All 31 Lines | |||||
static int | static int | ||||
udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) | udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
int error; | int error; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("udp6_bind: inp == NULL")); | KASSERT(inp != NULL, ("udp6_bind: inp == NULL")); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
INP_HASH_WLOCK(pcbinfo); | INP_HASH_WLOCK(pcbinfo); | ||||
inp->inp_vflag &= ~INP_IPV4; | inp->inp_vflag &= ~INP_IPV4; | ||||
inp->inp_vflag |= INP_IPV6; | inp->inp_vflag |= INP_IPV6; | ||||
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { | if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { | ||||
Show All 27 Lines | |||||
} | } | ||||
static void | static void | ||||
udp6_close(struct socket *so) | udp6_close(struct socket *so) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("udp6_close: inp == NULL")); | KASSERT(inp != NULL, ("udp6_close: inp == NULL")); | ||||
#ifdef INET | #ifdef INET | ||||
if (inp->inp_vflag & INP_IPV4) { | if (inp->inp_vflag & INP_IPV4) { | ||||
struct pr_usrreqs *pru; | struct pr_usrreqs *pru; | ||||
pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; | pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; | ||||
Show All 15 Lines | |||||
static int | static int | ||||
udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) | udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
struct sockaddr_in6 *sin6; | struct sockaddr_in6 *sin6; | ||||
int error; | int error; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
sin6 = (struct sockaddr_in6 *)nam; | sin6 = (struct sockaddr_in6 *)nam; | ||||
KASSERT(inp != NULL, ("udp6_connect: inp == NULL")); | KASSERT(inp != NULL, ("udp6_connect: inp == NULL")); | ||||
/* | /* | ||||
* XXXRW: Need to clarify locking of v4/v6 flags. | * XXXRW: Need to clarify locking of v4/v6 flags. | ||||
*/ | */ | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
udp6_detach(struct socket *so) | udp6_detach(struct socket *so) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
struct udpcb *up; | struct udpcb *up; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("udp6_detach: inp == NULL")); | KASSERT(inp != NULL, ("udp6_detach: inp == NULL")); | ||||
INP_INFO_WLOCK(pcbinfo); | INP_INFO_WLOCK(pcbinfo); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
up = intoudpcb(inp); | up = intoudpcb(inp); | ||||
KASSERT(up != NULL, ("%s: up == NULL", __func__)); | KASSERT(up != NULL, ("%s: up == NULL", __func__)); | ||||
in_pcbdetach(inp); | in_pcbdetach(inp); | ||||
in_pcbfree(inp); | in_pcbfree(inp); | ||||
INP_INFO_WUNLOCK(pcbinfo); | INP_INFO_WUNLOCK(pcbinfo); | ||||
udp_discardcb(up); | udp_discardcb(up); | ||||
} | } | ||||
static int | static int | ||||
udp6_disconnect(struct socket *so) | udp6_disconnect(struct socket *so) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
int error; | int error; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL")); | KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL")); | ||||
#ifdef INET | #ifdef INET | ||||
if (inp->inp_vflag & INP_IPV4) { | if (inp->inp_vflag & INP_IPV4) { | ||||
struct pr_usrreqs *pru; | struct pr_usrreqs *pru; | ||||
pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; | pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs; | ||||
Show All 24 Lines | |||||
static int | static int | ||||
udp6_send(struct socket *so, int flags, struct mbuf *m, | udp6_send(struct socket *so, int flags, struct mbuf *m, | ||||
struct sockaddr *addr, struct mbuf *control, struct thread *td) | struct sockaddr *addr, struct mbuf *control, struct thread *td) | ||||
{ | { | ||||
struct inpcb *inp; | struct inpcb *inp; | ||||
struct inpcbinfo *pcbinfo; | struct inpcbinfo *pcbinfo; | ||||
int error = 0; | int error = 0; | ||||
pcbinfo = get_inpcbinfo(so->so_proto->pr_protocol); | pcbinfo = udp_get_inpcbinfo(so->so_proto->pr_protocol); | ||||
inp = sotoinpcb(so); | inp = sotoinpcb(so); | ||||
KASSERT(inp != NULL, ("udp6_send: inp == NULL")); | KASSERT(inp != NULL, ("udp6_send: inp == NULL")); | ||||
INP_WLOCK(inp); | INP_WLOCK(inp); | ||||
if (addr) { | if (addr) { | ||||
if (addr->sa_len != sizeof(struct sockaddr_in6)) { | if (addr->sa_len != sizeof(struct sockaddr_in6)) { | ||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad; | ||||
▲ Show 20 Lines • Show All 74 Lines • Show Last 20 Lines |