Annotation of sys/net/pfkeyv2.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pfkeyv2.c,v 1.115 2007/06/22 12:14:05 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 "pf.h"
72:
73: #include <sys/types.h>
74: #include <sys/param.h>
75: #include <sys/socket.h>
76: #include <sys/systm.h>
77: #include <sys/mbuf.h>
78: #include <sys/kernel.h>
79: #include <sys/proc.h>
80: #include <net/route.h>
81: #include <netinet/ip_ipsp.h>
82: #include <net/pfkeyv2.h>
83: #include <netinet/ip_ah.h>
84: #include <netinet/ip_esp.h>
85: #include <netinet/ip_ipcomp.h>
86: #include <crypto/blf.h>
87:
88: #if NPF > 0
89: #include <net/if.h>
90: #include <net/pfvar.h>
91: #endif
92:
93: #define PFKEYV2_PROTOCOL 2
94: #define GETSPI_TRIES 10
95:
96: /* Static globals */
97: static struct pfkeyv2_socket *pfkeyv2_sockets = NULL;
98: static struct pfkey_version pfkeyv2_version;
99: static uint32_t pfkeyv2_seq = 1;
100: static int nregistered = 0;
101: static int npromisc = 0;
102:
103: static const struct sadb_alg ealgs[] = {
104: { SADB_EALG_NULL, 0, 0, 0 },
105: { SADB_EALG_DESCBC, 64, 64, 64 },
106: { SADB_EALG_3DESCBC, 64, 192, 192 },
107: { SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8},
108: { SADB_X_EALG_CAST, 64, 40, 128},
109: { SADB_X_EALG_SKIPJACK, 64, 80, 80},
110: { SADB_X_EALG_AES, 128, 128, 256},
111: { SADB_X_EALG_AESCTR, 128, 128 + 32, 256 + 32}
112: };
113:
114: static const struct sadb_alg aalgs[] = {
115: { SADB_AALG_SHA1HMAC, 0, 160, 160 },
116: { SADB_AALG_MD5HMAC, 0, 128, 128 },
117: { SADB_X_AALG_RIPEMD160HMAC, 0, 160, 160 },
118: { SADB_X_AALG_SHA2_256, 0, 256, 256 },
119: { SADB_X_AALG_SHA2_384, 0, 384, 384 },
120: { SADB_X_AALG_SHA2_512, 0, 512, 512 }
121: };
122:
123: static const struct sadb_alg calgs[] = {
124: { SADB_X_CALG_DEFLATE, 0, 0, 0},
125: { SADB_X_CALG_LZS, 0, 0, 0}
126: };
127:
128: extern uint64_t sadb_exts_allowed_out[SADB_MAX+1];
129: extern uint64_t sadb_exts_required_out[SADB_MAX+1];
130:
131: extern struct pool ipsec_policy_pool;
132:
133: /*
134: * Wrapper around m_devget(); copy data from contiguous buffer to mbuf
135: * chain.
136: */
137: int
138: pfdatatopacket(void *data, int len, struct mbuf **packet)
139: {
140: if (!(*packet = m_devget(data, len, 0, NULL, NULL)))
141: return (ENOMEM);
142: return (0);
143: }
144:
145: /*
146: * Create a new PF_KEYv2 socket.
147: */
148: int
149: pfkeyv2_create(struct socket *socket)
150: {
151: struct pfkeyv2_socket *pfkeyv2_socket;
152:
153: if (!(pfkeyv2_socket = malloc(sizeof(struct pfkeyv2_socket),
154: M_PFKEY, M_DONTWAIT)))
155: return (ENOMEM);
156:
157: bzero(pfkeyv2_socket, sizeof(struct pfkeyv2_socket));
158: pfkeyv2_socket->next = pfkeyv2_sockets;
159: pfkeyv2_socket->socket = socket;
160: pfkeyv2_socket->pid = curproc->p_pid;
161:
162: pfkeyv2_sockets = pfkeyv2_socket;
163:
164: return (0);
165: }
166:
167: /*
168: * Close a PF_KEYv2 socket.
169: */
170: int
171: pfkeyv2_release(struct socket *socket)
172: {
173: struct pfkeyv2_socket **pp;
174:
175: for (pp = &pfkeyv2_sockets; *pp && ((*pp)->socket != socket);
176: pp = &((*pp)->next))
177: /*EMPTY*/;
178:
179: if (*pp) {
180: struct pfkeyv2_socket *pfkeyv2_socket;
181:
182: pfkeyv2_socket = *pp;
183: *pp = (*pp)->next;
184:
185: if (pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)
186: nregistered--;
187:
188: if (pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_PROMISC)
189: npromisc--;
190:
191: free(pfkeyv2_socket, M_PFKEY);
192: }
193:
194: return (0);
195: }
196:
197: /*
198: * Send a PFKEYv2 message, possibly to many receivers, based on the
199: * satype of the socket (which is set by the REGISTER message), and the
200: * third argument.
201: */
202: int
203: pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket,
204: u_int8_t satype, int count)
205: {
206: int i, j, rval;
207: void *p, *buffer = NULL;
208: struct mbuf *packet;
209: struct pfkeyv2_socket *s;
210: struct sadb_msg *smsg;
211:
212: /* Find out how much space we'll need... */
213: j = sizeof(struct sadb_msg);
214:
215: for (i = 1; i <= SADB_EXT_MAX; i++)
216: if (headers[i])
217: j += ((struct sadb_ext *)headers[i])->sadb_ext_len *
218: sizeof(uint64_t);
219:
220: /* ...and allocate it */
221: if (!(buffer = malloc(j + sizeof(struct sadb_msg), M_PFKEY,
222: M_DONTWAIT))) {
223: rval = ENOMEM;
224: goto ret;
225: }
226:
227: p = buffer + sizeof(struct sadb_msg);
228: bcopy(headers[0], p, sizeof(struct sadb_msg));
229: ((struct sadb_msg *) p)->sadb_msg_len = j / sizeof(uint64_t);
230: p += sizeof(struct sadb_msg);
231:
232: /* Copy payloads in the packet */
233: for (i = 1; i <= SADB_EXT_MAX; i++)
234: if (headers[i]) {
235: ((struct sadb_ext *) headers[i])->sadb_ext_type = i;
236: bcopy(headers[i], p, EXTLEN(headers[i]));
237: p += EXTLEN(headers[i]);
238: }
239:
240: if ((rval = pfdatatopacket(buffer + sizeof(struct sadb_msg),
241: j, &packet)) != 0)
242: goto ret;
243:
244: switch (mode) {
245: case PFKEYV2_SENDMESSAGE_UNICAST:
246: /*
247: * Send message to the specified socket, plus all
248: * promiscuous listeners.
249: */
250: pfkey_sendup(socket, packet, 0);
251:
252: /*
253: * Promiscuous messages contain the original message
254: * encapsulated in another sadb_msg header.
255: */
256: bzero(buffer, sizeof(struct sadb_msg));
257: smsg = (struct sadb_msg *) buffer;
258: smsg->sadb_msg_version = PF_KEY_V2;
259: smsg->sadb_msg_type = SADB_X_PROMISC;
260: smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
261: sizeof(uint64_t);
262: smsg->sadb_msg_seq = 0;
263:
264: /* Copy to mbuf chain */
265: if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
266: &packet)) != 0)
267: goto ret;
268:
269: /*
270: * Search for promiscuous listeners, skipping the
271: * original destination.
272: */
273: for (s = pfkeyv2_sockets; s; s = s->next)
274: if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
275: (s->socket != socket))
276: pfkey_sendup(s->socket, packet, 1);
277:
278: /* Done, let's be a bit paranoid */
279: m_zero(packet);
280: m_freem(packet);
281: break;
282:
283: case PFKEYV2_SENDMESSAGE_REGISTERED:
284: /*
285: * Send the message to all registered sockets that match
286: * the specified satype (e.g., all IPSEC-ESP negotiators)
287: */
288: for (s = pfkeyv2_sockets; s; s = s->next)
289: if (s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) {
290: if (!satype) /* Just send to everyone registered */
291: pfkey_sendup(s->socket, packet, 1);
292: else {
293: /* Check for specified satype */
294: if ((1 << satype) & s->registration)
295: pfkey_sendup(s->socket, packet, 1);
296: }
297: }
298:
299: /* Free last/original copy of the packet */
300: m_freem(packet);
301:
302: /* Encapsulate the original message "inside" an sadb_msg header */
303: bzero(buffer, sizeof(struct sadb_msg));
304: smsg = (struct sadb_msg *) buffer;
305: smsg->sadb_msg_version = PF_KEY_V2;
306: smsg->sadb_msg_type = SADB_X_PROMISC;
307: smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
308: sizeof(uint64_t);
309: smsg->sadb_msg_seq = 0;
310:
311: /* Convert to mbuf chain */
312: if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
313: &packet)) != 0)
314: goto ret;
315:
316: /* Send to all registered promiscuous listeners */
317: for (s = pfkeyv2_sockets; s; s = s->next)
318: if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
319: !(s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED))
320: pfkey_sendup(s->socket, packet, 1);
321:
322: m_freem(packet);
323: break;
324:
325: case PFKEYV2_SENDMESSAGE_BROADCAST:
326: /* Send message to all sockets */
327: for (s = pfkeyv2_sockets; s; s = s->next)
328: pfkey_sendup(s->socket, packet, 1);
329:
330: m_freem(packet);
331: break;
332: }
333:
334: ret:
335: if (buffer != NULL) {
336: bzero(buffer, j + sizeof(struct sadb_msg));
337: free(buffer, M_PFKEY);
338: }
339:
340: return (rval);
341: }
342:
343: /*
344: * Get SPD information for an ACQUIRE. We setup the message such that
345: * the SRC/DST payloads are relative to us (regardless of whether the
346: * SPD rule was for incoming or outgoing packets).
347: */
348: int
349: pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer)
350: {
351: union sockaddr_union sunion;
352: struct sadb_protocol *sp;
353: int rval, i, dir;
354: void *p;
355:
356: /* Find out how big a buffer we need */
357: i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol);
358: bzero(&sunion, sizeof(union sockaddr_union));
359:
360: switch (ipa->ipa_info.sen_type) {
361: #ifdef INET
362: case SENT_IP4:
363: i += 4 * PADUP(sizeof(struct sockaddr_in));
364: sunion.sa.sa_family = AF_INET;
365: sunion.sa.sa_len = sizeof(struct sockaddr_in);
366: dir = ipa->ipa_info.sen_direction;
367: break;
368: #endif /* INET */
369:
370: #ifdef INET6
371: case SENT_IP6:
372: i += 4 * PADUP(sizeof(struct sockaddr_in6));
373: sunion.sa.sa_family = AF_INET6;
374: sunion.sa.sa_len = sizeof(struct sockaddr_in6);
375: dir = ipa->ipa_info.sen_ip6_direction;
376: break;
377: #endif /* INET6 */
378:
379: default:
380: return (EINVAL);
381: }
382:
383: if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
384: rval = ENOMEM;
385: goto ret;
386: } else {
387: *buffer = p;
388: bzero(p, i);
389: }
390:
391: if (dir == IPSP_DIRECTION_OUT)
392: headers[SADB_X_EXT_SRC_FLOW] = p;
393: else
394: headers[SADB_X_EXT_DST_FLOW] = p;
395: switch (sunion.sa.sa_family) {
396: #ifdef INET
397: case AF_INET:
398: sunion.sin.sin_addr = ipa->ipa_info.sen_ip_src;
399: sunion.sin.sin_port = ipa->ipa_info.sen_sport;
400: break;
401: #endif /* INET */
402:
403: #ifdef INET6
404: case AF_INET6:
405: sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_src;
406: sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sport;
407: break;
408: #endif /* INET6 */
409: }
410: export_address(&p, (struct sockaddr *) &sunion);
411:
412: if (dir == IPSP_DIRECTION_OUT)
413: headers[SADB_X_EXT_SRC_MASK] = p;
414: else
415: headers[SADB_X_EXT_DST_MASK] = p;
416: switch (sunion.sa.sa_family) {
417: #ifdef INET
418: case AF_INET:
419: sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_src;
420: sunion.sin.sin_port = ipa->ipa_mask.sen_sport;
421: break;
422: #endif /* INET */
423:
424: #ifdef INET6
425: case AF_INET6:
426: sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_src;
427: sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sport;
428: break;
429: #endif /* INET6 */
430: }
431: export_address(&p, (struct sockaddr *) &sunion);
432:
433: if (dir == IPSP_DIRECTION_OUT)
434: headers[SADB_X_EXT_DST_FLOW] = p;
435: else
436: headers[SADB_X_EXT_SRC_FLOW] = p;
437: switch (sunion.sa.sa_family) {
438: #ifdef INET
439: case AF_INET:
440: sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dst;
441: sunion.sin.sin_port = ipa->ipa_info.sen_dport;
442: break;
443: #endif /* INET */
444:
445: #ifdef INET6
446: case AF_INET6:
447: sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dst;
448: sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dport;
449: break;
450: #endif /* INET6 */
451: }
452: export_address(&p, (struct sockaddr *) &sunion);
453:
454: if (dir == IPSP_DIRECTION_OUT)
455: headers[SADB_X_EXT_DST_MASK] = p;
456: else
457: headers[SADB_X_EXT_SRC_MASK] = p;
458: switch (sunion.sa.sa_family) {
459: #ifdef INET
460: case AF_INET:
461: sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dst;
462: sunion.sin.sin_port = ipa->ipa_mask.sen_dport;
463: break;
464: #endif /* INET */
465:
466: #ifdef INET6
467: case AF_INET6:
468: sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dst;
469: sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dport;
470: break;
471: #endif /* INET6 */
472: }
473: export_address(&p, (struct sockaddr *) &sunion);
474:
475: headers[SADB_X_EXT_FLOW_TYPE] = p;
476: sp = p;
477: sp->sadb_protocol_len = sizeof(struct sadb_protocol) /
478: sizeof(u_int64_t);
479: switch (sunion.sa.sa_family) {
480: #ifdef INET
481: case AF_INET:
482: if (ipa->ipa_mask.sen_proto)
483: sp->sadb_protocol_proto = ipa->ipa_info.sen_proto;
484: sp->sadb_protocol_direction = ipa->ipa_info.sen_direction;
485: break;
486: #endif /* INET */
487:
488: #ifdef INET6
489: case AF_INET6:
490: if (ipa->ipa_mask.sen_ip6_proto)
491: sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_proto;
492: sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_direction;
493: break;
494: #endif /* INET6 */
495: }
496:
497: rval = 0;
498:
499: ret:
500: return (rval);
501: }
502:
503: /*
504: * Get all the information contained in an SA to a PFKEYV2 message.
505: */
506: int
507: pfkeyv2_get(struct tdb *sa, void **headers, void **buffer, int *lenp)
508: {
509: int rval, i;
510: void *p;
511:
512: /* Find how much space we need */
513: i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime);
514:
515: if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
516: sa->tdb_soft_timeout || sa->tdb_soft_first_use)
517: i += sizeof(struct sadb_lifetime);
518:
519: if (sa->tdb_exp_allocations || sa->tdb_exp_bytes ||
520: sa->tdb_exp_timeout || sa->tdb_exp_first_use)
521: i += sizeof(struct sadb_lifetime);
522:
523: if (sa->tdb_last_used)
524: i += sizeof(struct sadb_lifetime);
525:
526: if (sa->tdb_src.sa.sa_family)
527: i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_src.sa));
528:
529: if (sa->tdb_dst.sa.sa_family)
530: i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_dst.sa));
531:
532: if (sa->tdb_proxy.sa.sa_family)
533: i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_proxy.sa));
534:
535: if (sa->tdb_srcid)
536: i += PADUP(sa->tdb_srcid->ref_len) + sizeof(struct sadb_ident);
537:
538: if (sa->tdb_dstid)
539: i += PADUP(sa->tdb_dstid->ref_len) + sizeof(struct sadb_ident);
540:
541: if (sa->tdb_local_cred)
542: i += PADUP(sa->tdb_local_cred->ref_len) + sizeof(struct sadb_x_cred);
543:
544: if (sa->tdb_remote_cred)
545: i += PADUP(sa->tdb_remote_cred->ref_len) + sizeof(struct sadb_x_cred);
546:
547: if (sa->tdb_local_auth)
548: i += PADUP(sa->tdb_local_auth->ref_len) + sizeof(struct sadb_x_cred);
549:
550: if (sa->tdb_remote_auth)
551: i += PADUP(sa->tdb_remote_auth->ref_len) + sizeof(struct sadb_x_cred);
552:
553: if (sa->tdb_amxkey)
554: i+= PADUP(sa->tdb_amxkeylen) + sizeof(struct sadb_key);
555:
556: if (sa->tdb_emxkey)
557: i+= PADUP(sa->tdb_emxkeylen) + sizeof(struct sadb_key);
558:
559: if (sa->tdb_filter.sen_type) {
560: i += 2 * sizeof(struct sadb_protocol);
561:
562: /* We'll need four of them: src, src mask, dst, dst mask. */
563: switch (sa->tdb_filter.sen_type) {
564: #ifdef INET
565: case SENT_IP4:
566: i += 4 * PADUP(sizeof(struct sockaddr_in));
567: i += 4 * sizeof(struct sadb_address);
568: break;
569: #endif /* INET */
570: #ifdef INET6
571: case SENT_IP6:
572: i += 4 * PADUP(sizeof(struct sockaddr_in6));
573: i += 4 * sizeof(struct sadb_address);
574: break;
575: #endif /* INET6 */
576: default:
577: rval = EINVAL;
578: goto ret;
579: }
580: }
581:
582: if (sa->tdb_udpencap_port)
583: i+= sizeof(struct sadb_x_udpencap);
584:
585: #if NPF > 0
586: if (sa->tdb_tag)
587: i+= PADUP(PF_TAG_NAME_SIZE) + sizeof(struct sadb_x_tag);
588: #endif
589:
590: if (lenp)
591: *lenp = i;
592:
593: if (buffer == NULL) {
594: rval = 0;
595: goto ret;
596: }
597:
598: if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
599: rval = ENOMEM;
600: goto ret;
601: } else {
602: *buffer = p;
603: bzero(p, i);
604: }
605:
606: headers[SADB_EXT_SA] = p;
607:
608: export_sa(&p, sa); /* Export SA information (mostly flags) */
609:
610: /* Export lifetimes where applicable */
611: headers[SADB_EXT_LIFETIME_CURRENT] = p;
612: export_lifetime(&p, sa, PFKEYV2_LIFETIME_CURRENT);
613:
614: if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
615: sa->tdb_soft_first_use || sa->tdb_soft_timeout) {
616: headers[SADB_EXT_LIFETIME_SOFT] = p;
617: export_lifetime(&p, sa, PFKEYV2_LIFETIME_SOFT);
618: }
619:
620: if (sa->tdb_exp_allocations || sa->tdb_exp_bytes ||
621: sa->tdb_exp_first_use || sa->tdb_exp_timeout) {
622: headers[SADB_EXT_LIFETIME_HARD] = p;
623: export_lifetime(&p, sa, PFKEYV2_LIFETIME_HARD);
624: }
625:
626: if (sa->tdb_last_used) {
627: headers[SADB_X_EXT_LIFETIME_LASTUSE] = p;
628: export_lifetime(&p, sa, PFKEYV2_LIFETIME_LASTUSE);
629: }
630:
631: /* Export TDB source address */
632: headers[SADB_EXT_ADDRESS_SRC] = p;
633: export_address(&p, (struct sockaddr *) &sa->tdb_src);
634:
635: /* Export TDB destination address */
636: headers[SADB_EXT_ADDRESS_DST] = p;
637: export_address(&p, (struct sockaddr *) &sa->tdb_dst);
638:
639: /* Export TDB proxy address, if present */
640: if (SA_LEN(&sa->tdb_proxy.sa)) {
641: headers[SADB_EXT_ADDRESS_PROXY] = p;
642: export_address(&p, (struct sockaddr *) &sa->tdb_proxy);
643: }
644:
645: /* Export source identity, if present */
646: if (sa->tdb_srcid) {
647: headers[SADB_EXT_IDENTITY_SRC] = p;
648: export_identity(&p, sa, PFKEYV2_IDENTITY_SRC);
649: }
650:
651: /* Export destination identity, if present */
652: if (sa->tdb_dstid) {
653: headers[SADB_EXT_IDENTITY_DST] = p;
654: export_identity(&p, sa, PFKEYV2_IDENTITY_DST);
655: }
656:
657: /* Export credentials, if present */
658: if (sa->tdb_local_cred) {
659: headers[SADB_X_EXT_LOCAL_CREDENTIALS] = p;
660: export_credentials(&p, sa, PFKEYV2_CRED_LOCAL);
661: }
662:
663: if (sa->tdb_remote_cred) {
664: headers[SADB_X_EXT_REMOTE_CREDENTIALS] = p;
665: export_credentials(&p, sa, PFKEYV2_CRED_REMOTE);
666: }
667:
668: /* Export authentication information, if present */
669: if (sa->tdb_local_auth) {
670: headers[SADB_X_EXT_LOCAL_AUTH] = p;
671: export_auth(&p, sa, PFKEYV2_AUTH_LOCAL);
672: }
673:
674: if (sa->tdb_remote_auth) {
675: headers[SADB_X_EXT_REMOTE_AUTH] = p;
676: export_auth(&p, sa, PFKEYV2_AUTH_REMOTE);
677: }
678:
679: /* Export authentication key, if present */
680: if (sa->tdb_amxkey) {
681: headers[SADB_EXT_KEY_AUTH] = p;
682: export_key(&p, sa, PFKEYV2_AUTHENTICATION_KEY);
683: }
684:
685: /* Export encryption key, if present */
686: if (sa->tdb_emxkey) {
687: headers[SADB_EXT_KEY_ENCRYPT] = p;
688: export_key(&p, sa, PFKEYV2_ENCRYPTION_KEY);
689: }
690:
691: /* Export flow/filter, if present */
692: if (sa->tdb_filter.sen_type)
693: export_flow(&p, IPSP_IPSEC_USE, &sa->tdb_filter,
694: &sa->tdb_filtermask, headers);
695:
696: /* Export UDP encapsulation port, if present */
697: if (sa->tdb_udpencap_port) {
698: headers[SADB_X_EXT_UDPENCAP] = p;
699: export_udpencap(&p, sa);
700: }
701:
702: #if NPF > 0
703: /* Export tag information, if present */
704: if (sa->tdb_tag) {
705: headers[SADB_X_EXT_TAG] = p;
706: export_tag(&p, sa);
707: }
708: #endif
709:
710: rval = 0;
711:
712: ret:
713: return (rval);
714: }
715:
716: /*
717: * Dump a TDB.
718: */
719: int
720: pfkeyv2_dump_walker(struct tdb *sa, void *state, int last)
721: {
722: struct dump_state *dump_state = (struct dump_state *) state;
723: void *headers[SADB_EXT_MAX+1], *buffer;
724: int rval;
725:
726: /* If not satype was specified, dump all TDBs */
727: if (!dump_state->sadb_msg->sadb_msg_satype ||
728: (sa->tdb_satype == dump_state->sadb_msg->sadb_msg_satype)) {
729: bzero(headers, sizeof(headers));
730: headers[0] = (void *) dump_state->sadb_msg;
731:
732: /* Get the information from the TDB to a PFKEYv2 message */
733: if ((rval = pfkeyv2_get(sa, headers, &buffer, NULL)) != 0)
734: return (rval);
735:
736: if (last)
737: ((struct sadb_msg *)headers[0])->sadb_msg_seq = 0;
738:
739: /* Send the message to the specified socket */
740: rval = pfkeyv2_sendmessage(headers,
741: PFKEYV2_SENDMESSAGE_UNICAST, dump_state->socket, 0, 0);
742:
743: free(buffer, M_PFKEY);
744: if (rval)
745: return (rval);
746: }
747:
748: return (0);
749: }
750:
751: /*
752: * Delete an SA.
753: */
754: int
755: pfkeyv2_flush_walker(struct tdb *sa, void *satype_vp, int last)
756: {
757: if (!(*((u_int8_t *) satype_vp)) ||
758: sa->tdb_satype == *((u_int8_t *) satype_vp))
759: tdb_delete(sa);
760: return (0);
761: }
762:
763: /*
764: * Convert between SATYPEs and IPsec protocols, taking into consideration
765: * sysctl variables enabling/disabling ESP/AH and the presence of the old
766: * IPsec transforms.
767: */
768: int
769: pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg)
770: {
771: switch (satype) {
772: #ifdef IPSEC
773: case SADB_SATYPE_AH:
774: if (!ah_enable)
775: return (EOPNOTSUPP);
776:
777: *sproto = IPPROTO_AH;
778:
779: if(alg != NULL)
780: *alg = satype = XF_AH;
781:
782: break;
783:
784: case SADB_SATYPE_ESP:
785: if (!esp_enable)
786: return (EOPNOTSUPP);
787:
788: *sproto = IPPROTO_ESP;
789:
790: if(alg != NULL)
791: *alg = satype = XF_ESP;
792:
793: break;
794:
795: case SADB_X_SATYPE_IPIP:
796: *sproto = IPPROTO_IPIP;
797:
798: if (alg != NULL)
799: *alg = XF_IP4;
800:
801: break;
802:
803: case SADB_X_SATYPE_IPCOMP:
804: if (!ipcomp_enable)
805: return (EOPNOTSUPP);
806:
807: *sproto = IPPROTO_IPCOMP;
808:
809: if(alg != NULL)
810: *alg = satype = XF_IPCOMP;
811:
812: break;
813: #endif /* IPSEC */
814: #ifdef TCP_SIGNATURE
815: case SADB_X_SATYPE_TCPSIGNATURE:
816: *sproto = IPPROTO_TCP;
817:
818: if (alg != NULL)
819: *alg = XF_TCPSIGNATURE;
820:
821: break;
822: #endif /* TCP_SIGNATURE */
823:
824: default: /* Nothing else supported */
825: return (EOPNOTSUPP);
826: }
827:
828: return (0);
829: }
830:
831: /*
832: * Handle all messages from userland to kernel.
833: */
834: int
835: pfkeyv2_send(struct socket *socket, void *message, int len)
836: {
837: int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST;
838: int delflag = 0, s;
839: struct sockaddr_encap encapdst, encapnetmask, encapgw;
840: struct ipsec_policy *ipo, *tmpipo;
841: struct ipsec_acquire *ipa;
842:
843: struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL;
844:
845: void *freeme = NULL, *bckptr = NULL;
846: void *headers[SADB_EXT_MAX + 1];
847:
848: union sockaddr_union *sunionp;
849:
850: struct tdb sa, *sa2 = NULL;
851:
852: struct sadb_msg *smsg;
853: struct sadb_spirange *sprng;
854: struct sadb_sa *ssa;
855: struct sadb_supported *ssup;
856: struct sadb_ident *sid;
857:
858: /* Verify that we received this over a legitimate pfkeyv2 socket */
859: bzero(headers, sizeof(headers));
860:
861: for (pfkeyv2_socket = pfkeyv2_sockets; pfkeyv2_socket;
862: pfkeyv2_socket = pfkeyv2_socket->next)
863: if (pfkeyv2_socket->socket == socket)
864: break;
865:
866: if (!pfkeyv2_socket) {
867: rval = EINVAL;
868: goto ret;
869: }
870:
871: /* If we have any promiscuous listeners, send them a copy of the message */
872: if (npromisc) {
873: struct mbuf *packet;
874:
875: if (!(freeme = malloc(sizeof(struct sadb_msg) + len, M_PFKEY,
876: M_DONTWAIT))) {
877: rval = ENOMEM;
878: goto ret;
879: }
880:
881: /* Initialize encapsulating header */
882: bzero(freeme, sizeof(struct sadb_msg));
883: smsg = (struct sadb_msg *) freeme;
884: smsg->sadb_msg_version = PF_KEY_V2;
885: smsg->sadb_msg_type = SADB_X_PROMISC;
886: smsg->sadb_msg_len = (sizeof(struct sadb_msg) + len) /
887: sizeof(uint64_t);
888: smsg->sadb_msg_seq = curproc->p_pid;
889:
890: bcopy(message, freeme + sizeof(struct sadb_msg), len);
891:
892: /* Convert to mbuf chain */
893: if ((rval = pfdatatopacket(freeme,
894: sizeof(struct sadb_msg) + len, &packet)) != 0)
895: goto ret;
896:
897: /* Send to all promiscuous listeners */
898: for (so = pfkeyv2_sockets; so; so = so->next)
899: if (so->flags & PFKEYV2_SOCKETFLAGS_PROMISC)
900: pfkey_sendup(so->socket, packet, 1);
901:
902: /* Paranoid */
903: m_zero(packet);
904: m_freem(packet);
905:
906: /* Even more paranoid */
907: bzero(freeme, sizeof(struct sadb_msg) + len);
908: free(freeme, M_PFKEY);
909: freeme = NULL;
910: }
911:
912: /* Validate message format */
913: if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0)
914: goto ret;
915:
916: smsg = (struct sadb_msg *) headers[0];
917: switch (smsg->sadb_msg_type) {
918: case SADB_GETSPI: /* Reserve an SPI */
919: bzero(&sa, sizeof(struct tdb));
920:
921: sa.tdb_satype = smsg->sadb_msg_satype;
922: if ((rval = pfkeyv2_get_proto_alg(sa.tdb_satype,
923: &sa.tdb_sproto, 0)))
924: goto ret;
925:
926: import_address((struct sockaddr *) &sa.tdb_src,
927: headers[SADB_EXT_ADDRESS_SRC]);
928: import_address((struct sockaddr *) &sa.tdb_dst,
929: headers[SADB_EXT_ADDRESS_DST]);
930:
931: /* Find an unused SA identifier */
932: sprng = (struct sadb_spirange *) headers[SADB_EXT_SPIRANGE];
933: sa.tdb_spi = reserve_spi(sprng->sadb_spirange_min,
934: sprng->sadb_spirange_max, &sa.tdb_src, &sa.tdb_dst,
935: sa.tdb_sproto, &rval);
936: if (sa.tdb_spi == 0)
937: goto ret;
938:
939: /* Send a message back telling what the SA (the SPI really) is */
940: if (!(freeme = malloc(sizeof(struct sadb_sa), M_PFKEY,
941: M_DONTWAIT))) {
942: rval = ENOMEM;
943: goto ret;
944: }
945:
946: bzero(freeme, sizeof(struct sadb_sa));
947: headers[SADB_EXT_SPIRANGE] = NULL;
948: headers[SADB_EXT_SA] = freeme;
949: bckptr = freeme;
950:
951: /* We really only care about the SPI, but we'll export the SA */
952: export_sa((void **) &bckptr, &sa);
953: break;
954:
955: case SADB_UPDATE:
956: ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
957: sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
958: sizeof(struct sadb_address));
959:
960: /* Either all or none of the flow must be included */
961: if ((headers[SADB_X_EXT_SRC_FLOW] ||
962: headers[SADB_X_EXT_PROTOCOL] ||
963: headers[SADB_X_EXT_FLOW_TYPE] ||
964: headers[SADB_X_EXT_DST_FLOW] ||
965: headers[SADB_X_EXT_SRC_MASK] ||
966: headers[SADB_X_EXT_DST_MASK]) &&
967: !(headers[SADB_X_EXT_SRC_FLOW] &&
968: headers[SADB_X_EXT_PROTOCOL] &&
969: headers[SADB_X_EXT_FLOW_TYPE] &&
970: headers[SADB_X_EXT_DST_FLOW] &&
971: headers[SADB_X_EXT_SRC_MASK] &&
972: headers[SADB_X_EXT_DST_MASK])) {
973: rval = EINVAL;
974: goto ret;
975: }
976: #ifdef IPSEC
977: /* UDP encap has to be enabled and is only supported for ESP */
978: if (headers[SADB_X_EXT_UDPENCAP] &&
979: (!udpencap_enable ||
980: smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
981: rval = EINVAL;
982: goto ret;
983: }
984: #endif /* IPSEC */
985:
986: s = spltdb();
987:
988: /* Find TDB */
989: sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
990: SADB_X_GETSPROTO(smsg->sadb_msg_satype));
991:
992: /* If there's no such SA, we're done */
993: if (sa2 == NULL) {
994: rval = ESRCH;
995: goto splxret;
996: }
997:
998: /* If this is a reserved SA */
999: if (sa2->tdb_flags & TDBF_INVALID) {
1000: struct tdb *newsa;
1001: struct ipsecinit ii;
1002: int alg;
1003:
1004: /* Create new TDB */
1005: freeme = tdb_alloc();
1006: bzero(&ii, sizeof(struct ipsecinit));
1007:
1008: newsa = (struct tdb *) freeme;
1009: newsa->tdb_satype = smsg->sadb_msg_satype;
1010:
1011: if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1012: &newsa->tdb_sproto, &alg))) {
1013: tdb_free(freeme);
1014: freeme = NULL;
1015: goto splxret;
1016: }
1017:
1018: /* Initialize SA */
1019: import_sa(newsa, headers[SADB_EXT_SA], &ii);
1020: import_address((struct sockaddr *) &newsa->tdb_src,
1021: headers[SADB_EXT_ADDRESS_SRC]);
1022: import_address((struct sockaddr *) &newsa->tdb_dst,
1023: headers[SADB_EXT_ADDRESS_DST]);
1024: import_address((struct sockaddr *) &newsa->tdb_proxy,
1025: headers[SADB_EXT_ADDRESS_PROXY]);
1026: import_lifetime(newsa,
1027: headers[SADB_EXT_LIFETIME_CURRENT],
1028: PFKEYV2_LIFETIME_CURRENT);
1029: import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
1030: PFKEYV2_LIFETIME_SOFT);
1031: import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
1032: PFKEYV2_LIFETIME_HARD);
1033: import_key(&ii, headers[SADB_EXT_KEY_AUTH],
1034: PFKEYV2_AUTHENTICATION_KEY);
1035: import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
1036: PFKEYV2_ENCRYPTION_KEY);
1037: import_identity(newsa, headers[SADB_EXT_IDENTITY_SRC],
1038: PFKEYV2_IDENTITY_SRC);
1039: import_identity(newsa, headers[SADB_EXT_IDENTITY_DST],
1040: PFKEYV2_IDENTITY_DST);
1041: import_credentials(newsa,
1042: headers[SADB_X_EXT_LOCAL_CREDENTIALS],
1043: PFKEYV2_CRED_LOCAL);
1044: import_credentials(newsa,
1045: headers[SADB_X_EXT_REMOTE_CREDENTIALS],
1046: PFKEYV2_CRED_REMOTE);
1047: import_auth(newsa, headers[SADB_X_EXT_LOCAL_AUTH],
1048: PFKEYV2_AUTH_LOCAL);
1049: import_auth(newsa, headers[SADB_X_EXT_REMOTE_AUTH],
1050: PFKEYV2_AUTH_REMOTE);
1051: import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
1052: headers[SADB_X_EXT_SRC_FLOW],
1053: headers[SADB_X_EXT_SRC_MASK],
1054: headers[SADB_X_EXT_DST_FLOW],
1055: headers[SADB_X_EXT_DST_MASK],
1056: headers[SADB_X_EXT_PROTOCOL],
1057: headers[SADB_X_EXT_FLOW_TYPE]);
1058: import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
1059: #if NPF > 0
1060: import_tag(newsa, headers[SADB_X_EXT_TAG]);
1061: #endif
1062:
1063: headers[SADB_EXT_KEY_AUTH] = NULL;
1064: headers[SADB_EXT_KEY_ENCRYPT] = NULL;
1065: headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
1066:
1067: newsa->tdb_seq = smsg->sadb_msg_seq;
1068:
1069: rval = tdb_init(newsa, alg, &ii);
1070: if (rval) {
1071: rval = EINVAL;
1072: tdb_free(freeme);
1073: freeme = NULL;
1074: goto splxret;
1075: }
1076:
1077: newsa->tdb_cur_allocations = sa2->tdb_cur_allocations;
1078:
1079: /* Delete old version of the SA, insert new one */
1080: tdb_delete(sa2);
1081: puttdb((struct tdb *) freeme);
1082: sa2 = freeme = NULL;
1083: } else {
1084: /*
1085: * The SA is already initialized, so we're only allowed to
1086: * change lifetimes and some other information; we're
1087: * not allowed to change keys, addresses or identities.
1088: */
1089: if (headers[SADB_EXT_ADDRESS_PROXY] ||
1090: headers[SADB_EXT_KEY_AUTH] ||
1091: headers[SADB_EXT_KEY_ENCRYPT] ||
1092: headers[SADB_EXT_IDENTITY_SRC] ||
1093: headers[SADB_EXT_IDENTITY_DST] ||
1094: headers[SADB_EXT_SENSITIVITY]) {
1095: rval = EINVAL;
1096: goto splxret;
1097: }
1098:
1099: import_sa(sa2, headers[SADB_EXT_SA], NULL);
1100: import_lifetime(sa2,
1101: headers[SADB_EXT_LIFETIME_CURRENT],
1102: PFKEYV2_LIFETIME_CURRENT);
1103: import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT],
1104: PFKEYV2_LIFETIME_SOFT);
1105: import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD],
1106: PFKEYV2_LIFETIME_HARD);
1107: import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP]);
1108: #if NPF > 0
1109: import_tag(sa2, headers[SADB_X_EXT_TAG]);
1110: #endif
1111: }
1112:
1113: splx(s);
1114: break;
1115: case SADB_ADD:
1116: ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1117: sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
1118: sizeof(struct sadb_address));
1119:
1120: /* Either all or none of the flow must be included */
1121: if ((headers[SADB_X_EXT_SRC_FLOW] ||
1122: headers[SADB_X_EXT_PROTOCOL] ||
1123: headers[SADB_X_EXT_FLOW_TYPE] ||
1124: headers[SADB_X_EXT_DST_FLOW] ||
1125: headers[SADB_X_EXT_SRC_MASK] ||
1126: headers[SADB_X_EXT_DST_MASK]) &&
1127: !(headers[SADB_X_EXT_SRC_FLOW] &&
1128: headers[SADB_X_EXT_PROTOCOL] &&
1129: headers[SADB_X_EXT_FLOW_TYPE] &&
1130: headers[SADB_X_EXT_DST_FLOW] &&
1131: headers[SADB_X_EXT_SRC_MASK] &&
1132: headers[SADB_X_EXT_DST_MASK])) {
1133: rval = EINVAL;
1134: goto ret;
1135: }
1136: #ifdef IPSEC
1137: /* UDP encap has to be enabled and is only supported for ESP */
1138: if (headers[SADB_X_EXT_UDPENCAP] &&
1139: (!udpencap_enable ||
1140: smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
1141: rval = EINVAL;
1142: goto ret;
1143: }
1144: #endif /* IPSEC */
1145:
1146: s = spltdb();
1147:
1148: sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
1149: SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1150:
1151: /* We can't add an existing SA! */
1152: if (sa2 != NULL) {
1153: rval = EEXIST;
1154: goto splxret;
1155: }
1156:
1157: /* We can only add "mature" SAs */
1158: if (ssa->sadb_sa_state != SADB_SASTATE_MATURE) {
1159: rval = EINVAL;
1160: goto splxret;
1161: }
1162:
1163: /* Allocate and initialize new TDB */
1164: freeme = tdb_alloc();
1165:
1166: {
1167: struct tdb *newsa = (struct tdb *) freeme;
1168: struct ipsecinit ii;
1169: int alg;
1170:
1171: bzero(&ii, sizeof(struct ipsecinit));
1172:
1173: newsa->tdb_satype = smsg->sadb_msg_satype;
1174: if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
1175: &newsa->tdb_sproto, &alg))) {
1176: tdb_free(freeme);
1177: freeme = NULL;
1178: goto splxret;
1179: }
1180:
1181: import_sa(newsa, headers[SADB_EXT_SA], &ii);
1182: import_address((struct sockaddr *) &newsa->tdb_src,
1183: headers[SADB_EXT_ADDRESS_SRC]);
1184: import_address((struct sockaddr *) &newsa->tdb_dst,
1185: headers[SADB_EXT_ADDRESS_DST]);
1186: import_address((struct sockaddr *) &newsa->tdb_proxy,
1187: headers[SADB_EXT_ADDRESS_PROXY]);
1188:
1189: import_lifetime(newsa,
1190: headers[SADB_EXT_LIFETIME_CURRENT],
1191: PFKEYV2_LIFETIME_CURRENT);
1192: import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
1193: PFKEYV2_LIFETIME_SOFT);
1194: import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
1195: PFKEYV2_LIFETIME_HARD);
1196:
1197: import_key(&ii, headers[SADB_EXT_KEY_AUTH],
1198: PFKEYV2_AUTHENTICATION_KEY);
1199: import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
1200: PFKEYV2_ENCRYPTION_KEY);
1201:
1202: import_identity(newsa, headers[SADB_EXT_IDENTITY_SRC],
1203: PFKEYV2_IDENTITY_SRC);
1204: import_identity(newsa, headers[SADB_EXT_IDENTITY_DST],
1205: PFKEYV2_IDENTITY_DST);
1206:
1207: import_credentials(newsa,
1208: headers[SADB_X_EXT_LOCAL_CREDENTIALS],
1209: PFKEYV2_CRED_LOCAL);
1210: import_credentials(newsa,
1211: headers[SADB_X_EXT_REMOTE_CREDENTIALS],
1212: PFKEYV2_CRED_REMOTE);
1213: import_auth(newsa, headers[SADB_X_EXT_LOCAL_AUTH],
1214: PFKEYV2_AUTH_LOCAL);
1215: import_auth(newsa, headers[SADB_X_EXT_REMOTE_AUTH],
1216: PFKEYV2_AUTH_REMOTE);
1217: import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
1218: headers[SADB_X_EXT_SRC_FLOW],
1219: headers[SADB_X_EXT_SRC_MASK],
1220: headers[SADB_X_EXT_DST_FLOW],
1221: headers[SADB_X_EXT_DST_MASK],
1222: headers[SADB_X_EXT_PROTOCOL],
1223: headers[SADB_X_EXT_FLOW_TYPE]);
1224: import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
1225: #if NPF > 0
1226: import_tag(newsa, headers[SADB_X_EXT_TAG]);
1227: #endif
1228:
1229: headers[SADB_EXT_KEY_AUTH] = NULL;
1230: headers[SADB_EXT_KEY_ENCRYPT] = NULL;
1231: headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
1232:
1233: newsa->tdb_seq = smsg->sadb_msg_seq;
1234:
1235: rval = tdb_init(newsa, alg, &ii);
1236: if (rval) {
1237: rval = EINVAL;
1238: tdb_free(freeme);
1239: freeme = NULL;
1240: goto splxret;
1241: }
1242: }
1243:
1244: /* Add TDB in table */
1245: puttdb((struct tdb *) freeme);
1246:
1247: splx(s);
1248:
1249: freeme = NULL;
1250: break;
1251:
1252: case SADB_DELETE:
1253: ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1254: sunionp =
1255: (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
1256: sizeof(struct sadb_address));
1257: s = spltdb();
1258:
1259: sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
1260: SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1261: if (sa2 == NULL) {
1262: rval = ESRCH;
1263: goto splxret;
1264: }
1265:
1266: tdb_delete(sa2);
1267:
1268: splx(s);
1269:
1270: sa2 = NULL;
1271: break;
1272:
1273: case SADB_X_ASKPOLICY:
1274: /* Get the relevant policy */
1275: ipa = ipsec_get_acquire(((struct sadb_x_policy *) headers[SADB_X_EXT_POLICY])->sadb_x_policy_seq);
1276: if (ipa == NULL) {
1277: rval = ESRCH;
1278: goto ret;
1279: }
1280:
1281: rval = pfkeyv2_policy(ipa, headers, &freeme);
1282: if (rval)
1283: mode = PFKEYV2_SENDMESSAGE_UNICAST;
1284:
1285: break;
1286:
1287: case SADB_GET:
1288: ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1289: sunionp =
1290: (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
1291: sizeof(struct sadb_address));
1292:
1293: s = spltdb();
1294:
1295: sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
1296: SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1297: if (sa2 == NULL) {
1298: rval = ESRCH;
1299: goto splxret;
1300: }
1301:
1302: rval = pfkeyv2_get(sa2, headers, &freeme, NULL);
1303: if (rval)
1304: mode = PFKEYV2_SENDMESSAGE_UNICAST;
1305:
1306: splx(s);
1307:
1308: break;
1309:
1310: case SADB_REGISTER:
1311: if (!(pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) {
1312: pfkeyv2_socket->flags |= PFKEYV2_SOCKETFLAGS_REGISTERED;
1313: nregistered++;
1314: }
1315:
1316: i = sizeof(struct sadb_supported) + sizeof(ealgs);
1317:
1318: if (!(freeme = malloc(i, M_PFKEY, M_DONTWAIT))) {
1319: rval = ENOMEM;
1320: goto ret;
1321: }
1322:
1323: bzero(freeme, i);
1324:
1325: ssup = (struct sadb_supported *) freeme;
1326: ssup->sadb_supported_len = i / sizeof(uint64_t);
1327:
1328: {
1329: void *p = freeme + sizeof(struct sadb_supported);
1330:
1331: bcopy(&ealgs[0], p, sizeof(ealgs));
1332: }
1333:
1334: headers[SADB_EXT_SUPPORTED_ENCRYPT] = freeme;
1335:
1336: i = sizeof(struct sadb_supported) + sizeof(aalgs);
1337:
1338: if (!(freeme = malloc(i, M_PFKEY, M_DONTWAIT))) {
1339: rval = ENOMEM;
1340: goto ret;
1341: }
1342:
1343: /* Keep track what this socket has registered for */
1344: pfkeyv2_socket->registration |= (1 << ((struct sadb_msg *)message)->sadb_msg_satype);
1345:
1346: bzero(freeme, i);
1347:
1348: ssup = (struct sadb_supported *) freeme;
1349: ssup->sadb_supported_len = i / sizeof(uint64_t);
1350:
1351: {
1352: void *p = freeme + sizeof(struct sadb_supported);
1353:
1354: bcopy(&aalgs[0], p, sizeof(aalgs));
1355: }
1356:
1357: headers[SADB_EXT_SUPPORTED_AUTH] = freeme;
1358:
1359: i = sizeof(struct sadb_supported) + sizeof(calgs);
1360:
1361: if (!(freeme = malloc(i, M_PFKEY, M_DONTWAIT))) {
1362: rval = ENOMEM;
1363: goto ret;
1364: }
1365:
1366: bzero(freeme, i);
1367:
1368: ssup = (struct sadb_supported *) freeme;
1369: ssup->sadb_supported_len = i / sizeof(uint64_t);
1370:
1371: {
1372: void *p = freeme + sizeof(struct sadb_supported);
1373:
1374: bcopy(&calgs[0], p, sizeof(calgs));
1375: }
1376:
1377: headers[SADB_X_EXT_SUPPORTED_COMP] = freeme;
1378:
1379: break;
1380:
1381: case SADB_ACQUIRE:
1382: case SADB_EXPIRE:
1383: /* Nothing to handle */
1384: rval = 0;
1385: break;
1386:
1387: case SADB_FLUSH:
1388: rval = 0;
1389:
1390: switch (smsg->sadb_msg_satype) {
1391: case SADB_SATYPE_UNSPEC:
1392: s = spltdb();
1393:
1394: /*
1395: * Go through the list of policies, delete those that
1396: * are not socket-attached.
1397: */
1398: for (ipo = TAILQ_FIRST(&ipsec_policy_head);
1399: ipo != NULL; ipo = tmpipo) {
1400: tmpipo = TAILQ_NEXT(ipo, ipo_list);
1401: if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
1402: ipsec_delete_policy(ipo);
1403: }
1404: splx(s);
1405: /* FALLTHROUGH */
1406: case SADB_SATYPE_AH:
1407: case SADB_SATYPE_ESP:
1408: case SADB_X_SATYPE_IPIP:
1409: case SADB_X_SATYPE_IPCOMP:
1410: #ifdef TCP_SIGNATURE
1411: case SADB_X_SATYPE_TCPSIGNATURE:
1412: #endif /* TCP_SIGNATURE */
1413: s = spltdb();
1414:
1415: tdb_walk(pfkeyv2_flush_walker,
1416: (u_int8_t *) &(smsg->sadb_msg_satype));
1417:
1418: splx(s);
1419: break;
1420:
1421: default:
1422: rval = EINVAL; /* Unknown/unsupported type */
1423: }
1424:
1425: break;
1426:
1427: case SADB_DUMP:
1428: {
1429: struct dump_state dump_state;
1430: dump_state.sadb_msg = (struct sadb_msg *) headers[0];
1431: dump_state.socket = socket;
1432:
1433: s = spltdb();
1434: rval = tdb_walk(pfkeyv2_dump_walker, &dump_state);
1435: splx(s);
1436:
1437: if (!rval)
1438: goto realret;
1439:
1440: if ((rval == ENOMEM) || (rval == ENOBUFS))
1441: rval = 0;
1442: }
1443: break;
1444:
1445: case SADB_X_GRPSPIS:
1446: {
1447: struct tdb *tdb1, *tdb2, *tdb3;
1448: struct sadb_protocol *sa_proto;
1449:
1450: ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
1451: sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
1452: sizeof(struct sadb_address));
1453:
1454: s = spltdb();
1455:
1456: tdb1 = gettdb(ssa->sadb_sa_spi, sunionp,
1457: SADB_X_GETSPROTO(smsg->sadb_msg_satype));
1458: if (tdb1 == NULL) {
1459: rval = ESRCH;
1460: goto splxret;
1461: }
1462:
1463: ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2];
1464: sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] +
1465: sizeof(struct sadb_address));
1466: sa_proto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL]);
1467:
1468: tdb2 = gettdb(ssa->sadb_sa_spi, sunionp,
1469: SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto));
1470: if (tdb2 == NULL) {
1471: rval = ESRCH;
1472: goto splxret;
1473: }
1474:
1475: /* Detect cycles */
1476: for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext)
1477: if (tdb3 == tdb1) {
1478: rval = ESRCH;
1479: goto splxret;
1480: }
1481:
1482: /* Maintenance */
1483: if ((tdb1->tdb_onext) &&
1484: (tdb1->tdb_onext->tdb_inext == tdb1))
1485: tdb1->tdb_onext->tdb_inext = NULL;
1486:
1487: if ((tdb2->tdb_inext) &&
1488: (tdb2->tdb_inext->tdb_onext == tdb2))
1489: tdb2->tdb_inext->tdb_onext = NULL;
1490:
1491: /* Link them */
1492: tdb1->tdb_onext = tdb2;
1493: tdb2->tdb_inext = tdb1;
1494:
1495: splx(s);
1496: }
1497: break;
1498:
1499: case SADB_X_DELFLOW:
1500: delflag = 1;
1501: /*FALLTHROUGH*/
1502: case SADB_X_ADDFLOW:
1503: {
1504: struct sadb_protocol *sab;
1505: union sockaddr_union *ssrc;
1506: struct route_enc re;
1507: int exists = 0;
1508:
1509: sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE];
1510:
1511: if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN) &&
1512: (sab->sadb_protocol_direction != IPSP_DIRECTION_OUT)) {
1513: rval = EINVAL;
1514: goto ret;
1515: }
1516:
1517: /* If the security protocol wasn't specified, pretend it was ESP */
1518: if (smsg->sadb_msg_satype == 0)
1519: smsg->sadb_msg_satype = SADB_SATYPE_ESP;
1520:
1521: if (headers[SADB_EXT_ADDRESS_DST])
1522: sunionp = (union sockaddr_union *)
1523: (headers[SADB_EXT_ADDRESS_DST] +
1524: sizeof(struct sadb_address));
1525: else
1526: sunionp = NULL;
1527:
1528: if (headers[SADB_EXT_ADDRESS_SRC])
1529: ssrc = (union sockaddr_union *)
1530: (headers[SADB_EXT_ADDRESS_SRC] +
1531: sizeof(struct sadb_address));
1532: else
1533: ssrc = NULL;
1534:
1535: import_flow(&encapdst, &encapnetmask,
1536: headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
1537: headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
1538: headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]);
1539:
1540: /* Determine whether the exact same SPD entry already exists. */
1541: bzero(&encapgw, sizeof(struct sockaddr_encap));
1542: bzero(&re, sizeof(struct route_enc));
1543: bcopy(&encapdst, &re.re_dst, sizeof(struct sockaddr_encap));
1544:
1545: s = spltdb();
1546:
1547: rtalloc((struct route *) &re);
1548: if (re.re_rt != NULL) {
1549: ipo = ((struct sockaddr_encap *) re.re_rt->rt_gateway)->sen_ipsp;
1550: RTFREE(re.re_rt);
1551:
1552: /* Verify that the entry is identical */
1553: if (bcmp(&ipo->ipo_addr, &encapdst,
1554: sizeof(struct sockaddr_encap)) ||
1555: bcmp(&ipo->ipo_mask, &encapnetmask,
1556: sizeof(struct sockaddr_encap)))
1557: ipo = NULL; /* Fall through */
1558: else
1559: exists = 1;
1560: } else
1561: ipo = NULL;
1562:
1563: /*
1564: * If the existing policy is static, only delete or update
1565: * it if the new one is also static.
1566: */
1567: if (exists && (ipo->ipo_flags & IPSP_POLICY_STATIC)) {
1568: if (!(sab->sadb_protocol_flags &
1569: SADB_X_POLICYFLAGS_POLICY)) {
1570: splx(s);
1571: goto ret;
1572: }
1573: }
1574:
1575: /* Delete ? */
1576: if (delflag) {
1577: if (exists) {
1578: rval = ipsec_delete_policy(ipo);
1579: splx(s);
1580: goto ret;
1581: }
1582:
1583: /* If we were asked to delete something non-existant, error. */
1584: splx(s);
1585: rval = ESRCH;
1586: break;
1587: }
1588:
1589: if (!exists) {
1590: if (ipsec_policy_pool_initialized == 0) {
1591: ipsec_policy_pool_initialized = 1;
1592: pool_init(&ipsec_policy_pool,
1593: sizeof(struct ipsec_policy), 0, 0, 0,
1594: "ipsec policy", NULL);
1595: }
1596:
1597: /* Allocate policy entry */
1598: ipo = pool_get(&ipsec_policy_pool, 0);
1599: if (ipo == NULL) {
1600: splx(s);
1601: rval = ENOMEM;
1602: goto ret;
1603: }
1604:
1605: bzero(ipo, sizeof(struct ipsec_policy));
1606: ipo->ipo_ref_count = 1;
1607: TAILQ_INIT(&ipo->ipo_acquires);
1608:
1609: /* Finish initialization of SPD entry */
1610: encapgw.sen_len = SENT_LEN;
1611: encapgw.sen_family = PF_KEY;
1612: encapgw.sen_type = SENT_IPSP;
1613: encapgw.sen_ipsp = ipo;
1614:
1615: /* Initialize policy entry */
1616: bcopy(&encapdst, &ipo->ipo_addr,
1617: sizeof(struct sockaddr_encap));
1618: bcopy(&encapnetmask, &ipo->ipo_mask,
1619: sizeof(struct sockaddr_encap));
1620: }
1621:
1622: switch (((struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE])->sadb_protocol_proto) {
1623: case SADB_X_FLOW_TYPE_USE:
1624: ipo->ipo_type = IPSP_IPSEC_USE;
1625: break;
1626:
1627: case SADB_X_FLOW_TYPE_ACQUIRE:
1628: ipo->ipo_type = IPSP_IPSEC_ACQUIRE;
1629: break;
1630:
1631: case SADB_X_FLOW_TYPE_REQUIRE:
1632: ipo->ipo_type = IPSP_IPSEC_REQUIRE;
1633: break;
1634:
1635: case SADB_X_FLOW_TYPE_DENY:
1636: ipo->ipo_type = IPSP_DENY;
1637: break;
1638:
1639: case SADB_X_FLOW_TYPE_BYPASS:
1640: ipo->ipo_type = IPSP_PERMIT;
1641: break;
1642:
1643: case SADB_X_FLOW_TYPE_DONTACQ:
1644: ipo->ipo_type = IPSP_IPSEC_DONTACQ;
1645: break;
1646:
1647: default:
1648: if (!exists)
1649: pool_put(&ipsec_policy_pool, ipo);
1650: else
1651: ipsec_delete_policy(ipo);
1652:
1653: splx(s);
1654: rval = EINVAL;
1655: goto ret;
1656: }
1657:
1658: if (sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY)
1659: ipo->ipo_flags |= IPSP_POLICY_STATIC;
1660:
1661: if (sunionp)
1662: bcopy(sunionp, &ipo->ipo_dst,
1663: sizeof(union sockaddr_union));
1664: else
1665: bzero(&ipo->ipo_dst, sizeof(union sockaddr_union));
1666:
1667: if (ssrc)
1668: bcopy(ssrc, &ipo->ipo_src,
1669: sizeof(union sockaddr_union));
1670: else
1671: bzero(&ipo->ipo_src, sizeof(union sockaddr_union));
1672:
1673: ipo->ipo_sproto = SADB_X_GETSPROTO(smsg->sadb_msg_satype);
1674:
1675: if (ipo->ipo_srcid) {
1676: ipsp_reffree(ipo->ipo_srcid);
1677: ipo->ipo_srcid = NULL;
1678: }
1679:
1680: if (ipo->ipo_dstid) {
1681: ipsp_reffree(ipo->ipo_dstid);
1682: ipo->ipo_dstid = NULL;
1683: }
1684:
1685: if ((sid = headers[SADB_EXT_IDENTITY_SRC]) != NULL) {
1686: int clen = (sid->sadb_ident_len * sizeof(u_int64_t)) -
1687: sizeof(struct sadb_ident);
1688:
1689: MALLOC(ipo->ipo_srcid, struct ipsec_ref *, clen +
1690: sizeof(struct ipsec_ref), M_CREDENTIALS, M_DONTWAIT);
1691: if (ipo->ipo_srcid == NULL) {
1692: if (exists)
1693: ipsec_delete_policy(ipo);
1694: else
1695: pool_put(&ipsec_policy_pool, ipo);
1696: splx(s);
1697: rval = ENOBUFS;
1698: goto ret;
1699: }
1700: ipo->ipo_srcid->ref_type = sid->sadb_ident_type;
1701: ipo->ipo_srcid->ref_len = clen;
1702: ipo->ipo_srcid->ref_count = 1;
1703: ipo->ipo_srcid->ref_malloctype = M_CREDENTIALS;
1704: bcopy(sid + 1, ipo->ipo_srcid + 1, ipo->ipo_srcid->ref_len);
1705: }
1706:
1707: if ((sid = headers[SADB_EXT_IDENTITY_DST]) != NULL) {
1708: int clen = (sid->sadb_ident_len * sizeof(u_int64_t)) -
1709: sizeof(struct sadb_ident);
1710:
1711: MALLOC(ipo->ipo_dstid, struct ipsec_ref *,
1712: clen + sizeof(struct ipsec_ref),
1713: M_CREDENTIALS, M_DONTWAIT);
1714: if (ipo->ipo_dstid == NULL) {
1715: if (exists)
1716: ipsec_delete_policy(ipo);
1717: else {
1718: if (ipo->ipo_dstid)
1719: ipsp_reffree(ipo->ipo_dstid);
1720: pool_put(&ipsec_policy_pool, ipo);
1721: }
1722:
1723: splx(s);
1724: rval = ENOBUFS;
1725: goto ret;
1726: }
1727: ipo->ipo_dstid->ref_type = sid->sadb_ident_type;
1728: ipo->ipo_dstid->ref_len = clen;
1729: ipo->ipo_dstid->ref_count = 1;
1730: ipo->ipo_dstid->ref_malloctype = M_CREDENTIALS;
1731: bcopy(sid + 1, ipo->ipo_dstid + 1,
1732: ipo->ipo_dstid->ref_len);
1733: }
1734:
1735: /* Flow type */
1736: if (!exists) {
1737: /* Add SPD entry */
1738: if ((rval = rtrequest(RTM_ADD,
1739: (struct sockaddr *) &encapdst,
1740: (struct sockaddr *) &encapgw,
1741: (struct sockaddr *) &encapnetmask,
1742: RTF_UP | RTF_GATEWAY | RTF_STATIC,
1743: (struct rtentry **) 0, 0)) != 0) {
1744: /* Remove from linked list of policies on TDB */
1745: if (ipo->ipo_tdb)
1746: TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
1747: ipo, ipo_tdb_next);
1748:
1749: if (ipo->ipo_srcid)
1750: ipsp_reffree(ipo->ipo_srcid);
1751: if (ipo->ipo_dstid)
1752: ipsp_reffree(ipo->ipo_dstid);
1753: pool_put(&ipsec_policy_pool, ipo);
1754:
1755: splx(s);
1756: goto ret;
1757: }
1758:
1759: TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list);
1760: ipsec_in_use++;
1761: } else {
1762: ipo->ipo_last_searched = ipo->ipo_flags = 0;
1763: }
1764:
1765: splx(s);
1766: }
1767: break;
1768:
1769: case SADB_X_PROMISC:
1770: if (len >= 2 * sizeof(struct sadb_msg)) {
1771: struct mbuf *packet;
1772:
1773: if ((rval = pfdatatopacket(message, len, &packet)) != 0)
1774: goto ret;
1775:
1776: for (so = pfkeyv2_sockets; so; so = so->next)
1777: if ((so != pfkeyv2_socket) &&
1778: (!smsg->sadb_msg_seq ||
1779: (smsg->sadb_msg_seq == pfkeyv2_socket->pid)))
1780: pfkey_sendup(so->socket, packet, 1);
1781:
1782: m_freem(packet);
1783: } else {
1784: if (len != sizeof(struct sadb_msg)) {
1785: rval = EINVAL;
1786: goto ret;
1787: }
1788:
1789: i = (pfkeyv2_socket->flags &
1790: PFKEYV2_SOCKETFLAGS_PROMISC) ? 1 : 0;
1791: j = smsg->sadb_msg_satype ? 1 : 0;
1792:
1793: if (i ^ j) {
1794: if (j) {
1795: pfkeyv2_socket->flags |=
1796: PFKEYV2_SOCKETFLAGS_PROMISC;
1797: npromisc++;
1798: } else {
1799: pfkeyv2_socket->flags &=
1800: ~PFKEYV2_SOCKETFLAGS_PROMISC;
1801: npromisc--;
1802: }
1803: }
1804: }
1805:
1806:
1807: break;
1808:
1809: default:
1810: rval = EINVAL;
1811: goto ret;
1812: }
1813:
1814: ret:
1815: if (rval) {
1816: if ((rval == EINVAL) || (rval == ENOMEM) || (rval == ENOBUFS))
1817: goto realret;
1818:
1819: for (i = 1; i <= SADB_EXT_MAX; i++)
1820: headers[i] = NULL;
1821:
1822: smsg->sadb_msg_errno = abs(rval);
1823: } else {
1824: uint64_t seen = 0LL;
1825:
1826: for (i = 1; i <= SADB_EXT_MAX; i++)
1827: if (headers[i])
1828: seen |= (1LL << i);
1829:
1830: if ((seen & sadb_exts_allowed_out[smsg->sadb_msg_type])
1831: != seen)
1832: goto realret;
1833:
1834: if ((seen & sadb_exts_required_out[smsg->sadb_msg_type]) !=
1835: sadb_exts_required_out[smsg->sadb_msg_type])
1836: goto realret;
1837: }
1838:
1839: rval = pfkeyv2_sendmessage(headers, mode, socket, 0, 0);
1840:
1841: realret:
1842: if (freeme)
1843: free(freeme, M_PFKEY);
1844:
1845: free(message, M_PFKEY);
1846:
1847: return (rval);
1848:
1849: splxret:
1850: splx(s);
1851: goto ret;
1852: }
1853:
1854: /*
1855: * Send an ACQUIRE message to key management, to get a new SA.
1856: */
1857: int
1858: pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
1859: union sockaddr_union *laddr, u_int32_t *seq, struct sockaddr_encap *ddst)
1860: {
1861: void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL;
1862: struct sadb_ident *srcid, *dstid;
1863: struct sadb_x_cred *lcred, *lauth;
1864: struct sadb_comb *sadb_comb;
1865: struct sadb_address *sadd;
1866: struct sadb_prop *sa_prop;
1867: struct sadb_msg *smsg;
1868: int rval = 0;
1869: int i, j;
1870:
1871: *seq = pfkeyv2_seq++;
1872:
1873: if (!nregistered) {
1874: rval = ESRCH;
1875: goto ret;
1876: }
1877:
1878: /* How large a buffer do we need... XXX we only do one proposal for now */
1879: i = sizeof(struct sadb_msg) +
1880: (laddr == NULL ? 0 : sizeof(struct sadb_address) +
1881: PADUP(SA_LEN(&ipo->ipo_src.sa))) +
1882: sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa)) +
1883: sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb);
1884:
1885: if (ipo->ipo_srcid)
1886: i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
1887:
1888: if (ipo->ipo_dstid)
1889: i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
1890:
1891: if (ipo->ipo_local_cred)
1892: i += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_cred->ref_len);
1893:
1894: if (ipo->ipo_local_auth)
1895: i += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_auth->ref_len);
1896:
1897: /* Allocate */
1898: if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
1899: rval = ENOMEM;
1900: goto ret;
1901: }
1902:
1903: bzero(headers, sizeof(headers));
1904:
1905: buffer = p;
1906: bzero(p, i);
1907:
1908: headers[0] = p;
1909: p += sizeof(struct sadb_msg);
1910:
1911: smsg = (struct sadb_msg *) headers[0];
1912: smsg->sadb_msg_version = PF_KEY_V2;
1913: smsg->sadb_msg_type = SADB_ACQUIRE;
1914: smsg->sadb_msg_len = i / sizeof(uint64_t);
1915: smsg->sadb_msg_seq = *seq;
1916:
1917: if (ipo->ipo_sproto == IPPROTO_ESP)
1918: smsg->sadb_msg_satype = SADB_SATYPE_ESP;
1919: else if (ipo->ipo_sproto == IPPROTO_AH)
1920: smsg->sadb_msg_satype = SADB_SATYPE_AH;
1921: else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
1922: smsg->sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
1923:
1924: if (laddr) {
1925: headers[SADB_EXT_ADDRESS_SRC] = p;
1926: p += sizeof(struct sadb_address) + PADUP(SA_LEN(&laddr->sa));
1927: sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC];
1928: sadd->sadb_address_len = (sizeof(struct sadb_address) +
1929: SA_LEN(&laddr->sa) + sizeof(uint64_t) - 1) /
1930: sizeof(uint64_t);
1931: bcopy(laddr, headers[SADB_EXT_ADDRESS_SRC] +
1932: sizeof(struct sadb_address), SA_LEN(&laddr->sa));
1933: }
1934:
1935: headers[SADB_EXT_ADDRESS_DST] = p;
1936: p += sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa));
1937: sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST];
1938: sadd->sadb_address_len = (sizeof(struct sadb_address) +
1939: SA_LEN(&gw->sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
1940: bcopy(gw, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address),
1941: SA_LEN(&gw->sa));
1942:
1943: if (ipo->ipo_srcid) {
1944: headers[SADB_EXT_IDENTITY_SRC] = p;
1945: p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
1946: srcid = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_SRC];
1947: srcid->sadb_ident_len = (sizeof(struct sadb_ident) +
1948: PADUP(ipo->ipo_srcid->ref_len)) / sizeof(u_int64_t);
1949: srcid->sadb_ident_type = ipo->ipo_srcid->ref_type;
1950: bcopy(ipo->ipo_srcid + 1, headers[SADB_EXT_IDENTITY_SRC] +
1951: sizeof(struct sadb_ident), ipo->ipo_srcid->ref_len);
1952: }
1953:
1954: if (ipo->ipo_dstid) {
1955: headers[SADB_EXT_IDENTITY_DST] = p;
1956: p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
1957: dstid = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_DST];
1958: dstid->sadb_ident_len = (sizeof(struct sadb_ident) +
1959: PADUP(ipo->ipo_dstid->ref_len)) / sizeof(u_int64_t);
1960: dstid->sadb_ident_type = ipo->ipo_dstid->ref_type;
1961: bcopy(ipo->ipo_dstid + 1, headers[SADB_EXT_IDENTITY_DST] +
1962: sizeof(struct sadb_ident), ipo->ipo_dstid->ref_len);
1963: }
1964:
1965: if (ipo->ipo_local_cred) {
1966: headers[SADB_X_EXT_LOCAL_CREDENTIALS] = p;
1967: p += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_cred->ref_len);
1968: lcred = (struct sadb_x_cred *) headers[SADB_X_EXT_LOCAL_CREDENTIALS];
1969: lcred->sadb_x_cred_len = (sizeof(struct sadb_x_cred) +
1970: PADUP(ipo->ipo_local_cred->ref_len)) / sizeof(u_int64_t);
1971: switch (ipo->ipo_local_cred->ref_type) {
1972: case IPSP_CRED_KEYNOTE:
1973: lcred->sadb_x_cred_type = SADB_X_CREDTYPE_KEYNOTE;
1974: break;
1975: case IPSP_CRED_X509:
1976: lcred->sadb_x_cred_type = SADB_X_CREDTYPE_X509;
1977: break;
1978: }
1979: bcopy(ipo->ipo_local_cred + 1, headers[SADB_X_EXT_LOCAL_CREDENTIALS] +
1980: sizeof(struct sadb_x_cred), ipo->ipo_local_cred->ref_len);
1981: }
1982:
1983: if (ipo->ipo_local_auth) {
1984: headers[SADB_X_EXT_LOCAL_AUTH] = p;
1985: p += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_auth->ref_len);
1986: lauth = (struct sadb_x_cred *) headers[SADB_X_EXT_LOCAL_AUTH];
1987: lauth->sadb_x_cred_len = (sizeof(struct sadb_x_cred) +
1988: PADUP(ipo->ipo_local_auth->ref_len)) / sizeof(u_int64_t);
1989: switch (ipo->ipo_local_auth->ref_type) {
1990: case IPSP_AUTH_PASSPHRASE:
1991: lauth->sadb_x_cred_type = SADB_X_AUTHTYPE_PASSPHRASE;
1992: break;
1993: case IPSP_AUTH_RSA:
1994: lauth->sadb_x_cred_type = SADB_X_AUTHTYPE_RSA;
1995: break;
1996: }
1997:
1998: bcopy(ipo->ipo_local_auth + 1, headers[SADB_X_EXT_LOCAL_AUTH] +
1999: sizeof(struct sadb_x_cred), ipo->ipo_local_auth->ref_len);
2000: }
2001:
2002: headers[SADB_EXT_PROPOSAL] = p;
2003: p += sizeof(struct sadb_prop);
2004: sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL];
2005: sa_prop->sadb_prop_num = 1; /* XXX One proposal only */
2006: sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
2007: (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) /
2008: sizeof(uint64_t);
2009:
2010: sadb_comb = p;
2011:
2012: /* XXX Should actually ask the crypto layer what's supported */
2013: for (j = 0; j < sa_prop->sadb_prop_num; j++) {
2014: sadb_comb->sadb_comb_flags = 0;
2015:
2016: if (ipsec_require_pfs)
2017: sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS;
2018:
2019: /* Set the encryption algorithm */
2020: if (ipo->ipo_sproto == IPPROTO_ESP) {
2021: if (!strncasecmp(ipsec_def_enc, "aes",
2022: sizeof("aes"))) {
2023: sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES;
2024: sadb_comb->sadb_comb_encrypt_minbits = 128;
2025: sadb_comb->sadb_comb_encrypt_maxbits = 256;
2026: } else if (!strncasecmp(ipsec_def_enc, "aesctr",
2027: sizeof("aesctr"))) {
2028: sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR;
2029: sadb_comb->sadb_comb_encrypt_minbits = 128+32;
2030: sadb_comb->sadb_comb_encrypt_maxbits = 256+32;
2031: } else if (!strncasecmp(ipsec_def_enc, "3des",
2032: sizeof("3des"))) {
2033: sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
2034: sadb_comb->sadb_comb_encrypt_minbits = 192;
2035: sadb_comb->sadb_comb_encrypt_maxbits = 192;
2036: } else if (!strncasecmp(ipsec_def_enc, "des",
2037: sizeof("des"))) {
2038: sadb_comb->sadb_comb_encrypt = SADB_EALG_DESCBC;
2039: sadb_comb->sadb_comb_encrypt_minbits = 64;
2040: sadb_comb->sadb_comb_encrypt_maxbits = 64;
2041: } else if (!strncasecmp(ipsec_def_enc, "blowfish",
2042: sizeof("blowfish"))) {
2043: sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF;
2044: sadb_comb->sadb_comb_encrypt_minbits = 40;
2045: sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN * 8;
2046: } else if (!strncasecmp(ipsec_def_enc, "skipjack",
2047: sizeof("skipjack"))) {
2048: sadb_comb->sadb_comb_encrypt = SADB_X_EALG_SKIPJACK;
2049: sadb_comb->sadb_comb_encrypt_minbits = 80;
2050: sadb_comb->sadb_comb_encrypt_maxbits = 80;
2051: } else if (!strncasecmp(ipsec_def_enc, "cast128",
2052: sizeof("cast128"))) {
2053: sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST;
2054: sadb_comb->sadb_comb_encrypt_minbits = 40;
2055: sadb_comb->sadb_comb_encrypt_maxbits = 128;
2056: }
2057: } else if (ipo->ipo_sproto == IPPROTO_IPCOMP) {
2058: /* Set the compression algorithm */
2059: if (!strncasecmp(ipsec_def_comp, "deflate",
2060: sizeof("deflate"))) {
2061: sadb_comb->sadb_comb_encrypt = SADB_X_CALG_DEFLATE;
2062: sadb_comb->sadb_comb_encrypt_minbits = 0;
2063: sadb_comb->sadb_comb_encrypt_maxbits = 0;
2064: } else if (!strncasecmp(ipsec_def_comp, "lzs",
2065: sizeof("lzs"))) {
2066: sadb_comb->sadb_comb_encrypt = SADB_X_CALG_LZS;
2067: sadb_comb->sadb_comb_encrypt_minbits = 0;
2068: sadb_comb->sadb_comb_encrypt_maxbits = 0;
2069: }
2070: }
2071:
2072: /* Set the authentication algorithm */
2073: if (!strncasecmp(ipsec_def_auth, "hmac-sha1",
2074: sizeof("hmac-sha1"))) {
2075: sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC;
2076: sadb_comb->sadb_comb_auth_minbits = 160;
2077: sadb_comb->sadb_comb_auth_maxbits = 160;
2078: } else if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",
2079: sizeof("hmac_ripemd160"))) {
2080: sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC;
2081: sadb_comb->sadb_comb_auth_minbits = 160;
2082: sadb_comb->sadb_comb_auth_maxbits = 160;
2083: } else if (!strncasecmp(ipsec_def_auth, "hmac-md5",
2084: sizeof("hmac-md5"))) {
2085: sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC;
2086: sadb_comb->sadb_comb_auth_minbits = 128;
2087: sadb_comb->sadb_comb_auth_maxbits = 128;
2088: } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-256",
2089: sizeof("hmac-sha2-256"))) {
2090: sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
2091: sadb_comb->sadb_comb_auth_minbits = 256;
2092: sadb_comb->sadb_comb_auth_maxbits = 256;
2093: } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-384",
2094: sizeof("hmac-sha2-384"))) {
2095: sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_384;
2096: sadb_comb->sadb_comb_auth_minbits = 384;
2097: sadb_comb->sadb_comb_auth_maxbits = 384;
2098: } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-512",
2099: sizeof("hmac-sha2-512"))) {
2100: sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_512;
2101: sadb_comb->sadb_comb_auth_minbits = 512;
2102: sadb_comb->sadb_comb_auth_maxbits = 512;
2103: }
2104:
2105: sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations;
2106: sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations;
2107:
2108: sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes;
2109: sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes;
2110:
2111: sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout;
2112: sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout;
2113:
2114: sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use;
2115: sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use;
2116: sadb_comb++;
2117: }
2118:
2119: /* Send the ACQUIRE message to all compliant registered listeners. */
2120: if ((rval = pfkeyv2_sendmessage(headers,
2121: PFKEYV2_SENDMESSAGE_REGISTERED, NULL, smsg->sadb_msg_satype, 0))
2122: != 0)
2123: goto ret;
2124:
2125: rval = 0;
2126: ret:
2127: if (buffer != NULL) {
2128: bzero(buffer, i);
2129: free(buffer, M_PFKEY);
2130: }
2131:
2132: return (rval);
2133: }
2134:
2135: /*
2136: * Notify key management that an expiration went off. The second argument
2137: * specifies the type of expiration (soft or hard).
2138: */
2139: int
2140: pfkeyv2_expire(struct tdb *sa, u_int16_t type)
2141: {
2142: void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL;
2143: struct sadb_msg *smsg;
2144: int rval = 0;
2145: int i;
2146:
2147: switch (sa->tdb_sproto) {
2148: case IPPROTO_AH:
2149: case IPPROTO_ESP:
2150: case IPPROTO_IPIP:
2151: case IPPROTO_IPCOMP:
2152: #ifdef TCP_SIGNATURE
2153: case IPPROTO_TCP:
2154: #endif /* TCP_SIGNATURE */
2155: break;
2156:
2157: default:
2158: rval = EOPNOTSUPP;
2159: goto ret;
2160: }
2161:
2162: i = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) +
2163: 2 * sizeof(struct sadb_lifetime) +
2164: sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_src.sa)) +
2165: sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_dst.sa));
2166:
2167: if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
2168: rval = ENOMEM;
2169: goto ret;
2170: }
2171:
2172: bzero(headers, sizeof(headers));
2173:
2174: buffer = p;
2175: bzero(p, i);
2176:
2177: headers[0] = p;
2178: p += sizeof(struct sadb_msg);
2179:
2180: smsg = (struct sadb_msg *) headers[0];
2181: smsg->sadb_msg_version = PF_KEY_V2;
2182: smsg->sadb_msg_type = SADB_EXPIRE;
2183: smsg->sadb_msg_satype = sa->tdb_satype;
2184: smsg->sadb_msg_len = i / sizeof(uint64_t);
2185: smsg->sadb_msg_seq = pfkeyv2_seq++;
2186:
2187: headers[SADB_EXT_SA] = p;
2188: export_sa(&p, sa);
2189:
2190: headers[SADB_EXT_LIFETIME_CURRENT] = p;
2191: export_lifetime(&p, sa, 2);
2192:
2193: headers[type] = p;
2194: export_lifetime(&p, sa, type == SADB_EXT_LIFETIME_SOFT ?
2195: PFKEYV2_LIFETIME_SOFT : PFKEYV2_LIFETIME_HARD);
2196:
2197: headers[SADB_EXT_ADDRESS_SRC] = p;
2198: export_address(&p, (struct sockaddr *) &sa->tdb_src);
2199:
2200: headers[SADB_EXT_ADDRESS_DST] = p;
2201: export_address(&p, (struct sockaddr *) &sa->tdb_dst);
2202:
2203: if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST,
2204: NULL, 0, 0)) != 0)
2205: goto ret;
2206:
2207: rval = 0;
2208:
2209: ret:
2210: if (buffer != NULL) {
2211: bzero(buffer, i);
2212: free(buffer, M_PFKEY);
2213: }
2214:
2215: return (rval);
2216: }
2217:
2218: struct pfkeyv2_sysctl_walk {
2219: void *w_where;
2220: size_t w_len;
2221: int w_op;
2222: u_int8_t w_satype;
2223: };
2224:
2225: int
2226: pfkeyv2_sysctl_walker(struct tdb *sa, void *arg, int last)
2227: {
2228: struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2229: void *buffer = NULL;
2230: int error = 0;
2231: int buflen, i;
2232:
2233: if (w->w_satype != SADB_SATYPE_UNSPEC &&
2234: w->w_satype != sa->tdb_satype)
2235: return (0);
2236:
2237: if (w->w_where) {
2238: void *headers[SADB_EXT_MAX+1];
2239: struct sadb_msg msg;
2240:
2241: bzero(headers, sizeof(headers));
2242: if ((error = pfkeyv2_get(sa, headers, &buffer, &buflen)) != 0)
2243: goto done;
2244: if (w->w_len < sizeof(msg) + buflen) {
2245: error = ENOMEM;
2246: goto done;
2247: }
2248: /* prepend header */
2249: bzero(&msg, sizeof(msg));
2250: msg.sadb_msg_version = PF_KEY_V2;
2251: msg.sadb_msg_satype = sa->tdb_satype;
2252: msg.sadb_msg_type = SADB_DUMP;
2253: msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2254: if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2255: goto done;
2256: w->w_where += sizeof(msg);
2257: w->w_len -= sizeof(msg);
2258: /* set extension type */
2259: for (i = 1; i <= SADB_EXT_MAX; i++)
2260: if (headers[i])
2261: ((struct sadb_ext *)
2262: headers[i])->sadb_ext_type = i;
2263: if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2264: goto done;
2265: w->w_where += buflen;
2266: w->w_len -= buflen;
2267: } else {
2268: if ((error = pfkeyv2_get(sa, NULL, NULL, &buflen)) != 0)
2269: return (error);
2270: w->w_len += buflen;
2271: w->w_len += sizeof(struct sadb_msg);
2272: }
2273:
2274: done:
2275: if (buffer)
2276: free(buffer, M_PFKEY);
2277: return (error);
2278: }
2279:
2280: int
2281: pfkeyv2_dump_policy(struct ipsec_policy *ipo, void **headers, void **buffer,
2282: int *lenp)
2283: {
2284: struct sadb_ident *ident;
2285: int i, rval, perm;
2286: void *p;
2287:
2288: /* Find how much space we need. */
2289: i = 2 * sizeof(struct sadb_protocol);
2290:
2291: /* We'll need four of them: src, src mask, dst, dst mask. */
2292: switch (ipo->ipo_addr.sen_type) {
2293: #ifdef INET
2294: case SENT_IP4:
2295: i += 4 * PADUP(sizeof(struct sockaddr_in));
2296: i += 4 * sizeof(struct sadb_address);
2297: break;
2298: #endif /* INET */
2299: #ifdef INET6
2300: case SENT_IP6:
2301: i += 4 * PADUP(sizeof(struct sockaddr_in6));
2302: i += 4 * sizeof(struct sadb_address);
2303: break;
2304: #endif /* INET6 */
2305: default:
2306: return (EINVAL);
2307: }
2308:
2309: /* Local address, might be zeroed. */
2310: switch (ipo->ipo_src.sa.sa_family) {
2311: case 0:
2312: break;
2313: #ifdef INET
2314: case AF_INET:
2315: i += PADUP(sizeof(struct sockaddr_in));
2316: i += sizeof(struct sadb_address);
2317: break;
2318: #endif /* INET */
2319: #ifdef INET6
2320: case AF_INET6:
2321: i += PADUP(sizeof(struct sockaddr_in6));
2322: i += sizeof(struct sadb_address);
2323: break;
2324: #endif /* INET6 */
2325: default:
2326: return (EINVAL);
2327: }
2328:
2329: /* Remote address, might be zeroed. XXX ??? */
2330: switch (ipo->ipo_dst.sa.sa_family) {
2331: case 0:
2332: break;
2333: #ifdef INET
2334: case AF_INET:
2335: i += PADUP(sizeof(struct sockaddr_in));
2336: i += sizeof(struct sadb_address);
2337: break;
2338: #endif /* INET */
2339: #ifdef INET6
2340: case AF_INET6:
2341: i += PADUP(sizeof(struct sockaddr_in6));
2342: i += sizeof(struct sadb_address);
2343: break;
2344: #endif /* INET6 */
2345: default:
2346: return (EINVAL);
2347: }
2348:
2349: if (ipo->ipo_srcid)
2350: i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
2351: if (ipo->ipo_dstid)
2352: i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
2353:
2354: if (lenp)
2355: *lenp = i;
2356:
2357: if (buffer == NULL) {
2358: rval = 0;
2359: goto ret;
2360: }
2361:
2362: if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
2363: rval = ENOMEM;
2364: goto ret;
2365: } else {
2366: *buffer = p;
2367: bzero(p, i);
2368: }
2369:
2370: /* Local address. */
2371: if (ipo->ipo_src.sa.sa_family) {
2372: headers[SADB_EXT_ADDRESS_SRC] = p;
2373: export_address(&p, (struct sockaddr *)&ipo->ipo_src);
2374: }
2375:
2376: /* Remote address. */
2377: if (ipo->ipo_dst.sa.sa_family) {
2378: headers[SADB_EXT_ADDRESS_DST] = p;
2379: export_address(&p, (struct sockaddr *)&ipo->ipo_dst);
2380: }
2381:
2382: /* Get actual flow. */
2383: export_flow(&p, ipo->ipo_type, &ipo->ipo_addr, &ipo->ipo_mask,
2384: headers);
2385:
2386: /* Add ids only when we are root. */
2387: perm = suser(curproc, 0);
2388: if (perm == 0 && ipo->ipo_srcid) {
2389: headers[SADB_EXT_IDENTITY_SRC] = p;
2390: p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
2391: ident = (struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC];
2392: ident->sadb_ident_len = (sizeof(struct sadb_ident) +
2393: PADUP(ipo->ipo_srcid->ref_len)) / sizeof(uint64_t);
2394: ident->sadb_ident_type = ipo->ipo_srcid->ref_type;
2395: bcopy(ipo->ipo_srcid + 1, headers[SADB_EXT_IDENTITY_SRC] +
2396: sizeof(struct sadb_ident), ipo->ipo_srcid->ref_len);
2397: }
2398: if (perm == 0 && ipo->ipo_dstid) {
2399: headers[SADB_EXT_IDENTITY_DST] = p;
2400: p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
2401: ident = (struct sadb_ident *)headers[SADB_EXT_IDENTITY_DST];
2402: ident->sadb_ident_len = (sizeof(struct sadb_ident) +
2403: PADUP(ipo->ipo_dstid->ref_len)) / sizeof(uint64_t);
2404: ident->sadb_ident_type = ipo->ipo_dstid->ref_type;
2405: bcopy(ipo->ipo_dstid + 1, headers[SADB_EXT_IDENTITY_DST] +
2406: sizeof(struct sadb_ident), ipo->ipo_dstid->ref_len);
2407: }
2408:
2409: rval = 0;
2410: ret:
2411: return (rval);
2412: }
2413:
2414: /*
2415: * Caller is responsible for setting at least spltdb().
2416: */
2417: int
2418: pfkeyv2_ipo_walk(int (*walker)(struct ipsec_policy *, void *), void *arg)
2419: {
2420: int rval = 0;
2421: struct ipsec_policy *ipo;
2422:
2423: TAILQ_FOREACH(ipo, &ipsec_policy_head, ipo_list)
2424: rval = walker(ipo, (void *)arg);
2425: return (rval);
2426: }
2427:
2428: int
2429: pfkeyv2_sysctl_policydumper(struct ipsec_policy *ipo, void *arg)
2430: {
2431: struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
2432: void *buffer = 0;
2433: int i, buflen, error = 0;
2434:
2435: /* Do not dump policies attached to a socket. */
2436: if (ipo->ipo_flags & IPSP_POLICY_SOCKET)
2437: return (0);
2438:
2439: if (w->w_where) {
2440: void *headers[SADB_EXT_MAX + 1];
2441: struct sadb_msg msg;
2442:
2443: bzero(headers, sizeof(headers));
2444: if ((error = pfkeyv2_dump_policy(ipo, headers, &buffer,
2445: &buflen)) != 0)
2446: goto done;
2447: if (w->w_len < buflen) {
2448: error = ENOMEM;
2449: goto done;
2450: }
2451: /* prepend header */
2452: bzero(&msg, sizeof(msg));
2453: msg.sadb_msg_version = PF_KEY_V2;
2454: if (ipo->ipo_sproto == IPPROTO_ESP)
2455: msg.sadb_msg_satype = SADB_SATYPE_ESP;
2456: else if (ipo->ipo_sproto == IPPROTO_AH)
2457: msg.sadb_msg_satype = SADB_SATYPE_AH;
2458: else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
2459: msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
2460: else if (ipo->ipo_sproto == IPPROTO_IPIP)
2461: msg.sadb_msg_satype = SADB_X_SATYPE_IPIP;
2462: msg.sadb_msg_type = SADB_X_SPDDUMP;
2463: msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
2464: if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
2465: goto done;
2466: w->w_where += sizeof(msg);
2467: w->w_len -= sizeof(msg);
2468: /* set extension type */
2469: for (i = 1; i < SADB_EXT_MAX; i++)
2470: if (headers[i])
2471: ((struct sadb_ext *)
2472: headers[i])->sadb_ext_type = i;
2473: if ((error = copyout(buffer, w->w_where, buflen)) != 0)
2474: goto done;
2475: w->w_where += buflen;
2476: w->w_len -= buflen;
2477: } else {
2478: if ((error = pfkeyv2_dump_policy(ipo, NULL, NULL,
2479: &buflen)) != 0)
2480: goto done;
2481: w->w_len += buflen;
2482: w->w_len += sizeof(struct sadb_msg);
2483: }
2484:
2485: done:
2486: if (buffer)
2487: free(buffer, M_PFKEY);
2488: return (error);
2489: }
2490:
2491: int
2492: pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2493: void *new, size_t newlen)
2494: {
2495: struct pfkeyv2_sysctl_walk w;
2496: int s, error = EINVAL;
2497:
2498: if (new)
2499: return (EPERM);
2500: if (namelen < 1)
2501: return (EINVAL);
2502: w.w_op = name[0];
2503: w.w_satype = name[1];
2504: w.w_where = oldp;
2505: w.w_len = oldp ? *oldlenp : 0;
2506:
2507: switch(w.w_op) {
2508: case NET_KEY_SADB_DUMP:
2509: if ((error = suser(curproc, 0)) != 0)
2510: return (error);
2511: s = spltdb();
2512: error = tdb_walk(pfkeyv2_sysctl_walker, &w);
2513: splx(s);
2514: if (oldp)
2515: *oldlenp = w.w_where - oldp;
2516: else
2517: *oldlenp = w.w_len;
2518: break;
2519:
2520: case NET_KEY_SPD_DUMP:
2521: s = spltdb();
2522: error = pfkeyv2_ipo_walk(pfkeyv2_sysctl_policydumper, &w);
2523: splx(s);
2524: if (oldp)
2525: *oldlenp = w.w_where - oldp;
2526: else
2527: *oldlenp = w.w_len;
2528: break;
2529: }
2530:
2531: return (error);
2532: }
2533:
2534: int
2535: pfkeyv2_init(void)
2536: {
2537: int rval;
2538:
2539: bzero(&pfkeyv2_version, sizeof(struct pfkey_version));
2540: pfkeyv2_version.protocol = PFKEYV2_PROTOCOL;
2541: pfkeyv2_version.create = &pfkeyv2_create;
2542: pfkeyv2_version.release = &pfkeyv2_release;
2543: pfkeyv2_version.send = &pfkeyv2_send;
2544: pfkeyv2_version.sysctl = &pfkeyv2_sysctl;
2545:
2546: rval = pfkey_register(&pfkeyv2_version);
2547: return (rval);
2548: }
2549:
2550: int
2551: pfkeyv2_cleanup(void)
2552: {
2553: pfkey_unregister(&pfkeyv2_version);
2554: return (0);
2555: }
CVSweb