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