1/*
2 * Copyright (c) 2003-2007 Apple Computer, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*	$FreeBSD: src/lib/libipsec/pfkey.c,v 1.1.2.2 2001/07/03 11:01:14 ume Exp $	*/
17/*	$KAME: pfkey.c,v 1.39 2001/03/05 18:22:17 thorpej Exp $	*/
18
19/*
20 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
21 * All rights reserved.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. Neither the name of the project nor the names of its contributors
32 *    may be used to endorse or promote products derived from this software
33 *    without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48#include <sys/types.h>
49#include <sys/param.h>
50#include <sys/socket.h>
51#include <net/pfkeyv2.h>
52#include <netinet/in.h>
53#include <netinet6/ipsec.h>
54
55#include <stdlib.h>
56#include <unistd.h>
57#include <string.h>
58#include <errno.h>
59#include <stdio.h>
60#include <TargetConditionals.h>
61
62#include "ipsec_strerror.h"
63#include "libpfkey.h"
64#include "ipsec_options.h"
65
66#if TARGET_OS_EMBEDDED
67#ifndef MDNS_NO_IPSEC
68#define MDNS_NO_IPSEC 1
69#endif
70#endif
71
72#ifndef MDNS_NO_IPSEC
73
74#define CALLOC(size, cast) (cast)calloc(1, (size))
75
76static int findsupportedmap __P((int));
77static int setsupportedmap __P((struct sadb_supported *));
78static struct sadb_alg *findsupportedalg __P((u_int, u_int));
79static int pfkey_send_x1 __P((int, u_int, u_int, u_int, struct sockaddr *,
80                              struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t,
81                              u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t,
82                              u_int32_t, u_int32_t, u_int32_t));
83static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
84                              struct sockaddr *, struct sockaddr *, u_int32_t));
85static int pfkey_send_x3 __P((int, u_int, u_int));
86static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int,
87                              struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
88                              char *, int, u_int32_t));
89static int pfkey_send_x5 __P((int, u_int, u_int32_t));
90
91static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int,
92                                     u_int, u_int32_t, pid_t));
93static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int,
94                                    u_int, u_int, u_int32_t));
95static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int,
96                                      struct sockaddr *, u_int, u_int));
97static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int));
98static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t,
99                                          u_int32_t, u_int32_t, u_int32_t));
100static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t));
101
102/*
103 * make and search supported algorithm structure.
104 */
105static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, };
106
107static int supported_map[] = {
108    SADB_SATYPE_AH,
109    SADB_SATYPE_ESP,
110    SADB_X_SATYPE_IPCOMP,
111};
112
113static int
114findsupportedmap(satype)
115int satype;
116{
117    int i;
118
119    for (i = 0; (unsigned int)i < sizeof(supported_map)/sizeof(supported_map[0]); i++)
120        if (supported_map[i] == satype)
121            return i;
122    return -1;
123}
124
125static struct sadb_alg *
126findsupportedalg(satype, alg_id)
127u_int satype, alg_id;
128{
129    int algno;
130    int tlen;
131    caddr_t p;
132
133    /* validity check */
134    algno = findsupportedmap(satype);
135    if (algno == -1) {
136        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
137        return NULL;
138    }
139    if (ipsec_supported[algno] == NULL) {
140        __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
141        return NULL;
142    }
143
144    tlen = ipsec_supported[algno]->sadb_supported_len
145           - sizeof(struct sadb_supported);
146    p = (caddr_t)(ipsec_supported[algno] + 1);
147    while (tlen > 0) {
148        if ((unsigned int)tlen < sizeof(struct sadb_alg)) {
149            /* invalid format */
150            break;
151        }
152        if (((struct sadb_alg *)p)->sadb_alg_id == alg_id)
153            return (struct sadb_alg *)p;
154
155        tlen -= sizeof(struct sadb_alg);
156        p += sizeof(struct sadb_alg);
157    }
158
159    __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
160    return NULL;
161}
162
163static int
164setsupportedmap(sup)
165struct sadb_supported *sup;
166{
167    struct sadb_supported **ipsup;
168
169    switch (sup->sadb_supported_exttype) {
170    case SADB_EXT_SUPPORTED_AUTH:
171        ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)];
172        break;
173    case SADB_EXT_SUPPORTED_ENCRYPT:
174        ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)];
175        break;
176    default:
177        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
178        return -1;
179    }
180
181    if (*ipsup)
182        free(*ipsup);
183
184    *ipsup = malloc(sup->sadb_supported_len);
185    if (!*ipsup) {
186        __ipsec_set_strerror(strerror(errno));
187        return -1;
188    }
189    memcpy(*ipsup, sup, sup->sadb_supported_len);
190
191    return 0;
192}
193
194/*
195 * check key length against algorithm specified.
196 * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the
197 * augument, and only calls to ipsec_check_keylen2();
198 * keylen is the unit of bit.
199 * OUT:
200 *	-1: invalid.
201 *	 0: valid.
202 */
203int
204ipsec_check_keylen(supported, alg_id, keylen)
205u_int supported;
206u_int alg_id;
207u_int keylen;
208{
209    int satype;
210
211    /* validity check */
212    switch (supported) {
213    case SADB_EXT_SUPPORTED_AUTH:
214        satype = SADB_SATYPE_AH;
215        break;
216    case SADB_EXT_SUPPORTED_ENCRYPT:
217        satype = SADB_SATYPE_ESP;
218        break;
219    default:
220        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
221        return -1;
222    }
223
224    return ipsec_check_keylen2(satype, alg_id, keylen);
225}
226
227/*
228 * check key length against algorithm specified.
229 * satype is one of satype defined at pfkeyv2.h.
230 * keylen is the unit of bit.
231 * OUT:
232 *	-1: invalid.
233 *	 0: valid.
234 */
235int
236ipsec_check_keylen2(satype, alg_id, keylen)
237u_int satype;
238u_int alg_id;
239u_int keylen;
240{
241    struct sadb_alg *alg;
242
243    alg = findsupportedalg(satype, alg_id);
244    if (!alg)
245        return -1;
246
247    if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) {
248        __ipsec_errcode = EIPSEC_INVAL_KEYLEN;
249        return -1;
250    }
251
252    __ipsec_errcode = EIPSEC_NO_ERROR;
253    return 0;
254}
255
256/*
257 * get max/min key length against algorithm specified.
258 * satype is one of satype defined at pfkeyv2.h.
259 * keylen is the unit of bit.
260 * OUT:
261 *	-1: invalid.
262 *	 0: valid.
263 */
264int
265ipsec_get_keylen(supported, alg_id, alg0)
266u_int supported, alg_id;
267struct sadb_alg *alg0;
268{
269    struct sadb_alg *alg;
270    u_int satype;
271
272    /* validity check */
273    if (!alg0) {
274        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
275        return -1;
276    }
277
278    switch (supported) {
279    case SADB_EXT_SUPPORTED_AUTH:
280        satype = SADB_SATYPE_AH;
281        break;
282    case SADB_EXT_SUPPORTED_ENCRYPT:
283        satype = SADB_SATYPE_ESP;
284        break;
285    default:
286        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
287        return -1;
288    }
289
290    alg = findsupportedalg(satype, alg_id);
291    if (!alg)
292        return -1;
293
294    memcpy(alg0, alg, sizeof(*alg0));
295
296    __ipsec_errcode = EIPSEC_NO_ERROR;
297    return 0;
298}
299
300/*
301 * set the rate for SOFT lifetime against HARD one.
302 * If rate is more than 100 or equal to zero, then set to 100.
303 */
304static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
305static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
306static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
307static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
308
309u_int
310pfkey_set_softrate(type, rate)
311u_int type, rate;
312{
313    __ipsec_errcode = EIPSEC_NO_ERROR;
314
315    if (rate > 100 || rate == 0)
316        rate = 100;
317
318    switch (type) {
319    case SADB_X_LIFETIME_ALLOCATIONS:
320        soft_lifetime_allocations_rate = rate;
321        return 0;
322    case SADB_X_LIFETIME_BYTES:
323        soft_lifetime_bytes_rate = rate;
324        return 0;
325    case SADB_X_LIFETIME_ADDTIME:
326        soft_lifetime_addtime_rate = rate;
327        return 0;
328    case SADB_X_LIFETIME_USETIME:
329        soft_lifetime_usetime_rate = rate;
330        return 0;
331    }
332
333    __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
334    return 1;
335}
336
337/*
338 * get current rate for SOFT lifetime against HARD one.
339 * ATTENTION: ~0 is returned if invalid type was passed.
340 */
341u_int
342pfkey_get_softrate(type)
343u_int type;
344{
345    switch (type) {
346    case SADB_X_LIFETIME_ALLOCATIONS:
347        return soft_lifetime_allocations_rate;
348    case SADB_X_LIFETIME_BYTES:
349        return soft_lifetime_bytes_rate;
350    case SADB_X_LIFETIME_ADDTIME:
351        return soft_lifetime_addtime_rate;
352    case SADB_X_LIFETIME_USETIME:
353        return soft_lifetime_usetime_rate;
354    }
355
356    return ~0;
357}
358
359/*
360 * sending SADB_GETSPI message to the kernel.
361 * OUT:
362 *	positive: success and return length sent.
363 *	-1	: error occured, and set errno.
364 */
365int
366pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
367int so;
368u_int satype, mode;
369struct sockaddr *src, *dst;
370u_int32_t min, max, reqid, seq;
371{
372    struct sadb_msg *newmsg;
373    caddr_t ep;
374    int len;
375    int need_spirange = 0;
376    caddr_t p;
377    int plen;
378
379    /* validity check */
380    if (src == NULL || dst == NULL) {
381        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
382        return -1;
383    }
384    if (src->sa_family != dst->sa_family) {
385        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
386        return -1;
387    }
388    if (min > max || (min > 0 && min <= 255)) {
389        __ipsec_errcode = EIPSEC_INVAL_SPI;
390        return -1;
391    }
392    switch (src->sa_family) {
393    case AF_INET:
394        plen = sizeof(struct in_addr) << 3;
395        break;
396    case AF_INET6:
397        plen = sizeof(struct in6_addr) << 3;
398        break;
399    default:
400        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
401        return -1;
402    }
403
404    /* create new sadb_msg to send. */
405    len = sizeof(struct sadb_msg)
406          + sizeof(struct sadb_x_sa2)
407          + sizeof(struct sadb_address)
408          + PFKEY_ALIGN8(src->sa_len)
409          + sizeof(struct sadb_address)
410          + PFKEY_ALIGN8(dst->sa_len);
411
412    if (min > (u_int32_t)255 && max < (u_int32_t) ~0) {
413        need_spirange++;
414        len += sizeof(struct sadb_spirange);
415    }
416
417    if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
418        __ipsec_set_strerror(strerror(errno));
419        return -1;
420    }
421    ep = ((caddr_t)newmsg) + len;
422
423    p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI,
424                         len, satype, seq, getpid());
425    if (!p) {
426        free(newmsg);
427        return -1;
428    }
429
430    p = pfkey_setsadbxsa2(p, ep, mode, reqid);
431    if (!p) {
432        free(newmsg);
433        return -1;
434    }
435
436    /* set sadb_address for source */
437    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
438                          IPSEC_ULPROTO_ANY);
439    if (!p) {
440        free(newmsg);
441        return -1;
442    }
443
444    /* set sadb_address for destination */
445    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
446                          IPSEC_ULPROTO_ANY);
447    if (!p) {
448        free(newmsg);
449        return -1;
450    }
451
452    /* proccessing spi range */
453    if (need_spirange) {
454        struct sadb_spirange spirange;
455
456        if (p + sizeof(spirange) > ep) {
457            free(newmsg);
458            return -1;
459        }
460
461        memset(&spirange, 0, sizeof(spirange));
462        spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange));
463        spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
464        spirange.sadb_spirange_min = min;
465        spirange.sadb_spirange_max = max;
466
467        memcpy(p, &spirange, sizeof(spirange));
468
469        p += sizeof(spirange);
470    }
471    if (p != ep) {
472        free(newmsg);
473        return -1;
474    }
475
476    /* send message */
477    len = pfkey_send(so, newmsg, len);
478    free(newmsg);
479
480    if (len < 0)
481        return -1;
482
483    __ipsec_errcode = EIPSEC_NO_ERROR;
484    return len;
485}
486
487/*
488 * sending SADB_UPDATE message to the kernel.
489 * The length of key material is a_keylen + e_keylen.
490 * OUT:
491 *	positive: success and return length sent.
492 *	-1	: error occured, and set errno.
493 */
494int
495pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
496                  keymat, e_type, e_keylen, a_type, a_keylen, flags,
497                  l_alloc, l_bytes, l_addtime, l_usetime, seq)
498int so;
499u_int satype, mode, wsize;
500struct sockaddr *src, *dst;
501u_int32_t spi, reqid;
502caddr_t keymat;
503u_int e_type, e_keylen, a_type, a_keylen, flags;
504u_int32_t l_alloc;
505u_int64_t l_bytes, l_addtime, l_usetime;
506u_int32_t seq;
507{
508    int len;
509    if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi,
510                             reqid, wsize,
511                             keymat, e_type, e_keylen, a_type, a_keylen, flags,
512                             l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
513        return -1;
514
515    return len;
516}
517
518/*
519 * sending SADB_ADD message to the kernel.
520 * The length of key material is a_keylen + e_keylen.
521 * OUT:
522 *	positive: success and return length sent.
523 *	-1	: error occured, and set errno.
524 */
525int
526pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
527               keymat, e_type, e_keylen, a_type, a_keylen, flags,
528               l_alloc, l_bytes, l_addtime, l_usetime, seq)
529int so;
530u_int satype, mode, wsize;
531struct sockaddr *src, *dst;
532u_int32_t spi, reqid;
533caddr_t keymat;
534u_int e_type, e_keylen, a_type, a_keylen, flags;
535u_int32_t l_alloc;
536u_int64_t l_bytes, l_addtime, l_usetime;
537u_int32_t seq;
538{
539    int len;
540    if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi,
541                             reqid, wsize,
542                             keymat, e_type, e_keylen, a_type, a_keylen, flags,
543                             l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
544        return -1;
545
546    return len;
547}
548
549/*
550 * sending SADB_DELETE message to the kernel.
551 * OUT:
552 *	positive: success and return length sent.
553 *	-1	: error occured, and set errno.
554 */
555int
556pfkey_send_delete(so, satype, mode, src, dst, spi)
557int so;
558u_int satype, mode;
559struct sockaddr *src, *dst;
560u_int32_t spi;
561{
562    int len;
563    if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
564        return -1;
565
566    return len;
567}
568
569/*
570 * sending SADB_DELETE without spi to the kernel.  This is
571 * the "delete all" request (an extension also present in
572 * Solaris).
573 *
574 * OUT:
575 *	positive: success and return length sent
576 *	-1	: error occured, and set errno
577 */
578int
579pfkey_send_delete_all(so, satype, mode, src, dst)
580int so;
581u_int satype, mode;
582struct sockaddr *src, *dst;
583{
584    struct sadb_msg *newmsg;
585    int len;
586    caddr_t p;
587    int plen;
588    caddr_t ep;
589
590    (void)mode;
591
592    /* validity check */
593    if (src == NULL || dst == NULL) {
594        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
595        return -1;
596    }
597    if (src->sa_family != dst->sa_family) {
598        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
599        return -1;
600    }
601    switch (src->sa_family) {
602    case AF_INET:
603        plen = sizeof(struct in_addr) << 3;
604        break;
605    case AF_INET6:
606        plen = sizeof(struct in6_addr) << 3;
607        break;
608    default:
609        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
610        return -1;
611    }
612
613    /* create new sadb_msg to reply. */
614    len = sizeof(struct sadb_msg)
615          + sizeof(struct sadb_address)
616          + PFKEY_ALIGN8(src->sa_len)
617          + sizeof(struct sadb_address)
618          + PFKEY_ALIGN8(dst->sa_len);
619
620    if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
621        __ipsec_set_strerror(strerror(errno));
622        return -1;
623    }
624    ep = ((caddr_t)newmsg) + len;
625
626    p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0,
627                         getpid());
628    if (!p) {
629        free(newmsg);
630        return -1;
631    }
632    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
633                          IPSEC_ULPROTO_ANY);
634    if (!p) {
635        free(newmsg);
636        return -1;
637    }
638    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
639                          IPSEC_ULPROTO_ANY);
640    if (!p || p != ep) {
641        free(newmsg);
642        return -1;
643    }
644
645    /* send message */
646    len = pfkey_send(so, newmsg, len);
647    free(newmsg);
648
649    if (len < 0)
650        return -1;
651
652    __ipsec_errcode = EIPSEC_NO_ERROR;
653    return len;
654}
655
656/*
657 * sending SADB_GET message to the kernel.
658 * OUT:
659 *	positive: success and return length sent.
660 *	-1	: error occured, and set errno.
661 */
662int
663pfkey_send_get(so, satype, mode, src, dst, spi)
664int so;
665u_int satype, mode;
666struct sockaddr *src, *dst;
667u_int32_t spi;
668{
669    int len;
670    if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
671        return -1;
672
673    return len;
674}
675
676/*
677 * sending SADB_REGISTER message to the kernel.
678 * OUT:
679 *	positive: success and return length sent.
680 *	-1	: error occured, and set errno.
681 */
682int
683pfkey_send_register(so, satype)
684int so;
685u_int satype;
686{
687    int len, algno;
688
689    if (satype == PF_UNSPEC) {
690        for (algno = 0;
691             (unsigned int)algno < sizeof(supported_map)/sizeof(supported_map[0]);
692             algno++) {
693            if (ipsec_supported[algno]) {
694                free(ipsec_supported[algno]);
695                ipsec_supported[algno] = NULL;
696            }
697        }
698    } else {
699        algno = findsupportedmap(satype);
700        if (algno == -1) {
701            __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
702            return -1;
703        }
704
705        if (ipsec_supported[algno]) {
706            free(ipsec_supported[algno]);
707            ipsec_supported[algno] = NULL;
708        }
709    }
710
711    if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
712        return -1;
713
714    return len;
715}
716
717/*
718 * receiving SADB_REGISTER message from the kernel, and copy buffer for
719 * sadb_supported returned into ipsec_supported.
720 * OUT:
721 *	 0: success and return length sent.
722 *	-1: error occured, and set errno.
723 */
724int
725pfkey_recv_register(so)
726int so;
727{
728    pid_t pid = getpid();
729    struct sadb_msg *newmsg;
730    int error = -1;
731
732    /* receive message */
733    do {
734        if ((newmsg = pfkey_recv(so)) == NULL)
735            return -1;
736    } while (newmsg->sadb_msg_type != SADB_REGISTER
737             || (pid_t)newmsg->sadb_msg_pid != pid);
738
739    /* check and fix */
740    newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
741
742    error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);
743    free(newmsg);
744
745    if (error == 0)
746        __ipsec_errcode = EIPSEC_NO_ERROR;
747
748    return error;
749}
750
751/*
752 * receiving SADB_REGISTER message from the kernel, and copy buffer for
753 * sadb_supported returned into ipsec_supported.
754 * NOTE: sadb_msg_len must be host order.
755 * IN:
756 *	tlen: msg length, it's to makeing sure.
757 * OUT:
758 *	 0: success and return length sent.
759 *	-1: error occured, and set errno.
760 */
761int
762pfkey_set_supported(msg, tlen)
763struct sadb_msg *msg;
764int tlen;
765{
766    struct sadb_supported *sup;
767    caddr_t p;
768    caddr_t ep;
769
770    /* validity */
771    if (msg->sadb_msg_len != tlen) {
772        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
773        return -1;
774    }
775
776    p = (caddr_t)msg;
777    ep = p + tlen;
778
779    p += sizeof(struct sadb_msg);
780
781    while (p < ep) {
782        sup = (struct sadb_supported *)p;
783        if (ep < p + sizeof(*sup) ||
784            (size_t)PFKEY_EXTLEN(sup) < sizeof(*sup) ||
785            ep < p + sup->sadb_supported_len) {
786            /* invalid format */
787            break;
788        }
789
790        switch (sup->sadb_supported_exttype) {
791        case SADB_EXT_SUPPORTED_AUTH:
792        case SADB_EXT_SUPPORTED_ENCRYPT:
793            break;
794        default:
795            __ipsec_errcode = EIPSEC_INVAL_SATYPE;
796            return -1;
797        }
798
799        /* fixed length */
800        sup->sadb_supported_len = PFKEY_EXTLEN(sup);
801
802        /* set supported map */
803        if (setsupportedmap(sup) != 0)
804            return -1;
805
806        p += sup->sadb_supported_len;
807    }
808
809    if (p != ep) {
810        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
811        return -1;
812    }
813
814    __ipsec_errcode = EIPSEC_NO_ERROR;
815
816    return 0;
817}
818
819/*
820 * sending SADB_FLUSH message to the kernel.
821 * OUT:
822 *	positive: success and return length sent.
823 *	-1	: error occured, and set errno.
824 */
825int
826pfkey_send_flush(so, satype)
827int so;
828u_int satype;
829{
830    int len;
831
832    if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
833        return -1;
834
835    return len;
836}
837
838/*
839 * sending SADB_DUMP message to the kernel.
840 * OUT:
841 *	positive: success and return length sent.
842 *	-1	: error occured, and set errno.
843 */
844int
845pfkey_send_dump(so, satype)
846int so;
847u_int satype;
848{
849    int len;
850
851    if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
852        return -1;
853
854    return len;
855}
856
857/*
858 * sending SADB_X_PROMISC message to the kernel.
859 * NOTE that this function handles promisc mode toggle only.
860 * IN:
861 *	flag:	set promisc off if zero, set promisc on if non-zero.
862 * OUT:
863 *	positive: success and return length sent.
864 *	-1	: error occured, and set errno.
865 *	0     : error occured, and set errno.
866 *	others: a pointer to new allocated buffer in which supported
867 *	        algorithms is.
868 */
869int
870pfkey_send_promisc_toggle(so, flag)
871int so;
872int flag;
873{
874    int len;
875
876    if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0)
877        return -1;
878
879    return len;
880}
881
882/*
883 * sending SADB_X_SPDADD message to the kernel.
884 * OUT:
885 *	positive: success and return length sent.
886 *	-1	: error occured, and set errno.
887 */
888int
889pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
890int so;
891struct sockaddr *src, *dst;
892u_int prefs, prefd, proto;
893caddr_t policy;
894int policylen;
895u_int32_t seq;
896{
897    int len;
898
899    if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
900                             src, prefs, dst, prefd, proto,
901                             0, 0,
902                             policy, policylen, seq)) < 0)
903        return -1;
904
905    return len;
906}
907
908/*
909 * sending SADB_X_SPDADD message to the kernel.
910 * OUT:
911 *	positive: success and return length sent.
912 *	-1	: error occured, and set errno.
913 */
914int
915pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,
916                   policy, policylen, seq)
917int so;
918struct sockaddr *src, *dst;
919u_int prefs, prefd, proto;
920u_int64_t ltime, vtime;
921caddr_t policy;
922int policylen;
923u_int32_t seq;
924{
925    int len;
926
927    if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
928                             src, prefs, dst, prefd, proto,
929                             ltime, vtime,
930                             policy, policylen, seq)) < 0)
931        return -1;
932
933    return len;
934}
935
936/*
937 * sending SADB_X_SPDUPDATE message to the kernel.
938 * OUT:
939 *	positive: success and return length sent.
940 *	-1	: error occured, and set errno.
941 */
942int
943pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
944int so;
945struct sockaddr *src, *dst;
946u_int prefs, prefd, proto;
947caddr_t policy;
948int policylen;
949u_int32_t seq;
950{
951    int len;
952
953    if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
954                             src, prefs, dst, prefd, proto,
955                             0, 0,
956                             policy, policylen, seq)) < 0)
957        return -1;
958
959    return len;
960}
961
962/*
963 * sending SADB_X_SPDUPDATE message to the kernel.
964 * OUT:
965 *	positive: success and return length sent.
966 *	-1	: error occured, and set errno.
967 */
968int
969pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,
970                      policy, policylen, seq)
971int so;
972struct sockaddr *src, *dst;
973u_int prefs, prefd, proto;
974u_int64_t ltime, vtime;
975caddr_t policy;
976int policylen;
977u_int32_t seq;
978{
979    int len;
980
981    if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
982                             src, prefs, dst, prefd, proto,
983                             ltime, vtime,
984                             policy, policylen, seq)) < 0)
985        return -1;
986
987    return len;
988}
989
990/*
991 * sending SADB_X_SPDDELETE message to the kernel.
992 * OUT:
993 *	positive: success and return length sent.
994 *	-1	: error occured, and set errno.
995 */
996int
997pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
998int so;
999struct sockaddr *src, *dst;
1000u_int prefs, prefd, proto;
1001caddr_t policy;
1002int policylen;
1003u_int32_t seq;
1004{
1005    int len;
1006
1007    if (policylen != sizeof(struct sadb_x_policy)) {
1008        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1009        return -1;
1010    }
1011
1012    if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
1013                             src, prefs, dst, prefd, proto,
1014                             0, 0,
1015                             policy, policylen, seq)) < 0)
1016        return -1;
1017
1018    return len;
1019}
1020
1021/*
1022 * sending SADB_X_SPDDELETE message to the kernel.
1023 * OUT:
1024 *	positive: success and return length sent.
1025 *	-1	: error occured, and set errno.
1026 */
1027int
1028pfkey_send_spddelete2(so, spid)
1029int so;
1030u_int32_t spid;
1031{
1032    int len;
1033
1034    if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
1035        return -1;
1036
1037    return len;
1038}
1039
1040/*
1041 * sending SADB_X_SPDGET message to the kernel.
1042 * OUT:
1043 *	positive: success and return length sent.
1044 *	-1	: error occured, and set errno.
1045 */
1046int
1047pfkey_send_spdget(so, spid)
1048int so;
1049u_int32_t spid;
1050{
1051    int len;
1052
1053    if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
1054        return -1;
1055
1056    return len;
1057}
1058
1059/*
1060 * sending SADB_X_SPDSETIDX message to the kernel.
1061 * OUT:
1062 *	positive: success and return length sent.
1063 *	-1	: error occured, and set errno.
1064 */
1065int
1066pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
1067int so;
1068struct sockaddr *src, *dst;
1069u_int prefs, prefd, proto;
1070caddr_t policy;
1071int policylen;
1072u_int32_t seq;
1073{
1074    int len;
1075
1076    if (policylen != sizeof(struct sadb_x_policy)) {
1077        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1078        return -1;
1079    }
1080
1081    if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
1082                             src, prefs, dst, prefd, proto,
1083                             0, 0,
1084                             policy, policylen, seq)) < 0)
1085        return -1;
1086
1087    return len;
1088}
1089
1090/*
1091 * sending SADB_SPDFLUSH message to the kernel.
1092 * OUT:
1093 *	positive: success and return length sent.
1094 *	-1	: error occured, and set errno.
1095 */
1096int
1097pfkey_send_spdflush(so)
1098int so;
1099{
1100    int len;
1101
1102    if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
1103        return -1;
1104
1105    return len;
1106}
1107
1108/*
1109 * sending SADB_SPDDUMP message to the kernel.
1110 * OUT:
1111 *	positive: success and return length sent.
1112 *	-1	: error occured, and set errno.
1113 */
1114int
1115pfkey_send_spddump(so)
1116int so;
1117{
1118    int len;
1119
1120    if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
1121        return -1;
1122
1123    return len;
1124}
1125
1126/* sending SADB_ADD or SADB_UPDATE message to the kernel */
1127static int
1128pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize,
1129              keymat, e_type, e_keylen, a_type, a_keylen, flags,
1130              l_alloc, l_bytes, l_addtime, l_usetime, seq)
1131int so;
1132u_int type, satype, mode;
1133struct sockaddr *src, *dst;
1134u_int32_t spi, reqid;
1135u_int wsize;
1136caddr_t keymat;
1137u_int e_type, e_keylen, a_type, a_keylen, flags;
1138u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq;
1139{
1140    struct sadb_msg *newmsg;
1141    int len;
1142    caddr_t p;
1143    int plen;
1144    caddr_t ep;
1145
1146    /* validity check */
1147    if (src == NULL || dst == NULL) {
1148        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1149        return -1;
1150    }
1151    if (src->sa_family != dst->sa_family) {
1152        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1153        return -1;
1154    }
1155    switch (src->sa_family) {
1156    case AF_INET:
1157        plen = sizeof(struct in_addr) << 3;
1158        break;
1159    case AF_INET6:
1160        plen = sizeof(struct in6_addr) << 3;
1161        break;
1162    default:
1163        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1164        return -1;
1165    }
1166
1167    switch (satype) {
1168    case SADB_SATYPE_ESP:
1169        if (e_type == SADB_EALG_NONE) {
1170            __ipsec_errcode = EIPSEC_NO_ALGS;
1171            return -1;
1172        }
1173        break;
1174    case SADB_SATYPE_AH:
1175        if (e_type != SADB_EALG_NONE) {
1176            __ipsec_errcode = EIPSEC_INVAL_ALGS;
1177            return -1;
1178        }
1179        if (a_type == SADB_AALG_NONE) {
1180            __ipsec_errcode = EIPSEC_NO_ALGS;
1181            return -1;
1182        }
1183        break;
1184    case SADB_X_SATYPE_IPCOMP:
1185        if (e_type == SADB_X_CALG_NONE) {
1186            __ipsec_errcode = EIPSEC_INVAL_ALGS;
1187            return -1;
1188        }
1189        if (a_type != SADB_AALG_NONE) {
1190            __ipsec_errcode = EIPSEC_NO_ALGS;
1191            return -1;
1192        }
1193        break;
1194    default:
1195        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1196        return -1;
1197    }
1198
1199    /* create new sadb_msg to reply. */
1200    len = sizeof(struct sadb_msg)
1201          + sizeof(struct sadb_sa)
1202          + sizeof(struct sadb_x_sa2)
1203          + sizeof(struct sadb_address)
1204          + PFKEY_ALIGN8(src->sa_len)
1205          + sizeof(struct sadb_address)
1206          + PFKEY_ALIGN8(dst->sa_len)
1207          + sizeof(struct sadb_lifetime)
1208          + sizeof(struct sadb_lifetime);
1209
1210    if (e_type != SADB_EALG_NONE)
1211        len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));
1212    if (a_type != SADB_AALG_NONE)
1213        len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));
1214
1215    if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1216        __ipsec_set_strerror(strerror(errno));
1217        return -1;
1218    }
1219    ep = ((caddr_t)newmsg) + len;
1220
1221    p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
1222                         satype, seq, getpid());
1223    if (!p) {
1224        free(newmsg);
1225        return -1;
1226    }
1227    p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags);
1228    if (!p) {
1229        free(newmsg);
1230        return -1;
1231    }
1232    p = pfkey_setsadbxsa2(p, ep, mode, reqid);
1233    if (!p) {
1234        free(newmsg);
1235        return -1;
1236    }
1237    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
1238                          IPSEC_ULPROTO_ANY);
1239    if (!p) {
1240        free(newmsg);
1241        return -1;
1242    }
1243    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
1244                          IPSEC_ULPROTO_ANY);
1245    if (!p) {
1246        free(newmsg);
1247        return -1;
1248    }
1249
1250    if (e_type != SADB_EALG_NONE) {
1251        p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
1252                             keymat, e_keylen);
1253        if (!p) {
1254            free(newmsg);
1255            return -1;
1256        }
1257    }
1258    if (a_type != SADB_AALG_NONE) {
1259        p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
1260                             keymat + e_keylen, a_keylen);
1261        if (!p) {
1262            free(newmsg);
1263            return -1;
1264        }
1265    }
1266
1267    /* set sadb_lifetime for destination */
1268    p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1269                              l_alloc, l_bytes, l_addtime, l_usetime);
1270    if (!p) {
1271        free(newmsg);
1272        return -1;
1273    }
1274    p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
1275                              l_alloc, l_bytes, l_addtime, l_usetime);
1276    if (!p || p != ep) {
1277        free(newmsg);
1278        return -1;
1279    }
1280
1281    /* send message */
1282    len = pfkey_send(so, newmsg, len);
1283    free(newmsg);
1284
1285    if (len < 0)
1286        return -1;
1287
1288    __ipsec_errcode = EIPSEC_NO_ERROR;
1289    return len;
1290}
1291
1292/* sending SADB_DELETE or SADB_GET message to the kernel */
1293static int
1294pfkey_send_x2(so, type, satype, mode, src, dst, spi)
1295int so;
1296u_int type, satype, mode;
1297struct sockaddr *src, *dst;
1298u_int32_t spi;
1299{
1300    struct sadb_msg *newmsg;
1301    int len;
1302    caddr_t p;
1303    int plen;
1304    caddr_t ep;
1305
1306    (void)mode;
1307
1308    /* validity check */
1309    if (src == NULL || dst == NULL) {
1310        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1311        return -1;
1312    }
1313    if (src->sa_family != dst->sa_family) {
1314        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1315        return -1;
1316    }
1317    switch (src->sa_family) {
1318    case AF_INET:
1319        plen = sizeof(struct in_addr) << 3;
1320        break;
1321    case AF_INET6:
1322        plen = sizeof(struct in6_addr) << 3;
1323        break;
1324    default:
1325        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1326        return -1;
1327    }
1328
1329    /* create new sadb_msg to reply. */
1330    len = sizeof(struct sadb_msg)
1331          + sizeof(struct sadb_sa)
1332          + sizeof(struct sadb_address)
1333          + PFKEY_ALIGN8(src->sa_len)
1334          + sizeof(struct sadb_address)
1335          + PFKEY_ALIGN8(dst->sa_len);
1336
1337    if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1338        __ipsec_set_strerror(strerror(errno));
1339        return -1;
1340    }
1341    ep = ((caddr_t)newmsg) + len;
1342
1343    p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
1344                         getpid());
1345    if (!p) {
1346        free(newmsg);
1347        return -1;
1348    }
1349    p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
1350    if (!p) {
1351        free(newmsg);
1352        return -1;
1353    }
1354    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
1355                          IPSEC_ULPROTO_ANY);
1356    if (!p) {
1357        free(newmsg);
1358        return -1;
1359    }
1360    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
1361                          IPSEC_ULPROTO_ANY);
1362    if (!p || p != ep) {
1363        free(newmsg);
1364        return -1;
1365    }
1366
1367    /* send message */
1368    len = pfkey_send(so, newmsg, len);
1369    free(newmsg);
1370
1371    if (len < 0)
1372        return -1;
1373
1374    __ipsec_errcode = EIPSEC_NO_ERROR;
1375    return len;
1376}
1377
1378/*
1379 * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
1380 * to the kernel
1381 */
1382static int
1383pfkey_send_x3(so, type, satype)
1384int so;
1385u_int type, satype;
1386{
1387    struct sadb_msg *newmsg;
1388    int len;
1389    caddr_t p;
1390    caddr_t ep;
1391
1392    /* validity check */
1393    switch (type) {
1394    case SADB_X_PROMISC:
1395        if (satype != 0 && satype != 1) {
1396            __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1397            return -1;
1398        }
1399        break;
1400    default:
1401        switch (satype) {
1402        case SADB_SATYPE_UNSPEC:
1403        case SADB_SATYPE_AH:
1404        case SADB_SATYPE_ESP:
1405        case SADB_X_SATYPE_IPCOMP:
1406            break;
1407        default:
1408            __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1409            return -1;
1410        }
1411    }
1412
1413    /* create new sadb_msg to send. */
1414    len = sizeof(struct sadb_msg);
1415
1416    if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1417        __ipsec_set_strerror(strerror(errno));
1418        return -1;
1419    }
1420    ep = ((caddr_t)newmsg) + len;
1421
1422    p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
1423                         getpid());
1424    if (!p || p != ep) {
1425        free(newmsg);
1426        return -1;
1427    }
1428
1429    /* send message */
1430    len = pfkey_send(so, newmsg, len);
1431    free(newmsg);
1432
1433    if (len < 0)
1434        return -1;
1435
1436    __ipsec_errcode = EIPSEC_NO_ERROR;
1437    return len;
1438}
1439
1440/* sending SADB_X_SPDADD message to the kernel */
1441static int
1442pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
1443              ltime, vtime, policy, policylen, seq)
1444int so;
1445struct sockaddr *src, *dst;
1446u_int type, prefs, prefd, proto;
1447u_int64_t ltime, vtime;
1448char *policy;
1449int policylen;
1450u_int32_t seq;
1451{
1452    struct sadb_msg *newmsg;
1453    int len;
1454    caddr_t p;
1455    int plen;
1456    caddr_t ep;
1457
1458    /* validity check */
1459    if (src == NULL || dst == NULL) {
1460        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1461        return -1;
1462    }
1463    if (src->sa_family != dst->sa_family) {
1464        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1465        return -1;
1466    }
1467
1468    switch (src->sa_family) {
1469    case AF_INET:
1470        plen = sizeof(struct in_addr) << 3;
1471        break;
1472    case AF_INET6:
1473        plen = sizeof(struct in6_addr) << 3;
1474        break;
1475    default:
1476        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1477        return -1;
1478    }
1479    if (prefs > (u_int)plen || prefd > (u_int)plen) {
1480        __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1481        return -1;
1482    }
1483
1484    /* create new sadb_msg to reply. */
1485    len = sizeof(struct sadb_msg)
1486          + sizeof(struct sadb_address)
1487          + PFKEY_ALIGN8(src->sa_len)
1488          + sizeof(struct sadb_address)
1489          + PFKEY_ALIGN8(src->sa_len)
1490          + sizeof(struct sadb_lifetime)
1491          + policylen;
1492
1493    if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1494        __ipsec_set_strerror(strerror(errno));
1495        return -1;
1496    }
1497    ep = ((caddr_t)newmsg) + len;
1498
1499    p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
1500                         SADB_SATYPE_UNSPEC, seq, getpid());
1501    if (!p) {
1502        free(newmsg);
1503        return -1;
1504    }
1505    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
1506    if (!p) {
1507        free(newmsg);
1508        return -1;
1509    }
1510    p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
1511    if (!p) {
1512        free(newmsg);
1513        return -1;
1514    }
1515    p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1516                              0, 0, ltime, vtime);
1517    if (!p || p + policylen != ep) {
1518        free(newmsg);
1519        return -1;
1520    }
1521    memcpy(p, policy, policylen);
1522
1523    /* send message */
1524    len = pfkey_send(so, newmsg, len);
1525    free(newmsg);
1526
1527    if (len < 0)
1528        return -1;
1529
1530    __ipsec_errcode = EIPSEC_NO_ERROR;
1531    return len;
1532}
1533
1534/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
1535static int
1536pfkey_send_x5(so, type, spid)
1537int so;
1538u_int type;
1539u_int32_t spid;
1540{
1541    struct sadb_msg *newmsg;
1542    struct sadb_x_policy xpl;
1543    int len;
1544    caddr_t p;
1545    caddr_t ep;
1546
1547    /* create new sadb_msg to reply. */
1548    len = sizeof(struct sadb_msg)
1549          + sizeof(xpl);
1550
1551    if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1552        __ipsec_set_strerror(strerror(errno));
1553        return -1;
1554    }
1555    ep = ((caddr_t)newmsg) + len;
1556
1557    p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
1558                         SADB_SATYPE_UNSPEC, 0, getpid());
1559    if (!p) {
1560        free(newmsg);
1561        return -1;
1562    }
1563
1564    if (p + sizeof(xpl) != ep) {
1565        free(newmsg);
1566        return -1;
1567    }
1568    memset(&xpl, 0, sizeof(xpl));
1569    xpl.sadb_x_policy_len = PFKEY_UNUNIT64(sizeof(xpl));
1570    xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1571    xpl.sadb_x_policy_id = spid;
1572    memcpy(p, &xpl, sizeof(xpl));
1573
1574    /* send message */
1575    len = pfkey_send(so, newmsg, len);
1576    free(newmsg);
1577
1578    if (len < 0)
1579        return -1;
1580
1581    __ipsec_errcode = EIPSEC_NO_ERROR;
1582    return len;
1583}
1584
1585/*
1586 * open a socket.
1587 * OUT:
1588 *	-1: fail.
1589 *	others : success and return value of socket.
1590 */
1591int
1592pfkey_open()
1593{
1594    int so;
1595    const int bufsiz = 128 * 1024;  /*is 128K enough?*/
1596
1597    if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1598        __ipsec_set_strerror(strerror(errno));
1599        return -1;
1600    }
1601
1602    /*
1603     * This is a temporary workaround for KAME PR 154.
1604     * Don't really care even if it fails.
1605     */
1606    (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
1607    (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
1608
1609    __ipsec_errcode = EIPSEC_NO_ERROR;
1610    return so;
1611}
1612
1613/*
1614 * close a socket.
1615 * OUT:
1616 *	 0: success.
1617 *	-1: fail.
1618 */
1619void
1620pfkey_close(so)
1621int so;
1622{
1623    (void)close(so);
1624
1625    __ipsec_errcode = EIPSEC_NO_ERROR;
1626    return;
1627}
1628
1629/*
1630 * receive sadb_msg data, and return pointer to new buffer allocated.
1631 * Must free this buffer later.
1632 * OUT:
1633 *	NULL	: error occured.
1634 *	others	: a pointer to sadb_msg structure.
1635 *
1636 * XXX should be rewritten to pass length explicitly
1637 */
1638struct sadb_msg *
1639pfkey_recv(so)
1640int so;
1641{
1642    struct sadb_msg buf, *newmsg;
1643    int len, reallen;
1644
1645    while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1646        if (errno == EINTR)
1647            continue;
1648        __ipsec_set_strerror(strerror(errno));
1649        return NULL;
1650    }
1651
1652    if ((size_t)len < sizeof(buf)) {
1653        recv(so, (caddr_t)&buf, sizeof(buf), 0);
1654        __ipsec_errcode = EIPSEC_MAX;
1655        return NULL;
1656    }
1657
1658    /* read real message */
1659    reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1660    if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == 0) {
1661        __ipsec_set_strerror(strerror(errno));
1662        return NULL;
1663    }
1664
1665    while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
1666        if (errno == EINTR)
1667            continue;
1668        __ipsec_set_strerror(strerror(errno));
1669        free(newmsg);
1670        return NULL;
1671    }
1672
1673    if (len != reallen) {
1674        __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1675        free(newmsg);
1676        return NULL;
1677    }
1678
1679    /* don't trust what the kernel says, validate! */
1680    if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
1681        __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1682        free(newmsg);
1683        return NULL;
1684    }
1685
1686    __ipsec_errcode = EIPSEC_NO_ERROR;
1687    return newmsg;
1688}
1689
1690/*
1691 * send message to a socket.
1692 * OUT:
1693 *	 others: success and return length sent.
1694 *	-1     : fail.
1695 */
1696int
1697pfkey_send(so, msg, len)
1698int so;
1699struct sadb_msg *msg;
1700int len;
1701{
1702    if ((len = send(so, (caddr_t)msg, len, 0)) < 0) {
1703        __ipsec_set_strerror(strerror(errno));
1704        return -1;
1705    }
1706
1707    __ipsec_errcode = EIPSEC_NO_ERROR;
1708    return len;
1709}
1710
1711/*
1712 * %%% Utilities
1713 * NOTE: These functions are derived from netkey/key.c in KAME.
1714 */
1715/*
1716 * set the pointer to each header in this message buffer.
1717 * IN:	msg: pointer to message buffer.
1718 *	mhp: pointer to the buffer initialized like below:
1719 *		caddr_t mhp[SADB_EXT_MAX + 1];
1720 * OUT:	-1: invalid.
1721 *	 0: valid.
1722 *
1723 * XXX should be rewritten to obtain length explicitly
1724 */
1725int
1726pfkey_align(msg, mhp)
1727struct sadb_msg *msg;
1728caddr_t *mhp;
1729{
1730    struct sadb_ext *ext;
1731    int i;
1732    caddr_t p;
1733    caddr_t ep; /* XXX should be passed from upper layer */
1734
1735    /* validity check */
1736    if (msg == NULL || mhp == NULL) {
1737        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1738        return -1;
1739    }
1740
1741    /* initialize */
1742    for (i = 0; i < SADB_EXT_MAX + 1; i++)
1743        mhp[i] = NULL;
1744
1745    mhp[0] = (caddr_t)msg;
1746
1747    /* initialize */
1748    p = (caddr_t) msg;
1749    ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
1750
1751    /* skip base header */
1752    p += sizeof(struct sadb_msg);
1753
1754    while (p < ep) {
1755        ext = (struct sadb_ext *)p;
1756        if (ep < p + sizeof(*ext) || (size_t)PFKEY_EXTLEN(ext) < sizeof(*ext) ||
1757            ep < p + PFKEY_EXTLEN(ext)) {
1758            /* invalid format */
1759            break;
1760        }
1761
1762        /* duplicate check */
1763        /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
1764        if (mhp[ext->sadb_ext_type] != NULL) {
1765            __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1766            return -1;
1767        }
1768
1769        /* set pointer */
1770        switch (ext->sadb_ext_type) {
1771        case SADB_EXT_SA:
1772        case SADB_EXT_LIFETIME_CURRENT:
1773        case SADB_EXT_LIFETIME_HARD:
1774        case SADB_EXT_LIFETIME_SOFT:
1775        case SADB_EXT_ADDRESS_SRC:
1776        case SADB_EXT_ADDRESS_DST:
1777        case SADB_EXT_ADDRESS_PROXY:
1778        case SADB_EXT_KEY_AUTH:
1779        /* XXX should to be check weak keys. */
1780        case SADB_EXT_KEY_ENCRYPT:
1781        /* XXX should to be check weak keys. */
1782        case SADB_EXT_IDENTITY_SRC:
1783        case SADB_EXT_IDENTITY_DST:
1784        case SADB_EXT_SENSITIVITY:
1785        case SADB_EXT_PROPOSAL:
1786        case SADB_EXT_SUPPORTED_AUTH:
1787        case SADB_EXT_SUPPORTED_ENCRYPT:
1788        case SADB_EXT_SPIRANGE:
1789        case SADB_X_EXT_POLICY:
1790        case SADB_X_EXT_SA2:
1791            mhp[ext->sadb_ext_type] = (caddr_t)ext;
1792            break;
1793        default:
1794            __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
1795            return -1;
1796        }
1797
1798        p += PFKEY_EXTLEN(ext);
1799    }
1800
1801    if (p != ep) {
1802        __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
1803        return -1;
1804    }
1805
1806    __ipsec_errcode = EIPSEC_NO_ERROR;
1807    return 0;
1808}
1809
1810/*
1811 * check basic usage for sadb_msg,
1812 * NOTE: This routine is derived from netkey/key.c in KAME.
1813 * IN:	msg: pointer to message buffer.
1814 *	mhp: pointer to the buffer initialized like below:
1815 *
1816 *		caddr_t mhp[SADB_EXT_MAX + 1];
1817 *
1818 * OUT:	-1: invalid.
1819 *	 0: valid.
1820 */
1821int
1822pfkey_check(mhp)
1823caddr_t *mhp;
1824{
1825    struct sadb_msg *msg;
1826
1827    /* validity check */
1828    if (mhp == NULL || mhp[0] == NULL) {
1829        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1830        return -1;
1831    }
1832
1833    msg = (struct sadb_msg *)mhp[0];
1834
1835    /* check version */
1836    if (msg->sadb_msg_version != PF_KEY_V2) {
1837        __ipsec_errcode = EIPSEC_INVAL_VERSION;
1838        return -1;
1839    }
1840
1841    /* check type */
1842    if (msg->sadb_msg_type > SADB_MAX) {
1843        __ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
1844        return -1;
1845    }
1846
1847    /* check SA type */
1848    switch (msg->sadb_msg_satype) {
1849    case SADB_SATYPE_UNSPEC:
1850        switch (msg->sadb_msg_type) {
1851        case SADB_GETSPI:
1852        case SADB_UPDATE:
1853        case SADB_ADD:
1854        case SADB_DELETE:
1855        case SADB_GET:
1856        case SADB_ACQUIRE:
1857        case SADB_EXPIRE:
1858            __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1859            return -1;
1860        }
1861        break;
1862    case SADB_SATYPE_ESP:
1863    case SADB_SATYPE_AH:
1864    case SADB_X_SATYPE_IPCOMP:
1865        switch (msg->sadb_msg_type) {
1866        case SADB_X_SPDADD:
1867        case SADB_X_SPDDELETE:
1868        case SADB_X_SPDGET:
1869        case SADB_X_SPDDUMP:
1870        case SADB_X_SPDFLUSH:
1871            __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1872            return -1;
1873        }
1874        break;
1875    case SADB_SATYPE_RSVP:
1876    case SADB_SATYPE_OSPFV2:
1877    case SADB_SATYPE_RIPV2:
1878    case SADB_SATYPE_MIP:
1879        __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
1880        return -1;
1881    case 1: /* XXX: What does it do ? */
1882        if (msg->sadb_msg_type == SADB_X_PROMISC)
1883            break;
1884    /*FALLTHROUGH*/
1885    default:
1886        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1887        return -1;
1888    }
1889
1890    /* check field of upper layer protocol and address family */
1891    if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
1892        && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
1893        struct sadb_address *src0, *dst0;
1894
1895        src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]);
1896        dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]);
1897
1898        if (src0->sadb_address_proto != dst0->sadb_address_proto) {
1899            __ipsec_errcode = EIPSEC_PROTO_MISMATCH;
1900            return -1;
1901        }
1902
1903        if (PFKEY_ADDR_SADDR(src0)->sa_family
1904            != PFKEY_ADDR_SADDR(dst0)->sa_family) {
1905            __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1906            return -1;
1907        }
1908
1909        switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
1910        case AF_INET:
1911        case AF_INET6:
1912            break;
1913        default:
1914            __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1915            return -1;
1916        }
1917
1918        /*
1919         * prefixlen == 0 is valid because there must be the case
1920         * all addresses are matched.
1921         */
1922    }
1923
1924    __ipsec_errcode = EIPSEC_NO_ERROR;
1925    return 0;
1926}
1927
1928/*
1929 * set data into sadb_msg.
1930 * `buf' must has been allocated sufficiently.
1931 */
1932static caddr_t
1933pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
1934caddr_t buf;
1935caddr_t lim;
1936u_int type, satype;
1937u_int tlen;
1938u_int32_t seq;
1939pid_t pid;
1940{
1941    struct sadb_msg *p;
1942    u_int len;
1943
1944    p = (struct sadb_msg *)buf;
1945    len = sizeof(struct sadb_msg);
1946
1947    if (buf + len > lim)
1948        return NULL;
1949
1950    memset(p, 0, len);
1951    p->sadb_msg_version = PF_KEY_V2;
1952    p->sadb_msg_type = type;
1953    p->sadb_msg_errno = 0;
1954    p->sadb_msg_satype = satype;
1955    p->sadb_msg_len = PFKEY_UNIT64(tlen);
1956    p->sadb_msg_reserved = 0;
1957    p->sadb_msg_seq = seq;
1958    p->sadb_msg_pid = (u_int32_t)pid;
1959
1960    return(buf + len);
1961}
1962
1963/*
1964 * copy secasvar data into sadb_address.
1965 * `buf' must has been allocated sufficiently.
1966 */
1967static caddr_t
1968pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
1969caddr_t buf;
1970caddr_t lim;
1971u_int32_t spi, flags;
1972u_int wsize, auth, enc;
1973{
1974    struct sadb_sa *p;
1975    u_int len;
1976
1977    p = (struct sadb_sa *)buf;
1978    len = sizeof(struct sadb_sa);
1979
1980    if (buf + len > lim)
1981        return NULL;
1982
1983    memset(p, 0, len);
1984    p->sadb_sa_len = PFKEY_UNIT64(len);
1985    p->sadb_sa_exttype = SADB_EXT_SA;
1986    p->sadb_sa_spi = spi;
1987    p->sadb_sa_replay = wsize;
1988    p->sadb_sa_state = SADB_SASTATE_LARVAL;
1989    p->sadb_sa_auth = auth;
1990    p->sadb_sa_encrypt = enc;
1991    p->sadb_sa_flags = flags;
1992
1993    return(buf + len);
1994}
1995
1996/*
1997 * set data into sadb_address.
1998 * `buf' must has been allocated sufficiently.
1999 * prefixlen is in bits.
2000 */
2001static caddr_t
2002pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
2003caddr_t buf;
2004caddr_t lim;
2005u_int exttype;
2006struct sockaddr *saddr;
2007u_int prefixlen;
2008u_int ul_proto;
2009{
2010    struct sadb_address *p;
2011    u_int len;
2012
2013    p = (struct sadb_address *)buf;
2014    len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len);
2015
2016    if (buf + len > lim)
2017        return NULL;
2018
2019    memset(p, 0, len);
2020    p->sadb_address_len = PFKEY_UNIT64(len);
2021    p->sadb_address_exttype = exttype & 0xffff;
2022    p->sadb_address_proto = ul_proto & 0xff;
2023    p->sadb_address_prefixlen = prefixlen;
2024    p->sadb_address_reserved = 0;
2025
2026    memcpy(p + 1, saddr, saddr->sa_len);
2027
2028    return(buf + len);
2029}
2030
2031/*
2032 * set sadb_key structure after clearing buffer with zero.
2033 * OUT: the pointer of buf + len.
2034 */
2035static caddr_t
2036pfkey_setsadbkey(buf, lim, type, key, keylen)
2037caddr_t buf;
2038caddr_t lim;
2039caddr_t key;
2040u_int type, keylen;
2041{
2042    struct sadb_key *p;
2043    u_int len;
2044
2045    p = (struct sadb_key *)buf;
2046    len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
2047
2048    if (buf + len > lim)
2049        return NULL;
2050
2051    memset(p, 0, len);
2052    p->sadb_key_len = PFKEY_UNIT64(len);
2053    p->sadb_key_exttype = type;
2054    p->sadb_key_bits = keylen << 3;
2055    p->sadb_key_reserved = 0;
2056
2057    memcpy(p + 1, key, keylen);
2058
2059    return buf + len;
2060}
2061
2062/*
2063 * set sadb_lifetime structure after clearing buffer with zero.
2064 * OUT: the pointer of buf + len.
2065 */
2066static caddr_t
2067pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
2068caddr_t buf;
2069caddr_t lim;
2070u_int type;
2071u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
2072{
2073    struct sadb_lifetime *p;
2074    u_int len;
2075
2076    p = (struct sadb_lifetime *)buf;
2077    len = sizeof(struct sadb_lifetime);
2078
2079    if (buf + len > lim)
2080        return NULL;
2081
2082    memset(p, 0, len);
2083    p->sadb_lifetime_len = PFKEY_UNIT64(len);
2084    p->sadb_lifetime_exttype = type;
2085
2086    switch (type) {
2087    case SADB_EXT_LIFETIME_SOFT:
2088        p->sadb_lifetime_allocations
2089            = (l_alloc * soft_lifetime_allocations_rate) /100;
2090        p->sadb_lifetime_bytes
2091            = (l_bytes * soft_lifetime_bytes_rate) /100;
2092        p->sadb_lifetime_addtime
2093            = (l_addtime * soft_lifetime_addtime_rate) /100;
2094        p->sadb_lifetime_usetime
2095            = (l_usetime * soft_lifetime_usetime_rate) /100;
2096        break;
2097    case SADB_EXT_LIFETIME_HARD:
2098        p->sadb_lifetime_allocations = l_alloc;
2099        p->sadb_lifetime_bytes = l_bytes;
2100        p->sadb_lifetime_addtime = l_addtime;
2101        p->sadb_lifetime_usetime = l_usetime;
2102        break;
2103    }
2104
2105    return buf + len;
2106}
2107
2108/*
2109 * copy secasvar data into sadb_address.
2110 * `buf' must has been allocated sufficiently.
2111 */
2112static caddr_t
2113pfkey_setsadbxsa2(buf, lim, mode0, reqid)
2114caddr_t buf;
2115caddr_t lim;
2116u_int32_t mode0;
2117u_int32_t reqid;
2118{
2119    struct sadb_x_sa2 *p;
2120    u_int8_t mode = mode0 & 0xff;
2121    u_int len;
2122
2123    p = (struct sadb_x_sa2 *)buf;
2124    len = sizeof(struct sadb_x_sa2);
2125
2126    if (buf + len > lim)
2127        return NULL;
2128
2129    memset(p, 0, len);
2130    p->sadb_x_sa2_len = PFKEY_UNIT64(len);
2131    p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
2132    p->sadb_x_sa2_mode = mode;
2133    p->sadb_x_sa2_reqid = reqid;
2134
2135    return(buf + len);
2136}
2137
2138#endif /* ndef MDNS_NO_IPSEC */
2139