OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [ipsec/] [libipsec/] [current/] [src/] [pfkey.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.