Annotation of sys/net/pfkey.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: pfkey.c,v 1.16 2004/11/26 18:02:22 markus Exp $ */
! 2:
! 3: /*
! 4: * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
! 5: *
! 6: * NRL grants permission for redistribution and use in source and binary
! 7: * forms, with or without modification, of the software and documentation
! 8: * created at NRL provided that the following conditions are met:
! 9: *
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgements:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * This product includes software developed at the Information
! 20: * Technology Division, US Naval Research Laboratory.
! 21: * 4. Neither the name of the NRL nor the names of its contributors
! 22: * may be used to endorse or promote products derived from this software
! 23: * without specific prior written permission.
! 24: *
! 25: * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
! 26: * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 27: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
! 28: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NRL OR
! 29: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 30: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 31: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
! 32: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
! 33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
! 34: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
! 35: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 36: *
! 37: * The views and conclusions contained in the software and documentation
! 38: * are those of the authors and should not be interpreted as representing
! 39: * official policies, either expressed or implied, of the US Naval
! 40: * Research Laboratory (NRL).
! 41: */
! 42:
! 43: /*
! 44: * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved.
! 45: *
! 46: * Redistribution and use in source and binary forms, with or without
! 47: * modification, are permitted provided that the following conditions
! 48: * are met:
! 49: * 1. Redistributions of source code must retain the above copyright
! 50: * notice, this list of conditions and the following disclaimer.
! 51: * 2. Redistributions in binary form must reproduce the above copyright
! 52: * notice, this list of conditions and the following disclaimer in the
! 53: * documentation and/or other materials provided with the distribution.
! 54: * 3. Neither the name of the author nor the names of any contributors
! 55: * may be used to endorse or promote products derived from this software
! 56: * without specific prior written permission.
! 57: *
! 58: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 59: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 60: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 61: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 62: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 63: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 64: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 65: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 66: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 67: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 68: * SUCH DAMAGE.
! 69: */
! 70:
! 71: #include <sys/types.h>
! 72: #include <sys/param.h>
! 73: #include <sys/systm.h>
! 74: #include <sys/socket.h>
! 75: #include <sys/mbuf.h>
! 76: #include <sys/socketvar.h>
! 77: #include <net/route.h>
! 78: #include <netinet/ip_ipsp.h>
! 79: #include <net/pfkeyv2.h>
! 80:
! 81: #include <sys/protosw.h>
! 82: #include <sys/domain.h>
! 83: #include <net/raw_cb.h>
! 84:
! 85: #define PFKEY_PROTOCOL_MAX 3
! 86: static struct pfkey_version *pfkey_versions[PFKEY_PROTOCOL_MAX+1] =
! 87: { NULL, NULL, NULL, NULL };
! 88:
! 89: #define PFKEY_MSG_MAXSZ 4096
! 90:
! 91: struct sockaddr pfkey_addr = { 2, PF_KEY, };
! 92:
! 93: /* static struct domain pfkey_domain; */
! 94: static int pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
! 95: struct mbuf *nam, struct mbuf *control);
! 96: static int pfkey_output(struct mbuf *mbuf, struct socket *socket);
! 97:
! 98: int pfkey_register(struct pfkey_version *version);
! 99: int pfkey_unregister(struct pfkey_version *version);
! 100: int pfkey_sendup(struct socket *socket, struct mbuf *packet, int more);
! 101: void pfkey_init(void);
! 102: int pfkey_buildprotosw(void);
! 103:
! 104: int
! 105: pfkey_register(struct pfkey_version *version)
! 106: {
! 107: int rval;
! 108:
! 109: if ((version->protocol > PFKEY_PROTOCOL_MAX) ||
! 110: (version->protocol < 0))
! 111: return (EPROTONOSUPPORT);
! 112:
! 113: if (pfkey_versions[version->protocol])
! 114: return (EADDRINUSE);
! 115:
! 116: pfkey_versions[version->protocol] = version;
! 117:
! 118: if ((rval = pfkey_buildprotosw()) != 0) {
! 119: pfkey_versions[version->protocol] = NULL;
! 120: return (rval);
! 121: }
! 122:
! 123: return (0);
! 124: }
! 125:
! 126: int
! 127: pfkey_unregister(struct pfkey_version *version)
! 128: {
! 129: int rval;
! 130:
! 131: if ((rval = pfkey_buildprotosw()) != 0)
! 132: return (rval);
! 133:
! 134: pfkey_versions[version->protocol] = NULL;
! 135: return (0);
! 136: }
! 137:
! 138: int
! 139: pfkey_sendup(struct socket *socket, struct mbuf *packet, int more)
! 140: {
! 141: struct mbuf *packet2;
! 142: int s;
! 143:
! 144: if (more) {
! 145: if (!(packet2 = m_copym2(packet, 0, M_COPYALL, M_DONTWAIT)))
! 146: return (ENOMEM);
! 147: } else
! 148: packet2 = packet;
! 149:
! 150: s = spltdb();
! 151: if (!sbappendaddr(&socket->so_rcv, &pfkey_addr, packet2, NULL)) {
! 152: m_freem(packet2);
! 153: splx(s);
! 154: return (ENOBUFS);
! 155: }
! 156: splx(s);
! 157:
! 158: sorwakeup(socket);
! 159: return (0);
! 160: }
! 161:
! 162: static int
! 163: pfkey_output(struct mbuf *mbuf, struct socket *socket)
! 164: {
! 165: void *message;
! 166: int error = 0;
! 167:
! 168: #ifdef DIAGNOSTIC
! 169: if (!mbuf || !(mbuf->m_flags & M_PKTHDR)) {
! 170: error = EINVAL;
! 171: goto ret;
! 172: }
! 173: #endif /* DIAGNOSTIC */
! 174:
! 175: if (mbuf->m_pkthdr.len > PFKEY_MSG_MAXSZ) {
! 176: error = EMSGSIZE;
! 177: goto ret;
! 178: }
! 179:
! 180: if (!(message = malloc((unsigned long) mbuf->m_pkthdr.len,
! 181: M_PFKEY, M_DONTWAIT))) {
! 182: error = ENOMEM;
! 183: goto ret;
! 184: }
! 185:
! 186: m_copydata(mbuf, 0, mbuf->m_pkthdr.len, message);
! 187:
! 188: error = pfkey_versions[socket->so_proto->pr_protocol]->send(socket,
! 189: message, mbuf->m_pkthdr.len);
! 190:
! 191: ret:
! 192: if (mbuf)
! 193: m_freem (mbuf);
! 194: return (error);
! 195: }
! 196:
! 197: static int
! 198: pfkey_attach(struct socket *socket, struct mbuf *proto)
! 199: {
! 200: int rval;
! 201: int s;
! 202:
! 203: if (!(socket->so_pcb = malloc(sizeof(struct rawcb),
! 204: M_PCB, M_DONTWAIT)))
! 205: return (ENOMEM);
! 206: bzero(socket->so_pcb, sizeof(struct rawcb));
! 207:
! 208: s = splnet();
! 209: rval = raw_usrreq(socket, PRU_ATTACH, NULL, proto, NULL);
! 210: splx(s);
! 211: if (rval)
! 212: goto ret;
! 213:
! 214: ((struct rawcb *)socket->so_pcb)->rcb_faddr = &pfkey_addr;
! 215: soisconnected(socket);
! 216:
! 217: socket->so_options |= SO_USELOOPBACK;
! 218: if ((rval =
! 219: pfkey_versions[socket->so_proto->pr_protocol]->create(socket)) != 0)
! 220: goto ret;
! 221:
! 222: return (0);
! 223:
! 224: ret:
! 225: free(socket->so_pcb, M_PCB);
! 226: return (rval);
! 227: }
! 228:
! 229: static int
! 230: pfkey_detach(struct socket *socket)
! 231: {
! 232: int rval, i, s;
! 233:
! 234: rval = pfkey_versions[socket->so_proto->pr_protocol]->release(socket);
! 235: s = splnet();
! 236: i = raw_usrreq(socket, PRU_DETACH, NULL, NULL, NULL);
! 237: splx(s);
! 238:
! 239: if (!rval)
! 240: rval = i;
! 241:
! 242: return (rval);
! 243: }
! 244:
! 245: static int
! 246: pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
! 247: struct mbuf *nam, struct mbuf *control)
! 248: {
! 249: int rval;
! 250: int s;
! 251:
! 252: if ((socket->so_proto->pr_protocol > PFKEY_PROTOCOL_MAX) ||
! 253: (socket->so_proto->pr_protocol < 0) ||
! 254: !pfkey_versions[socket->so_proto->pr_protocol])
! 255: return (EPROTONOSUPPORT);
! 256:
! 257: switch (req) {
! 258: case PRU_ATTACH:
! 259: return (pfkey_attach(socket, nam));
! 260:
! 261: case PRU_DETACH:
! 262: return (pfkey_detach(socket));
! 263:
! 264: default:
! 265: s = splnet();
! 266: rval = raw_usrreq(socket, req, mbuf, nam, control);
! 267: splx(s);
! 268: }
! 269:
! 270: return (rval);
! 271: }
! 272:
! 273: static struct domain pfkey_domain = {
! 274: PF_KEY,
! 275: "PF_KEY",
! 276: NULL, /* init */
! 277: NULL, /* externalize */
! 278: NULL, /* dispose */
! 279: NULL, /* protosw */
! 280: NULL, /* protoswNPROTOSW */
! 281: NULL, /* dom_next */
! 282: rn_inithead, /* dom_rtattach */
! 283: 16, /* rtoffset */
! 284: sizeof(struct sockaddr_encap) /* maxrtkey */
! 285: };
! 286:
! 287: static struct protosw pfkey_protosw_template = {
! 288: SOCK_RAW,
! 289: &pfkey_domain,
! 290: -1, /* protocol */
! 291: PR_ATOMIC | PR_ADDR,
! 292: (void *) raw_input,
! 293: (void *) pfkey_output,
! 294: (void *) raw_ctlinput,
! 295: NULL, /* ctloutput */
! 296: pfkey_usrreq,
! 297: NULL, /* init */
! 298: NULL, /* fasttimo */
! 299: NULL, /* slowtimo */
! 300: NULL, /* drain */
! 301: NULL /* sysctl */
! 302: };
! 303:
! 304: int
! 305: pfkey_buildprotosw(void)
! 306: {
! 307: struct protosw *protosw, *p;
! 308: int i, j;
! 309:
! 310: for (i = j = 0; i <= PFKEY_PROTOCOL_MAX; i++)
! 311: if (pfkey_versions[i])
! 312: j++;
! 313:
! 314: if (j) {
! 315: if (!(protosw = malloc(j * sizeof(struct protosw),
! 316: M_PFKEY, M_DONTWAIT)))
! 317: return (ENOMEM);
! 318:
! 319: for (i = 0, p = protosw; i <= PFKEY_PROTOCOL_MAX; i++)
! 320: if (pfkey_versions[i]) {
! 321: bcopy(&pfkey_protosw_template, p,
! 322: sizeof(struct protosw));
! 323: p->pr_protocol = pfkey_versions[i]->protocol;
! 324: p->pr_sysctl = pfkey_versions[i]->sysctl;
! 325: p++;
! 326: }
! 327:
! 328: if (pfkey_domain.dom_protosw)
! 329: free(pfkey_domain.dom_protosw, M_PFKEY);
! 330:
! 331: pfkey_domain.dom_protosw = protosw;
! 332: pfkey_domain.dom_protoswNPROTOSW = p;
! 333: } else {
! 334: if (!(protosw = malloc(sizeof(struct protosw), M_PFKEY,
! 335: M_DONTWAIT)))
! 336: return (ENOMEM);
! 337:
! 338: bcopy(&pfkey_protosw_template, protosw,
! 339: sizeof(struct protosw));
! 340:
! 341: if (pfkey_domain.dom_protosw)
! 342: free(pfkey_domain.dom_protosw, M_PFKEY);
! 343:
! 344: pfkey_domain.dom_protosw = protosw;
! 345: pfkey_domain.dom_protoswNPROTOSW = protosw;
! 346: }
! 347:
! 348: return (0);
! 349: }
! 350:
! 351: void
! 352: pfkey_init(void)
! 353: {
! 354: if (pfkey_buildprotosw() != 0)
! 355: return;
! 356:
! 357: pfkey_domain.dom_next = domains;
! 358: domains = &pfkey_domain;
! 359: pfkeyv2_init();
! 360: }
CVSweb