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

5-freebsd-12
Last change on this file since 8645c9d7 was 8645c9d7, checked in by Christian Mauderer <christian.mauderer@…>, on Jun 6, 2018 at 9:11:52 AM

ipsec-tools: Apply patches from FreeBSD ports.

Source: https://svnweb.freebsd.org/ports/head/security/ipsec-tools/files/ revision 468617.

  • Property mode set to 100644
File size: 59.6 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_oai)
1339                        len += sizeof(struct sadb_address) +
1340                          PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oai));
1341                if (sa_parms->l_natt_oar)
1342                        len += sizeof(struct sadb_address) +
1343                          PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oar));
1344#ifdef SADB_X_EXT_NAT_T_FRAG
1345                if (sa_parms->l_natt_frag)
1346                        len += sizeof(struct sadb_x_nat_t_frag);
1347#endif
1348        }
1349#endif
1350
1351        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1352                __ipsec_set_strerror(strerror(errno));
1353                return -1;
1354        }
1355        ep = ((caddr_t)(void *)newmsg) + len;
1356
1357        p = pfkey_setsadbmsg((void *)newmsg, ep, sa_parms->type, (u_int)len,
1358                             sa_parms->satype, sa_parms->seq, getpid());
1359        if (!p) {
1360                free(newmsg);
1361                return -1;
1362        }
1363        p = pfkey_setsadbsa(p, ep, sa_parms->spi, sa_parms->wsize, 
1364                            sa_parms->a_type, sa_parms->e_type, 
1365                            sa_parms->flags);
1366        if (!p) {
1367                free(newmsg);
1368                return -1;
1369        }
1370        p = pfkey_setsadbxsa2(p, ep, sa_parms->mode, sa_parms->reqid);
1371        if (!p) {
1372                free(newmsg);
1373                return -1;
1374        }
1375        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, sa_parms->src, 
1376                              (u_int)plen, IPSEC_ULPROTO_ANY);
1377        if (!p) {
1378                free(newmsg);
1379                return -1;
1380        }
1381        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, sa_parms->dst, 
1382                              (u_int)plen, IPSEC_ULPROTO_ANY);
1383        if (!p) {
1384                free(newmsg);
1385                return -1;
1386        }
1387
1388        if (sa_parms->e_type != SADB_EALG_NONE && 
1389            sa_parms->satype != SADB_X_SATYPE_IPCOMP) {
1390                p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
1391                                   sa_parms->keymat, sa_parms->e_keylen);
1392                if (!p) {
1393                        free(newmsg);
1394                        return -1;
1395                }
1396        }
1397        if (sa_parms->a_type != SADB_AALG_NONE) {
1398                p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
1399                                     sa_parms->keymat + sa_parms->e_keylen, 
1400                                     sa_parms->a_keylen);
1401                if (!p) {
1402                        free(newmsg);
1403                        return -1;
1404                }
1405        }
1406
1407        /* set sadb_lifetime for destination */
1408        p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1409                        sa_parms->l_alloc, sa_parms->l_bytes, 
1410                        sa_parms->l_addtime, sa_parms->l_usetime);
1411        if (!p) {
1412                free(newmsg);
1413                return -1;
1414        }
1415        p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
1416                                  sa_parms->l_alloc, sa_parms->l_bytes, 
1417                                  sa_parms->l_addtime, sa_parms->l_usetime);
1418        if (!p) {
1419                free(newmsg);
1420                return -1;
1421        }
1422#ifdef SADB_X_EXT_SEC_CTX
1423        if (sa_parms->ctxstr != NULL) {
1424                p = pfkey_setsecctx(p, ep, SADB_X_EXT_SEC_CTX, sa_parms->ctxdoi,
1425                                    sa_parms->ctxalg, sa_parms->ctxstr, 
1426                                    sa_parms->ctxstrlen);
1427                if (!p) {
1428                        free(newmsg);
1429                        return -1;
1430                }
1431        }
1432#endif
1433
1434#ifdef SADB_X_EXT_NAT_T_TYPE
1435        /* Add nat-t messages */
1436        if (sa_parms->l_natt_type) {
1437                p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, 
1438                                        sa_parms->l_natt_type);
1439                if (!p) {
1440                        free(newmsg);
1441                        return -1;
1442                }
1443
1444                p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT,
1445                                        sa_parms->l_natt_sport);
1446                if (!p) {
1447                        free(newmsg);
1448                        return -1;
1449                }
1450
1451                p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT,
1452                                        sa_parms->l_natt_dport);
1453                if (!p) {
1454                        free(newmsg);
1455                        return -1;
1456                }
1457
1458                if (sa_parms->l_natt_oai) {
1459                        p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OAI,
1460                                              sa_parms->l_natt_oai,
1461                                              (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oai)),
1462                                              IPSEC_ULPROTO_ANY);
1463                        if (!p) {
1464                                free(newmsg);
1465                                return -1;
1466                        }
1467                }
1468
1469                if (sa_parms->l_natt_oar) {
1470                        p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OAR,
1471                                              sa_parms->l_natt_oar,
1472                                              (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oar)),
1473                                              IPSEC_ULPROTO_ANY);
1474                        if (!p) {
1475                                free(newmsg);
1476                                return -1;
1477                        }
1478                }
1479
1480#ifdef SADB_X_EXT_NAT_T_FRAG
1481                if (sa_parms->l_natt_frag) {
1482                        p = pfkey_set_natt_frag(p, ep, SADB_X_EXT_NAT_T_FRAG,
1483                                        sa_parms->l_natt_frag);
1484                        if (!p) {
1485                                free(newmsg);
1486                                return -1;
1487                        }
1488                }
1489#endif
1490        }
1491#endif
1492
1493        if (p != ep) {
1494                free(newmsg);
1495                return -1;
1496        }
1497
1498        /* send message */
1499        len = pfkey_send(sa_parms->so, newmsg, len);
1500        free(newmsg);
1501
1502        if (len < 0)
1503                return -1;
1504
1505        __ipsec_errcode = EIPSEC_NO_ERROR;
1506        return len;
1507}
1508
1509/* sending SADB_DELETE or SADB_GET message to the kernel */
1510/*ARGSUSED*/
1511static int
1512pfkey_send_x2(int so, u_int type, u_int satype, u_int mode,
1513    struct sockaddr *src, struct sockaddr *dst, u_int32_t spi)
1514{
1515        struct sadb_msg *newmsg;
1516        int len;
1517        caddr_t p;
1518        int plen;
1519        caddr_t ep;
1520
1521        /* validity check */
1522        if (src == NULL || dst == NULL) {
1523                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1524                return -1;
1525        }
1526        if (src->sa_family != dst->sa_family) {
1527                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1528                return -1;
1529        }
1530        switch (src->sa_family) {
1531        case AF_INET:
1532                plen = sizeof(struct in_addr) << 3;
1533                break;
1534        case AF_INET6:
1535                plen = sizeof(struct in6_addr) << 3;
1536                break;
1537        default:
1538                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1539                return -1;
1540        }
1541
1542        /* create new sadb_msg to reply. */
1543        len = sizeof(struct sadb_msg)
1544                + sizeof(struct sadb_sa)
1545                + sizeof(struct sadb_address)
1546                + PFKEY_ALIGN8(sysdep_sa_len(src))
1547                + sizeof(struct sadb_address)
1548                + PFKEY_ALIGN8(sysdep_sa_len(dst));
1549
1550        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1551                __ipsec_set_strerror(strerror(errno));
1552                return -1;
1553        }
1554        ep = ((caddr_t)(void *)newmsg) + len;
1555
1556        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
1557            getpid());
1558        if (!p) {
1559                free(newmsg);
1560                return -1;
1561        }
1562        p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
1563        if (!p) {
1564                free(newmsg);
1565                return -1;
1566        }
1567        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen,
1568            IPSEC_ULPROTO_ANY);
1569        if (!p) {
1570                free(newmsg);
1571                return -1;
1572        }
1573        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen,
1574            IPSEC_ULPROTO_ANY);
1575        if (!p || p != ep) {
1576                free(newmsg);
1577                return -1;
1578        }
1579
1580        /* send message */
1581        len = pfkey_send(so, newmsg, len);
1582        free(newmsg);
1583
1584        if (len < 0)
1585                return -1;
1586
1587        __ipsec_errcode = EIPSEC_NO_ERROR;
1588        return len;
1589}
1590
1591/*
1592 * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
1593 * to the kernel
1594 */
1595static int
1596pfkey_send_x3(int so, u_int type, u_int satype)
1597{
1598        struct sadb_msg *newmsg;
1599        int len;
1600        caddr_t p;
1601        caddr_t ep;
1602
1603        /* validity check */
1604        switch (type) {
1605        case SADB_X_PROMISC:
1606                if (satype != 0 && satype != 1) {
1607                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1608                        return -1;
1609                }
1610                break;
1611        default:
1612                switch (satype) {
1613                case SADB_SATYPE_UNSPEC:
1614                case SADB_SATYPE_AH:
1615                case SADB_SATYPE_ESP:
1616                case SADB_X_SATYPE_IPCOMP:
1617#ifdef SADB_X_SATYPE_TCPSIGNATURE
1618                case SADB_X_SATYPE_TCPSIGNATURE:
1619#endif
1620                        break;
1621                default:
1622                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
1623                        return -1;
1624                }
1625        }
1626
1627        /* create new sadb_msg to send. */
1628        len = sizeof(struct sadb_msg);
1629
1630        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1631                __ipsec_set_strerror(strerror(errno));
1632                return -1;
1633        }
1634        ep = ((caddr_t)(void *)newmsg) + len;
1635
1636        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0,
1637            getpid());
1638        if (!p || p != ep) {
1639                free(newmsg);
1640                return -1;
1641        }
1642
1643        /* send message */
1644        len = pfkey_send(so, newmsg, len);
1645        free(newmsg);
1646
1647        if (len < 0)
1648                return -1;
1649
1650        __ipsec_errcode = EIPSEC_NO_ERROR;
1651        return len;
1652}
1653
1654/* sending SADB_X_SPDADD message to the kernel */
1655static int
1656pfkey_send_x4(int so, u_int type, struct sockaddr *src, u_int prefs,
1657    struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime,
1658    u_int64_t vtime, char *policy, int policylen, u_int32_t seq)
1659{
1660        struct sadb_msg *newmsg;
1661        int len;
1662        caddr_t p;
1663        int plen;
1664        caddr_t ep;
1665
1666        /* validity check */
1667        if (src == NULL || dst == NULL) {
1668                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1669                return -1;
1670        }
1671        if (src->sa_family != dst->sa_family) {
1672                __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
1673                return -1;
1674        }
1675
1676        switch (src->sa_family) {
1677        case AF_INET:
1678                plen = sizeof(struct in_addr) << 3;
1679                break;
1680        case AF_INET6:
1681                plen = sizeof(struct in6_addr) << 3;
1682                break;
1683        default:
1684                __ipsec_errcode = EIPSEC_INVAL_FAMILY;
1685                return -1;
1686        }
1687        if (prefs > plen || prefd > plen) {
1688                __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
1689                return -1;
1690        }
1691
1692        /* create new sadb_msg to reply. */
1693        len = sizeof(struct sadb_msg)
1694                + sizeof(struct sadb_address)
1695                + PFKEY_ALIGN8(sysdep_sa_len(src))
1696                + sizeof(struct sadb_address)
1697                + PFKEY_ALIGN8(sysdep_sa_len(src))
1698                + sizeof(struct sadb_lifetime)
1699                + policylen;
1700
1701        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1702                __ipsec_set_strerror(strerror(errno));
1703                return -1;
1704        }
1705        ep = ((caddr_t)(void *)newmsg) + len;
1706
1707        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
1708            SADB_SATYPE_UNSPEC, seq, getpid());
1709        if (!p) {
1710                free(newmsg);
1711                return -1;
1712        }
1713        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
1714        if (!p) {
1715                free(newmsg);
1716                return -1;
1717        }
1718        p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
1719        if (!p) {
1720                free(newmsg);
1721                return -1;
1722        }
1723        p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
1724                        0, 0, (u_int)ltime, (u_int)vtime);
1725        if (!p || p + policylen != ep) {
1726                free(newmsg);
1727                return -1;
1728        }
1729        memcpy(p, policy, (size_t)policylen);
1730
1731        /* send message */
1732        len = pfkey_send(so, newmsg, len);
1733        free(newmsg);
1734
1735        if (len < 0)
1736                return -1;
1737
1738        __ipsec_errcode = EIPSEC_NO_ERROR;
1739        return len;
1740}
1741
1742/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
1743static int
1744pfkey_send_x5(int so, u_int type, u_int32_t spid)
1745{
1746        struct sadb_msg *newmsg;
1747        struct sadb_x_policy xpl;
1748        int len;
1749        caddr_t p;
1750        caddr_t ep;
1751
1752        /* create new sadb_msg to reply. */
1753        len = sizeof(struct sadb_msg)
1754                + sizeof(xpl);
1755
1756        if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) {
1757                __ipsec_set_strerror(strerror(errno));
1758                return -1;
1759        }
1760        ep = ((caddr_t)(void *)newmsg) + len;
1761
1762        p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len,
1763            SADB_SATYPE_UNSPEC, 0, getpid());
1764        if (!p) {
1765                free(newmsg);
1766                return -1;
1767        }
1768
1769        if (p + sizeof(xpl) != ep) {
1770                free(newmsg);
1771                return -1;
1772        }
1773        memset(&xpl, 0, sizeof(xpl));
1774        xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
1775        xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
1776        xpl.sadb_x_policy_id = spid;
1777        memcpy(p, &xpl, sizeof(xpl));
1778
1779        /* send message */
1780        len = pfkey_send(so, newmsg, len);
1781        free(newmsg);
1782
1783        if (len < 0)
1784                return -1;
1785
1786        __ipsec_errcode = EIPSEC_NO_ERROR;
1787        return len;
1788}
1789
1790/*
1791 * open a socket.
1792 * OUT:
1793 *      -1: fail.
1794 *      others : success and return value of socket.
1795 */
1796int
1797pfkey_open(void)
1798{
1799        int so;
1800        int bufsiz_current, bufsiz_wanted;
1801        int ret;
1802        socklen_t len;
1803
1804        if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
1805                __ipsec_set_strerror(strerror(errno));
1806                return -1;
1807        }
1808
1809        /*
1810         * This is a temporary workaround for KAME PR 154.
1811         * Don't really care even if it fails.
1812         */
1813        /* Try to have 128k. If we have more, do not lower it. */
1814        bufsiz_wanted = 128 * 1024;
1815        len = sizeof(bufsiz_current);
1816        ret = getsockopt(so, SOL_SOCKET, SO_SNDBUF,
1817                &bufsiz_current, &len);
1818        if ((ret < 0) || (bufsiz_current < bufsiz_wanted))
1819                (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF,
1820                        &bufsiz_wanted, sizeof(bufsiz_wanted));
1821
1822        /* Try to have have at least 2MB. If we have more, do not lower it. */
1823        bufsiz_wanted = 2 * 1024 * 1024;
1824        len = sizeof(bufsiz_current);
1825        ret = getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1826                &bufsiz_current, &len);
1827        if (ret < 0)
1828                bufsiz_current = 128 * 1024;
1829
1830        for (; bufsiz_wanted > bufsiz_current; bufsiz_wanted /= 2) {
1831                if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
1832                                &bufsiz_wanted, sizeof(bufsiz_wanted)) == 0)
1833                        break;
1834        }
1835
1836        __ipsec_errcode = EIPSEC_NO_ERROR;
1837        return so;
1838}
1839
1840int
1841pfkey_set_buffer_size(int so, int size)
1842{
1843        int newsize;
1844        int actual_bufsiz;
1845        socklen_t sizebufsiz;
1846        int desired_bufsiz;
1847
1848        /*
1849         * on linux you may need to allow the kernel to allocate
1850         * more buffer space by increasing:
1851         * /proc/sys/net/core/rmem_max and wmem_max
1852         */
1853        if (size > 0) {
1854                actual_bufsiz = 0;
1855                sizebufsiz = sizeof(actual_bufsiz);
1856                desired_bufsiz = size * 1024;
1857                if ((getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1858                                &actual_bufsiz, &sizebufsiz) < 0)
1859                    || (actual_bufsiz < desired_bufsiz)) {
1860                        if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
1861                                       &desired_bufsiz, sizeof(desired_bufsiz)) < 0) {
1862                                __ipsec_set_strerror(strerror(errno));
1863                                return -1;
1864                        }
1865                }
1866        }
1867
1868        /* return actual buffer size */
1869        actual_bufsiz = 0;
1870        sizebufsiz = sizeof(actual_bufsiz);
1871        getsockopt(so, SOL_SOCKET, SO_RCVBUF,
1872                   &actual_bufsiz, &sizebufsiz);
1873        return actual_bufsiz / 1024;
1874}
1875
1876/*
1877 * close a socket.
1878 * OUT:
1879 *       0: success.
1880 *      -1: fail.
1881 */
1882void
1883pfkey_close(int so)
1884{
1885        (void)close(so);
1886
1887        __ipsec_errcode = EIPSEC_NO_ERROR;
1888        return;
1889}
1890
1891/*
1892 * receive sadb_msg data, and return pointer to new buffer allocated.
1893 * Must free this buffer later.
1894 * OUT:
1895 *      NULL    : error occured.
1896 *      others  : a pointer to sadb_msg structure.
1897 *
1898 * XXX should be rewritten to pass length explicitly
1899 */
1900struct sadb_msg *
1901pfkey_recv(int so)
1902{
1903        struct sadb_msg buf, *newmsg;
1904        int len, reallen;
1905
1906        while ((len = recv(so, (void *)&buf, sizeof(buf), MSG_PEEK)) < 0) {
1907                if (errno == EINTR)
1908                        continue;
1909                __ipsec_set_strerror(strerror(errno));
1910                return NULL;
1911        }
1912
1913        if (len < sizeof(buf)) {
1914                recv(so, (void *)&buf, sizeof(buf), 0);
1915                __ipsec_errcode = EIPSEC_MAX;
1916                return NULL;
1917        }
1918
1919        /* read real message */
1920        reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
1921        if ((newmsg = CALLOC((size_t)reallen, struct sadb_msg *)) == 0) {
1922                __ipsec_set_strerror(strerror(errno));
1923                return NULL;
1924        }
1925
1926        while ((len = recv(so, (void *)newmsg, (socklen_t)reallen, 0)) < 0) {
1927                if (errno == EINTR)
1928                        continue;
1929                __ipsec_set_strerror(strerror(errno));
1930                free(newmsg);
1931                return NULL;
1932        }
1933
1934        if (len != reallen) {
1935                __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1936                free(newmsg);
1937                return NULL;
1938        }
1939
1940        /* don't trust what the kernel says, validate! */
1941        if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
1942                __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
1943                free(newmsg);
1944                return NULL;
1945        }
1946
1947        __ipsec_errcode = EIPSEC_NO_ERROR;
1948        return newmsg;
1949}
1950
1951/*
1952 * send message to a socket.
1953 * OUT:
1954 *       others: success and return length sent.
1955 *      -1     : fail.
1956 */
1957int
1958pfkey_send(int so, struct sadb_msg *msg, int len)
1959{
1960        if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) {
1961                __ipsec_set_strerror(strerror(errno));
1962                return -1;
1963        }
1964
1965        __ipsec_errcode = EIPSEC_NO_ERROR;
1966        return len;
1967}
1968
1969/*
1970 * %%% Utilities
1971 * NOTE: These functions are derived from netkey/key.c in KAME.
1972 */
1973/*
1974 * set the pointer to each header in this message buffer.
1975 * IN:  msg: pointer to message buffer.
1976 *      mhp: pointer to the buffer initialized like below:
1977 *              caddr_t mhp[SADB_EXT_MAX + 1];
1978 * OUT: -1: invalid.
1979 *       0: valid.
1980 *
1981 * XXX should be rewritten to obtain length explicitly
1982 */
1983int
1984pfkey_align(struct sadb_msg *msg, caddr_t *mhp)
1985{
1986        struct sadb_ext *ext;
1987        int i;
1988        caddr_t p;
1989        caddr_t ep;     /* XXX should be passed from upper layer */
1990
1991        /* validity check */
1992        if (msg == NULL || mhp == NULL) {
1993                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
1994                return -1;
1995        }
1996
1997        /* initialize */
1998        for (i = 0; i < SADB_EXT_MAX + 1; i++)
1999                mhp[i] = NULL;
2000
2001        mhp[0] = (void *)msg;
2002
2003        /* initialize */
2004        p = (void *) msg;
2005        ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
2006
2007        /* skip base header */
2008        p += sizeof(struct sadb_msg);
2009
2010        while (p < ep) {
2011                ext = (void *)p;
2012                if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
2013                    ep < p + PFKEY_EXTLEN(ext)) {
2014                        /* invalid format */
2015                        break;
2016                }
2017
2018                /* duplicate check */
2019                /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
2020                if (mhp[ext->sadb_ext_type] != NULL) {
2021                        __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
2022                        return -1;
2023                }
2024
2025                /* set pointer */
2026                switch (ext->sadb_ext_type) {
2027                case SADB_EXT_SA:
2028                case SADB_EXT_LIFETIME_CURRENT:
2029                case SADB_EXT_LIFETIME_HARD:
2030                case SADB_EXT_LIFETIME_SOFT:
2031                case SADB_EXT_ADDRESS_SRC:
2032                case SADB_EXT_ADDRESS_DST:
2033                case SADB_EXT_ADDRESS_PROXY:
2034                case SADB_EXT_KEY_AUTH:
2035                        /* XXX should to be check weak keys. */
2036                case SADB_EXT_KEY_ENCRYPT:
2037                        /* XXX should to be check weak keys. */
2038                case SADB_EXT_IDENTITY_SRC:
2039                case SADB_EXT_IDENTITY_DST:
2040                case SADB_EXT_SENSITIVITY:
2041                case SADB_EXT_PROPOSAL:
2042                case SADB_EXT_SUPPORTED_AUTH:
2043                case SADB_EXT_SUPPORTED_ENCRYPT:
2044                case SADB_EXT_SPIRANGE:
2045                case SADB_X_EXT_POLICY:
2046                case SADB_X_EXT_SA2:
2047#ifdef SADB_X_EXT_NAT_T_TYPE
2048                case SADB_X_EXT_NAT_T_TYPE:
2049                case SADB_X_EXT_NAT_T_SPORT:
2050                case SADB_X_EXT_NAT_T_DPORT:
2051                case SADB_X_EXT_NAT_T_OAI:
2052                case SADB_X_EXT_NAT_T_OAR:
2053#endif
2054#ifdef SADB_X_EXT_TAG
2055                case SADB_X_EXT_TAG:
2056#endif
2057#ifdef SADB_X_EXT_PACKET
2058                case SADB_X_EXT_PACKET:
2059#endif
2060#ifdef SADB_X_EXT_KMADDRESS
2061                case SADB_X_EXT_KMADDRESS:
2062#endif
2063#ifdef SADB_X_EXT_SEC_CTX
2064                case SADB_X_EXT_SEC_CTX:
2065#endif
2066                        mhp[ext->sadb_ext_type] = (void *)ext;
2067                        break;
2068                default:
2069                        __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
2070                        return -1;
2071                }
2072
2073                p += PFKEY_EXTLEN(ext);
2074        }
2075
2076        if (p != ep) {
2077                __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
2078                return -1;
2079        }
2080
2081        __ipsec_errcode = EIPSEC_NO_ERROR;
2082        return 0;
2083}
2084
2085/*
2086 * check basic usage for sadb_msg,
2087 * NOTE: This routine is derived from netkey/key.c in KAME.
2088 * IN:  msg: pointer to message buffer.
2089 *      mhp: pointer to the buffer initialized like below:
2090 *
2091 *              caddr_t mhp[SADB_EXT_MAX + 1];
2092 *
2093 * OUT: -1: invalid.
2094 *       0: valid.
2095 */
2096int
2097pfkey_check(caddr_t *mhp)
2098{
2099        struct sadb_msg *msg;
2100
2101        /* validity check */
2102        if (mhp == NULL || mhp[0] == NULL) {
2103                __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
2104                return -1;
2105        }
2106
2107        msg = (void *)mhp[0];
2108
2109        /* check version */
2110        if (msg->sadb_msg_version != PF_KEY_V2) {
2111                __ipsec_errcode = EIPSEC_INVAL_VERSION;
2112                return -1;
2113        }
2114
2115        /* check type */
2116        if (msg->sadb_msg_type > SADB_MAX) {
2117                __ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
2118                return -1;
2119        }
2120
2121        /* check SA type */
2122        switch (msg->sadb_msg_satype) {
2123        case SADB_SATYPE_UNSPEC:
2124                switch (msg->sadb_msg_type) {
2125                case SADB_GETSPI:
2126                case SADB_UPDATE:
2127                case SADB_ADD:
2128                case SADB_DELETE:
2129                case SADB_GET:
2130                case SADB_ACQUIRE:
2131                case SADB_EXPIRE:
2132#ifdef SADB_X_NAT_T_NEW_MAPPING
2133                case SADB_X_NAT_T_NEW_MAPPING:
2134#endif
2135                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2136                        return -1;
2137                }
2138                break;
2139        case SADB_SATYPE_ESP:
2140        case SADB_SATYPE_AH:
2141        case SADB_X_SATYPE_IPCOMP:
2142#ifdef SADB_X_SATYPE_TCPSIGNATURE
2143        case SADB_X_SATYPE_TCPSIGNATURE:
2144#endif
2145                switch (msg->sadb_msg_type) {
2146                case SADB_X_SPDADD:
2147                case SADB_X_SPDDELETE:
2148                case SADB_X_SPDGET:
2149                case SADB_X_SPDDUMP:
2150                case SADB_X_SPDFLUSH:
2151                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2152                        return -1;
2153                }
2154#ifdef SADB_X_NAT_T_NEW_MAPPING
2155                if (msg->sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING &&
2156                    msg->sadb_msg_satype != SADB_SATYPE_ESP) {
2157                        __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2158                        return -1;
2159                }
2160#endif
2161                break;
2162        case SADB_SATYPE_RSVP:
2163        case SADB_SATYPE_OSPFV2:
2164        case SADB_SATYPE_RIPV2:
2165        case SADB_SATYPE_MIP:
2166                __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
2167                return -1;
2168        case 1: /* XXX: What does it do ? */
2169                if (msg->sadb_msg_type == SADB_X_PROMISC)
2170                        break;
2171                /*FALLTHROUGH*/
2172        default:
2173#ifdef __linux__
2174                /* Linux kernel seems to be buggy and return
2175                 * uninitialized satype for spd flush message */
2176                if (msg->sadb_msg_type == SADB_X_SPDFLUSH)
2177                        break;
2178#endif
2179                __ipsec_errcode = EIPSEC_INVAL_SATYPE;
2180                return -1;
2181        }
2182
2183        /* check field of upper layer protocol and address family */
2184        if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
2185         && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
2186                struct sadb_address *src0, *dst0;
2187
2188                src0 = (void *)(mhp[SADB_EXT_ADDRESS_SRC]);
2189                dst0 = (void *)(mhp[SADB_EXT_ADDRESS_DST]);
2190
2191                if (src0->sadb_address_proto != dst0->sadb_address_proto) {
2192                        __ipsec_errcode = EIPSEC_PROTO_MISMATCH;
2193                        return -1;
2194                }
2195
2196                if (PFKEY_ADDR_SADDR(src0)->sa_family
2197                 != PFKEY_ADDR_SADDR(dst0)->sa_family) {
2198                        __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
2199                        return -1;
2200                }
2201
2202                switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
2203                case AF_INET:
2204                case AF_INET6:
2205                        break;
2206                default:
2207                        __ipsec_errcode = EIPSEC_INVAL_FAMILY;
2208                        return -1;
2209                }
2210
2211                /*
2212                 * prefixlen == 0 is valid because there must be the case
2213                 * all addresses are matched.
2214                 */
2215        }
2216
2217        __ipsec_errcode = EIPSEC_NO_ERROR;
2218        return 0;
2219}
2220
2221/*
2222 * set data into sadb_msg.
2223 * `buf' must has been allocated sufficiently.
2224 */
2225static caddr_t
2226pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen,
2227    u_int satype, u_int32_t seq, pid_t pid)
2228{
2229        struct sadb_msg *p;
2230        u_int len;
2231
2232        p = (void *)buf;
2233        len = sizeof(struct sadb_msg);
2234
2235        if (buf + len > lim)
2236                return NULL;
2237
2238        memset(p, 0, len);
2239        p->sadb_msg_version = PF_KEY_V2;
2240        p->sadb_msg_type = type;
2241        p->sadb_msg_errno = 0;
2242        p->sadb_msg_satype = satype;
2243        p->sadb_msg_len = PFKEY_UNIT64(tlen);
2244        p->sadb_msg_reserved = 0;
2245        p->sadb_msg_seq = seq;
2246        p->sadb_msg_pid = (u_int32_t)pid;
2247
2248        return(buf + len);
2249}
2250
2251/*
2252 * copy secasvar data into sadb_address.
2253 * `buf' must has been allocated sufficiently.
2254 */
2255static caddr_t
2256pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize,
2257    u_int auth, u_int enc, u_int32_t flags)
2258{
2259        struct sadb_sa *p;
2260        u_int len;
2261
2262        p = (void *)buf;
2263        len = sizeof(struct sadb_sa);
2264
2265        if (buf + len > lim)
2266                return NULL;
2267
2268        memset(p, 0, len);
2269        p->sadb_sa_len = PFKEY_UNIT64(len);
2270        p->sadb_sa_exttype = SADB_EXT_SA;
2271        p->sadb_sa_spi = spi;
2272        p->sadb_sa_replay = wsize;
2273        p->sadb_sa_state = SADB_SASTATE_LARVAL;
2274        p->sadb_sa_auth = auth;
2275        p->sadb_sa_encrypt = enc;
2276        p->sadb_sa_flags = flags;
2277
2278        return(buf + len);
2279}
2280
2281/*
2282 * set data into sadb_address.
2283 * `buf' must has been allocated sufficiently.
2284 * prefixlen is in bits.
2285 */
2286static caddr_t
2287pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype,
2288    struct sockaddr *saddr, u_int prefixlen, u_int ul_proto)
2289{
2290        struct sadb_address *p;
2291        u_int len;
2292
2293        p = (void *)buf;
2294        len = sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(saddr));
2295
2296        if (buf + len > lim)
2297                return NULL;
2298
2299        memset(p, 0, len);
2300        p->sadb_address_len = PFKEY_UNIT64(len);
2301        p->sadb_address_exttype = exttype & 0xffff;
2302        p->sadb_address_proto = ul_proto & 0xff;
2303        p->sadb_address_prefixlen = prefixlen;
2304        p->sadb_address_reserved = 0;
2305
2306        memcpy(p + 1, saddr, (size_t)sysdep_sa_len(saddr));
2307
2308        return(buf + len);
2309}
2310
2311#ifdef SADB_X_EXT_KMADDRESS
2312/*
2313 * set data into sadb_x_kmaddress.
2314 * `buf' must has been allocated sufficiently.
2315 */
2316static caddr_t
2317pfkey_setsadbkmaddr(caddr_t buf, caddr_t lim, struct sockaddr *local,
2318    struct sockaddr *remote)
2319{
2320        struct sadb_x_kmaddress *p;
2321        struct sockaddr *sa;
2322        u_int salen = sysdep_sa_len(local);
2323        u_int len;
2324
2325        /* sanity check */
2326        if (local->sa_family != remote->sa_family)
2327                return NULL;
2328
2329        p = (void *)buf;
2330        len = sizeof(struct sadb_x_kmaddress) + PFKEY_ALIGN8(2*salen);
2331
2332        if (buf + len > lim)
2333                return NULL;
2334
2335        memset(p, 0, len);
2336        p->sadb_x_kmaddress_len = PFKEY_UNIT64(len);
2337        p->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS;
2338        p->sadb_x_kmaddress_reserved = 0;
2339        sa = (struct sockaddr *)(p + 1);
2340        memcpy(sa, local, salen);
2341        sa = (struct sockaddr *)((char *)sa + salen);
2342        memcpy(sa, remote, salen);
2343
2344        return(buf + len);
2345}
2346#endif
2347
2348/*
2349 * set sadb_key structure after clearing buffer with zero.
2350 * OUT: the pointer of buf + len.
2351 */
2352static caddr_t
2353pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key,
2354    u_int keylen)
2355{
2356        struct sadb_key *p;
2357        u_int len;
2358
2359        p = (void *)buf;
2360        len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
2361
2362        if (buf + len > lim)
2363                return NULL;
2364
2365        memset(p, 0, len);
2366        p->sadb_key_len = PFKEY_UNIT64(len);
2367        p->sadb_key_exttype = type;
2368        p->sadb_key_bits = keylen << 3;
2369        p->sadb_key_reserved = 0;
2370
2371        memcpy(p + 1, key, keylen);
2372
2373        return buf + len;
2374}
2375
2376/*
2377 * set sadb_lifetime structure after clearing buffer with zero.
2378 * OUT: the pointer of buf + len.
2379 */
2380static caddr_t
2381pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc,
2382    u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime)
2383{
2384        struct sadb_lifetime *p;
2385        u_int len;
2386
2387        p = (void *)buf;
2388        len = sizeof(struct sadb_lifetime);
2389
2390        if (buf + len > lim)
2391                return NULL;
2392
2393        memset(p, 0, len);
2394        p->sadb_lifetime_len = PFKEY_UNIT64(len);
2395        p->sadb_lifetime_exttype = type;
2396
2397        switch (type) {
2398        case SADB_EXT_LIFETIME_SOFT:
2399                p->sadb_lifetime_allocations
2400                        = (l_alloc * soft_lifetime_allocations_rate) /100;
2401                p->sadb_lifetime_bytes
2402                        = (l_bytes * soft_lifetime_bytes_rate) /100;
2403                p->sadb_lifetime_addtime
2404                        = (l_addtime * soft_lifetime_addtime_rate) /100;
2405                p->sadb_lifetime_usetime
2406                        = (l_usetime * soft_lifetime_usetime_rate) /100;
2407                break;
2408        case SADB_EXT_LIFETIME_HARD:
2409                p->sadb_lifetime_allocations = l_alloc;
2410                p->sadb_lifetime_bytes = l_bytes;
2411                p->sadb_lifetime_addtime = l_addtime;
2412                p->sadb_lifetime_usetime = l_usetime;
2413                break;
2414        }
2415
2416        return buf + len;
2417}
2418
2419/*
2420 * copy secasvar data into sadb_address.
2421 * `buf' must has been allocated sufficiently.
2422 */
2423static caddr_t
2424pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid)
2425{
2426        struct sadb_x_sa2 *p;
2427        u_int8_t mode = mode0 & 0xff;
2428        u_int len;
2429
2430        p = (void *)buf;
2431        len = sizeof(struct sadb_x_sa2);
2432
2433        if (buf + len > lim)
2434                return NULL;
2435
2436        memset(p, 0, len);
2437        p->sadb_x_sa2_len = PFKEY_UNIT64(len);
2438        p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
2439        p->sadb_x_sa2_mode = mode;
2440        p->sadb_x_sa2_reqid = reqid;
2441
2442        return(buf + len);
2443}
2444
2445#ifdef SADB_X_EXT_NAT_T_TYPE
2446static caddr_t
2447pfkey_set_natt_type(caddr_t buf, caddr_t lim, u_int type, u_int8_t l_natt_type)
2448{
2449        struct sadb_x_nat_t_type *p;
2450        u_int len;
2451
2452        p = (void *)buf;
2453        len = sizeof(struct sadb_x_nat_t_type);
2454
2455        if (buf + len > lim)
2456                return NULL;
2457
2458        memset(p, 0, len);
2459        p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
2460        p->sadb_x_nat_t_type_exttype = type;
2461        p->sadb_x_nat_t_type_type = l_natt_type;
2462
2463        return(buf + len);
2464}
2465
2466static caddr_t
2467pfkey_set_natt_port(caddr_t buf, caddr_t lim, u_int type, u_int16_t l_natt_port)
2468{
2469        struct sadb_x_nat_t_port *p;
2470        u_int len;
2471
2472        p = (void *)buf;
2473        len = sizeof(struct sadb_x_nat_t_port);
2474
2475        if (buf + len > lim)
2476                return NULL;
2477
2478        memset(p, 0, len);
2479        p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
2480        p->sadb_x_nat_t_port_exttype = type;
2481        p->sadb_x_nat_t_port_port = htons(l_natt_port);
2482
2483        return(buf + len);
2484}
2485#endif
2486
2487#ifdef SADB_X_EXT_NAT_T_FRAG
2488static caddr_t
2489pfkey_set_natt_frag(caddr_t buf, caddr_t lim, u_int type, 
2490    u_int16_t l_natt_frag)
2491{
2492        struct sadb_x_nat_t_frag *p;
2493        u_int len;
2494
2495        p = (void *)buf;
2496        len = sizeof(struct sadb_x_nat_t_frag);
2497
2498        if (buf + len > lim)
2499                return NULL;
2500
2501        memset(p, 0, len);
2502        p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
2503        p->sadb_x_nat_t_frag_exttype = type;
2504        p->sadb_x_nat_t_frag_fraglen = l_natt_frag;
2505
2506        return(buf + len);
2507}
2508#endif
2509
2510#ifdef SADB_X_EXT_SEC_CTX
2511static caddr_t
2512pfkey_setsecctx(caddr_t buf, caddr_t lim, u_int type, u_int8_t ctx_doi,
2513    u_int8_t ctx_alg, caddr_t sec_ctx, u_int16_t sec_ctxlen)
2514{
2515        struct sadb_x_sec_ctx *p;
2516        u_int len;
2517
2518        p = (struct sadb_x_sec_ctx *)buf;
2519        len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen);
2520
2521        if (buf + len > lim)
2522                return NULL;
2523
2524        memset(p, 0, len);
2525        p->sadb_x_sec_len = PFKEY_UNIT64(len);
2526        p->sadb_x_sec_exttype = type;
2527        p->sadb_x_ctx_len = sec_ctxlen;
2528        p->sadb_x_ctx_doi = ctx_doi;
2529        p->sadb_x_ctx_alg = ctx_alg;
2530
2531        memcpy(p + 1, sec_ctx, sec_ctxlen);
2532
2533        return buf + len;
2534}
2535#endif
2536
2537/*
2538 * Deprecated, available for backward compatibility with third party
2539 * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead
2540 */
2541int
2542pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src,
2543    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2544    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2545    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2546    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
2547{
2548        struct pfkey_send_sa_args psaa;
2549
2550        memset(&psaa, 0, sizeof(psaa));
2551        psaa.so = so;
2552        psaa.type = SADB_UPDATE;
2553        psaa.satype = satype;
2554        psaa.mode = mode;
2555        psaa.wsize = wsize;
2556        psaa.src = src;
2557        psaa.dst = dst;
2558        psaa.spi = spi;
2559        psaa.reqid = reqid;
2560        psaa.keymat = keymat;
2561        psaa.e_type = e_type;
2562        psaa.e_keylen = e_keylen;
2563        psaa.a_type = a_type;
2564        psaa.a_keylen = a_keylen;
2565        psaa.flags = flags;
2566        psaa.l_alloc = l_alloc;
2567        psaa.l_bytes = l_bytes;
2568        psaa.l_addtime = l_addtime;
2569        psaa.l_usetime = l_usetime;
2570        psaa.seq = seq;
2571
2572        return pfkey_send_update2(&psaa);
2573}
2574
2575int
2576pfkey_send_update_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
2577    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2578    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2579    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2580    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
2581    u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
2582    struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
2583{
2584        struct pfkey_send_sa_args psaa;
2585
2586        memset(&psaa, 0, sizeof(psaa));
2587        psaa.so = so;
2588        psaa.type = SADB_UPDATE;
2589        psaa.satype = satype;
2590        psaa.mode = mode;
2591        psaa.wsize = wsize;
2592        psaa.src = src;
2593        psaa.dst = dst;
2594        psaa.spi = spi;
2595        psaa.reqid = reqid;
2596        psaa.keymat = keymat;
2597        psaa.e_type = e_type;
2598        psaa.e_keylen = e_keylen;
2599        psaa.a_type = a_type;
2600        psaa.a_keylen = a_keylen;
2601        psaa.flags = flags;
2602        psaa.l_alloc = l_alloc;
2603        psaa.l_bytes = l_bytes;
2604        psaa.l_addtime = l_addtime;
2605        psaa.l_usetime = l_usetime;
2606        psaa.seq = seq;
2607        psaa.l_natt_type = l_natt_type;
2608        psaa.l_natt_sport = l_natt_sport;
2609        psaa.l_natt_dport = l_natt_dport;
2610        psaa.l_natt_oar = l_natt_oa;
2611        psaa.l_natt_frag = l_natt_frag;
2612
2613        return pfkey_send_update2(&psaa);
2614}
2615
2616int
2617pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src,
2618    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2619    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2620    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2621    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq)
2622{
2623        struct pfkey_send_sa_args psaa;
2624
2625        memset(&psaa, 0, sizeof(psaa));
2626        psaa.so = so;
2627        psaa.type = SADB_ADD;
2628        psaa.satype = satype;
2629        psaa.mode = mode;
2630        psaa.wsize = wsize;
2631        psaa.src = src;
2632        psaa.dst = dst;
2633        psaa.spi = spi;
2634        psaa.reqid = reqid;
2635        psaa.keymat = keymat;
2636        psaa.e_type = e_type;
2637        psaa.e_keylen = e_keylen;
2638        psaa.a_type = a_type;
2639        psaa.a_keylen = a_keylen;
2640        psaa.flags = flags;
2641        psaa.l_alloc = l_alloc;
2642        psaa.l_bytes = l_bytes;
2643        psaa.l_addtime = l_addtime;
2644        psaa.l_usetime = l_usetime;
2645        psaa.seq = seq;
2646
2647        return pfkey_send_add2(&psaa);
2648}
2649
2650int
2651pfkey_send_add_nat(int so, u_int satype, u_int mode, struct sockaddr *src,
2652    struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize,
2653    caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type,
2654    u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes,
2655    u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq,
2656    u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport,
2657    struct sockaddr *l_natt_oa, u_int16_t l_natt_frag)
2658{
2659        struct pfkey_send_sa_args psaa;
2660
2661        memset(&psaa, 0, sizeof(psaa));
2662        psaa.so = so;
2663        psaa.type = SADB_ADD;
2664        psaa.satype = satype;
2665        psaa.mode = mode;
2666        psaa.wsize = wsize;
2667        psaa.src = src;
2668        psaa.dst = dst;
2669        psaa.spi = spi;
2670        psaa.reqid = reqid;
2671        psaa.keymat = keymat;
2672        psaa.e_type = e_type;
2673        psaa.e_keylen = e_keylen;
2674        psaa.a_type = a_type;
2675        psaa.a_keylen = a_keylen;
2676        psaa.flags = flags;
2677        psaa.l_alloc = l_alloc;
2678        psaa.l_bytes = l_bytes;
2679        psaa.l_addtime = l_addtime;
2680        psaa.l_usetime = l_usetime;
2681        psaa.seq = seq;
2682        psaa.l_natt_type = l_natt_type;
2683        psaa.l_natt_sport = l_natt_sport;
2684        psaa.l_natt_dport = l_natt_dport;
2685        psaa.l_natt_oai = l_natt_oa;
2686        psaa.l_natt_frag = l_natt_frag;
2687
2688        return pfkey_send_add2(&psaa);
2689}
Note: See TracBrowser for help on using the repository browser.