source: rtems-libbsd/ipsec-tools/src/libipsec/pfkey.c @ ff36f5e

5-freebsd-12
Last change on this file since ff36f5e was ff36f5e, checked in by Christian Mauderer <christian.mauderer@…>, on May 30, 2018 at 12:27:35 PM

Import ipsec-tools 0.8.2.

Import unchanged ipsec-tools sources in the release version 0.8.2. The
homepage of ipsec-tools is http://ipsec-tools.sourceforge.net/. The
sources can be obtained from there.

  • Property mode set to 100644
File size: 59.1 KB
Line 
1/*      $NetBSD: pfkey.c,v 1.21.2.1 2011/11/14 13:25:06 tteras Exp $    */
2
3/*      $KAME: pfkey.c,v 1.47 2003/10/02 19:52:12 itojun Exp $  */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include <sys/types.h>
39#include <sys/param.h>
40#include <sys/socket.h>
41#include <net/pfkeyv2.h>
42#include <netinet/in.h>
43#include PATH_IPSEC_H
44
45#include <stdlib.h>
46#include <unistd.h>
47#include <string.h>
48#include <errno.h>
49#include <stdio.h>
50
51#include "ipsec_strerror.h"
52#include "libpfkey.h"
53
54#define CALLOC(size, cast) (cast)calloc(1, (size))
55
56static int findsupportedmap __P((int));
57static int setsupportedmap __P((struct sadb_supported *));
58static struct sadb_alg *findsupportedalg __P((u_int, u_int));
59static int pfkey_send_x1 __P((struct pfkey_send_sa_args *));
60static int pfkey_send_x2 __P((int, u_int, u_int, u_int,
61        struct sockaddr *, struct sockaddr *, u_int32_t));
62static int pfkey_send_x3 __P((int, u_int, u_int));
63static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int,
64        struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
65        char *, int, u_int32_t));
66static int pfkey_send_x5 __P((int, u_int, u_int32_t));
67
68static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int,
69        u_int, u_int32_t, pid_t));
70static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int,
71        u_int, u_int, u_int32_t));
72static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int,
73        struct sockaddr *, u_int, u_int));
74
75#ifdef SADB_X_EXT_KMADDRESS
76static caddr_t pfkey_setsadbkmaddr __P((caddr_t, caddr_t, struct sockaddr *,
77        struct sockaddr *));
78#endif
79
80static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int));
81static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t,
82        u_int32_t, u_int32_t, u_int32_t));
83static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t));
84
85#ifdef SADB_X_EXT_NAT_T_TYPE
86static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int, u_int8_t));
87static caddr_t pfkey_set_natt_port __P((caddr_t, caddr_t, u_int, u_int16_t));
88#endif
89#ifdef SADB_X_EXT_NAT_T_FRAG
90static caddr_t pfkey_set_natt_frag __P((caddr_t, caddr_t, u_int, u_int16_t));
91#endif
92
93#ifdef SADB_X_EXT_SEC_CTX
94static caddr_t pfkey_setsecctx __P((caddr_t, caddr_t, u_int, u_int8_t, u_int8_t,
95                                    caddr_t, u_int16_t));
96#endif
97
98int libipsec_opt = 0
99#ifdef SADB_X_EXT_NAT_T_TYPE
100        | LIBIPSEC_OPT_NATT
101#endif
102#ifdef SADB_X_EXT_NAT_T_FRAG
103        | LIBIPSEC_OPT_FRAG
104#endif
105#ifdef SADB_X_EXT_NAT_T_SEC_CTX
106        | LIBIPSEC_OPT_SEC_CTX
107#endif
108        ;
109
110/*
111 * make and search supported algorithm structure.
112 */
113static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, 
114#ifdef SADB_X_SATYPE_TCPSIGNATURE
115    NULL,
116#endif
117};
118
119static int supported_map[] = {
120        SADB_SATYPE_AH,
121        SADB_SATYPE_ESP,
122        SADB_X_SATYPE_IPCOMP,
123#ifdef SADB_X_SATYPE_TCPSIGNATURE
124        SADB_X_SATYPE_TCPSIGNATURE,
125#endif
126};
127
128static int
129findsupportedmap(satype)
130        int satype;
131{
132        int i;
133
134        for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++)
135                if (supported_map[i] == satype)
136                        return i;
137        return -1;
138}
139
140static struct sadb_alg *
141findsupportedalg(satype, alg_id)
142        u_int satype, alg_id;
143{
144        int algno;
145        int tlen;
146        caddr_t p;
147
148        /* validity check */
149        algno = findsupportedmap((int)satype);
150        if (algno == -1) {
151                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
152                return NULL;
153        }
154        if (ipsec_supported[algno] == NULL) {
155                __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
156                return NULL;
157        }
158
159        tlen = ipsec_supported[algno]->sadb_supported_len
160                - sizeof(struct sadb_supported);
161        p = (void *)(ipsec_supported[algno] + 1);
162        while (tlen > 0) {
163                if (tlen < sizeof(struct sadb_alg)) {
164                        /* invalid format */
165                        break;
166                }
167                if (((struct sadb_alg *)(void *)p)->sadb_alg_id == alg_id)
168                        return (void *)p;
169
170                tlen -= sizeof(struct sadb_alg);
171                p += sizeof(struct sadb_alg);
172        }
173
174        __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
175        return NULL;
176}
177
178static int
179setsupportedmap(sup)
180        struct sadb_supported *sup;
181{
182        struct sadb_supported **ipsup;
183
184        switch (sup->sadb_supported_exttype) {
185        case SADB_EXT_SUPPORTED_AUTH:
186                ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)];
187                break;
188        case SADB_EXT_SUPPORTED_ENCRYPT:
189                ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)];
190                break;
191        default:
192                __ipsec_errcode = EIPSEC_INVAL_SATYPE;
193                return -1;
194        }
195
196        if (*ipsup)
197                free(*ipsup);
198
199        *ipsup = malloc((size_t)sup->sadb_supported_len);
200        if (!*ipsup) {
201                __ipsec_set_strerror(strerror(errno));
202                return -1;
203        }
204        memcpy(*ipsup, sup, (size_t)sup->sadb_supported_len);
205
206        return 0;
207}
208
209/*
210 * check key length against algorithm specified.
211 * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the
212 * augument, and only calls to ipsec_check_keylen2();
213 * keylen is the unit of bit.
214 * OUT:
215 *      -1: invalid.
216 *       0: valid.
217 */
218int
219ipsec_check_keylen(supported, alg_id, keylen)
220        u_int supported;
221        u_int alg_id;
222        u_int keylen;
223{
224        u_int satype;
225
226        /* validity check */
227        switch (supported) {
228        case SADB_EXT_SUPPORTED_AUTH:
229                satype = SADB_SATYPE_AH;
230                break;
231        case SADB_EXT_SUPPORTED_ENCRYPT:
232                satype = SADB_SATYPE_ESP;
233                break;
234        default:
235                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
236                return -1;
237        }
238
239        return ipsec_check_keylen2(satype, alg_id, keylen);
240}
241
242/*
243 * check key length against algorithm specified.
244 * satype is one of satype defined at pfkeyv2.h.
245 * keylen is the unit of bit.
246 * OUT:
247 *      -1: invalid.
248 *       0: valid.
249 */
250int
251ipsec_check_keylen2(satype, alg_id, keylen)
252        u_int satype;
253        u_int alg_id;
254        u_int keylen;
255{
256        struct sadb_alg *alg;
257
258        alg = findsupportedalg(satype, alg_id);
259        if (!alg)
260                return -1;
261
262        if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) {
263                fprintf(stderr, "%d %d %d\n", keylen, alg->sadb_alg_minbits,
264                        alg->sadb_alg_maxbits);
265                __ipsec_errcode = EIPSEC_INVAL_KEYLEN;
266                return -1;
267        }
268
269        __ipsec_errcode = EIPSEC_NO_ERROR;
270        return 0;
271}
272
273/*
274 * get max/min key length against algorithm specified.
275 * satype is one of satype defined at pfkeyv2.h.
276 * keylen is the unit of bit.
277 * OUT:
278 *      -1: invalid.
279 *       0: valid.
280 */
281int
282ipsec_get_keylen(supported, alg_id, alg0)
283        u_int supported, alg_id;
284        struct sadb_alg *alg0;
285{
286        struct sadb_alg *alg;
287        u_int satype;
288
289        /* validity check */
290        if (!alg0) {
291                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
292                return -1;
293        }
294
295        switch (supported) {
296        case SADB_EXT_SUPPORTED_AUTH:
297                satype = SADB_SATYPE_AH;
298                break;
299        case SADB_EXT_SUPPORTED_ENCRYPT:
300                satype = SADB_SATYPE_ESP;
301                break;
302        default:
303                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
304                return -1;
305        }
306
307        alg = findsupportedalg(satype, alg_id);
308        if (!alg)
309                return -1;
310
311        memcpy(alg0, alg, sizeof(*alg0));
312
313        __ipsec_errcode = EIPSEC_NO_ERROR;
314        return 0;
315}
316
317/*
318 * set the rate for SOFT lifetime against HARD one.
319 * If rate is more than 100 or equal to zero, then set to 100.
320 */
321static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
322static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
323static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
324static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
325
326u_int
327pfkey_set_softrate(type, rate)
328        u_int type, rate;
329{
330        __ipsec_errcode = EIPSEC_NO_ERROR;
331
332        if (rate > 100 || rate == 0)
333                rate = 100;
334
335        switch (type) {
336        case SADB_X_LIFETIME_ALLOCATIONS:
337                soft_lifetime_allocations_rate = rate;
338                return 0;
339        case SADB_X_LIFETIME_BYTES:
340                soft_lifetime_bytes_rate = rate;
341                return 0;
342        case SADB_X_LIFETIME_ADDTIME:
343                soft_lifetime_addtime_rate = rate;
344                return 0;
345        case SADB_X_LIFETIME_USETIME:
346                soft_lifetime_usetime_rate = rate;
347                return 0;
348        }
349
350        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
351        return 1;
352}
353
354/*
355 * get current rate for SOFT lifetime against HARD one.
356 * ATTENTION: ~0 is returned if invalid type was passed.
357 */
358u_int
359pfkey_get_softrate(type)
360        u_int type;
361{
362        switch (type) {
363        case SADB_X_LIFETIME_ALLOCATIONS:
364                return soft_lifetime_allocations_rate;
365        case SADB_X_LIFETIME_BYTES:
366                return soft_lifetime_bytes_rate;
367        case SADB_X_LIFETIME_ADDTIME:
368                return soft_lifetime_addtime_rate;
369        case SADB_X_LIFETIME_USETIME:
370                return soft_lifetime_usetime_rate;
371        }
372
373        return (u_int)~0;
374}
375
376/*
377 * sending SADB_GETSPI message to the kernel.
378 * OUT:
379 *      positive: success and return length sent.
380 *      -1      : error occured, and set errno.
381 */
382int
383pfkey_send_getspi_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
384    struct sockaddr *dst, u_int8_t natt_type, u_int16_t sport,
385    u_int16_t dport, u_int32_t min, u_int32_t max, u_int32_t reqid,
386    u_int32_t seq)
387{
388        struct sadb_msg *newmsg;
389        caddr_t ep;
390        int len;
391        int need_spirange = 0;
392        caddr_t p;
393        int plen;
394
395        /* validity check */
396        if (src == NULL || dst == NULL) {
397                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
398                return -1;
399        }
400        if (src->sa_family != dst->sa_family) {
401                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
402                return -1;
403        }
404        if (min > max || (min > 0 && min <= 255)) {
405                __ipsec_errcode = EIPSEC_INVAL_SPI;
406                return -1;
407        }
408        switch (src->sa_family) {
409        case AF_INET:
410                plen = sizeof(struct in_addr) << 3;
411                break;
412        case AF_INET6:
413                plen = sizeof(struct in6_addr) << 3;
414                break;
415        default:
416                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
417                return -1;
418        }
419
420        /* create new sadb_msg to send. */
421        len = sizeof(struct sadb_msg)
422                + sizeof(struct sadb_x_sa2)
423                + sizeof(struct sadb_address)
424                + PFKEY_ALIGN8(sysdep_sa_len(src))
425                + sizeof(struct sadb_address)
426                + PFKEY_ALIGN8(sysdep_sa_len(dst));
427
428        if (min > 255 && max < (u_int)~0) {
429                need_spirange++;
430                len += sizeof(struct sadb_spirange);
431        }
432
433#ifdef SADB_X_EXT_NAT_T_TYPE
434        if(natt_type||sport||dport){
435                len += sizeof(struct sadb_x_nat_t_type);
436                len += sizeof(struct sadb_x_nat_t_port);
437                len += sizeof(struct sadb_x_nat_t_port);
438        }
439#endif
440
441        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
442                __ipsec_set_strerror(strerror(errno));
443                return -1;
444        }
445        ep = ((caddr_t)(void *)newmsg) + len;
446
447        p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_GETSPI,
448            (u_int)len, satype, seq, getpid());
449        if (!p) {
450                free(newmsg);
451                return -1;
452        }
453
454        p = pfkey_setsadbxsa2(p, ep, mode, reqid);
455        if (!p) {
456                free(newmsg);
457                return -1;
458        }
459
460        /* set sadb_address for source */
461        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
462            IPSEC_ULPROTO_ANY);
463        if (!p) {
464                free(newmsg);
465                return -1;
466        }
467
468        /* set sadb_address for destination */
469        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
470            IPSEC_ULPROTO_ANY);
471        if (!p) {
472                free(newmsg);
473                return -1;
474        }
475
476#ifdef SADB_X_EXT_NAT_T_TYPE
477        /* Add nat-t messages */
478        if (natt_type) {
479                p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, 
480                                        natt_type);
481                if (!p) {
482                        free(newmsg);
483                        return -1;
484                }
485
486                p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
487                                        sport);
488                if (!p) {
489                        free(newmsg);
490                        return -1;
491                }
492
493                p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
494                                        dport);
495                if (!p) {
496                        free(newmsg);
497                        return -1;
498                }
499        }
500#endif
501
502        /* proccessing spi range */
503        if (need_spirange) {
504                struct sadb_spirange spirange;
505
506                if (p + sizeof(spirange) > ep) {
507                        free(newmsg);
508                        return -1;
509                }
510
511                memset(&spirange, 0, sizeof(spirange));
512                spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange));
513                spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
514                spirange.sadb_spirange_min = min;
515                spirange.sadb_spirange_max = max;
516
517                memcpy(p, &spirange, sizeof(spirange));
518
519                p += sizeof(spirange);
520        }
521        if (p != ep) {
522                free(newmsg);
523                return -1;
524        }
525
526        /* send message */
527        len = pfkey_send(so, newmsg, len);
528        free(newmsg);
529
530        if (len < 0)
531                return -1;
532
533        __ipsec_errcode = EIPSEC_NO_ERROR;
534        return len;
535}
536
537int
538pfkey_send_getspi(int so, u_int satype, u_int mode, struct sockaddr *src,
539    struct sockaddr *dst, u_int32_t min, u_int32_t max, u_int32_t reqid,
540    u_int32_t seq)
541{
542        return pfkey_send_getspi_nat(so, satype, mode, src, dst, 0, 0, 0,
543                min, max, reqid, seq);
544}
545
546/*
547 * sending SADB_UPDATE message to the kernel.
548 * The length of key material is a_keylen + e_keylen.
549 * OUT:
550 *      positive: success and return length sent.
551 *      -1      : error occured, and set errno.
552 */
553int
554pfkey_send_update2(struct pfkey_send_sa_args *sa_parms)
555{
556        int len;
557
558        sa_parms->type = SADB_UPDATE;
559        if ((len = pfkey_send_x1(sa_parms)) < 0)
560                return -1;
561
562        return len;
563}
564
565/*
566 * sending SADB_ADD message to the kernel.
567 * The length of key material is a_keylen + e_keylen.
568 * OUT:
569 *      positive: success and return length sent.
570 *      -1      : error occured, and set errno.
571 */
572int
573pfkey_send_add2(struct pfkey_send_sa_args *sa_parms)
574{
575        int len;
576       
577        sa_parms->type = SADB_ADD;
578        if ((len = pfkey_send_x1(sa_parms)) < 0)
579                return -1;
580
581        return len;
582}
583
584/*
585 * sending SADB_DELETE message to the kernel.
586 * OUT:
587 *      positive: success and return length sent.
588 *      -1      : error occured, and set errno.
589 */
590int
591pfkey_send_delete(int so, u_int satype, u_int mode, struct sockaddr *src,
592    struct sockaddr *dst, u_int32_t spi)
593{
594        int len;
595        if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
596                return -1;
597
598        return len;
599}
600
601/*
602 * sending SADB_DELETE without spi to the kernel.  This is
603 * the "delete all" request (an extension also present in
604 * Solaris).
605 *
606 * OUT:
607 *      positive: success and return length sent
608 *      -1      : error occured, and set errno
609 */
610/*ARGSUSED*/
611int
612pfkey_send_delete_all(int so, u_int satype, u_int mode, struct sockaddr *src,
613    struct sockaddr *dst)
614{
615        struct sadb_msg *newmsg;
616        int len;
617        caddr_t p;
618        int plen;
619        caddr_t ep;
620
621        /* validity check */
622        if (src == NULL || dst == NULL) {
623                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
624                return -1;
625        }
626        if (src->sa_family != dst->sa_family) {
627                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
628                return -1;
629        }
630        switch (src->sa_family) {
631        case AF_INET:
632                plen = sizeof(struct in_addr) << 3;
633                break;
634        case AF_INET6:
635                plen = sizeof(struct in6_addr) << 3;
636                break;
637        default:
638                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
639                return -1;
640        }
641
642        /* create new sadb_msg to reply. */
643        len = sizeof(struct sadb_msg)
644                + sizeof(struct sadb_address)
645                + PFKEY_ALIGN8(sysdep_sa_len(src))
646                + sizeof(struct sadb_address)
647                + PFKEY_ALIGN8(sysdep_sa_len(dst));
648
649        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
650                __ipsec_set_strerror(strerror(errno));
651                return -1;
652        }
653        ep = ((caddr_t)(void *)newmsg) + len;
654
655        p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_DELETE, (u_int)len, 
656            satype, 0, getpid());
657        if (!p) {
658                free(newmsg);
659                return -1;
660        }
661        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
662            IPSEC_ULPROTO_ANY);
663        if (!p) {
664                free(newmsg);
665                return -1;
666        }
667        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
668            IPSEC_ULPROTO_ANY);
669        if (!p || p != ep) {
670                free(newmsg);
671                return -1;
672        }
673
674        /* send message */
675        len = pfkey_send(so, newmsg, len);
676        free(newmsg);
677
678        if (len < 0)
679                return -1;
680
681        __ipsec_errcode = EIPSEC_NO_ERROR;
682        return len;
683}
684
685/*
686 * sending SADB_GET message to the kernel.
687 * OUT:
688 *      positive: success and return length sent.
689 *      -1      : error occured, and set errno.
690 */
691int
692pfkey_send_get(int so, u_int satype, u_int mode, struct sockaddr *src,
693    struct sockaddr *dst, u_int32_t spi)
694{
695        int len;
696        if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
697                return -1;
698
699        return len;
700}
701
702/*
703 * sending SADB_REGISTER message to the kernel.
704 * OUT:
705 *      positive: success and return length sent.
706 *      -1      : error occured, and set errno.
707 */
708int
709pfkey_send_register(int so, u_int satype)
710{
711        int len, algno;
712
713        if (satype == PF_UNSPEC) {
714                for (algno = 0;
715                     algno < sizeof(supported_map)/sizeof(supported_map[0]);
716                     algno++) {
717                        if (ipsec_supported[algno]) {
718                                free(ipsec_supported[algno]);
719                                ipsec_supported[algno] = NULL;
720                        }
721                }
722        } else {
723                algno = findsupportedmap((int)satype);
724                if (algno == -1) {
725                        __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
726                        return -1;
727                }
728
729                if (ipsec_supported[algno]) {
730                        free(ipsec_supported[algno]);
731                        ipsec_supported[algno] = NULL;
732                }
733        }
734
735        if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
736                return -1;
737
738        return len;
739}
740
741/*
742 * receiving SADB_REGISTER message from the kernel, and copy buffer for
743 * sadb_supported returned into ipsec_supported.
744 * OUT:
745 *       0: success and return length sent.
746 *      -1: error occured, and set errno.
747 */
748int
749pfkey_recv_register(int so)
750{
751        pid_t pid = getpid();
752        struct sadb_msg *newmsg;
753        int error = -1;
754
755        /* receive message */
756        for (;;) {
757                if ((newmsg = pfkey_recv(so)) == NULL)
758                        return -1;
759                if (newmsg->sadb_msg_type == SADB_REGISTER &&
760                    newmsg->sadb_msg_pid == pid)
761                        break;
762                free(newmsg);
763        }
764
765        /* check and fix */
766        newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
767
768        error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);
769        free(newmsg);
770
771        if (error == 0)
772                __ipsec_errcode = EIPSEC_NO_ERROR;
773
774        return error;
775}
776
777/*
778 * receiving SADB_REGISTER message from the kernel, and copy buffer for
779 * sadb_supported returned into ipsec_supported.
780 * NOTE: sadb_msg_len must be host order.
781 * IN:
782 *      tlen: msg length, it's to makeing sure.
783 * OUT:
784 *       0: success and return length sent.
785 *      -1: error occured, and set errno.
786 */
787int
788pfkey_set_supported(struct sadb_msg *msg, int tlen)
789{
790        struct sadb_supported *sup;
791        caddr_t p;
792        caddr_t ep;
793
794        /* validity */
795        if (msg->sadb_msg_len != tlen) {
796                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
797                return -1;
798        }
799
800        p = (void *)msg;
801        ep = p + tlen;
802
803        p += sizeof(struct sadb_msg);
804
805        while (p < ep) {
806                sup = (void *)p;
807                if (ep < p + sizeof(*sup) ||
808                    PFKEY_EXTLEN(sup) < sizeof(*sup) ||
809                    ep < p + sup->sadb_supported_len) {
810                        /* invalid format */
811                        break;
812                }
813
814                switch (sup->sadb_supported_exttype) {
815                case SADB_EXT_SUPPORTED_AUTH:
816                case SADB_EXT_SUPPORTED_ENCRYPT:
817                        break;
818                default:
819                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
820                        return -1;
821                }
822
823                /* fixed length */
824                sup->sadb_supported_len = PFKEY_EXTLEN(sup);
825
826                /* set supported map */
827                if (setsupportedmap(sup) != 0)
828                        return -1;
829
830                p += sup->sadb_supported_len;
831        }
832
833        if (p != ep) {
834                __ipsec_errcode = EIPSEC_INVAL_SATYPE;
835                return -1;
836        }
837
838        __ipsec_errcode = EIPSEC_NO_ERROR;
839
840        return 0;
841}
842
843/*
844 * sending SADB_FLUSH message to the kernel.
845 * OUT:
846 *      positive: success and return length sent.
847 *      -1      : error occured, and set errno.
848 */
849int
850pfkey_send_flush(int so, u_int satype)
851{
852        int len;
853
854        if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
855                return -1;
856
857        return len;
858}
859
860/*
861 * sending SADB_DUMP message to the kernel.
862 * OUT:
863 *      positive: success and return length sent.
864 *      -1      : error occured, and set errno.
865 */
866int
867pfkey_send_dump(int so, u_int satype)
868{
869        int len;
870
871        if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
872                return -1;
873
874        return len;
875}
876
877/*
878 * sending SADB_X_PROMISC message to the kernel.
879 * NOTE that this function handles promisc mode toggle only.
880 * IN:
881 *      flag:   set promisc off if zero, set promisc on if non-zero.
882 * OUT:
883 *      positive: success and return length sent.
884 *      -1      : error occured, and set errno.
885 *      0     : error occured, and set errno.
886 *      others: a pointer to new allocated buffer in which supported
887 *              algorithms is.
888 */
889int
890pfkey_send_promisc_toggle(int so, int flag)
891{
892        int len;
893
894        if ((len = pfkey_send_x3(so, SADB_X_PROMISC, 
895            (u_int)(flag ? 1 : 0))) < 0)
896                return -1;
897
898        return len;
899}
900
901/*
902 * sending SADB_X_SPDADD message to the kernel.
903 * OUT:
904 *      positive: success and return length sent.
905 *      -1      : error occured, and set errno.
906 */
907int
908pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs,
909    struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
910    int policylen, u_int32_t seq)
911{
912        int len;
913
914        if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
915                                src, prefs, dst, prefd, proto,
916                                (u_int64_t)0, (u_int64_t)0,
917                                policy, policylen, seq)) < 0)
918                return -1;
919
920        return len;
921}
922
923/*
924 * sending SADB_X_SPDADD message to the kernel.
925 * OUT:
926 *      positive: success and return length sent.
927 *      -1      : error occured, and set errno.
928 */
929int
930pfkey_send_spdadd2(int so, struct sockaddr *src, u_int prefs,
931    struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
932    u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq)
933{
934        int len;
935
936        if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
937                                src, prefs, dst, prefd, proto,
938                                ltime, vtime,
939                                policy, policylen, seq)) < 0)
940                return -1;
941
942        return len;
943}
944
945/*
946 * sending SADB_X_SPDUPDATE message to the kernel.
947 * OUT:
948 *      positive: success and return length sent.
949 *      -1      : error occured, and set errno.
950 */
951int
952pfkey_send_spdupdate(int so, struct sockaddr *src, u_int prefs,
953    struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
954    int policylen, u_int32_t seq)
955{
956        int len;
957
958        if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
959                                src, prefs, dst, prefd, proto,
960                                (u_int64_t)0, (u_int64_t)0,
961                                policy, policylen, seq)) < 0)
962                return -1;
963
964        return len;
965}
966
967/*
968 * sending SADB_X_SPDUPDATE message to the kernel.
969 * OUT:
970 *      positive: success and return length sent.
971 *      -1      : error occured, and set errno.
972 */
973int
974pfkey_send_spdupdate2(int so, struct sockaddr *src, u_int prefs,
975    struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
976    u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq)
977{
978        int len;
979
980        if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
981                                src, prefs, dst, prefd, proto,
982                                ltime, vtime,
983                                policy, policylen, seq)) < 0)
984                return -1;
985
986        return len;
987}
988
989/*
990 * sending SADB_X_SPDDELETE message to the kernel.
991 * OUT:
992 *      positive: success and return length sent.
993 *      -1      : error occured, and set errno.
994 */
995int
996pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs,
997    struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
998    int policylen, u_int32_t seq)
999{
1000        int len;
1001
1002        if (policylen != sizeof(struct sadb_x_policy)) {
1003                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1004                return -1;
1005        }
1006
1007        if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
1008                                src, prefs, dst, prefd, proto,
1009                                (u_int64_t)0, (u_int64_t)0,
1010                                policy, policylen, seq)) < 0)
1011                return -1;
1012
1013        return len;
1014}
1015
1016/*
1017 * sending SADB_X_SPDDELETE message to the kernel.
1018 * OUT:
1019 *      positive: success and return length sent.
1020 *      -1      : error occured, and set errno.
1021 */
1022int
1023pfkey_send_spddelete2(int so, u_int32_t spid)
1024{
1025        int len;
1026
1027        if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
1028                return -1;
1029
1030        return len;
1031}
1032
1033/*
1034 * sending SADB_X_SPDGET message to the kernel.
1035 * OUT:
1036 *      positive: success and return length sent.
1037 *      -1      : error occured, and set errno.
1038 */
1039int
1040pfkey_send_spdget(int so, u_int32_t spid)
1041{
1042        int len;
1043
1044        if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
1045                return -1;
1046
1047        return len;
1048}
1049
1050/*
1051 * sending SADB_X_SPDSETIDX message to the kernel.
1052 * OUT:
1053 *      positive: success and return length sent.
1054 *      -1      : error occured, and set errno.
1055 */
1056int
1057pfkey_send_spdsetidx(int so, struct sockaddr *src, u_int prefs,
1058    struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy,
1059    int policylen, u_int32_t seq)
1060{
1061        int len;
1062
1063        if (policylen != sizeof(struct sadb_x_policy)) {
1064                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1065                return -1;
1066        }
1067
1068        if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
1069                                src, prefs, dst, prefd, proto,
1070                                (u_int64_t)0, (u_int64_t)0,
1071                                policy, policylen, seq)) < 0)
1072                return -1;
1073
1074        return len;
1075}
1076
1077/*
1078 * sending SADB_SPDFLUSH message to the kernel.
1079 * OUT:
1080 *      positive: success and return length sent.
1081 *      -1      : error occured, and set errno.
1082 */
1083int
1084pfkey_send_spdflush(int so)
1085{
1086        int len;
1087
1088        if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
1089                return -1;
1090
1091        return len;
1092}
1093
1094/*
1095 * sending SADB_SPDDUMP message to the kernel.
1096 * OUT:
1097 *      positive: success and return length sent.
1098 *      -1      : error occured, and set errno.
1099 */
1100int
1101pfkey_send_spddump(int so)
1102{
1103        int len;
1104
1105        if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
1106                return -1;
1107
1108        return len;
1109}
1110
1111
1112#ifdef SADB_X_MIGRATE
1113/*
1114 * sending SADB_X_MIGRATE message to the kernel.
1115 * OUT:
1116 *      positive: success and return length sent.
1117 *      -1      : error occured, and set errno.
1118 */
1119int
1120pfkey_send_migrate(int so, struct sockaddr *local, struct sockaddr *remote,
1121    struct sockaddr *src, u_int prefs, struct sockaddr *dst, u_int prefd,
1122    u_int proto, caddr_t policy, int policylen, u_int32_t seq)
1123{
1124        struct sadb_msg *newmsg;
1125        int len;
1126        caddr_t p;
1127        int plen;
1128        caddr_t ep;
1129
1130        /* validity check */
1131        if (src == NULL || dst == NULL) {
1132                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1133                return -1;
1134        }
1135        if (src->sa_family != dst->sa_family) {
1136                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1137                return -1;
1138        }
1139
1140        if (local == NULL || remote == NULL) {
1141                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1142                return -1;
1143        }
1144#ifdef SADB_X_EXT_KMADDRESS
1145        if (local->sa_family != remote->sa_family) {
1146                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1147                return -1;
1148        }
1149#endif
1150
1151        switch (src->sa_family) {
1152        case AF_INET:
1153                plen = sizeof(struct in_addr) << 3;
1154                break;
1155        case AF_INET6:
1156                plen = sizeof(struct in6_addr) << 3;
1157                break;
1158        default:
1159                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1160                return -1;
1161        }
1162        if (prefs > plen || prefd > plen) {
1163                __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1164                return -1;
1165        }
1166
1167        /* create new sadb_msg to reply. */
1168        len = sizeof(struct sadb_msg)
1169#ifdef SADB_X_EXT_KMADDRESS
1170                + sizeof(struct sadb_x_kmaddress)
1171                + PFKEY_ALIGN8(2*sysdep_sa_len(local))
1172#endif
1173                + sizeof(struct sadb_address)
1174                + PFKEY_ALIGN8(sysdep_sa_len(src))
1175                + sizeof(struct sadb_address)
1176                + PFKEY_ALIGN8(sysdep_sa_len(dst))
1177                + policylen;
1178
1179        if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
1180                __ipsec_set_strerror(strerror(errno));
1181                return -1;
1182        }
1183        ep = ((caddr_t)newmsg) + len;
1184
1185        p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_X_MIGRATE, (u_int)len,
1186            SADB_SATYPE_UNSPEC, seq, getpid());
1187        if (!p) {
1188                free(newmsg);
1189                return -1;
1190        }
1191#ifdef SADB_X_EXT_KMADDRESS
1192        p = pfkey_setsadbkmaddr(p, ep, local, remote);
1193        if (!p) {
1194                free(newmsg);
1195                return -1;
1196        }
1197#endif
1198        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
1199        if (!p) {
1200                free(newmsg);
1201                return -1;
1202        }
1203        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
1204        if (!p || p + policylen != ep) {
1205                free(newmsg);
1206                return -1;
1207        }
1208        memcpy(p, policy, policylen);
1209
1210        /* send message */
1211        len = pfkey_send(so, newmsg, len);
1212        free(newmsg);
1213
1214        if (len < 0)
1215                return -1;
1216
1217        __ipsec_errcode = EIPSEC_NO_ERROR;
1218        return len;
1219}
1220#endif
1221
1222
1223/* sending SADB_ADD or SADB_UPDATE message to the kernel */
1224static int
1225pfkey_send_x1(struct pfkey_send_sa_args *sa_parms)
1226{
1227        struct sadb_msg *newmsg;
1228        int len;
1229        caddr_t p;
1230        int plen;
1231        caddr_t ep;
1232
1233        /* validity check */
1234        if (sa_parms->src == NULL || sa_parms->dst == NULL) {
1235                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1236                return -1;
1237        }
1238        if (sa_parms->src->sa_family != sa_parms->dst->sa_family) {
1239                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1240                return -1;
1241        }
1242        switch (sa_parms->src->sa_family) {
1243        case AF_INET:
1244                plen = sizeof(struct in_addr) << 3;
1245                break;
1246        case AF_INET6:
1247                plen = sizeof(struct in6_addr) << 3;
1248                break;
1249        default:
1250                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1251                return -1;
1252        }
1253
1254        switch (sa_parms->satype) {
1255        case SADB_SATYPE_ESP:
1256                if (sa_parms->e_type == SADB_EALG_NONE) {
1257                        __ipsec_errcode = EIPSEC_NO_ALGS;
1258                        return -1;
1259                }
1260                break;
1261        case SADB_SATYPE_AH:
1262                if (sa_parms->e_type != SADB_EALG_NONE) {
1263                        __ipsec_errcode = EIPSEC_INVAL_ALGS;
1264                        return -1;
1265                }
1266                if (sa_parms->a_type == SADB_AALG_NONE) {
1267                        __ipsec_errcode = EIPSEC_NO_ALGS;
1268                        return -1;
1269                }
1270                break;
1271        case SADB_X_SATYPE_IPCOMP:
1272                if (sa_parms->e_type == SADB_X_CALG_NONE) {
1273                        __ipsec_errcode = EIPSEC_INVAL_ALGS;
1274                        return -1;
1275                }
1276                if (sa_parms->a_type != SADB_AALG_NONE) {
1277                        __ipsec_errcode = EIPSEC_NO_ALGS;
1278                        return -1;
1279                }
1280                break;
1281#ifdef SADB_X_AALG_TCP_MD5
1282        case SADB_X_SATYPE_TCPSIGNATURE:
1283                if (sa_parms->e_type != SADB_EALG_NONE) {
1284                        __ipsec_errcode = EIPSEC_INVAL_ALGS;
1285                        return -1;
1286                }
1287                if (sa_parms->a_type != SADB_X_AALG_TCP_MD5) {
1288                        __ipsec_errcode = EIPSEC_INVAL_ALGS;
1289                        return -1;
1290                }
1291                break;
1292#endif
1293        default:
1294                __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1295                return -1;
1296        }
1297
1298        /* create new sadb_msg to reply. */
1299        len = sizeof(struct sadb_msg)
1300                + sizeof(struct sadb_sa)
1301                + sizeof(struct sadb_x_sa2)
1302                + sizeof(struct sadb_address)
1303                + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->src))
1304                + sizeof(struct sadb_address)
1305                + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->dst))
1306                + sizeof(struct sadb_lifetime)
1307                + sizeof(struct sadb_lifetime);
1308
1309        if (sa_parms->e_type != SADB_EALG_NONE && 
1310            sa_parms->satype != SADB_X_SATYPE_IPCOMP)
1311                len += (sizeof(struct sadb_key) + 
1312                        PFKEY_ALIGN8(sa_parms->e_keylen));
1313        if (sa_parms->a_type != SADB_AALG_NONE)
1314                len += (sizeof(struct sadb_key) + 
1315                        PFKEY_ALIGN8(sa_parms->a_keylen));
1316
1317#ifdef SADB_X_EXT_SEC_CTX
1318        if (sa_parms->ctxstr != NULL)
1319                len += (sizeof(struct sadb_x_sec_ctx)
1320                    + PFKEY_ALIGN8(sa_parms->ctxstrlen));
1321#endif
1322
1323#ifdef SADB_X_EXT_NAT_T_TYPE
1324        /* add nat-t packets */
1325        if (sa_parms->l_natt_type) {
1326                switch(sa_parms->satype) {
1327                case SADB_SATYPE_ESP:
1328                case SADB_X_SATYPE_IPCOMP:
1329                        break;
1330                default:
1331                        __ipsec_errcode = EIPSEC_NO_ALGS;
1332                        return -1;
1333                }
1334
1335                len += sizeof(struct sadb_x_nat_t_type);
1336                len += sizeof(struct sadb_x_nat_t_port);
1337                len += sizeof(struct sadb_x_nat_t_port);
1338                if (sa_parms->l_natt_oa)
1339                        len += sizeof(struct sadb_address) +
1340                          PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa));
1341#ifdef SADB_X_EXT_NAT_T_FRAG
1342                if (sa_parms->l_natt_frag)
1343                        len += sizeof(struct sadb_x_nat_t_frag);
1344#endif
1345        }
1346#endif
1347
1348        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1349                __ipsec_set_strerror(strerror(errno));
1350                return -1;
1351        }
1352        ep = ((caddr_t)(void *)newmsg) + len;
1353
1354        p = pfkey_setsadbmsg((void *)newmsg, ep, sa_parms->type, (u_int)len,
1355                             sa_parms->satype, sa_parms->seq, getpid());
1356        if (!p) {
1357                free(newmsg);
1358                return -1;
1359        }
1360        p = pfkey_setsadbsa(p, ep, sa_parms->spi, sa_parms->wsize, 
1361                            sa_parms->a_type, sa_parms->e_type, 
1362                            sa_parms->flags);
1363        if (!p) {
1364                free(newmsg);
1365                return -1;
1366        }
1367        p = pfkey_setsadbxsa2(p, ep, sa_parms->mode, sa_parms->reqid);
1368        if (!p) {
1369                free(newmsg);
1370                return -1;
1371        }
1372        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, sa_parms->src, 
1373                              (u_int)plen, IPSEC_ULPROTO_ANY);
1374        if (!p) {
1375                free(newmsg);
1376                return -1;
1377        }
1378        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, sa_parms->dst, 
1379                              (u_int)plen, IPSEC_ULPROTO_ANY);
1380        if (!p) {
1381                free(newmsg);
1382                return -1;
1383        }
1384
1385        if (sa_parms->e_type != SADB_EALG_NONE && 
1386            sa_parms->satype != SADB_X_SATYPE_IPCOMP) {
1387                p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
1388                                   sa_parms->keymat, sa_parms->e_keylen);
1389                if (!p) {
1390                        free(newmsg);
1391                        return -1;
1392                }
1393        }
1394        if (sa_parms->a_type != SADB_AALG_NONE) {
1395                p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
1396                                     sa_parms->keymat + sa_parms->e_keylen, 
1397                                     sa_parms->a_keylen);
1398                if (!p) {
1399                        free(newmsg);
1400                        return -1;
1401                }
1402        }
1403
1404        /* set sadb_lifetime for destination */
1405        p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1406                        sa_parms->l_alloc, sa_parms->l_bytes, 
1407                        sa_parms->l_addtime, sa_parms->l_usetime);
1408        if (!p) {
1409                free(newmsg);
1410                return -1;
1411        }
1412        p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
1413                                  sa_parms->l_alloc, sa_parms->l_bytes, 
1414                                  sa_parms->l_addtime, sa_parms->l_usetime);
1415        if (!p) {
1416                free(newmsg);
1417                return -1;
1418        }
1419#ifdef SADB_X_EXT_SEC_CTX
1420        if (sa_parms->ctxstr != NULL) {
1421                p = pfkey_setsecctx(p, ep, SADB_X_EXT_SEC_CTX, sa_parms->ctxdoi,
1422                                    sa_parms->ctxalg, sa_parms->ctxstr, 
1423                                    sa_parms->ctxstrlen);
1424                if (!p) {
1425                        free(newmsg);
1426                        return -1;
1427                }
1428        }
1429#endif
1430
1431#ifdef SADB_X_EXT_NAT_T_TYPE
1432        /* Add nat-t messages */
1433        if (sa_parms->l_natt_type) {
1434                p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, 
1435                                        sa_parms->l_natt_type);
1436                if (!p) {
1437                        free(newmsg);
1438                        return -1;
1439                }
1440
1441                p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
1442                                        sa_parms->l_natt_sport);
1443                if (!p) {
1444                        free(newmsg);
1445                        return -1;
1446                }
1447
1448                p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
1449                                        sa_parms->l_natt_dport);
1450                if (!p) {
1451                        free(newmsg);
1452                        return -1;
1453                }
1454
1455                if (sa_parms->l_natt_oa) {
1456                        p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OA,
1457                                              sa_parms->l_natt_oa,
1458                                              (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)),
1459                                              IPSEC_ULPROTO_ANY);
1460                        if (!p) {
1461                                free(newmsg);
1462                                return -1;
1463                        }
1464                }
1465
1466#ifdef SADB_X_EXT_NAT_T_FRAG
1467                if (sa_parms->l_natt_frag) {
1468                        p = pfkey_set_natt_frag(p, ep, SADB_X_EXT_NAT_T_FRAG,
1469                                        sa_parms->l_natt_frag);
1470                        if (!p) {
1471                                free(newmsg);
1472                                return -1;
1473                        }
1474                }
1475#endif
1476        }
1477#endif
1478
1479        if (p != ep) {
1480                free(newmsg);
1481                return -1;
1482        }
1483
1484        /* send message */
1485        len = pfkey_send(sa_parms->so, newmsg, len);
1486        free(newmsg);
1487
1488        if (len < 0)
1489                return -1;
1490
1491        __ipsec_errcode = EIPSEC_NO_ERROR;
1492        return len;
1493}
1494
1495/* sending SADB_DELETE or SADB_GET message to the kernel */
1496/*ARGSUSED*/
1497static int
1498pfkey_send_x2(int so, u_int type, u_int satype, u_int mode,
1499    struct sockaddr *src, struct sockaddr *dst, u_int32_t spi)
1500{
1501        struct sadb_msg *newmsg;
1502        int len;
1503        caddr_t p;
1504        int plen;
1505        caddr_t ep;
1506
1507        /* validity check */
1508        if (src == NULL || dst == NULL) {
1509                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1510                return -1;
1511        }
1512        if (src->sa_family != dst->sa_family) {
1513                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1514                return -1;
1515        }
1516        switch (src->sa_family) {
1517        case AF_INET:
1518                plen = sizeof(struct in_addr) << 3;
1519                break;
1520        case AF_INET6:
1521                plen = sizeof(struct in6_addr) << 3;
1522                break;
1523        default:
1524                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1525                return -1;
1526        }
1527
1528        /* create new sadb_msg to reply. */
1529        len = sizeof(struct sadb_msg)
1530                + sizeof(struct sadb_sa)
1531                + sizeof(struct sadb_address)
1532                + PFKEY_ALIGN8(sysdep_sa_len(src))
1533                + sizeof(struct sadb_address)
1534                + PFKEY_ALIGN8(sysdep_sa_len(dst));
1535
1536        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1537                __ipsec_set_strerror(strerror(errno));
1538                return -1;
1539        }
1540        ep = ((caddr_t)(void *)newmsg) + len;
1541
1542        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
1543            getpid());
1544        if (!p) {
1545                free(newmsg);
1546                return -1;
1547        }
1548        p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
1549        if (!p) {
1550                free(newmsg);
1551                return -1;
1552        }
1553        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
1554            IPSEC_ULPROTO_ANY);
1555        if (!p) {
1556                free(newmsg);
1557                return -1;
1558        }
1559        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
1560            IPSEC_ULPROTO_ANY);
1561        if (!p || p != ep) {
1562                free(newmsg);
1563                return -1;
1564        }
1565
1566        /* send message */
1567        len = pfkey_send(so, newmsg, len);
1568        free(newmsg);
1569
1570        if (len < 0)
1571                return -1;
1572
1573        __ipsec_errcode = EIPSEC_NO_ERROR;
1574        return len;
1575}
1576
1577/*
1578 * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
1579 * to the kernel
1580 */
1581static int
1582pfkey_send_x3(int so, u_int type, u_int satype)
1583{
1584        struct sadb_msg *newmsg;
1585        int len;
1586        caddr_t p;
1587        caddr_t ep;
1588
1589        /* validity check */
1590        switch (type) {
1591        case SADB_X_PROMISC:
1592                if (satype != 0 && satype != 1) {
1593                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1594                        return -1;
1595                }
1596                break;
1597        default:
1598                switch (satype) {
1599                case SADB_SATYPE_UNSPEC:
1600                case SADB_SATYPE_AH:
1601                case SADB_SATYPE_ESP:
1602                case SADB_X_SATYPE_IPCOMP:
1603#ifdef SADB_X_SATYPE_TCPSIGNATURE
1604                case SADB_X_SATYPE_TCPSIGNATURE:
1605#endif
1606                        break;
1607                default:
1608                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1609                        return -1;
1610                }
1611        }
1612
1613        /* create new sadb_msg to send. */
1614        len = sizeof(struct sadb_msg);
1615
1616        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1617                __ipsec_set_strerror(strerror(errno));
1618                return -1;
1619        }
1620        ep = ((caddr_t)(void *)newmsg) + len;
1621
1622        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
1623            getpid());
1624        if (!p || p != ep) {
1625                free(newmsg);
1626                return -1;
1627        }
1628
1629        /* send message */
1630        len = pfkey_send(so, newmsg, len);
1631        free(newmsg);
1632
1633        if (len < 0)
1634                return -1;
1635
1636        __ipsec_errcode = EIPSEC_NO_ERROR;
1637        return len;
1638}
1639
1640/* sending SADB_X_SPDADD message to the kernel */
1641static int
1642pfkey_send_x4(int so, u_int type, struct sockaddr *src, u_int prefs,
1643    struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
1644    u_int64_t vtime, char *policy, int policylen, u_int32_t seq)
1645{
1646        struct sadb_msg *newmsg;
1647        int len;
1648        caddr_t p;
1649        int plen;
1650        caddr_t ep;
1651
1652        /* validity check */
1653        if (src == NULL || dst == NULL) {
1654                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1655                return -1;
1656        }
1657        if (src->sa_family != dst->sa_family) {
1658                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1659                return -1;
1660        }
1661
1662        switch (src->sa_family) {
1663        case AF_INET:
1664                plen = sizeof(struct in_addr) << 3;
1665                break;
1666        case AF_INET6:
1667                plen = sizeof(struct in6_addr) << 3;
1668                break;
1669        default:
1670                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1671                return -1;
1672        }
1673        if (prefs > plen || prefd > plen) {
1674                __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1675                return -1;
1676        }
1677
1678        /* create new sadb_msg to reply. */
1679        len = sizeof(struct sadb_msg)
1680                + sizeof(struct sadb_address)
1681                + PFKEY_ALIGN8(sysdep_sa_len(src))
1682                + sizeof(struct sadb_address)
1683                + PFKEY_ALIGN8(sysdep_sa_len(src))
1684                + sizeof(struct sadb_lifetime)
1685                + policylen;
1686
1687        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1688                __ipsec_set_strerror(strerror(errno));
1689                return -1;
1690        }
1691        ep = ((caddr_t)(void *)newmsg) + len;
1692
1693        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
1694            SADB_SATYPE_UNSPEC, seq, getpid());
1695        if (!p) {
1696                free(newmsg);
1697                return -1;
1698        }
1699        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
1700        if (!p) {
1701                free(newmsg);
1702                return -1;
1703        }
1704        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
1705        if (!p) {
1706                free(newmsg);
1707                return -1;
1708        }
1709        p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1710                        0, 0, (u_int)ltime, (u_int)vtime);
1711        if (!p || p + policylen != ep) {
1712                free(newmsg);
1713                return -1;
1714        }
1715        memcpy(p, policy, (size_t)policylen);
1716
1717        /* send message */
1718        len = pfkey_send(so, newmsg, len);
1719        free(newmsg);
1720
1721        if (len < 0)
1722                return -1;
1723
1724        __ipsec_errcode = EIPSEC_NO_ERROR;
1725        return len;
1726}
1727
1728/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
1729static int
1730pfkey_send_x5(int so, u_int type, u_int32_t spid)
1731{
1732        struct sadb_msg *newmsg;
1733        struct sadb_x_policy xpl;
1734        int len;
1735        caddr_t p;
1736        caddr_t ep;
1737
1738        /* create new sadb_msg to reply. */
1739        len = sizeof(struct sadb_msg)
1740                + sizeof(xpl);
1741
1742        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1743                __ipsec_set_strerror(strerror(errno));
1744                return -1;
1745        }
1746        ep = ((caddr_t)(void *)newmsg) + len;
1747
1748        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
1749            SADB_SATYPE_UNSPEC, 0, getpid());
1750        if (!p) {
1751                free(newmsg);
1752                return -1;
1753        }
1754
1755        if (p + sizeof(xpl) != ep) {
1756                free(newmsg);
1757                return -1;
1758        }
1759        memset(&xpl, 0, sizeof(xpl));
1760        xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
1761        xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1762        xpl.sadb_x_policy_id = spid;
1763        memcpy(p, &xpl, sizeof(xpl));
1764
1765        /* send message */
1766        len = pfkey_send(so, newmsg, len);
1767        free(newmsg);
1768
1769        if (len < 0)
1770                return -1;
1771
1772        __ipsec_errcode = EIPSEC_NO_ERROR;
1773        return len;
1774}
1775
1776/*
1777 * open a socket.
1778 * OUT:
1779 *      -1: fail.
1780 *      others : success and return value of socket.
1781 */
1782int
1783pfkey_open(void)
1784{
1785        int so;
1786        int bufsiz_current, bufsiz_wanted;
1787        int ret;
1788        socklen_t len;
1789
1790        if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1791                __ipsec_set_strerror(strerror(errno));
1792                return -1;
1793        }
1794
1795        /*
1796         * This is a temporary workaround for KAME PR 154.
1797         * Don't really care even if it fails.
1798         */
1799        /* Try to have 128k. If we have more, do not lower it. */
1800        bufsiz_wanted = 128 * 1024;
1801        len = sizeof(bufsiz_current);
1802        ret = getsockopt(so, SOL_SOCKET, SO_SNDBUF,
1803                &bufsiz_current, &len);
1804        if ((ret < 0) || (bufsiz_current < bufsiz_wanted))
1805                (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF,
1806                        &bufsiz_wanted, sizeof(bufsiz_wanted));
1807
1808        /* Try to have have at least 2MB. If we have more, do not lower it. */
1809        bufsiz_wanted = 2 * 1024 * 1024;
1810        len = sizeof(bufsiz_current);
1811        ret = getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1812                &bufsiz_current, &len);
1813        if (ret < 0)
1814                bufsiz_current = 128 * 1024;
1815
1816        for (; bufsiz_wanted > bufsiz_current; bufsiz_wanted /= 2) {
1817                if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
1818                                &bufsiz_wanted, sizeof(bufsiz_wanted)) == 0)
1819                        break;
1820        }
1821
1822        __ipsec_errcode = EIPSEC_NO_ERROR;
1823        return so;
1824}
1825
1826int
1827pfkey_set_buffer_size(int so, int size)
1828{
1829        int newsize;
1830        int actual_bufsiz;
1831        socklen_t sizebufsiz;
1832        int desired_bufsiz;
1833
1834        /*
1835         * on linux you may need to allow the kernel to allocate
1836         * more buffer space by increasing:
1837         * /proc/sys/net/core/rmem_max and wmem_max
1838         */
1839        if (size > 0) {
1840                actual_bufsiz = 0;
1841                sizebufsiz = sizeof(actual_bufsiz);
1842                desired_bufsiz = size * 1024;
1843                if ((getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1844                                &actual_bufsiz, &sizebufsiz) < 0)
1845                    || (actual_bufsiz < desired_bufsiz)) {
1846                        if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
1847                                       &desired_bufsiz, sizeof(desired_bufsiz)) < 0) {
1848                                __ipsec_set_strerror(strerror(errno));
1849                                return -1;
1850                        }
1851                }
1852        }
1853
1854        /* return actual buffer size */
1855        actual_bufsiz = 0;
1856        sizebufsiz = sizeof(actual_bufsiz);
1857        getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1858                   &actual_bufsiz, &sizebufsiz);
1859        return actual_bufsiz / 1024;
1860}
1861
1862/*
1863 * close a socket.
1864 * OUT:
1865 *       0: success.
1866 *      -1: fail.
1867 */
1868void
1869pfkey_close(int so)
1870{
1871        (void)close(so);
1872
1873        __ipsec_errcode = EIPSEC_NO_ERROR;
1874        return;
1875}
1876
1877/*
1878 * receive sadb_msg data, and return pointer to new buffer allocated.
1879 * Must free this buffer later.
1880 * OUT:
1881 *      NULL    : error occured.
1882 *      others  : a pointer to sadb_msg structure.
1883 *
1884 * XXX should be rewritten to pass length explicitly
1885 */
1886struct sadb_msg *
1887pfkey_recv(int so)
1888{
1889        struct sadb_msg buf, *newmsg;
1890        int len, reallen;
1891
1892        while ((len = recv(so, (void *)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1893                if (errno == EINTR)
1894                        continue;
1895                __ipsec_set_strerror(strerror(errno));
1896                return NULL;
1897        }
1898
1899        if (len < sizeof(buf)) {
1900                recv(so, (void *)&buf, sizeof(buf), 0);
1901                __ipsec_errcode = EIPSEC_MAX;
1902                return NULL;
1903        }
1904
1905        /* read real message */
1906        reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1907        if ((newmsg = CALLOC((size_t)reallen, struct sadb_msg *)) == 0) {
1908                __ipsec_set_strerror(strerror(errno));
1909                return NULL;
1910        }
1911
1912        while ((len = recv(so, (void *)newmsg, (socklen_t)reallen, 0)) < 0) {
1913                if (errno == EINTR)
1914                        continue;
1915                __ipsec_set_strerror(strerror(errno));
1916                free(newmsg);
1917                return NULL;
1918        }
1919
1920        if (len != reallen) {
1921                __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1922                free(newmsg);
1923                return NULL;
1924        }
1925
1926        /* don't trust what the kernel says, validate! */
1927        if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
1928                __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1929                free(newmsg);
1930                return NULL;
1931        }
1932
1933        __ipsec_errcode = EIPSEC_NO_ERROR;
1934        return newmsg;
1935}
1936
1937/*
1938 * send message to a socket.
1939 * OUT:
1940 *       others: success and return length sent.
1941 *      -1     : fail.
1942 */
1943int
1944pfkey_send(int so, struct sadb_msg *msg, int len)
1945{
1946        if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) {
1947                __ipsec_set_strerror(strerror(errno));
1948                return -1;
1949        }
1950
1951        __ipsec_errcode = EIPSEC_NO_ERROR;
1952        return len;
1953}
1954
1955/*
1956 * %%% Utilities
1957 * NOTE: These functions are derived from netkey/key.c in KAME.
1958 */
1959/*
1960 * set the pointer to each header in this message buffer.
1961 * IN:  msg: pointer to message buffer.
1962 *      mhp: pointer to the buffer initialized like below:
1963 *              caddr_t mhp[SADB_EXT_MAX + 1];
1964 * OUT: -1: invalid.
1965 *       0: valid.
1966 *
1967 * XXX should be rewritten to obtain length explicitly
1968 */
1969int
1970pfkey_align(struct sadb_msg *msg, caddr_t *mhp)
1971{
1972        struct sadb_ext *ext;
1973        int i;
1974        caddr_t p;
1975        caddr_t ep;     /* XXX should be passed from upper layer */
1976
1977        /* validity check */
1978        if (msg == NULL || mhp == NULL) {
1979                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1980                return -1;
1981        }
1982
1983        /* initialize */
1984        for (i = 0; i < SADB_EXT_MAX + 1; i++)
1985                mhp[i] = NULL;
1986
1987        mhp[0] = (void *)msg;
1988
1989        /* initialize */
1990        p = (void *) msg;
1991        ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
1992
1993        /* skip base header */
1994        p += sizeof(struct sadb_msg);
1995
1996        while (p < ep) {
1997                ext = (void *)p;
1998                if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
1999                    ep < p + PFKEY_EXTLEN(ext)) {
2000                        /* invalid format */
2001                        break;
2002                }
2003
2004                /* duplicate check */
2005                /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
2006                if (mhp[ext->sadb_ext_type] != NULL) {
2007                        __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
2008                        return -1;
2009                }
2010
2011                /* set pointer */
2012                switch (ext->sadb_ext_type) {
2013                case SADB_EXT_SA:
2014                case SADB_EXT_LIFETIME_CURRENT:
2015                case SADB_EXT_LIFETIME_HARD:
2016                case SADB_EXT_LIFETIME_SOFT:
2017                case SADB_EXT_ADDRESS_SRC:
2018                case SADB_EXT_ADDRESS_DST:
2019                case SADB_EXT_ADDRESS_PROXY:
2020                case SADB_EXT_KEY_AUTH:
2021                        /* XXX should to be check weak keys. */
2022                case SADB_EXT_KEY_ENCRYPT:
2023                        /* XXX should to be check weak keys. */
2024                case SADB_EXT_IDENTITY_SRC:
2025                case SADB_EXT_IDENTITY_DST:
2026                case SADB_EXT_SENSITIVITY:
2027                case SADB_EXT_PROPOSAL:
2028                case SADB_EXT_SUPPORTED_AUTH:
2029                case SADB_EXT_SUPPORTED_ENCRYPT:
2030                case SADB_EXT_SPIRANGE:
2031                case SADB_X_EXT_POLICY:
2032                case SADB_X_EXT_SA2:
2033#ifdef SADB_X_EXT_NAT_T_TYPE
2034                case SADB_X_EXT_NAT_T_TYPE:
2035                case SADB_X_EXT_NAT_T_SPORT:
2036                case SADB_X_EXT_NAT_T_DPORT:
2037                case SADB_X_EXT_NAT_T_OA:
2038#endif
2039#ifdef SADB_X_EXT_TAG
2040                case SADB_X_EXT_TAG:
2041#endif
2042#ifdef SADB_X_EXT_PACKET
2043                case SADB_X_EXT_PACKET:
2044#endif
2045#ifdef SADB_X_EXT_KMADDRESS
2046                case SADB_X_EXT_KMADDRESS:
2047#endif
2048#ifdef SADB_X_EXT_SEC_CTX
2049                case SADB_X_EXT_SEC_CTX:
2050#endif
2051                        mhp[ext->sadb_ext_type] = (void *)ext;
2052                        break;
2053                default:
2054                        __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
2055                        return -1;
2056                }
2057
2058                p += PFKEY_EXTLEN(ext);
2059        }
2060
2061        if (p != ep) {
2062                __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
2063                return -1;
2064        }
2065
2066        __ipsec_errcode = EIPSEC_NO_ERROR;
2067        return 0;
2068}
2069
2070/*
2071 * check basic usage for sadb_msg,
2072 * NOTE: This routine is derived from netkey/key.c in KAME.
2073 * IN:  msg: pointer to message buffer.
2074 *      mhp: pointer to the buffer initialized like below:
2075 *
2076 *              caddr_t mhp[SADB_EXT_MAX + 1];
2077 *
2078 * OUT: -1: invalid.
2079 *       0: valid.
2080 */
2081int
2082pfkey_check(caddr_t *mhp)
2083{
2084        struct sadb_msg *msg;
2085
2086        /* validity check */
2087        if (mhp == NULL || mhp[0] == NULL) {
2088                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
2089                return -1;
2090        }
2091
2092        msg = (void *)mhp[0];
2093
2094        /* check version */
2095        if (msg->sadb_msg_version != PF_KEY_V2) {
2096                __ipsec_errcode = EIPSEC_INVAL_VERSION;
2097                return -1;
2098        }
2099
2100        /* check type */
2101        if (msg->sadb_msg_type > SADB_MAX) {
2102                __ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
2103                return -1;
2104        }
2105
2106        /* check SA type */
2107        switch (msg->sadb_msg_satype) {
2108        case SADB_SATYPE_UNSPEC:
2109                switch (msg->sadb_msg_type) {
2110                case SADB_GETSPI:
2111                case SADB_UPDATE:
2112                case SADB_ADD:
2113                case SADB_DELETE:
2114                case SADB_GET:
2115                case SADB_ACQUIRE:
2116                case SADB_EXPIRE:
2117#ifdef SADB_X_NAT_T_NEW_MAPPING
2118                case SADB_X_NAT_T_NEW_MAPPING:
2119#endif
2120                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2121                        return -1;
2122                }
2123                break;
2124        case SADB_SATYPE_ESP:
2125        case SADB_SATYPE_AH:
2126        case SADB_X_SATYPE_IPCOMP:
2127#ifdef SADB_X_SATYPE_TCPSIGNATURE
2128        case SADB_X_SATYPE_TCPSIGNATURE:
2129#endif
2130                switch (msg->sadb_msg_type) {
2131                case SADB_X_SPDADD:
2132                case SADB_X_SPDDELETE:
2133                case SADB_X_SPDGET:
2134                case SADB_X_SPDDUMP:
2135                case SADB_X_SPDFLUSH:
2136                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2137                        return -1;
2138                }
2139#ifdef SADB_X_NAT_T_NEW_MAPPING
2140                if (msg->sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING &&
2141                    msg->sadb_msg_satype != SADB_SATYPE_ESP) {
2142                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2143                        return -1;
2144                }
2145#endif
2146                break;
2147        case SADB_SATYPE_RSVP:
2148        case SADB_SATYPE_OSPFV2:
2149        case SADB_SATYPE_RIPV2:
2150        case SADB_SATYPE_MIP:
2151                __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
2152                return -1;
2153        case 1: /* XXX: What does it do ? */
2154                if (msg->sadb_msg_type == SADB_X_PROMISC)
2155                        break;
2156                /*FALLTHROUGH*/
2157        default:
2158#ifdef __linux__
2159                /* Linux kernel seems to be buggy and return
2160                 * uninitialized satype for spd flush message */
2161                if (msg->sadb_msg_type == SADB_X_SPDFLUSH)
2162                        break;
2163#endif
2164                __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2165                return -1;
2166        }
2167
2168        /* check field of upper layer protocol and address family */
2169        if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
2170         && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
2171                struct sadb_address *src0, *dst0;
2172
2173                src0 = (void *)(mhp[SADB_EXT_ADDRESS_SRC]);
2174                dst0 = (void *)(mhp[SADB_EXT_ADDRESS_DST]);
2175
2176                if (src0->sadb_address_proto != dst0->sadb_address_proto) {
2177                        __ipsec_errcode = EIPSEC_PROTO_MISMATCH;
2178                        return -1;
2179                }
2180
2181                if (PFKEY_ADDR_SADDR(src0)->sa_family
2182                 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
2183                        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
2184                        return -1;
2185                }
2186
2187                switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
2188                case AF_INET:
2189                case AF_INET6:
2190                        break;
2191                default:
2192                        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
2193                        return -1;
2194                }
2195
2196                /*
2197                 * prefixlen == 0 is valid because there must be the case
2198                 * all addresses are matched.
2199                 */
2200        }
2201
2202        __ipsec_errcode = EIPSEC_NO_ERROR;
2203        return 0;
2204}
2205
2206/*
2207 * set data into sadb_msg.
2208 * `buf' must has been allocated sufficiently.
2209 */
2210static caddr_t
2211pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen,
2212    u_int satype, u_int32_t seq, pid_t pid)
2213{
2214        struct sadb_msg *p;
2215        u_int len;
2216
2217        p = (void *)buf;
2218        len = sizeof(struct sadb_msg);
2219
2220        if (buf + len > lim)
2221                return NULL;
2222
2223        memset(p, 0, len);
2224        p->sadb_msg_version = PF_KEY_V2;
2225        p->sadb_msg_type = type;
2226        p->sadb_msg_errno = 0;
2227        p->sadb_msg_satype = satype;
2228        p->sadb_msg_len = PFKEY_UNIT64(tlen);
2229        p->sadb_msg_reserved = 0;
2230        p->sadb_msg_seq = seq;
2231        p->sadb_msg_pid = (u_int32_t)pid;
2232
2233        return(buf + len);
2234}
2235
2236/*
2237 * copy secasvar data into sadb_address.
2238 * `buf' must has been allocated sufficiently.
2239 */
2240static caddr_t
2241pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize,
2242    u_int auth, u_int enc, u_int32_t flags)
2243{
2244        struct sadb_sa *p;
2245        u_int len;
2246
2247        p = (void *)buf;
2248        len = sizeof(struct sadb_sa);
2249
2250        if (buf + len > lim)
2251                return NULL;
2252
2253        memset(p, 0, len);
2254        p->sadb_sa_len = PFKEY_UNIT64(len);
2255        p->sadb_sa_exttype = SADB_EXT_SA;
2256        p->sadb_sa_spi = spi;
2257        p->sadb_sa_replay = wsize;
2258        p->sadb_sa_state = SADB_SASTATE_LARVAL;
2259        p->sadb_sa_auth = auth;
2260        p->sadb_sa_encrypt = enc;
2261        p->sadb_sa_flags = flags;
2262
2263        return(buf + len);
2264}
2265
2266/*
2267 * set data into sadb_address.
2268 * `buf' must has been allocated sufficiently.
2269 * prefixlen is in bits.
2270 */
2271static caddr_t
2272pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype,
2273    struct sockaddr *saddr, u_int prefixlen, u_int ul_proto)
2274{
2275        struct sadb_address *p;
2276        u_int len;
2277
2278        p = (void *)buf;
2279        len = sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(saddr));
2280
2281        if (buf + len > lim)
2282                return NULL;
2283
2284        memset(p, 0, len);
2285        p->sadb_address_len = PFKEY_UNIT64(len);
2286        p->sadb_address_exttype = exttype & 0xffff;
2287        p->sadb_address_proto = ul_proto & 0xff;
2288        p->sadb_address_prefixlen = prefixlen;
2289        p->sadb_address_reserved = 0;
2290
2291        memcpy(p + 1, saddr, (size_t)sysdep_sa_len(saddr));
2292
2293        return(buf + len);
2294}
2295
2296#ifdef SADB_X_EXT_KMADDRESS
2297/*
2298 * set data into sadb_x_kmaddress.
2299 * `buf' must has been allocated sufficiently.
2300 */
2301static caddr_t
2302pfkey_setsadbkmaddr(caddr_t buf, caddr_t lim, struct sockaddr *local,
2303    struct sockaddr *remote)
2304{
2305        struct sadb_x_kmaddress *p;
2306        struct sockaddr *sa;
2307        u_int salen = sysdep_sa_len(local);
2308        u_int len;
2309
2310        /* sanity check */
2311        if (local->sa_family != remote->sa_family)
2312                return NULL;
2313
2314        p = (void *)buf;
2315        len = sizeof(struct sadb_x_kmaddress) + PFKEY_ALIGN8(2*salen);
2316
2317        if (buf + len > lim)
2318                return NULL;
2319
2320        memset(p, 0, len);
2321        p->sadb_x_kmaddress_len = PFKEY_UNIT64(len);
2322        p->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS;
2323        p->sadb_x_kmaddress_reserved = 0;
2324        sa = (struct sockaddr *)(p + 1);
2325        memcpy(sa, local, salen);
2326        sa = (struct sockaddr *)((char *)sa + salen);
2327        memcpy(sa, remote, salen);
2328
2329        return(buf + len);
2330}
2331#endif
2332
2333/*
2334 * set sadb_key structure after clearing buffer with zero.
2335 * OUT: the pointer of buf + len.
2336 */
2337static caddr_t
2338pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key,
2339    u_int keylen)
2340{
2341        struct sadb_key *p;
2342        u_int len;
2343
2344        p = (void *)buf;
2345        len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
2346
2347        if (buf + len > lim)
2348                return NULL;
2349
2350        memset(p, 0, len);
2351        p->sadb_key_len = PFKEY_UNIT64(len);
2352        p->sadb_key_exttype = type;
2353        p->sadb_key_bits = keylen << 3;
2354        p->sadb_key_reserved = 0;
2355
2356        memcpy(p + 1, key, keylen);
2357
2358        return buf + len;
2359}
2360
2361/*
2362 * set sadb_lifetime structure after clearing buffer with zero.
2363 * OUT: the pointer of buf + len.
2364 */
2365static caddr_t
2366pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc,
2367    u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime)
2368{
2369        struct sadb_lifetime *p;
2370        u_int len;
2371
2372        p = (void *)buf;
2373        len = sizeof(struct sadb_lifetime);
2374
2375        if (buf + len > lim)
2376                return NULL;
2377
2378        memset(p, 0, len);
2379        p->sadb_lifetime_len = PFKEY_UNIT64(len);
2380        p->sadb_lifetime_exttype = type;
2381
2382        switch (type) {
2383        case SADB_EXT_LIFETIME_SOFT:
2384                p->sadb_lifetime_allocations
2385                        = (l_alloc * soft_lifetime_allocations_rate) /100;
2386                p->sadb_lifetime_bytes
2387                        = (l_bytes * soft_lifetime_bytes_rate) /100;
2388                p->sadb_lifetime_addtime
2389                        = (l_addtime * soft_lifetime_addtime_rate) /100;
2390                p->sadb_lifetime_usetime
2391                        = (l_usetime * soft_lifetime_usetime_rate) /100;
2392                break;
2393        case SADB_EXT_LIFETIME_HARD:
2394                p->sadb_lifetime_allocations = l_alloc;
2395                p->sadb_lifetime_bytes = l_bytes;
2396                p->sadb_lifetime_addtime = l_addtime;
2397                p->sadb_lifetime_usetime = l_usetime;
2398                break;
2399        }
2400
2401        return buf + len;
2402}
2403
2404/*
2405 * copy secasvar data into sadb_address.
2406 * `buf' must has been allocated sufficiently.
2407 */
2408static caddr_t
2409pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid)
2410{
2411        struct sadb_x_sa2 *p;
2412        u_int8_t mode = mode0 & 0xff;
2413        u_int len;
2414
2415        p = (void *)buf;
2416        len = sizeof(struct sadb_x_sa2);
2417
2418        if (buf + len > lim)
2419                return NULL;
2420
2421        memset(p, 0, len);
2422        p->sadb_x_sa2_len = PFKEY_UNIT64(len);
2423        p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
2424        p->sadb_x_sa2_mode = mode;
2425        p->sadb_x_sa2_reqid = reqid;
2426
2427        return(buf + len);
2428}
2429
2430#ifdef SADB_X_EXT_NAT_T_TYPE
2431static caddr_t
2432pfkey_set_natt_type(caddr_t buf, caddr_t lim, u_int type, u_int8_t l_natt_type)
2433{
2434        struct sadb_x_nat_t_type *p;
2435        u_int len;
2436
2437        p = (void *)buf;
2438        len = sizeof(struct sadb_x_nat_t_type);
2439
2440        if (buf + len > lim)
2441                return NULL;
2442
2443        memset(p, 0, len);
2444        p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
2445        p->sadb_x_nat_t_type_exttype = type;
2446        p->sadb_x_nat_t_type_type = l_natt_type;
2447
2448        return(buf + len);
2449}
2450
2451static caddr_t
2452pfkey_set_natt_port(caddr_t buf, caddr_t lim, u_int type, u_int16_t l_natt_port)
2453{
2454        struct sadb_x_nat_t_port *p;
2455        u_int len;
2456
2457        p = (void *)buf;
2458        len = sizeof(struct sadb_x_nat_t_port);
2459
2460        if (buf + len > lim)
2461                return NULL;
2462
2463        memset(p, 0, len);
2464        p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
2465        p->sadb_x_nat_t_port_exttype = type;
2466        p->sadb_x_nat_t_port_port = htons(l_natt_port);
2467
2468        return(buf + len);
2469}
2470#endif
2471
2472#ifdef SADB_X_EXT_NAT_T_FRAG
2473static caddr_t
2474pfkey_set_natt_frag(caddr_t buf, caddr_t lim, u_int type, 
2475    u_int16_t l_natt_frag)
2476{
2477        struct sadb_x_nat_t_frag *p;
2478        u_int len;
2479
2480        p = (void *)buf;
2481        len = sizeof(struct sadb_x_nat_t_frag);
2482
2483        if (buf + len > lim)
2484                return NULL;
2485
2486        memset(p, 0, len);
2487        p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
2488        p->sadb_x_nat_t_frag_exttype = type;
2489        p->sadb_x_nat_t_frag_fraglen = l_natt_frag;
2490
2491        return(buf + len);
2492}
2493#endif
2494
2495#ifdef SADB_X_EXT_SEC_CTX
2496static caddr_t
2497pfkey_setsecctx(caddr_t buf, caddr_t lim, u_int type, u_int8_t ctx_doi,
2498    u_int8_t ctx_alg, caddr_t sec_ctx, u_int16_t sec_ctxlen)
2499{
2500        struct sadb_x_sec_ctx *p;
2501        u_int len;
2502
2503        p = (struct sadb_x_sec_ctx *)buf;
2504        len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen);
2505
2506        if (buf + len > lim)
2507                return NULL;
2508
2509        memset(p, 0, len);
2510        p->sadb_x_sec_len = PFKEY_UNIT64(len);
2511        p->sadb_x_sec_exttype = type;
2512        p->sadb_x_ctx_len = sec_ctxlen;
2513        p->sadb_x_ctx_doi = ctx_doi;
2514        p->sadb_x_ctx_alg = ctx_alg;
2515
2516        memcpy(p + 1, sec_ctx, sec_ctxlen);
2517
2518        return buf + len;
2519}
2520#endif
2521
2522/*
2523 * Deprecated, available for backward compatibility with third party
2524 * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead
2525 */
2526int
2527pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src,
2528    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2529    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2530    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2531    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
2532{
2533        struct pfkey_send_sa_args psaa;
2534
2535        memset(&psaa, 0, sizeof(psaa));
2536        psaa.so = so;
2537        psaa.type = SADB_UPDATE;
2538        psaa.satype = satype;
2539        psaa.mode = mode;
2540        psaa.wsize = wsize;
2541        psaa.src = src;
2542        psaa.dst = dst;
2543        psaa.spi = spi;
2544        psaa.reqid = reqid;
2545        psaa.keymat = keymat;
2546        psaa.e_type = e_type;
2547        psaa.e_keylen = e_keylen;
2548        psaa.a_type = a_type;
2549        psaa.a_keylen = a_keylen;
2550        psaa.flags = flags;
2551        psaa.l_alloc = l_alloc;
2552        psaa.l_bytes = l_bytes;
2553        psaa.l_addtime = l_addtime;
2554        psaa.l_usetime = l_usetime;
2555        psaa.seq = seq;
2556
2557        return pfkey_send_update2(&psaa);
2558}
2559
2560int
2561pfkey_send_update_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
2562    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2563    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2564    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2565    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
2566    u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
2567    struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
2568{
2569        struct pfkey_send_sa_args psaa;
2570
2571        memset(&psaa, 0, sizeof(psaa));
2572        psaa.so = so;
2573        psaa.type = SADB_UPDATE;
2574        psaa.satype = satype;
2575        psaa.mode = mode;
2576        psaa.wsize = wsize;
2577        psaa.src = src;
2578        psaa.dst = dst;
2579        psaa.spi = spi;
2580        psaa.reqid = reqid;
2581        psaa.keymat = keymat;
2582        psaa.e_type = e_type;
2583        psaa.e_keylen = e_keylen;
2584        psaa.a_type = a_type;
2585        psaa.a_keylen = a_keylen;
2586        psaa.flags = flags;
2587        psaa.l_alloc = l_alloc;
2588        psaa.l_bytes = l_bytes;
2589        psaa.l_addtime = l_addtime;
2590        psaa.l_usetime = l_usetime;
2591        psaa.seq = seq;
2592        psaa.l_natt_type = l_natt_type;
2593        psaa.l_natt_sport = l_natt_sport;
2594        psaa.l_natt_dport = l_natt_dport;
2595        psaa.l_natt_oa = l_natt_oa;
2596        psaa.l_natt_frag = l_natt_frag;
2597
2598        return pfkey_send_update2(&psaa);
2599}
2600
2601int
2602pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src,
2603    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2604    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2605    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2606    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
2607{
2608        struct pfkey_send_sa_args psaa;
2609
2610        memset(&psaa, 0, sizeof(psaa));
2611        psaa.so = so;
2612        psaa.type = SADB_ADD;
2613        psaa.satype = satype;
2614        psaa.mode = mode;
2615        psaa.wsize = wsize;
2616        psaa.src = src;
2617        psaa.dst = dst;
2618        psaa.spi = spi;
2619        psaa.reqid = reqid;
2620        psaa.keymat = keymat;
2621        psaa.e_type = e_type;
2622        psaa.e_keylen = e_keylen;
2623        psaa.a_type = a_type;
2624        psaa.a_keylen = a_keylen;
2625        psaa.flags = flags;
2626        psaa.l_alloc = l_alloc;
2627        psaa.l_bytes = l_bytes;
2628        psaa.l_addtime = l_addtime;
2629        psaa.l_usetime = l_usetime;
2630        psaa.seq = seq;
2631
2632        return pfkey_send_add2(&psaa);
2633}
2634
2635int
2636pfkey_send_add_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
2637    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2638    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2639    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2640    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
2641    u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
2642    struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
2643{
2644        struct pfkey_send_sa_args psaa;
2645
2646        memset(&psaa, 0, sizeof(psaa));
2647        psaa.so = so;
2648        psaa.type = SADB_ADD;
2649        psaa.satype = satype;
2650        psaa.mode = mode;
2651        psaa.wsize = wsize;
2652        psaa.src = src;
2653        psaa.dst = dst;
2654        psaa.spi = spi;
2655        psaa.reqid = reqid;
2656        psaa.keymat = keymat;
2657        psaa.e_type = e_type;
2658        psaa.e_keylen = e_keylen;
2659        psaa.a_type = a_type;
2660        psaa.a_keylen = a_keylen;
2661        psaa.flags = flags;
2662        psaa.l_alloc = l_alloc;
2663        psaa.l_bytes = l_bytes;
2664        psaa.l_addtime = l_addtime;
2665        psaa.l_usetime = l_usetime;
2666        psaa.seq = seq;
2667        psaa.l_natt_type = l_natt_type;
2668        psaa.l_natt_sport = l_natt_sport;
2669        psaa.l_natt_dport = l_natt_dport;
2670        psaa.l_natt_oa = l_natt_oa;
2671        psaa.l_natt_frag = l_natt_frag;
2672
2673        return pfkey_send_add2(&psaa);
2674}
Note: See TracBrowser for help on using the repository browser.