Annotation of sys/net/pfkey.c, Revision 1.1.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