diff options
Diffstat (limited to 'sys/net/pfkeyv2.c')
-rw-r--r-- | sys/net/pfkeyv2.c | 152 |
1 files changed, 71 insertions, 81 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 6e870613c92..5fbb23a2578 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.c,v 1.162 2017/06/26 09:32:32 mpi Exp $ */ +/* $OpenBSD: pfkeyv2.c,v 1.163 2017/07/03 19:23:47 claudio Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 @@ -131,14 +131,16 @@ extern struct radix_node_head **spd_tables; struct sockaddr pfkey_addr = { 2, PF_KEY, }; struct domain pfkeydomain; -struct pfkeyv2_socket { - LIST_ENTRY(pfkeyv2_socket) kcb_list; - struct socket *socket; +struct keycb { + struct rawcb rcb; + LIST_ENTRY(keycb) kcb_list; int flags; uint32_t pid; uint32_t registration; /* Increase size if SATYPE_MAX > 31 */ uint rdomain; }; +#define sotokeycb(so) ((struct keycb *)(so)->so_pcb) + struct dump_state { struct sadb_msg *sadb_msg; @@ -146,8 +148,7 @@ struct dump_state { }; /* Static globals */ -static LIST_HEAD(, pfkeyv2_socket) pfkeyv2_sockets = - LIST_HEAD_INITIALIZER(pfkeyv2_sockets); +static LIST_HEAD(, keycb) pfkeyv2_sockets = LIST_HEAD_INITIALIZER(keycb); static uint32_t pfkeyv2_seq = 1; static int nregistered = 0; static int npromisc = 0; @@ -160,7 +161,7 @@ int pfkeyv2_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); int pfkeyv2_output(struct mbuf *, struct socket *, struct sockaddr *, struct mbuf *); -int pfkey_sendup(struct socket *socket, struct mbuf *packet, int more); +int pfkey_sendup(struct keycb *, struct mbuf *, int); /* * Wrapper around m_devget(); copy data from contiguous buffer to mbuf @@ -212,72 +213,62 @@ pfkey_init(void) int pfkeyv2_attach(struct socket *so, int proto) { - struct pfkeyv2_socket *pfkeyv2_socket; + struct rawcb *rp; + struct keycb *pk; int error; if ((so->so_state & SS_PRIV) == 0) return EACCES; - if (!(so->so_pcb = malloc(sizeof(struct rawcb), - M_PCB, M_DONTWAIT | M_ZERO))) - return (ENOMEM); - - error = raw_attach(so, so->so_proto->pr_protocol); - if (error) - goto ret; + pk = malloc(sizeof(struct keycb), M_PCB, M_WAITOK | M_ZERO); + rp = &pk->rcb; + so->so_pcb = rp; - ((struct rawcb *)so->so_pcb)->rcb_faddr = &pfkey_addr; + error = raw_attach(so, proto); + if (error) { + free(pk, M_PCB, sizeof(struct keycb)); + return (error); + } - if (!(pfkeyv2_socket = malloc(sizeof(struct pfkeyv2_socket), - M_PFKEY, M_NOWAIT | M_ZERO))) - return (ENOMEM); + so->so_options |= SO_USELOOPBACK; + soisconnected(so); - LIST_INSERT_HEAD(&pfkeyv2_sockets, pfkeyv2_socket, kcb_list); - pfkeyv2_socket->socket = so; - pfkeyv2_socket->pid = curproc->p_p->ps_pid; + rp->rcb_faddr = &pfkey_addr; + pk->pid = curproc->p_p->ps_pid; /* * XXX we should get this from the socket instead but * XXX rawcb doesn't store the rdomain like inpcb does. */ - pfkeyv2_socket->rdomain = rtable_l2(curproc->p_p->ps_rtableid); + pk->rdomain = rtable_l2(curproc->p_p->ps_rtableid); - so->so_options |= SO_USELOOPBACK; - soisconnected(so); + LIST_INSERT_HEAD(&pfkeyv2_sockets, pk, kcb_list); return (0); -ret: - free(so->so_pcb, M_PCB, sizeof(struct rawcb)); - return (error); } /* * Close a PF_KEYv2 socket. */ int -pfkeyv2_detach(struct socket *socket, struct proc *p) +pfkeyv2_detach(struct socket *so, struct proc *p) { - struct pfkeyv2_socket *pp; - int error; - - LIST_FOREACH(pp, &pfkeyv2_sockets, kcb_list) - if (pp->socket == socket) - break; + struct keycb *pk; - if (pp) { - LIST_REMOVE(pp, kcb_list); + pk = sotokeycb(so); + if (pk == NULL) + return ENOTCONN; - if (pp->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) - nregistered--; + LIST_REMOVE(pk, kcb_list); - if (pp->flags & PFKEYV2_SOCKETFLAGS_PROMISC) - npromisc--; + if (pk->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) + nregistered--; - free(pp, M_PFKEY, 0); - } + if (pk->flags & PFKEYV2_SOCKETFLAGS_PROMISC) + npromisc--; - error = raw_usrreq(socket, PRU_DETACH, NULL, NULL, NULL, p); - return (error); + raw_detach(&pk->rcb); + return (0); } int @@ -293,7 +284,7 @@ pfkeyv2_usrreq(struct socket *so, int req, struct mbuf *mbuf, } int -pfkeyv2_output(struct mbuf *mbuf, struct socket *socket, +pfkeyv2_output(struct mbuf *mbuf, struct socket *so, struct sockaddr *dstaddr, struct mbuf *control) { void *message; @@ -319,7 +310,7 @@ pfkeyv2_output(struct mbuf *mbuf, struct socket *socket, m_copydata(mbuf, 0, mbuf->m_pkthdr.len, message); - error = pfkeyv2_send(socket, message, mbuf->m_pkthdr.len); + error = pfkeyv2_send(so, message, mbuf->m_pkthdr.len); ret: m_freem(mbuf); @@ -327,8 +318,9 @@ ret: } int -pfkey_sendup(struct socket *so, struct mbuf *packet, int more) +pfkey_sendup(struct keycb *kp, struct mbuf *packet, int more) { + struct socket *so = kp->rcb.rcb_socket; struct mbuf *packet2; NET_ASSERT_LOCKED(); @@ -354,13 +346,13 @@ pfkey_sendup(struct socket *so, struct mbuf *packet, int more) * third argument. */ int -pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket, +pfkeyv2_sendmessage(void **headers, int mode, struct socket *so, u_int8_t satype, int count, u_int rdomain) { int i, j, rval; void *p, *buffer = NULL; struct mbuf *packet; - struct pfkeyv2_socket *s; + struct keycb *s; struct sadb_msg *smsg; /* Find out how much space we'll need... */ @@ -401,7 +393,7 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket, * Send message to the specified socket, plus all * promiscuous listeners. */ - pfkey_sendup(socket, packet, 0); + pfkey_sendup(sotokeycb(so), packet, 0); /* * Promiscuous messages contain the original message @@ -426,9 +418,9 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket, */ LIST_FOREACH(s, &pfkeyv2_sockets, kcb_list) { if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) && - (s->socket != socket) && + (s->rcb.rcb_socket != so) && (s->rdomain == rdomain)) - pfkey_sendup(s->socket, packet, 1); + pfkey_sendup(s, packet, 1); } m_freem(packet); break; @@ -442,11 +434,11 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket, if ((s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) && (s->rdomain == rdomain)) { if (!satype) /* Just send to everyone registered */ - pfkey_sendup(s->socket, packet, 1); + pfkey_sendup(s, packet, 1); else { /* Check for specified satype */ if ((1 << satype) & s->registration) - pfkey_sendup(s->socket, packet, 1); + pfkey_sendup(s, packet, 1); } } } @@ -472,7 +464,7 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket, if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) && !(s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) && (s->rdomain == rdomain)) - pfkey_sendup(s->socket, packet, 1); + pfkey_sendup(s, packet, 1); } m_freem(packet); break; @@ -481,7 +473,7 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket, /* Send message to all sockets */ LIST_FOREACH(s, &pfkeyv2_sockets, kcb_list) { if (s->rdomain == rdomain) - pfkey_sendup(s->socket, packet, 1); + pfkey_sendup(s, packet, 1); } m_freem(packet); break; @@ -940,7 +932,7 @@ pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg) * Handle all messages from userland to kernel. */ int -pfkeyv2_send(struct socket *socket, void *message, int len) +pfkeyv2_send(struct socket *so, void *message, int len) { int i, j, s, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST; int delflag = 0; @@ -950,7 +942,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) struct radix_node_head *rnh; struct radix_node *rn = NULL; - struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL; + struct keycb *pk, *bpk = NULL; void *freeme = NULL, *bckptr = NULL; void *headers[SADB_EXT_MAX + 1]; @@ -972,16 +964,14 @@ pfkeyv2_send(struct socket *socket, void *message, int len) /* Verify that we received this over a legitimate pfkeyv2 socket */ bzero(headers, sizeof(headers)); - LIST_FOREACH(pfkeyv2_socket, &pfkeyv2_sockets, kcb_list) - if (pfkeyv2_socket->socket == socket) - break; + pk = sotokeycb(so); - if (!pfkeyv2_socket) { + if (!pk) { rval = EINVAL; goto ret; } - rdomain = pfkeyv2_socket->rdomain; + rdomain = pk->rdomain; /* If we have any promiscuous listeners, send them a copy of the message */ if (npromisc) { @@ -1010,10 +1000,10 @@ pfkeyv2_send(struct socket *socket, void *message, int len) goto ret; /* Send to all promiscuous listeners */ - LIST_FOREACH(so, &pfkeyv2_sockets, kcb_list) { - if ((so->flags & PFKEYV2_SOCKETFLAGS_PROMISC) && - (so->rdomain == rdomain)) - pfkey_sendup(so->socket, packet, 1); + LIST_FOREACH(bpk, &pfkeyv2_sockets, kcb_list) { + if ((bpk->flags & PFKEYV2_SOCKETFLAGS_PROMISC) && + (bpk->rdomain == rdomain)) + pfkey_sendup(bpk, packet, 1); } m_freem(packet); @@ -1402,8 +1392,8 @@ pfkeyv2_send(struct socket *socket, void *message, int len) break; case SADB_REGISTER: - if (!(pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) { - pfkeyv2_socket->flags |= PFKEYV2_SOCKETFLAGS_REGISTERED; + if (!(pk->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) { + pk->flags |= PFKEYV2_SOCKETFLAGS_REGISTERED; nregistered++; } @@ -1433,7 +1423,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) } /* Keep track what this socket has registered for */ - pfkeyv2_socket->registration |= (1 << ((struct sadb_msg *)message)->sadb_msg_satype); + pk->registration |= (1 << ((struct sadb_msg *)message)->sadb_msg_satype); ssup = (struct sadb_supported *) freeme; ssup->sadb_supported_len = i / sizeof(uint64_t); @@ -1506,7 +1496,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) { struct dump_state dump_state; dump_state.sadb_msg = (struct sadb_msg *) headers[0]; - dump_state.socket = socket; + dump_state.socket = so; rval = tdb_walk(rdomain, pfkeyv2_dump_walker, &dump_state); if (!rval) @@ -1778,12 +1768,12 @@ pfkeyv2_send(struct socket *socket, void *message, int len) if ((rval = pfdatatopacket(message, len, &packet)) != 0) goto ret; - LIST_FOREACH(so, &pfkeyv2_sockets, kcb_list) - if ((so != pfkeyv2_socket) && - (so->rdomain == rdomain) && + LIST_FOREACH(bpk, &pfkeyv2_sockets, kcb_list) + if ((bpk != pk) && + (bpk->rdomain == rdomain) && (!smsg->sadb_msg_seq || - (smsg->sadb_msg_seq == pfkeyv2_socket->pid))) - pfkey_sendup(so->socket, packet, 1); + (smsg->sadb_msg_seq == pk->pid))) + pfkey_sendup(bpk, packet, 1); m_freem(packet); } else { @@ -1792,17 +1782,17 @@ pfkeyv2_send(struct socket *socket, void *message, int len) goto ret; } - i = (pfkeyv2_socket->flags & + i = (pk->flags & PFKEYV2_SOCKETFLAGS_PROMISC) ? 1 : 0; j = smsg->sadb_msg_satype ? 1 : 0; if (i ^ j) { if (j) { - pfkeyv2_socket->flags |= + pk->flags |= PFKEYV2_SOCKETFLAGS_PROMISC; npromisc++; } else { - pfkeyv2_socket->flags &= + pk->flags &= ~PFKEYV2_SOCKETFLAGS_PROMISC; npromisc--; } @@ -1841,7 +1831,7 @@ ret: goto realret; } - rval = pfkeyv2_sendmessage(headers, mode, socket, 0, 0, rdomain); + rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, rdomain); realret: NET_UNLOCK(s); |