1bd9f52d5SHajimu UMEMOTO /* $KAME: pfkey.c,v 1.46 2003/08/26 03:37:06 itojun Exp $ */ 23c62e87aSJun-ichiro itojun Hagino 38a16b7a1SPedro F. Giffuni /*- 48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 58a16b7a1SPedro F. Giffuni * 69a4365d0SYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 79a4365d0SYoshinobu Inoue * All rights reserved. 89a4365d0SYoshinobu Inoue * 99a4365d0SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 109a4365d0SYoshinobu Inoue * modification, are permitted provided that the following conditions 119a4365d0SYoshinobu Inoue * are met: 129a4365d0SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 139a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 149a4365d0SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 159a4365d0SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 169a4365d0SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 179a4365d0SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 189a4365d0SYoshinobu Inoue * may be used to endorse or promote products derived from this software 199a4365d0SYoshinobu Inoue * without specific prior written permission. 209a4365d0SYoshinobu Inoue * 219a4365d0SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 229a4365d0SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 239a4365d0SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 249a4365d0SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 259a4365d0SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 269a4365d0SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 279a4365d0SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 289a4365d0SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 299a4365d0SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 309a4365d0SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 319a4365d0SYoshinobu Inoue * SUCH DAMAGE. 329a4365d0SYoshinobu Inoue */ 339a4365d0SYoshinobu Inoue 349a4365d0SYoshinobu Inoue #include <sys/types.h> 359a4365d0SYoshinobu Inoue #include <sys/param.h> 369a4365d0SYoshinobu Inoue #include <sys/socket.h> 379a4365d0SYoshinobu Inoue #include <net/pfkeyv2.h> 388409aedfSGeorge V. Neville-Neil #include <netipsec/key_var.h> 399a4365d0SYoshinobu Inoue #include <netinet/in.h> 408409aedfSGeorge V. Neville-Neil #include <netipsec/ipsec.h> 419a4365d0SYoshinobu Inoue 429a4365d0SYoshinobu Inoue #include <stdlib.h> 434e0e8f31SAndrey V. Elsukov #include <stdint.h> 449a4365d0SYoshinobu Inoue #include <unistd.h> 459a4365d0SYoshinobu Inoue #include <string.h> 469a4365d0SYoshinobu Inoue #include <errno.h> 479a4365d0SYoshinobu Inoue 489a4365d0SYoshinobu Inoue #include "ipsec_strerror.h" 493c62e87aSJun-ichiro itojun Hagino #include "libpfkey.h" 509a4365d0SYoshinobu Inoue 519a4365d0SYoshinobu Inoue #define CALLOC(size, cast) (cast)calloc(1, (size)) 529a4365d0SYoshinobu Inoue 5369160b1eSDavid E. O'Brien static int findsupportedmap(int); 5469160b1eSDavid E. O'Brien static int setsupportedmap(struct sadb_supported *); 5569160b1eSDavid E. O'Brien static struct sadb_alg *findsupportedalg(u_int, u_int); 561372519bSDavid E. O'Brien static int pfkey_send_x1(int, u_int, u_int, u_int, struct sockaddr *, 573c62e87aSJun-ichiro itojun Hagino struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t, 583c62e87aSJun-ichiro itojun Hagino u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t, 591372519bSDavid E. O'Brien u_int32_t, u_int32_t, u_int32_t); 601372519bSDavid E. O'Brien static int pfkey_send_x2(int, u_int, u_int, u_int, 611372519bSDavid E. O'Brien struct sockaddr *, struct sockaddr *, u_int32_t); 6269160b1eSDavid E. O'Brien static int pfkey_send_x3(int, u_int, u_int); 631372519bSDavid E. O'Brien static int pfkey_send_x4(int, u_int, struct sockaddr *, u_int, 6433841545SHajimu UMEMOTO struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, 651372519bSDavid E. O'Brien char *, int, u_int32_t); 6669160b1eSDavid E. O'Brien static int pfkey_send_x5(int, u_int, u_int32_t); 679a4365d0SYoshinobu Inoue 681372519bSDavid E. O'Brien static caddr_t pfkey_setsadbmsg(caddr_t, caddr_t, u_int, u_int, 691372519bSDavid E. O'Brien u_int, u_int32_t, pid_t); 701372519bSDavid E. O'Brien static caddr_t pfkey_setsadbsa(caddr_t, caddr_t, u_int32_t, u_int, 711372519bSDavid E. O'Brien u_int, u_int, u_int32_t); 724e0e8f31SAndrey V. Elsukov static caddr_t pfkey_setsadbxreplay(caddr_t, caddr_t, uint32_t); 731372519bSDavid E. O'Brien static caddr_t pfkey_setsadbaddr(caddr_t, caddr_t, u_int, 741372519bSDavid E. O'Brien struct sockaddr *, u_int, u_int); 7569160b1eSDavid E. O'Brien static caddr_t pfkey_setsadbkey(caddr_t, caddr_t, u_int, caddr_t, u_int); 761372519bSDavid E. O'Brien static caddr_t pfkey_setsadblifetime(caddr_t, caddr_t, u_int, u_int32_t, 771372519bSDavid E. O'Brien u_int32_t, u_int32_t, u_int32_t); 7869160b1eSDavid E. O'Brien static caddr_t pfkey_setsadbxsa2(caddr_t, caddr_t, u_int32_t, u_int32_t); 7933841545SHajimu UMEMOTO 8033841545SHajimu UMEMOTO /* 8133841545SHajimu UMEMOTO * make and search supported algorithm structure. 8233841545SHajimu UMEMOTO */ 831922fd12SBruce M Simpson static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, NULL }; 8433841545SHajimu UMEMOTO 8533841545SHajimu UMEMOTO static int supported_map[] = { 8633841545SHajimu UMEMOTO SADB_SATYPE_AH, 8733841545SHajimu UMEMOTO SADB_SATYPE_ESP, 8833841545SHajimu UMEMOTO SADB_X_SATYPE_IPCOMP, 891922fd12SBruce M Simpson SADB_X_SATYPE_TCPSIGNATURE 9033841545SHajimu UMEMOTO }; 9133841545SHajimu UMEMOTO 9233841545SHajimu UMEMOTO static int 93650d6cc1SKonstantin Belousov findsupportedmap(int satype) 9433841545SHajimu UMEMOTO { 9533841545SHajimu UMEMOTO int i; 9633841545SHajimu UMEMOTO 9733841545SHajimu UMEMOTO for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++) 9833841545SHajimu UMEMOTO if (supported_map[i] == satype) 9933841545SHajimu UMEMOTO return i; 10033841545SHajimu UMEMOTO return -1; 10133841545SHajimu UMEMOTO } 10233841545SHajimu UMEMOTO 10333841545SHajimu UMEMOTO static struct sadb_alg * 104650d6cc1SKonstantin Belousov findsupportedalg(u_int satype, u_int alg_id) 10533841545SHajimu UMEMOTO { 10633841545SHajimu UMEMOTO int algno; 10733841545SHajimu UMEMOTO int tlen; 10833841545SHajimu UMEMOTO caddr_t p; 10933841545SHajimu UMEMOTO 11033841545SHajimu UMEMOTO /* validity check */ 11133841545SHajimu UMEMOTO algno = findsupportedmap(satype); 11233841545SHajimu UMEMOTO if (algno == -1) { 11333841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 11433841545SHajimu UMEMOTO return NULL; 11533841545SHajimu UMEMOTO } 11633841545SHajimu UMEMOTO if (ipsec_supported[algno] == NULL) { 11733841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; 11833841545SHajimu UMEMOTO return NULL; 11933841545SHajimu UMEMOTO } 12033841545SHajimu UMEMOTO 12133841545SHajimu UMEMOTO tlen = ipsec_supported[algno]->sadb_supported_len 12233841545SHajimu UMEMOTO - sizeof(struct sadb_supported); 12333841545SHajimu UMEMOTO p = (caddr_t)(ipsec_supported[algno] + 1); 12433841545SHajimu UMEMOTO while (tlen > 0) { 12533841545SHajimu UMEMOTO if (tlen < sizeof(struct sadb_alg)) { 12633841545SHajimu UMEMOTO /* invalid format */ 12733841545SHajimu UMEMOTO break; 12833841545SHajimu UMEMOTO } 12933841545SHajimu UMEMOTO if (((struct sadb_alg *)p)->sadb_alg_id == alg_id) 13033841545SHajimu UMEMOTO return (struct sadb_alg *)p; 13133841545SHajimu UMEMOTO 13233841545SHajimu UMEMOTO tlen -= sizeof(struct sadb_alg); 13333841545SHajimu UMEMOTO p += sizeof(struct sadb_alg); 13433841545SHajimu UMEMOTO } 13533841545SHajimu UMEMOTO 13633841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_NOT_SUPPORTED; 13733841545SHajimu UMEMOTO return NULL; 13833841545SHajimu UMEMOTO } 13933841545SHajimu UMEMOTO 14033841545SHajimu UMEMOTO static int 141650d6cc1SKonstantin Belousov setsupportedmap(struct sadb_supported *sup) 14233841545SHajimu UMEMOTO { 14333841545SHajimu UMEMOTO struct sadb_supported **ipsup; 14433841545SHajimu UMEMOTO 14533841545SHajimu UMEMOTO switch (sup->sadb_supported_exttype) { 14633841545SHajimu UMEMOTO case SADB_EXT_SUPPORTED_AUTH: 14733841545SHajimu UMEMOTO ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)]; 14833841545SHajimu UMEMOTO break; 14933841545SHajimu UMEMOTO case SADB_EXT_SUPPORTED_ENCRYPT: 15033841545SHajimu UMEMOTO ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)]; 15133841545SHajimu UMEMOTO break; 15233841545SHajimu UMEMOTO default: 15333841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_SATYPE; 15433841545SHajimu UMEMOTO return -1; 15533841545SHajimu UMEMOTO } 15633841545SHajimu UMEMOTO 15733841545SHajimu UMEMOTO if (*ipsup) 15833841545SHajimu UMEMOTO free(*ipsup); 15933841545SHajimu UMEMOTO 16033841545SHajimu UMEMOTO *ipsup = malloc(sup->sadb_supported_len); 16133841545SHajimu UMEMOTO if (!*ipsup) { 16233841545SHajimu UMEMOTO __ipsec_set_strerror(strerror(errno)); 16333841545SHajimu UMEMOTO return -1; 16433841545SHajimu UMEMOTO } 16533841545SHajimu UMEMOTO memcpy(*ipsup, sup, sup->sadb_supported_len); 16633841545SHajimu UMEMOTO 16733841545SHajimu UMEMOTO return 0; 16833841545SHajimu UMEMOTO } 1699a4365d0SYoshinobu Inoue 1709a4365d0SYoshinobu Inoue /* 1719a4365d0SYoshinobu Inoue * check key length against algorithm specified. 17233841545SHajimu UMEMOTO * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the 17333841545SHajimu UMEMOTO * augument, and only calls to ipsec_check_keylen2(); 1749a4365d0SYoshinobu Inoue * keylen is the unit of bit. 1759a4365d0SYoshinobu Inoue * OUT: 1769a4365d0SYoshinobu Inoue * -1: invalid. 1779a4365d0SYoshinobu Inoue * 0: valid. 1789a4365d0SYoshinobu Inoue */ 1799a4365d0SYoshinobu Inoue int 180650d6cc1SKonstantin Belousov ipsec_check_keylen(u_int supported, u_int alg_id, u_int keylen) 1819a4365d0SYoshinobu Inoue { 18233841545SHajimu UMEMOTO int satype; 1839a4365d0SYoshinobu Inoue 1849a4365d0SYoshinobu Inoue /* validity check */ 1859a4365d0SYoshinobu Inoue switch (supported) { 1869a4365d0SYoshinobu Inoue case SADB_EXT_SUPPORTED_AUTH: 18733841545SHajimu UMEMOTO satype = SADB_SATYPE_AH; 18833841545SHajimu UMEMOTO break; 1899a4365d0SYoshinobu Inoue case SADB_EXT_SUPPORTED_ENCRYPT: 19033841545SHajimu UMEMOTO satype = SADB_SATYPE_ESP; 1919a4365d0SYoshinobu Inoue break; 1929a4365d0SYoshinobu Inoue default: 1933c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 1949a4365d0SYoshinobu Inoue return -1; 1959a4365d0SYoshinobu Inoue } 1969a4365d0SYoshinobu Inoue 19733841545SHajimu UMEMOTO return ipsec_check_keylen2(satype, alg_id, keylen); 19833841545SHajimu UMEMOTO } 1999a4365d0SYoshinobu Inoue 20033841545SHajimu UMEMOTO /* 20133841545SHajimu UMEMOTO * check key length against algorithm specified. 20233841545SHajimu UMEMOTO * satype is one of satype defined at pfkeyv2.h. 20333841545SHajimu UMEMOTO * keylen is the unit of bit. 20433841545SHajimu UMEMOTO * OUT: 20533841545SHajimu UMEMOTO * -1: invalid. 20633841545SHajimu UMEMOTO * 0: valid. 20733841545SHajimu UMEMOTO */ 20833841545SHajimu UMEMOTO int 209650d6cc1SKonstantin Belousov ipsec_check_keylen2(u_int satype, u_int alg_id, u_int keylen) 2109a4365d0SYoshinobu Inoue { 21133841545SHajimu UMEMOTO struct sadb_alg *alg; 2129a4365d0SYoshinobu Inoue 21333841545SHajimu UMEMOTO alg = findsupportedalg(satype, alg_id); 21433841545SHajimu UMEMOTO if (!alg) 2159a4365d0SYoshinobu Inoue return -1; 2169a4365d0SYoshinobu Inoue 21733841545SHajimu UMEMOTO if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) { 2183c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_KEYLEN; 2199a4365d0SYoshinobu Inoue return -1; 2209a4365d0SYoshinobu Inoue } 2219a4365d0SYoshinobu Inoue 2223c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 2239a4365d0SYoshinobu Inoue return 0; 2249a4365d0SYoshinobu Inoue } 2259a4365d0SYoshinobu Inoue 2269a4365d0SYoshinobu Inoue /* 22733841545SHajimu UMEMOTO * get max/min key length against algorithm specified. 22833841545SHajimu UMEMOTO * satype is one of satype defined at pfkeyv2.h. 22933841545SHajimu UMEMOTO * keylen is the unit of bit. 23033841545SHajimu UMEMOTO * OUT: 23133841545SHajimu UMEMOTO * -1: invalid. 23233841545SHajimu UMEMOTO * 0: valid. 23333841545SHajimu UMEMOTO */ 23433841545SHajimu UMEMOTO int 235650d6cc1SKonstantin Belousov ipsec_get_keylen(u_int supported, u_int alg_id, struct sadb_alg *alg0) 23633841545SHajimu UMEMOTO { 23733841545SHajimu UMEMOTO struct sadb_alg *alg; 23833841545SHajimu UMEMOTO u_int satype; 23933841545SHajimu UMEMOTO 24033841545SHajimu UMEMOTO /* validity check */ 24133841545SHajimu UMEMOTO if (!alg0) { 24233841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 24333841545SHajimu UMEMOTO return -1; 24433841545SHajimu UMEMOTO } 24533841545SHajimu UMEMOTO 24633841545SHajimu UMEMOTO switch (supported) { 24733841545SHajimu UMEMOTO case SADB_EXT_SUPPORTED_AUTH: 24833841545SHajimu UMEMOTO satype = SADB_SATYPE_AH; 24933841545SHajimu UMEMOTO break; 25033841545SHajimu UMEMOTO case SADB_EXT_SUPPORTED_ENCRYPT: 25133841545SHajimu UMEMOTO satype = SADB_SATYPE_ESP; 25233841545SHajimu UMEMOTO break; 25333841545SHajimu UMEMOTO default: 25433841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 25533841545SHajimu UMEMOTO return -1; 25633841545SHajimu UMEMOTO } 25733841545SHajimu UMEMOTO 25833841545SHajimu UMEMOTO alg = findsupportedalg(satype, alg_id); 25933841545SHajimu UMEMOTO if (!alg) 26033841545SHajimu UMEMOTO return -1; 26133841545SHajimu UMEMOTO 26233841545SHajimu UMEMOTO memcpy(alg0, alg, sizeof(*alg0)); 26333841545SHajimu UMEMOTO 26433841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_NO_ERROR; 26533841545SHajimu UMEMOTO return 0; 26633841545SHajimu UMEMOTO } 26733841545SHajimu UMEMOTO 26833841545SHajimu UMEMOTO /* 2699a4365d0SYoshinobu Inoue * set the rate for SOFT lifetime against HARD one. 2709a4365d0SYoshinobu Inoue * If rate is more than 100 or equal to zero, then set to 100. 2719a4365d0SYoshinobu Inoue */ 2729a4365d0SYoshinobu Inoue static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE; 2739a4365d0SYoshinobu Inoue static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE; 2749a4365d0SYoshinobu Inoue static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE; 2759a4365d0SYoshinobu Inoue static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE; 2769a4365d0SYoshinobu Inoue 2779a4365d0SYoshinobu Inoue u_int 278650d6cc1SKonstantin Belousov pfkey_set_softrate(u_int type, u_int rate) 2799a4365d0SYoshinobu Inoue { 2803c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 2819a4365d0SYoshinobu Inoue 2829a4365d0SYoshinobu Inoue if (rate > 100 || rate == 0) 2839a4365d0SYoshinobu Inoue rate = 100; 2849a4365d0SYoshinobu Inoue 2859a4365d0SYoshinobu Inoue switch (type) { 2869a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_ALLOCATIONS: 2879a4365d0SYoshinobu Inoue soft_lifetime_allocations_rate = rate; 2889a4365d0SYoshinobu Inoue return 0; 2899a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_BYTES: 2909a4365d0SYoshinobu Inoue soft_lifetime_bytes_rate = rate; 2919a4365d0SYoshinobu Inoue return 0; 2929a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_ADDTIME: 2939a4365d0SYoshinobu Inoue soft_lifetime_addtime_rate = rate; 2949a4365d0SYoshinobu Inoue return 0; 2959a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_USETIME: 2969a4365d0SYoshinobu Inoue soft_lifetime_usetime_rate = rate; 2979a4365d0SYoshinobu Inoue return 0; 2989a4365d0SYoshinobu Inoue } 2999a4365d0SYoshinobu Inoue 3003c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 3019a4365d0SYoshinobu Inoue return 1; 3029a4365d0SYoshinobu Inoue } 3039a4365d0SYoshinobu Inoue 3049a4365d0SYoshinobu Inoue /* 3059a4365d0SYoshinobu Inoue * get current rate for SOFT lifetime against HARD one. 3069a4365d0SYoshinobu Inoue * ATTENTION: ~0 is returned if invalid type was passed. 3079a4365d0SYoshinobu Inoue */ 3089a4365d0SYoshinobu Inoue u_int 309650d6cc1SKonstantin Belousov pfkey_get_softrate(u_int type) 3109a4365d0SYoshinobu Inoue { 3119a4365d0SYoshinobu Inoue switch (type) { 3129a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_ALLOCATIONS: 3139a4365d0SYoshinobu Inoue return soft_lifetime_allocations_rate; 3149a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_BYTES: 3159a4365d0SYoshinobu Inoue return soft_lifetime_bytes_rate; 3169a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_ADDTIME: 3179a4365d0SYoshinobu Inoue return soft_lifetime_addtime_rate; 3189a4365d0SYoshinobu Inoue case SADB_X_LIFETIME_USETIME: 3199a4365d0SYoshinobu Inoue return soft_lifetime_usetime_rate; 3209a4365d0SYoshinobu Inoue } 3219a4365d0SYoshinobu Inoue 3229a4365d0SYoshinobu Inoue return ~0; 3239a4365d0SYoshinobu Inoue } 3249a4365d0SYoshinobu Inoue 3259a4365d0SYoshinobu Inoue /* 3269a4365d0SYoshinobu Inoue * sending SADB_GETSPI message to the kernel. 3279a4365d0SYoshinobu Inoue * OUT: 3289a4365d0SYoshinobu Inoue * positive: success and return length sent. 3295666643aSGordon Bergling * -1 : error occurred, and set errno. 3309a4365d0SYoshinobu Inoue */ 3319a4365d0SYoshinobu Inoue int 332650d6cc1SKonstantin Belousov pfkey_send_getspi(int so, u_int satype, u_int mode, struct sockaddr *src, 333650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int32_t min, uint32_t max, uint32_t reqid, 334650d6cc1SKonstantin Belousov uint32_t seq) 3359a4365d0SYoshinobu Inoue { 3369a4365d0SYoshinobu Inoue struct sadb_msg *newmsg; 33733841545SHajimu UMEMOTO caddr_t ep; 3389a4365d0SYoshinobu Inoue int len; 3399a4365d0SYoshinobu Inoue int need_spirange = 0; 3409a4365d0SYoshinobu Inoue caddr_t p; 3413c62e87aSJun-ichiro itojun Hagino int plen; 3429a4365d0SYoshinobu Inoue 3439a4365d0SYoshinobu Inoue /* validity check */ 3449a4365d0SYoshinobu Inoue if (src == NULL || dst == NULL) { 3453c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 3469a4365d0SYoshinobu Inoue return -1; 3479a4365d0SYoshinobu Inoue } 3489a4365d0SYoshinobu Inoue if (src->sa_family != dst->sa_family) { 3493c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; 3509a4365d0SYoshinobu Inoue return -1; 3519a4365d0SYoshinobu Inoue } 3529a4365d0SYoshinobu Inoue if (min > max || (min > 0 && min <= 255)) { 3533c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SPI; 3543c62e87aSJun-ichiro itojun Hagino return -1; 3553c62e87aSJun-ichiro itojun Hagino } 3563c62e87aSJun-ichiro itojun Hagino switch (src->sa_family) { 3573c62e87aSJun-ichiro itojun Hagino case AF_INET: 3583c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in_addr) << 3; 3593c62e87aSJun-ichiro itojun Hagino break; 3603c62e87aSJun-ichiro itojun Hagino case AF_INET6: 3613c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in6_addr) << 3; 3623c62e87aSJun-ichiro itojun Hagino break; 3633c62e87aSJun-ichiro itojun Hagino default: 3643c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_FAMILY; 3659a4365d0SYoshinobu Inoue return -1; 3669a4365d0SYoshinobu Inoue } 3679a4365d0SYoshinobu Inoue 3689a4365d0SYoshinobu Inoue /* create new sadb_msg to send. */ 3699a4365d0SYoshinobu Inoue len = sizeof(struct sadb_msg) 3703c62e87aSJun-ichiro itojun Hagino + sizeof(struct sadb_x_sa2) 3719a4365d0SYoshinobu Inoue + sizeof(struct sadb_address) 3729a4365d0SYoshinobu Inoue + PFKEY_ALIGN8(src->sa_len) 3739a4365d0SYoshinobu Inoue + sizeof(struct sadb_address) 3749a4365d0SYoshinobu Inoue + PFKEY_ALIGN8(dst->sa_len); 3759a4365d0SYoshinobu Inoue 3769a4365d0SYoshinobu Inoue if (min > 255 && max < ~0) { 3779a4365d0SYoshinobu Inoue need_spirange++; 3789a4365d0SYoshinobu Inoue len += sizeof(struct sadb_spirange); 3799a4365d0SYoshinobu Inoue } 3809a4365d0SYoshinobu Inoue 3819a4365d0SYoshinobu Inoue if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { 3823c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 3839a4365d0SYoshinobu Inoue return -1; 3849a4365d0SYoshinobu Inoue } 38533841545SHajimu UMEMOTO ep = ((caddr_t)newmsg) + len; 3869a4365d0SYoshinobu Inoue 38733841545SHajimu UMEMOTO p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI, 3883c62e87aSJun-ichiro itojun Hagino len, satype, seq, getpid()); 38933841545SHajimu UMEMOTO if (!p) { 39033841545SHajimu UMEMOTO free(newmsg); 39133841545SHajimu UMEMOTO return -1; 39233841545SHajimu UMEMOTO } 3933c62e87aSJun-ichiro itojun Hagino 39433841545SHajimu UMEMOTO p = pfkey_setsadbxsa2(p, ep, mode, reqid); 39533841545SHajimu UMEMOTO if (!p) { 39633841545SHajimu UMEMOTO free(newmsg); 39733841545SHajimu UMEMOTO return -1; 39833841545SHajimu UMEMOTO } 3999a4365d0SYoshinobu Inoue 4009a4365d0SYoshinobu Inoue /* set sadb_address for source */ 40133841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, 4029a4365d0SYoshinobu Inoue IPSEC_ULPROTO_ANY); 40333841545SHajimu UMEMOTO if (!p) { 40433841545SHajimu UMEMOTO free(newmsg); 40533841545SHajimu UMEMOTO return -1; 40633841545SHajimu UMEMOTO } 4079a4365d0SYoshinobu Inoue 4089a4365d0SYoshinobu Inoue /* set sadb_address for destination */ 40933841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, 4109a4365d0SYoshinobu Inoue IPSEC_ULPROTO_ANY); 41133841545SHajimu UMEMOTO if (!p) { 41233841545SHajimu UMEMOTO free(newmsg); 41333841545SHajimu UMEMOTO return -1; 41433841545SHajimu UMEMOTO } 4159a4365d0SYoshinobu Inoue 41638dd27d2SGordon Bergling /* processing spi range */ 4179a4365d0SYoshinobu Inoue if (need_spirange) { 41833841545SHajimu UMEMOTO struct sadb_spirange spirange; 4199a4365d0SYoshinobu Inoue 42033841545SHajimu UMEMOTO if (p + sizeof(spirange) > ep) { 42133841545SHajimu UMEMOTO free(newmsg); 42233841545SHajimu UMEMOTO return -1; 42333841545SHajimu UMEMOTO } 42433841545SHajimu UMEMOTO 42533841545SHajimu UMEMOTO memset(&spirange, 0, sizeof(spirange)); 42633841545SHajimu UMEMOTO spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange)); 42733841545SHajimu UMEMOTO spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; 42833841545SHajimu UMEMOTO spirange.sadb_spirange_min = min; 42933841545SHajimu UMEMOTO spirange.sadb_spirange_max = max; 43033841545SHajimu UMEMOTO 43133841545SHajimu UMEMOTO memcpy(p, &spirange, sizeof(spirange)); 43233841545SHajimu UMEMOTO 43333841545SHajimu UMEMOTO p += sizeof(spirange); 43433841545SHajimu UMEMOTO } 43533841545SHajimu UMEMOTO if (p != ep) { 43633841545SHajimu UMEMOTO free(newmsg); 43733841545SHajimu UMEMOTO return -1; 4389a4365d0SYoshinobu Inoue } 4399a4365d0SYoshinobu Inoue 4409a4365d0SYoshinobu Inoue /* send message */ 4419a4365d0SYoshinobu Inoue len = pfkey_send(so, newmsg, len); 4429a4365d0SYoshinobu Inoue free(newmsg); 4439a4365d0SYoshinobu Inoue 4449a4365d0SYoshinobu Inoue if (len < 0) 4459a4365d0SYoshinobu Inoue return -1; 4469a4365d0SYoshinobu Inoue 4473c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 4489a4365d0SYoshinobu Inoue return len; 4499a4365d0SYoshinobu Inoue } 4509a4365d0SYoshinobu Inoue 4519a4365d0SYoshinobu Inoue /* 4529a4365d0SYoshinobu Inoue * sending SADB_UPDATE message to the kernel. 4539a4365d0SYoshinobu Inoue * The length of key material is a_keylen + e_keylen. 4549a4365d0SYoshinobu Inoue * OUT: 4559a4365d0SYoshinobu Inoue * positive: success and return length sent. 4565666643aSGordon Bergling * -1 : error occurred, and set errno. 4579a4365d0SYoshinobu Inoue */ 4589a4365d0SYoshinobu Inoue int 459650d6cc1SKonstantin Belousov pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src, 460650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, 461650d6cc1SKonstantin Belousov caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, u_int a_keylen, 462650d6cc1SKonstantin Belousov u_int flags, u_int32_t l_alloc, u_int64_t l_bytes, u_int64_t l_addtime, 463650d6cc1SKonstantin Belousov u_int64_t l_usetime, u_int32_t seq) 4649a4365d0SYoshinobu Inoue { 4659a4365d0SYoshinobu Inoue int len; 4669a4365d0SYoshinobu Inoue if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi, 4673c62e87aSJun-ichiro itojun Hagino reqid, wsize, 4683c62e87aSJun-ichiro itojun Hagino keymat, e_type, e_keylen, a_type, a_keylen, flags, 4699a4365d0SYoshinobu Inoue l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0) 4709a4365d0SYoshinobu Inoue return -1; 4719a4365d0SYoshinobu Inoue 4729a4365d0SYoshinobu Inoue return len; 4739a4365d0SYoshinobu Inoue } 4749a4365d0SYoshinobu Inoue 4759a4365d0SYoshinobu Inoue /* 4769a4365d0SYoshinobu Inoue * sending SADB_ADD message to the kernel. 4779a4365d0SYoshinobu Inoue * The length of key material is a_keylen + e_keylen. 4789a4365d0SYoshinobu Inoue * OUT: 4799a4365d0SYoshinobu Inoue * positive: success and return length sent. 4805666643aSGordon Bergling * -1 : error occurred, and set errno. 4819a4365d0SYoshinobu Inoue */ 4829a4365d0SYoshinobu Inoue int 483650d6cc1SKonstantin Belousov pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src, 484650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, 485650d6cc1SKonstantin Belousov caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, u_int a_keylen, 486650d6cc1SKonstantin Belousov u_int flags, u_int32_t l_alloc, u_int64_t l_bytes, u_int64_t l_addtime, 487650d6cc1SKonstantin Belousov u_int64_t l_usetime, u_int32_t seq) 4889a4365d0SYoshinobu Inoue { 4899a4365d0SYoshinobu Inoue int len; 4909a4365d0SYoshinobu Inoue if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi, 4913c62e87aSJun-ichiro itojun Hagino reqid, wsize, 4923c62e87aSJun-ichiro itojun Hagino keymat, e_type, e_keylen, a_type, a_keylen, flags, 4939a4365d0SYoshinobu Inoue l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0) 4949a4365d0SYoshinobu Inoue return -1; 4959a4365d0SYoshinobu Inoue 4969a4365d0SYoshinobu Inoue return len; 4979a4365d0SYoshinobu Inoue } 4989a4365d0SYoshinobu Inoue 4999a4365d0SYoshinobu Inoue /* 5009a4365d0SYoshinobu Inoue * sending SADB_DELETE message to the kernel. 5019a4365d0SYoshinobu Inoue * OUT: 5029a4365d0SYoshinobu Inoue * positive: success and return length sent. 5035666643aSGordon Bergling * -1 : error occurred, and set errno. 5049a4365d0SYoshinobu Inoue */ 5059a4365d0SYoshinobu Inoue int 506650d6cc1SKonstantin Belousov pfkey_send_delete(int so, u_int satype, u_int mode, struct sockaddr *src, 507650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int32_t spi) 5089a4365d0SYoshinobu Inoue { 5099a4365d0SYoshinobu Inoue int len; 5109a4365d0SYoshinobu Inoue if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0) 5119a4365d0SYoshinobu Inoue return -1; 5129a4365d0SYoshinobu Inoue 5139a4365d0SYoshinobu Inoue return len; 5149a4365d0SYoshinobu Inoue } 5159a4365d0SYoshinobu Inoue 5169a4365d0SYoshinobu Inoue /* 51733841545SHajimu UMEMOTO * sending SADB_DELETE without spi to the kernel. This is 51833841545SHajimu UMEMOTO * the "delete all" request (an extension also present in 51933841545SHajimu UMEMOTO * Solaris). 52033841545SHajimu UMEMOTO * 52133841545SHajimu UMEMOTO * OUT: 52233841545SHajimu UMEMOTO * positive: success and return length sent 5235666643aSGordon Bergling * -1 : error occurred, and set errno 52433841545SHajimu UMEMOTO */ 52533841545SHajimu UMEMOTO int 526650d6cc1SKonstantin Belousov pfkey_send_delete_all(int so, u_int satype, u_int mode, struct sockaddr *src, 527650d6cc1SKonstantin Belousov struct sockaddr *dst) 52833841545SHajimu UMEMOTO { 52933841545SHajimu UMEMOTO struct sadb_msg *newmsg; 53033841545SHajimu UMEMOTO int len; 53133841545SHajimu UMEMOTO caddr_t p; 53233841545SHajimu UMEMOTO int plen; 53333841545SHajimu UMEMOTO caddr_t ep; 53433841545SHajimu UMEMOTO 53533841545SHajimu UMEMOTO /* validity check */ 53633841545SHajimu UMEMOTO if (src == NULL || dst == NULL) { 53733841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 53833841545SHajimu UMEMOTO return -1; 53933841545SHajimu UMEMOTO } 54033841545SHajimu UMEMOTO if (src->sa_family != dst->sa_family) { 54133841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; 54233841545SHajimu UMEMOTO return -1; 54333841545SHajimu UMEMOTO } 54433841545SHajimu UMEMOTO switch (src->sa_family) { 54533841545SHajimu UMEMOTO case AF_INET: 54633841545SHajimu UMEMOTO plen = sizeof(struct in_addr) << 3; 54733841545SHajimu UMEMOTO break; 54833841545SHajimu UMEMOTO case AF_INET6: 54933841545SHajimu UMEMOTO plen = sizeof(struct in6_addr) << 3; 55033841545SHajimu UMEMOTO break; 55133841545SHajimu UMEMOTO default: 55233841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_FAMILY; 55333841545SHajimu UMEMOTO return -1; 55433841545SHajimu UMEMOTO } 55533841545SHajimu UMEMOTO 55633841545SHajimu UMEMOTO /* create new sadb_msg to reply. */ 55733841545SHajimu UMEMOTO len = sizeof(struct sadb_msg) 55833841545SHajimu UMEMOTO + sizeof(struct sadb_address) 55933841545SHajimu UMEMOTO + PFKEY_ALIGN8(src->sa_len) 56033841545SHajimu UMEMOTO + sizeof(struct sadb_address) 56133841545SHajimu UMEMOTO + PFKEY_ALIGN8(dst->sa_len); 56233841545SHajimu UMEMOTO 56333841545SHajimu UMEMOTO if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { 56433841545SHajimu UMEMOTO __ipsec_set_strerror(strerror(errno)); 56533841545SHajimu UMEMOTO return -1; 56633841545SHajimu UMEMOTO } 56733841545SHajimu UMEMOTO ep = ((caddr_t)newmsg) + len; 56833841545SHajimu UMEMOTO 56933841545SHajimu UMEMOTO p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0, 57033841545SHajimu UMEMOTO getpid()); 57133841545SHajimu UMEMOTO if (!p) { 57233841545SHajimu UMEMOTO free(newmsg); 57333841545SHajimu UMEMOTO return -1; 57433841545SHajimu UMEMOTO } 57533841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, 57633841545SHajimu UMEMOTO IPSEC_ULPROTO_ANY); 57733841545SHajimu UMEMOTO if (!p) { 57833841545SHajimu UMEMOTO free(newmsg); 57933841545SHajimu UMEMOTO return -1; 58033841545SHajimu UMEMOTO } 58133841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, 58233841545SHajimu UMEMOTO IPSEC_ULPROTO_ANY); 58333841545SHajimu UMEMOTO if (!p || p != ep) { 58433841545SHajimu UMEMOTO free(newmsg); 58533841545SHajimu UMEMOTO return -1; 58633841545SHajimu UMEMOTO } 58733841545SHajimu UMEMOTO 58833841545SHajimu UMEMOTO /* send message */ 58933841545SHajimu UMEMOTO len = pfkey_send(so, newmsg, len); 59033841545SHajimu UMEMOTO free(newmsg); 59133841545SHajimu UMEMOTO 59233841545SHajimu UMEMOTO if (len < 0) 59333841545SHajimu UMEMOTO return -1; 59433841545SHajimu UMEMOTO 59533841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_NO_ERROR; 59633841545SHajimu UMEMOTO return len; 59733841545SHajimu UMEMOTO } 59833841545SHajimu UMEMOTO 59933841545SHajimu UMEMOTO /* 6009a4365d0SYoshinobu Inoue * sending SADB_GET message to the kernel. 6019a4365d0SYoshinobu Inoue * OUT: 6029a4365d0SYoshinobu Inoue * positive: success and return length sent. 6035666643aSGordon Bergling * -1 : error occurred, and set errno. 6049a4365d0SYoshinobu Inoue */ 6059a4365d0SYoshinobu Inoue int 606650d6cc1SKonstantin Belousov pfkey_send_get(int so, u_int satype, u_int mode, struct sockaddr *src, 607650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int32_t spi) 6089a4365d0SYoshinobu Inoue { 6099a4365d0SYoshinobu Inoue int len; 6109a4365d0SYoshinobu Inoue if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0) 6119a4365d0SYoshinobu Inoue return -1; 6129a4365d0SYoshinobu Inoue 6139a4365d0SYoshinobu Inoue return len; 6149a4365d0SYoshinobu Inoue } 6159a4365d0SYoshinobu Inoue 6169a4365d0SYoshinobu Inoue /* 6179a4365d0SYoshinobu Inoue * sending SADB_REGISTER message to the kernel. 6189a4365d0SYoshinobu Inoue * OUT: 6199a4365d0SYoshinobu Inoue * positive: success and return length sent. 6205666643aSGordon Bergling * -1 : error occurred, and set errno. 6219a4365d0SYoshinobu Inoue */ 6229a4365d0SYoshinobu Inoue int 623650d6cc1SKonstantin Belousov pfkey_send_register(int so, u_int satype) 6249a4365d0SYoshinobu Inoue { 62533841545SHajimu UMEMOTO int len, algno; 62633841545SHajimu UMEMOTO 627b4549038SBjoern A. Zeeb if (satype == SADB_SATYPE_UNSPEC) { 62833841545SHajimu UMEMOTO for (algno = 0; 62933841545SHajimu UMEMOTO algno < sizeof(supported_map)/sizeof(supported_map[0]); 63033841545SHajimu UMEMOTO algno++) { 63133841545SHajimu UMEMOTO if (ipsec_supported[algno]) { 63233841545SHajimu UMEMOTO free(ipsec_supported[algno]); 63333841545SHajimu UMEMOTO ipsec_supported[algno] = NULL; 63433841545SHajimu UMEMOTO } 63533841545SHajimu UMEMOTO } 63633841545SHajimu UMEMOTO } else { 63733841545SHajimu UMEMOTO algno = findsupportedmap(satype); 63833841545SHajimu UMEMOTO if (algno == -1) { 63933841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 64033841545SHajimu UMEMOTO return -1; 64133841545SHajimu UMEMOTO } 64233841545SHajimu UMEMOTO 64333841545SHajimu UMEMOTO if (ipsec_supported[algno]) { 64433841545SHajimu UMEMOTO free(ipsec_supported[algno]); 64533841545SHajimu UMEMOTO ipsec_supported[algno] = NULL; 64633841545SHajimu UMEMOTO } 64733841545SHajimu UMEMOTO } 6489a4365d0SYoshinobu Inoue 6499a4365d0SYoshinobu Inoue if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0) 6509a4365d0SYoshinobu Inoue return -1; 6519a4365d0SYoshinobu Inoue 6529a4365d0SYoshinobu Inoue return len; 6539a4365d0SYoshinobu Inoue } 6549a4365d0SYoshinobu Inoue 6559a4365d0SYoshinobu Inoue /* 6569a4365d0SYoshinobu Inoue * receiving SADB_REGISTER message from the kernel, and copy buffer for 6579a4365d0SYoshinobu Inoue * sadb_supported returned into ipsec_supported. 6589a4365d0SYoshinobu Inoue * OUT: 6599a4365d0SYoshinobu Inoue * 0: success and return length sent. 6605666643aSGordon Bergling * -1: error occurred, and set errno. 6619a4365d0SYoshinobu Inoue */ 6629a4365d0SYoshinobu Inoue int 663650d6cc1SKonstantin Belousov pfkey_recv_register(int so) 6649a4365d0SYoshinobu Inoue { 6659a4365d0SYoshinobu Inoue pid_t pid = getpid(); 6669a4365d0SYoshinobu Inoue struct sadb_msg *newmsg; 66733841545SHajimu UMEMOTO int error = -1; 6689a4365d0SYoshinobu Inoue 6699a4365d0SYoshinobu Inoue /* receive message */ 670bd9f52d5SHajimu UMEMOTO for (;;) { 6719a4365d0SYoshinobu Inoue if ((newmsg = pfkey_recv(so)) == NULL) 6729a4365d0SYoshinobu Inoue return -1; 673bd9f52d5SHajimu UMEMOTO if (newmsg->sadb_msg_type == SADB_REGISTER && 674bd9f52d5SHajimu UMEMOTO newmsg->sadb_msg_pid == pid) 675bd9f52d5SHajimu UMEMOTO break; 676bd9f52d5SHajimu UMEMOTO free(newmsg); 677bd9f52d5SHajimu UMEMOTO } 6789a4365d0SYoshinobu Inoue 6799a4365d0SYoshinobu Inoue /* check and fix */ 6809a4365d0SYoshinobu Inoue newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len); 6819a4365d0SYoshinobu Inoue 68233841545SHajimu UMEMOTO error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len); 68333841545SHajimu UMEMOTO free(newmsg); 68433841545SHajimu UMEMOTO 68533841545SHajimu UMEMOTO if (error == 0) 68633841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_NO_ERROR; 68733841545SHajimu UMEMOTO 68833841545SHajimu UMEMOTO return error; 68933841545SHajimu UMEMOTO } 69033841545SHajimu UMEMOTO 69133841545SHajimu UMEMOTO /* 69233841545SHajimu UMEMOTO * receiving SADB_REGISTER message from the kernel, and copy buffer for 69333841545SHajimu UMEMOTO * sadb_supported returned into ipsec_supported. 69433841545SHajimu UMEMOTO * NOTE: sadb_msg_len must be host order. 69533841545SHajimu UMEMOTO * IN: 69633841545SHajimu UMEMOTO * tlen: msg length, it's to makeing sure. 69733841545SHajimu UMEMOTO * OUT: 69833841545SHajimu UMEMOTO * 0: success and return length sent. 6995666643aSGordon Bergling * -1: error occurred, and set errno. 70033841545SHajimu UMEMOTO */ 70133841545SHajimu UMEMOTO int 702650d6cc1SKonstantin Belousov pfkey_set_supported(struct sadb_msg *msg, int tlen) 70333841545SHajimu UMEMOTO { 70433841545SHajimu UMEMOTO struct sadb_supported *sup; 70533841545SHajimu UMEMOTO caddr_t p; 70633841545SHajimu UMEMOTO caddr_t ep; 70733841545SHajimu UMEMOTO 70833841545SHajimu UMEMOTO /* validity */ 70933841545SHajimu UMEMOTO if (msg->sadb_msg_len != tlen) { 71033841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 71133841545SHajimu UMEMOTO return -1; 71233841545SHajimu UMEMOTO } 71333841545SHajimu UMEMOTO 71433841545SHajimu UMEMOTO p = (caddr_t)msg; 71533841545SHajimu UMEMOTO ep = p + tlen; 71633841545SHajimu UMEMOTO 71733841545SHajimu UMEMOTO p += sizeof(struct sadb_msg); 71833841545SHajimu UMEMOTO 71933841545SHajimu UMEMOTO while (p < ep) { 7209a4365d0SYoshinobu Inoue sup = (struct sadb_supported *)p; 72133841545SHajimu UMEMOTO if (ep < p + sizeof(*sup) || 72233841545SHajimu UMEMOTO PFKEY_EXTLEN(sup) < sizeof(*sup) || 72333841545SHajimu UMEMOTO ep < p + sup->sadb_supported_len) { 72433841545SHajimu UMEMOTO /* invalid format */ 72533841545SHajimu UMEMOTO break; 72633841545SHajimu UMEMOTO } 72733841545SHajimu UMEMOTO 7289a4365d0SYoshinobu Inoue switch (sup->sadb_supported_exttype) { 7299a4365d0SYoshinobu Inoue case SADB_EXT_SUPPORTED_AUTH: 7309a4365d0SYoshinobu Inoue case SADB_EXT_SUPPORTED_ENCRYPT: 7319a4365d0SYoshinobu Inoue break; 7329a4365d0SYoshinobu Inoue default: 7333c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 7349a4365d0SYoshinobu Inoue return -1; 7359a4365d0SYoshinobu Inoue } 7369a4365d0SYoshinobu Inoue 73733841545SHajimu UMEMOTO /* fixed length */ 73833841545SHajimu UMEMOTO sup->sadb_supported_len = PFKEY_EXTLEN(sup); 73933841545SHajimu UMEMOTO 74033841545SHajimu UMEMOTO /* set supported map */ 74133841545SHajimu UMEMOTO if (setsupportedmap(sup) != 0) 74233841545SHajimu UMEMOTO return -1; 74333841545SHajimu UMEMOTO 7449a4365d0SYoshinobu Inoue p += sup->sadb_supported_len; 7459a4365d0SYoshinobu Inoue } 7469a4365d0SYoshinobu Inoue 74733841545SHajimu UMEMOTO if (p != ep) { 7483c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 7499a4365d0SYoshinobu Inoue return -1; 7509a4365d0SYoshinobu Inoue } 7519a4365d0SYoshinobu Inoue 7523c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 75333841545SHajimu UMEMOTO 7549a4365d0SYoshinobu Inoue return 0; 7559a4365d0SYoshinobu Inoue } 7569a4365d0SYoshinobu Inoue 7579a4365d0SYoshinobu Inoue /* 7589a4365d0SYoshinobu Inoue * sending SADB_FLUSH message to the kernel. 7599a4365d0SYoshinobu Inoue * OUT: 7609a4365d0SYoshinobu Inoue * positive: success and return length sent. 7615666643aSGordon Bergling * -1 : error occurred, and set errno. 7629a4365d0SYoshinobu Inoue */ 7639a4365d0SYoshinobu Inoue int 764650d6cc1SKonstantin Belousov pfkey_send_flush(int so, u_int satype) 7659a4365d0SYoshinobu Inoue { 7669a4365d0SYoshinobu Inoue int len; 7679a4365d0SYoshinobu Inoue 7689a4365d0SYoshinobu Inoue if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0) 7699a4365d0SYoshinobu Inoue return -1; 7709a4365d0SYoshinobu Inoue 7719a4365d0SYoshinobu Inoue return len; 7729a4365d0SYoshinobu Inoue } 7739a4365d0SYoshinobu Inoue 7749a4365d0SYoshinobu Inoue /* 7759a4365d0SYoshinobu Inoue * sending SADB_DUMP message to the kernel. 7769a4365d0SYoshinobu Inoue * OUT: 7779a4365d0SYoshinobu Inoue * positive: success and return length sent. 7785666643aSGordon Bergling * -1 : error occurred, and set errno. 7799a4365d0SYoshinobu Inoue */ 7809a4365d0SYoshinobu Inoue int 781650d6cc1SKonstantin Belousov pfkey_send_dump(int so, u_int satype) 7829a4365d0SYoshinobu Inoue { 7839a4365d0SYoshinobu Inoue int len; 7849a4365d0SYoshinobu Inoue 7859a4365d0SYoshinobu Inoue if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0) 7869a4365d0SYoshinobu Inoue return -1; 7879a4365d0SYoshinobu Inoue 7889a4365d0SYoshinobu Inoue return len; 7899a4365d0SYoshinobu Inoue } 7909a4365d0SYoshinobu Inoue 7919a4365d0SYoshinobu Inoue /* 7929a4365d0SYoshinobu Inoue * sending SADB_X_PROMISC message to the kernel. 7939a4365d0SYoshinobu Inoue * NOTE that this function handles promisc mode toggle only. 7949a4365d0SYoshinobu Inoue * IN: 7959a4365d0SYoshinobu Inoue * flag: set promisc off if zero, set promisc on if non-zero. 7969a4365d0SYoshinobu Inoue * OUT: 7979a4365d0SYoshinobu Inoue * positive: success and return length sent. 7985666643aSGordon Bergling * -1 : error occurred, and set errno. 7995666643aSGordon Bergling * 0 : error occurred, and set errno. 8009a4365d0SYoshinobu Inoue * others: a pointer to new allocated buffer in which supported 8019a4365d0SYoshinobu Inoue * algorithms is. 8029a4365d0SYoshinobu Inoue */ 8039a4365d0SYoshinobu Inoue int 804650d6cc1SKonstantin Belousov pfkey_send_promisc_toggle(int so, int flag) 8059a4365d0SYoshinobu Inoue { 8069a4365d0SYoshinobu Inoue int len; 8079a4365d0SYoshinobu Inoue 8089a4365d0SYoshinobu Inoue if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0) 8099a4365d0SYoshinobu Inoue return -1; 8109a4365d0SYoshinobu Inoue 8119a4365d0SYoshinobu Inoue return len; 8129a4365d0SYoshinobu Inoue } 8139a4365d0SYoshinobu Inoue 8149a4365d0SYoshinobu Inoue /* 8159a4365d0SYoshinobu Inoue * sending SADB_X_SPDADD message to the kernel. 8169a4365d0SYoshinobu Inoue * OUT: 8179a4365d0SYoshinobu Inoue * positive: success and return length sent. 8185666643aSGordon Bergling * -1 : error occurred, and set errno. 8199a4365d0SYoshinobu Inoue */ 8209a4365d0SYoshinobu Inoue int 821650d6cc1SKonstantin Belousov pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs, 822650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, 823650d6cc1SKonstantin Belousov int policylen, u_int32_t seq) 8249a4365d0SYoshinobu Inoue { 8259a4365d0SYoshinobu Inoue int len; 8269a4365d0SYoshinobu Inoue 8273c62e87aSJun-ichiro itojun Hagino if ((len = pfkey_send_x4(so, SADB_X_SPDADD, 8283c62e87aSJun-ichiro itojun Hagino src, prefs, dst, prefd, proto, 82933841545SHajimu UMEMOTO 0, 0, 83033841545SHajimu UMEMOTO policy, policylen, seq)) < 0) 83133841545SHajimu UMEMOTO return -1; 83233841545SHajimu UMEMOTO 83333841545SHajimu UMEMOTO return len; 83433841545SHajimu UMEMOTO } 83533841545SHajimu UMEMOTO 83633841545SHajimu UMEMOTO /* 83733841545SHajimu UMEMOTO * sending SADB_X_SPDADD message to the kernel. 83833841545SHajimu UMEMOTO * OUT: 83933841545SHajimu UMEMOTO * positive: success and return length sent. 8405666643aSGordon Bergling * -1 : error occurred, and set errno. 84133841545SHajimu UMEMOTO */ 84233841545SHajimu UMEMOTO int 843650d6cc1SKonstantin Belousov pfkey_send_spdadd2(int so, struct sockaddr *src, u_int prefs, 844650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, 845650d6cc1SKonstantin Belousov u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq) 84633841545SHajimu UMEMOTO { 84733841545SHajimu UMEMOTO int len; 84833841545SHajimu UMEMOTO 84933841545SHajimu UMEMOTO if ((len = pfkey_send_x4(so, SADB_X_SPDADD, 85033841545SHajimu UMEMOTO src, prefs, dst, prefd, proto, 85133841545SHajimu UMEMOTO ltime, vtime, 8523c62e87aSJun-ichiro itojun Hagino policy, policylen, seq)) < 0) 8539a4365d0SYoshinobu Inoue return -1; 8549a4365d0SYoshinobu Inoue 8559a4365d0SYoshinobu Inoue return len; 8569a4365d0SYoshinobu Inoue } 8579a4365d0SYoshinobu Inoue 8589a4365d0SYoshinobu Inoue /* 8593c62e87aSJun-ichiro itojun Hagino * sending SADB_X_SPDUPDATE message to the kernel. 8609a4365d0SYoshinobu Inoue * OUT: 8619a4365d0SYoshinobu Inoue * positive: success and return length sent. 8625666643aSGordon Bergling * -1 : error occurred, and set errno. 8639a4365d0SYoshinobu Inoue */ 8649a4365d0SYoshinobu Inoue int 865650d6cc1SKonstantin Belousov pfkey_send_spdupdate(int so, struct sockaddr *src, u_int prefs, 866650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, 867650d6cc1SKonstantin Belousov int policylen, u_int32_t seq) 8689a4365d0SYoshinobu Inoue { 8699a4365d0SYoshinobu Inoue int len; 8709a4365d0SYoshinobu Inoue 8713c62e87aSJun-ichiro itojun Hagino if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, 8723c62e87aSJun-ichiro itojun Hagino src, prefs, dst, prefd, proto, 87333841545SHajimu UMEMOTO 0, 0, 87433841545SHajimu UMEMOTO policy, policylen, seq)) < 0) 87533841545SHajimu UMEMOTO return -1; 87633841545SHajimu UMEMOTO 87733841545SHajimu UMEMOTO return len; 87833841545SHajimu UMEMOTO } 87933841545SHajimu UMEMOTO 88033841545SHajimu UMEMOTO /* 88133841545SHajimu UMEMOTO * sending SADB_X_SPDUPDATE message to the kernel. 88233841545SHajimu UMEMOTO * OUT: 88333841545SHajimu UMEMOTO * positive: success and return length sent. 8845666643aSGordon Bergling * -1 : error occurred, and set errno. 88533841545SHajimu UMEMOTO */ 88633841545SHajimu UMEMOTO int 887650d6cc1SKonstantin Belousov pfkey_send_spdupdate2(int so, struct sockaddr *src, u_int prefs, 888650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, 889650d6cc1SKonstantin Belousov u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq) 89033841545SHajimu UMEMOTO { 89133841545SHajimu UMEMOTO int len; 89233841545SHajimu UMEMOTO 89333841545SHajimu UMEMOTO if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, 89433841545SHajimu UMEMOTO src, prefs, dst, prefd, proto, 89533841545SHajimu UMEMOTO ltime, vtime, 8963c62e87aSJun-ichiro itojun Hagino policy, policylen, seq)) < 0) 8979a4365d0SYoshinobu Inoue return -1; 8983c62e87aSJun-ichiro itojun Hagino 8993c62e87aSJun-ichiro itojun Hagino return len; 9009a4365d0SYoshinobu Inoue } 9013c62e87aSJun-ichiro itojun Hagino 9023c62e87aSJun-ichiro itojun Hagino /* 9033c62e87aSJun-ichiro itojun Hagino * sending SADB_X_SPDDELETE message to the kernel. 9043c62e87aSJun-ichiro itojun Hagino * OUT: 9053c62e87aSJun-ichiro itojun Hagino * positive: success and return length sent. 9065666643aSGordon Bergling * -1 : error occurred, and set errno. 9073c62e87aSJun-ichiro itojun Hagino */ 9083c62e87aSJun-ichiro itojun Hagino int 909650d6cc1SKonstantin Belousov pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs, 910650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, 911650d6cc1SKonstantin Belousov int policylen, u_int32_t seq) 9123c62e87aSJun-ichiro itojun Hagino { 9133c62e87aSJun-ichiro itojun Hagino int len; 9143c62e87aSJun-ichiro itojun Hagino 9153c62e87aSJun-ichiro itojun Hagino if (policylen != sizeof(struct sadb_x_policy)) { 9163c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 9179a4365d0SYoshinobu Inoue return -1; 9189a4365d0SYoshinobu Inoue } 9199a4365d0SYoshinobu Inoue 9203c62e87aSJun-ichiro itojun Hagino if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE, 9213c62e87aSJun-ichiro itojun Hagino src, prefs, dst, prefd, proto, 92233841545SHajimu UMEMOTO 0, 0, 9233c62e87aSJun-ichiro itojun Hagino policy, policylen, seq)) < 0) 9243c62e87aSJun-ichiro itojun Hagino return -1; 9259a4365d0SYoshinobu Inoue 9263c62e87aSJun-ichiro itojun Hagino return len; 9273c62e87aSJun-ichiro itojun Hagino } 9283c62e87aSJun-ichiro itojun Hagino 9293c62e87aSJun-ichiro itojun Hagino /* 9303c62e87aSJun-ichiro itojun Hagino * sending SADB_X_SPDDELETE message to the kernel. 9313c62e87aSJun-ichiro itojun Hagino * OUT: 9323c62e87aSJun-ichiro itojun Hagino * positive: success and return length sent. 9335666643aSGordon Bergling * -1 : error occurred, and set errno. 9343c62e87aSJun-ichiro itojun Hagino */ 9353c62e87aSJun-ichiro itojun Hagino int 936650d6cc1SKonstantin Belousov pfkey_send_spddelete2(int so, u_int32_t spid) 9373c62e87aSJun-ichiro itojun Hagino { 9383c62e87aSJun-ichiro itojun Hagino int len; 9393c62e87aSJun-ichiro itojun Hagino 9403c62e87aSJun-ichiro itojun Hagino if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0) 9413c62e87aSJun-ichiro itojun Hagino return -1; 9423c62e87aSJun-ichiro itojun Hagino 9433c62e87aSJun-ichiro itojun Hagino return len; 9443c62e87aSJun-ichiro itojun Hagino } 9453c62e87aSJun-ichiro itojun Hagino 9463c62e87aSJun-ichiro itojun Hagino /* 9473c62e87aSJun-ichiro itojun Hagino * sending SADB_X_SPDGET message to the kernel. 9483c62e87aSJun-ichiro itojun Hagino * OUT: 9493c62e87aSJun-ichiro itojun Hagino * positive: success and return length sent. 9505666643aSGordon Bergling * -1 : error occurred, and set errno. 9513c62e87aSJun-ichiro itojun Hagino */ 9523c62e87aSJun-ichiro itojun Hagino int 953650d6cc1SKonstantin Belousov pfkey_send_spdget(int so, u_int32_t spid) 9543c62e87aSJun-ichiro itojun Hagino { 9553c62e87aSJun-ichiro itojun Hagino int len; 9563c62e87aSJun-ichiro itojun Hagino 9573c62e87aSJun-ichiro itojun Hagino if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0) 9583c62e87aSJun-ichiro itojun Hagino return -1; 9593c62e87aSJun-ichiro itojun Hagino 9603c62e87aSJun-ichiro itojun Hagino return len; 9613c62e87aSJun-ichiro itojun Hagino } 9623c62e87aSJun-ichiro itojun Hagino 9633c62e87aSJun-ichiro itojun Hagino /* 9643c62e87aSJun-ichiro itojun Hagino * sending SADB_X_SPDSETIDX message to the kernel. 9653c62e87aSJun-ichiro itojun Hagino * OUT: 9663c62e87aSJun-ichiro itojun Hagino * positive: success and return length sent. 9675666643aSGordon Bergling * -1 : error occurred, and set errno. 9683c62e87aSJun-ichiro itojun Hagino */ 9693c62e87aSJun-ichiro itojun Hagino int 970650d6cc1SKonstantin Belousov pfkey_send_spdsetidx(int so, struct sockaddr *src, u_int prefs, 971650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, 972650d6cc1SKonstantin Belousov int policylen, u_int32_t seq) 9733c62e87aSJun-ichiro itojun Hagino { 9743c62e87aSJun-ichiro itojun Hagino int len; 9753c62e87aSJun-ichiro itojun Hagino 9763c62e87aSJun-ichiro itojun Hagino if (policylen != sizeof(struct sadb_x_policy)) { 9773c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 9789a4365d0SYoshinobu Inoue return -1; 9799a4365d0SYoshinobu Inoue } 9809a4365d0SYoshinobu Inoue 9813c62e87aSJun-ichiro itojun Hagino if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX, 9823c62e87aSJun-ichiro itojun Hagino src, prefs, dst, prefd, proto, 98333841545SHajimu UMEMOTO 0, 0, 9843c62e87aSJun-ichiro itojun Hagino policy, policylen, seq)) < 0) 9859a4365d0SYoshinobu Inoue return -1; 9869a4365d0SYoshinobu Inoue 9879a4365d0SYoshinobu Inoue return len; 9889a4365d0SYoshinobu Inoue } 9899a4365d0SYoshinobu Inoue 9909a4365d0SYoshinobu Inoue /* 9919a4365d0SYoshinobu Inoue * sending SADB_SPDFLUSH message to the kernel. 9929a4365d0SYoshinobu Inoue * OUT: 9939a4365d0SYoshinobu Inoue * positive: success and return length sent. 9945666643aSGordon Bergling * -1 : error occurred, and set errno. 9959a4365d0SYoshinobu Inoue */ 9969a4365d0SYoshinobu Inoue int 997650d6cc1SKonstantin Belousov pfkey_send_spdflush(int so) 9989a4365d0SYoshinobu Inoue { 9999a4365d0SYoshinobu Inoue int len; 10009a4365d0SYoshinobu Inoue 10019a4365d0SYoshinobu Inoue if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0) 10029a4365d0SYoshinobu Inoue return -1; 10039a4365d0SYoshinobu Inoue 10049a4365d0SYoshinobu Inoue return len; 10059a4365d0SYoshinobu Inoue } 10069a4365d0SYoshinobu Inoue 10079a4365d0SYoshinobu Inoue /* 10089a4365d0SYoshinobu Inoue * sending SADB_SPDDUMP message to the kernel. 10099a4365d0SYoshinobu Inoue * OUT: 10109a4365d0SYoshinobu Inoue * positive: success and return length sent. 10115666643aSGordon Bergling * -1 : error occurred, and set errno. 10129a4365d0SYoshinobu Inoue */ 10139a4365d0SYoshinobu Inoue int 1014650d6cc1SKonstantin Belousov pfkey_send_spddump(int so) 10159a4365d0SYoshinobu Inoue { 10169a4365d0SYoshinobu Inoue int len; 10179a4365d0SYoshinobu Inoue 10189a4365d0SYoshinobu Inoue if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0) 10199a4365d0SYoshinobu Inoue return -1; 10209a4365d0SYoshinobu Inoue 10219a4365d0SYoshinobu Inoue return len; 10229a4365d0SYoshinobu Inoue } 10239a4365d0SYoshinobu Inoue 10249a4365d0SYoshinobu Inoue /* sending SADB_ADD or SADB_UPDATE message to the kernel */ 10259a4365d0SYoshinobu Inoue static int 1026650d6cc1SKonstantin Belousov pfkey_send_x1(int so, u_int type, u_int satype, u_int mode, 1027650d6cc1SKonstantin Belousov struct sockaddr *src, struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, 1028650d6cc1SKonstantin Belousov u_int wsize, caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, 1029650d6cc1SKonstantin Belousov u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int32_t l_bytes, 1030650d6cc1SKonstantin Belousov u_int32_t l_addtime, u_int32_t l_usetime, u_int32_t seq) 10319a4365d0SYoshinobu Inoue { 10329a4365d0SYoshinobu Inoue struct sadb_msg *newmsg; 10339a4365d0SYoshinobu Inoue int len; 10349a4365d0SYoshinobu Inoue caddr_t p; 10353c62e87aSJun-ichiro itojun Hagino int plen; 103633841545SHajimu UMEMOTO caddr_t ep; 10379a4365d0SYoshinobu Inoue 10389a4365d0SYoshinobu Inoue /* validity check */ 10399a4365d0SYoshinobu Inoue if (src == NULL || dst == NULL) { 10403c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 10419a4365d0SYoshinobu Inoue return -1; 10429a4365d0SYoshinobu Inoue } 10439a4365d0SYoshinobu Inoue if (src->sa_family != dst->sa_family) { 10443c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; 10453c62e87aSJun-ichiro itojun Hagino return -1; 10463c62e87aSJun-ichiro itojun Hagino } 10473c62e87aSJun-ichiro itojun Hagino switch (src->sa_family) { 10483c62e87aSJun-ichiro itojun Hagino case AF_INET: 10493c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in_addr) << 3; 10503c62e87aSJun-ichiro itojun Hagino break; 10513c62e87aSJun-ichiro itojun Hagino case AF_INET6: 10523c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in6_addr) << 3; 10533c62e87aSJun-ichiro itojun Hagino break; 10543c62e87aSJun-ichiro itojun Hagino default: 10553c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_FAMILY; 10569a4365d0SYoshinobu Inoue return -1; 10579a4365d0SYoshinobu Inoue } 10589a4365d0SYoshinobu Inoue 10599a4365d0SYoshinobu Inoue switch (satype) { 10609a4365d0SYoshinobu Inoue case SADB_SATYPE_ESP: 10619a4365d0SYoshinobu Inoue if (e_type == SADB_EALG_NONE) { 10623c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ALGS; 10639a4365d0SYoshinobu Inoue return -1; 10649a4365d0SYoshinobu Inoue } 10659a4365d0SYoshinobu Inoue break; 10669a4365d0SYoshinobu Inoue case SADB_SATYPE_AH: 10679a4365d0SYoshinobu Inoue if (e_type != SADB_EALG_NONE) { 10683c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ALGS; 10699a4365d0SYoshinobu Inoue return -1; 10709a4365d0SYoshinobu Inoue } 10719a4365d0SYoshinobu Inoue if (a_type == SADB_AALG_NONE) { 10723c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ALGS; 10739a4365d0SYoshinobu Inoue return -1; 10749a4365d0SYoshinobu Inoue } 10759a4365d0SYoshinobu Inoue break; 10769a4365d0SYoshinobu Inoue case SADB_X_SATYPE_IPCOMP: 107733841545SHajimu UMEMOTO if (e_type == SADB_X_CALG_NONE) { 107833841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_ALGS; 107933841545SHajimu UMEMOTO return -1; 108033841545SHajimu UMEMOTO } 108133841545SHajimu UMEMOTO if (a_type != SADB_AALG_NONE) { 108233841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_NO_ALGS; 108333841545SHajimu UMEMOTO return -1; 108433841545SHajimu UMEMOTO } 10859a4365d0SYoshinobu Inoue break; 10861922fd12SBruce M Simpson case SADB_X_SATYPE_TCPSIGNATURE: 10871922fd12SBruce M Simpson if (e_type != SADB_EALG_NONE) { 10881922fd12SBruce M Simpson __ipsec_errcode = EIPSEC_INVAL_ALGS; 10891922fd12SBruce M Simpson return -1; 10901922fd12SBruce M Simpson } 10911922fd12SBruce M Simpson if (a_type != SADB_X_AALG_TCP_MD5) { 10921922fd12SBruce M Simpson __ipsec_errcode = EIPSEC_INVAL_ALGS; 10931922fd12SBruce M Simpson return -1; 10941922fd12SBruce M Simpson } 10951922fd12SBruce M Simpson break; 10969a4365d0SYoshinobu Inoue default: 10973c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 10989a4365d0SYoshinobu Inoue return -1; 10999a4365d0SYoshinobu Inoue } 11009a4365d0SYoshinobu Inoue 11019a4365d0SYoshinobu Inoue /* create new sadb_msg to reply. */ 11029a4365d0SYoshinobu Inoue len = sizeof(struct sadb_msg) 11039a4365d0SYoshinobu Inoue + sizeof(struct sadb_sa) 11043c62e87aSJun-ichiro itojun Hagino + sizeof(struct sadb_x_sa2) 11059a4365d0SYoshinobu Inoue + sizeof(struct sadb_address) 11069a4365d0SYoshinobu Inoue + PFKEY_ALIGN8(src->sa_len) 11079a4365d0SYoshinobu Inoue + sizeof(struct sadb_address) 11089a4365d0SYoshinobu Inoue + PFKEY_ALIGN8(dst->sa_len) 11099a4365d0SYoshinobu Inoue + sizeof(struct sadb_lifetime) 11109a4365d0SYoshinobu Inoue + sizeof(struct sadb_lifetime); 11119a4365d0SYoshinobu Inoue 11124e0e8f31SAndrey V. Elsukov if (wsize > UINT8_MAX) { 11134e0e8f31SAndrey V. Elsukov if (wsize > (UINT32_MAX - 32) >> 3) { 11144e0e8f31SAndrey V. Elsukov __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 11154e0e8f31SAndrey V. Elsukov return (-1); 11164e0e8f31SAndrey V. Elsukov } 11174e0e8f31SAndrey V. Elsukov len += sizeof(struct sadb_x_sa_replay); 11184e0e8f31SAndrey V. Elsukov } 11199a4365d0SYoshinobu Inoue if (e_type != SADB_EALG_NONE) 11209a4365d0SYoshinobu Inoue len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen)); 11219a4365d0SYoshinobu Inoue if (a_type != SADB_AALG_NONE) 11229a4365d0SYoshinobu Inoue len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen)); 11239a4365d0SYoshinobu Inoue 11249a4365d0SYoshinobu Inoue if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { 11253c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 11269a4365d0SYoshinobu Inoue return -1; 11279a4365d0SYoshinobu Inoue } 112833841545SHajimu UMEMOTO ep = ((caddr_t)newmsg) + len; 11299a4365d0SYoshinobu Inoue 113033841545SHajimu UMEMOTO p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, 11313c62e87aSJun-ichiro itojun Hagino satype, seq, getpid()); 113233841545SHajimu UMEMOTO if (!p) { 113333841545SHajimu UMEMOTO free(newmsg); 113433841545SHajimu UMEMOTO return -1; 113533841545SHajimu UMEMOTO } 113633841545SHajimu UMEMOTO p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags); 113733841545SHajimu UMEMOTO if (!p) { 113833841545SHajimu UMEMOTO free(newmsg); 113933841545SHajimu UMEMOTO return -1; 114033841545SHajimu UMEMOTO } 114133841545SHajimu UMEMOTO p = pfkey_setsadbxsa2(p, ep, mode, reqid); 114233841545SHajimu UMEMOTO if (!p) { 114333841545SHajimu UMEMOTO free(newmsg); 114433841545SHajimu UMEMOTO return -1; 114533841545SHajimu UMEMOTO } 11464e0e8f31SAndrey V. Elsukov if (wsize > UINT8_MAX) { 11474e0e8f31SAndrey V. Elsukov p = pfkey_setsadbxreplay(p, ep, wsize); 11484e0e8f31SAndrey V. Elsukov if (!p) { 11494e0e8f31SAndrey V. Elsukov free(newmsg); 11504e0e8f31SAndrey V. Elsukov return (-1); 11514e0e8f31SAndrey V. Elsukov } 11524e0e8f31SAndrey V. Elsukov } 115333841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, 11549a4365d0SYoshinobu Inoue IPSEC_ULPROTO_ANY); 115533841545SHajimu UMEMOTO if (!p) { 115633841545SHajimu UMEMOTO free(newmsg); 115733841545SHajimu UMEMOTO return -1; 115833841545SHajimu UMEMOTO } 115933841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, 11609a4365d0SYoshinobu Inoue IPSEC_ULPROTO_ANY); 116133841545SHajimu UMEMOTO if (!p) { 116233841545SHajimu UMEMOTO free(newmsg); 116333841545SHajimu UMEMOTO return -1; 116433841545SHajimu UMEMOTO } 11659a4365d0SYoshinobu Inoue 116633841545SHajimu UMEMOTO if (e_type != SADB_EALG_NONE) { 116733841545SHajimu UMEMOTO p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT, 11689a4365d0SYoshinobu Inoue keymat, e_keylen); 116933841545SHajimu UMEMOTO if (!p) { 117033841545SHajimu UMEMOTO free(newmsg); 117133841545SHajimu UMEMOTO return -1; 117233841545SHajimu UMEMOTO } 117333841545SHajimu UMEMOTO } 117433841545SHajimu UMEMOTO if (a_type != SADB_AALG_NONE) { 117533841545SHajimu UMEMOTO p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH, 11769a4365d0SYoshinobu Inoue keymat + e_keylen, a_keylen); 117733841545SHajimu UMEMOTO if (!p) { 117833841545SHajimu UMEMOTO free(newmsg); 117933841545SHajimu UMEMOTO return -1; 118033841545SHajimu UMEMOTO } 118133841545SHajimu UMEMOTO } 11829a4365d0SYoshinobu Inoue 11839a4365d0SYoshinobu Inoue /* set sadb_lifetime for destination */ 118433841545SHajimu UMEMOTO p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, 11859a4365d0SYoshinobu Inoue l_alloc, l_bytes, l_addtime, l_usetime); 118633841545SHajimu UMEMOTO if (!p) { 118733841545SHajimu UMEMOTO free(newmsg); 118833841545SHajimu UMEMOTO return -1; 118933841545SHajimu UMEMOTO } 119033841545SHajimu UMEMOTO p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT, 11919a4365d0SYoshinobu Inoue l_alloc, l_bytes, l_addtime, l_usetime); 119233841545SHajimu UMEMOTO if (!p || p != ep) { 119333841545SHajimu UMEMOTO free(newmsg); 119433841545SHajimu UMEMOTO return -1; 119533841545SHajimu UMEMOTO } 11969a4365d0SYoshinobu Inoue 11979a4365d0SYoshinobu Inoue /* send message */ 11989a4365d0SYoshinobu Inoue len = pfkey_send(so, newmsg, len); 11999a4365d0SYoshinobu Inoue free(newmsg); 12009a4365d0SYoshinobu Inoue 12019a4365d0SYoshinobu Inoue if (len < 0) 12029a4365d0SYoshinobu Inoue return -1; 12039a4365d0SYoshinobu Inoue 12043c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 12059a4365d0SYoshinobu Inoue return len; 12069a4365d0SYoshinobu Inoue } 12079a4365d0SYoshinobu Inoue 12089a4365d0SYoshinobu Inoue /* sending SADB_DELETE or SADB_GET message to the kernel */ 12099a4365d0SYoshinobu Inoue static int 1210650d6cc1SKonstantin Belousov pfkey_send_x2(int so, u_int type, u_int satype, u_int mode, 1211650d6cc1SKonstantin Belousov struct sockaddr *src, struct sockaddr *dst, u_int32_t spi) 12129a4365d0SYoshinobu Inoue { 12139a4365d0SYoshinobu Inoue struct sadb_msg *newmsg; 12149a4365d0SYoshinobu Inoue int len; 12159a4365d0SYoshinobu Inoue caddr_t p; 12163c62e87aSJun-ichiro itojun Hagino int plen; 121733841545SHajimu UMEMOTO caddr_t ep; 12189a4365d0SYoshinobu Inoue 12199a4365d0SYoshinobu Inoue /* validity check */ 12209a4365d0SYoshinobu Inoue if (src == NULL || dst == NULL) { 12213c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 12229a4365d0SYoshinobu Inoue return -1; 12239a4365d0SYoshinobu Inoue } 12249a4365d0SYoshinobu Inoue if (src->sa_family != dst->sa_family) { 12253c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; 12263c62e87aSJun-ichiro itojun Hagino return -1; 12273c62e87aSJun-ichiro itojun Hagino } 12283c62e87aSJun-ichiro itojun Hagino switch (src->sa_family) { 12293c62e87aSJun-ichiro itojun Hagino case AF_INET: 12303c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in_addr) << 3; 12313c62e87aSJun-ichiro itojun Hagino break; 12323c62e87aSJun-ichiro itojun Hagino case AF_INET6: 12333c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in6_addr) << 3; 12343c62e87aSJun-ichiro itojun Hagino break; 12353c62e87aSJun-ichiro itojun Hagino default: 12363c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_FAMILY; 12379a4365d0SYoshinobu Inoue return -1; 12389a4365d0SYoshinobu Inoue } 12399a4365d0SYoshinobu Inoue 12409a4365d0SYoshinobu Inoue /* create new sadb_msg to reply. */ 12419a4365d0SYoshinobu Inoue len = sizeof(struct sadb_msg) 12429a4365d0SYoshinobu Inoue + sizeof(struct sadb_sa) 12439a4365d0SYoshinobu Inoue + sizeof(struct sadb_address) 12449a4365d0SYoshinobu Inoue + PFKEY_ALIGN8(src->sa_len) 12459a4365d0SYoshinobu Inoue + sizeof(struct sadb_address) 12469a4365d0SYoshinobu Inoue + PFKEY_ALIGN8(dst->sa_len); 12479a4365d0SYoshinobu Inoue 12489a4365d0SYoshinobu Inoue if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { 12493c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 12509a4365d0SYoshinobu Inoue return -1; 12519a4365d0SYoshinobu Inoue } 125233841545SHajimu UMEMOTO ep = ((caddr_t)newmsg) + len; 12539a4365d0SYoshinobu Inoue 125433841545SHajimu UMEMOTO p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, 125533841545SHajimu UMEMOTO getpid()); 125633841545SHajimu UMEMOTO if (!p) { 125733841545SHajimu UMEMOTO free(newmsg); 125833841545SHajimu UMEMOTO return -1; 125933841545SHajimu UMEMOTO } 126033841545SHajimu UMEMOTO p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0); 126133841545SHajimu UMEMOTO if (!p) { 126233841545SHajimu UMEMOTO free(newmsg); 126333841545SHajimu UMEMOTO return -1; 126433841545SHajimu UMEMOTO } 126533841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, 12669a4365d0SYoshinobu Inoue IPSEC_ULPROTO_ANY); 126733841545SHajimu UMEMOTO if (!p) { 126833841545SHajimu UMEMOTO free(newmsg); 126933841545SHajimu UMEMOTO return -1; 127033841545SHajimu UMEMOTO } 127133841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, 12729a4365d0SYoshinobu Inoue IPSEC_ULPROTO_ANY); 127333841545SHajimu UMEMOTO if (!p || p != ep) { 127433841545SHajimu UMEMOTO free(newmsg); 127533841545SHajimu UMEMOTO return -1; 127633841545SHajimu UMEMOTO } 12779a4365d0SYoshinobu Inoue 12789a4365d0SYoshinobu Inoue /* send message */ 12799a4365d0SYoshinobu Inoue len = pfkey_send(so, newmsg, len); 12809a4365d0SYoshinobu Inoue free(newmsg); 12819a4365d0SYoshinobu Inoue 12829a4365d0SYoshinobu Inoue if (len < 0) 12839a4365d0SYoshinobu Inoue return -1; 12849a4365d0SYoshinobu Inoue 12853c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 12869a4365d0SYoshinobu Inoue return len; 12879a4365d0SYoshinobu Inoue } 12889a4365d0SYoshinobu Inoue 12899a4365d0SYoshinobu Inoue /* 12909a4365d0SYoshinobu Inoue * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message 12919a4365d0SYoshinobu Inoue * to the kernel 12929a4365d0SYoshinobu Inoue */ 12939a4365d0SYoshinobu Inoue static int 1294650d6cc1SKonstantin Belousov pfkey_send_x3(int so, u_int type, u_int satype) 12959a4365d0SYoshinobu Inoue { 12969a4365d0SYoshinobu Inoue struct sadb_msg *newmsg; 12979a4365d0SYoshinobu Inoue int len; 129833841545SHajimu UMEMOTO caddr_t p; 129933841545SHajimu UMEMOTO caddr_t ep; 13009a4365d0SYoshinobu Inoue 13019a4365d0SYoshinobu Inoue /* validity check */ 13029a4365d0SYoshinobu Inoue switch (type) { 13039a4365d0SYoshinobu Inoue case SADB_X_PROMISC: 13049a4365d0SYoshinobu Inoue if (satype != 0 && satype != 1) { 13053c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 13069a4365d0SYoshinobu Inoue return -1; 13079a4365d0SYoshinobu Inoue } 13089a4365d0SYoshinobu Inoue break; 13099a4365d0SYoshinobu Inoue default: 13109a4365d0SYoshinobu Inoue switch (satype) { 13119a4365d0SYoshinobu Inoue case SADB_SATYPE_UNSPEC: 13129a4365d0SYoshinobu Inoue case SADB_SATYPE_AH: 13139a4365d0SYoshinobu Inoue case SADB_SATYPE_ESP: 13149a4365d0SYoshinobu Inoue case SADB_X_SATYPE_IPCOMP: 13151922fd12SBruce M Simpson case SADB_X_SATYPE_TCPSIGNATURE: 13169a4365d0SYoshinobu Inoue break; 13179a4365d0SYoshinobu Inoue default: 13183c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 13199a4365d0SYoshinobu Inoue return -1; 13209a4365d0SYoshinobu Inoue } 13219a4365d0SYoshinobu Inoue } 13229a4365d0SYoshinobu Inoue 13239a4365d0SYoshinobu Inoue /* create new sadb_msg to send. */ 13249a4365d0SYoshinobu Inoue len = sizeof(struct sadb_msg); 13259a4365d0SYoshinobu Inoue 13269a4365d0SYoshinobu Inoue if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { 13273c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 13289a4365d0SYoshinobu Inoue return -1; 13299a4365d0SYoshinobu Inoue } 133033841545SHajimu UMEMOTO ep = ((caddr_t)newmsg) + len; 13319a4365d0SYoshinobu Inoue 133233841545SHajimu UMEMOTO p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, 133333841545SHajimu UMEMOTO getpid()); 133433841545SHajimu UMEMOTO if (!p || p != ep) { 133533841545SHajimu UMEMOTO free(newmsg); 133633841545SHajimu UMEMOTO return -1; 133733841545SHajimu UMEMOTO } 13389a4365d0SYoshinobu Inoue 13399a4365d0SYoshinobu Inoue /* send message */ 13409a4365d0SYoshinobu Inoue len = pfkey_send(so, newmsg, len); 13419a4365d0SYoshinobu Inoue free(newmsg); 13429a4365d0SYoshinobu Inoue 13439a4365d0SYoshinobu Inoue if (len < 0) 13449a4365d0SYoshinobu Inoue return -1; 13459a4365d0SYoshinobu Inoue 13463c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 13473c62e87aSJun-ichiro itojun Hagino return len; 13483c62e87aSJun-ichiro itojun Hagino } 13493c62e87aSJun-ichiro itojun Hagino 13503c62e87aSJun-ichiro itojun Hagino /* sending SADB_X_SPDADD message to the kernel */ 13513c62e87aSJun-ichiro itojun Hagino static int 1352650d6cc1SKonstantin Belousov pfkey_send_x4(int so, u_int type, struct sockaddr *src, u_int prefs, 1353650d6cc1SKonstantin Belousov struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, 1354650d6cc1SKonstantin Belousov u_int64_t vtime, char *policy, int policylen, u_int32_t seq) 13553c62e87aSJun-ichiro itojun Hagino { 13563c62e87aSJun-ichiro itojun Hagino struct sadb_msg *newmsg; 13573c62e87aSJun-ichiro itojun Hagino int len; 13583c62e87aSJun-ichiro itojun Hagino caddr_t p; 13593c62e87aSJun-ichiro itojun Hagino int plen; 136033841545SHajimu UMEMOTO caddr_t ep; 13613c62e87aSJun-ichiro itojun Hagino 13623c62e87aSJun-ichiro itojun Hagino /* validity check */ 13633c62e87aSJun-ichiro itojun Hagino if (src == NULL || dst == NULL) { 13643c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 13653c62e87aSJun-ichiro itojun Hagino return -1; 13663c62e87aSJun-ichiro itojun Hagino } 13673c62e87aSJun-ichiro itojun Hagino if (src->sa_family != dst->sa_family) { 13683c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; 13693c62e87aSJun-ichiro itojun Hagino return -1; 13703c62e87aSJun-ichiro itojun Hagino } 13713c62e87aSJun-ichiro itojun Hagino 13723c62e87aSJun-ichiro itojun Hagino switch (src->sa_family) { 13733c62e87aSJun-ichiro itojun Hagino case AF_INET: 13743c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in_addr) << 3; 13753c62e87aSJun-ichiro itojun Hagino break; 13763c62e87aSJun-ichiro itojun Hagino case AF_INET6: 13773c62e87aSJun-ichiro itojun Hagino plen = sizeof(struct in6_addr) << 3; 13783c62e87aSJun-ichiro itojun Hagino break; 13793c62e87aSJun-ichiro itojun Hagino default: 13803c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_FAMILY; 13813c62e87aSJun-ichiro itojun Hagino return -1; 13823c62e87aSJun-ichiro itojun Hagino } 13833c62e87aSJun-ichiro itojun Hagino if (prefs > plen || prefd > plen) { 13843c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN; 13853c62e87aSJun-ichiro itojun Hagino return -1; 13863c62e87aSJun-ichiro itojun Hagino } 13873c62e87aSJun-ichiro itojun Hagino 13883c62e87aSJun-ichiro itojun Hagino /* create new sadb_msg to reply. */ 13893c62e87aSJun-ichiro itojun Hagino len = sizeof(struct sadb_msg) 13903c62e87aSJun-ichiro itojun Hagino + sizeof(struct sadb_address) 13913c62e87aSJun-ichiro itojun Hagino + PFKEY_ALIGN8(src->sa_len) 13923c62e87aSJun-ichiro itojun Hagino + sizeof(struct sadb_address) 13933c62e87aSJun-ichiro itojun Hagino + PFKEY_ALIGN8(src->sa_len) 139433841545SHajimu UMEMOTO + sizeof(struct sadb_lifetime) 13953c62e87aSJun-ichiro itojun Hagino + policylen; 13963c62e87aSJun-ichiro itojun Hagino 13973c62e87aSJun-ichiro itojun Hagino if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { 13983c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 13993c62e87aSJun-ichiro itojun Hagino return -1; 14003c62e87aSJun-ichiro itojun Hagino } 140133841545SHajimu UMEMOTO ep = ((caddr_t)newmsg) + len; 14023c62e87aSJun-ichiro itojun Hagino 140333841545SHajimu UMEMOTO p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, 14043c62e87aSJun-ichiro itojun Hagino SADB_SATYPE_UNSPEC, seq, getpid()); 140533841545SHajimu UMEMOTO if (!p) { 140633841545SHajimu UMEMOTO free(newmsg); 140733841545SHajimu UMEMOTO return -1; 140833841545SHajimu UMEMOTO } 140933841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto); 141033841545SHajimu UMEMOTO if (!p) { 141133841545SHajimu UMEMOTO free(newmsg); 141233841545SHajimu UMEMOTO return -1; 141333841545SHajimu UMEMOTO } 141433841545SHajimu UMEMOTO p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto); 141533841545SHajimu UMEMOTO if (!p) { 141633841545SHajimu UMEMOTO free(newmsg); 141733841545SHajimu UMEMOTO return -1; 141833841545SHajimu UMEMOTO } 141933841545SHajimu UMEMOTO p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, 142033841545SHajimu UMEMOTO 0, 0, ltime, vtime); 142133841545SHajimu UMEMOTO if (!p || p + policylen != ep) { 142233841545SHajimu UMEMOTO free(newmsg); 142333841545SHajimu UMEMOTO return -1; 142433841545SHajimu UMEMOTO } 14253c62e87aSJun-ichiro itojun Hagino memcpy(p, policy, policylen); 14263c62e87aSJun-ichiro itojun Hagino 14273c62e87aSJun-ichiro itojun Hagino /* send message */ 14283c62e87aSJun-ichiro itojun Hagino len = pfkey_send(so, newmsg, len); 14293c62e87aSJun-ichiro itojun Hagino free(newmsg); 14303c62e87aSJun-ichiro itojun Hagino 14313c62e87aSJun-ichiro itojun Hagino if (len < 0) 14323c62e87aSJun-ichiro itojun Hagino return -1; 14333c62e87aSJun-ichiro itojun Hagino 14343c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 14353c62e87aSJun-ichiro itojun Hagino return len; 14363c62e87aSJun-ichiro itojun Hagino } 14373c62e87aSJun-ichiro itojun Hagino 14383c62e87aSJun-ichiro itojun Hagino /* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */ 14393c62e87aSJun-ichiro itojun Hagino static int 1440650d6cc1SKonstantin Belousov pfkey_send_x5(int so, u_int type, u_int32_t spid) 14413c62e87aSJun-ichiro itojun Hagino { 14423c62e87aSJun-ichiro itojun Hagino struct sadb_msg *newmsg; 14433c62e87aSJun-ichiro itojun Hagino struct sadb_x_policy xpl; 14443c62e87aSJun-ichiro itojun Hagino int len; 14453c62e87aSJun-ichiro itojun Hagino caddr_t p; 144633841545SHajimu UMEMOTO caddr_t ep; 14473c62e87aSJun-ichiro itojun Hagino 14483c62e87aSJun-ichiro itojun Hagino /* create new sadb_msg to reply. */ 14493c62e87aSJun-ichiro itojun Hagino len = sizeof(struct sadb_msg) 14503c62e87aSJun-ichiro itojun Hagino + sizeof(xpl); 14513c62e87aSJun-ichiro itojun Hagino 14523c62e87aSJun-ichiro itojun Hagino if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { 14533c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 14543c62e87aSJun-ichiro itojun Hagino return -1; 14553c62e87aSJun-ichiro itojun Hagino } 145633841545SHajimu UMEMOTO ep = ((caddr_t)newmsg) + len; 14573c62e87aSJun-ichiro itojun Hagino 145833841545SHajimu UMEMOTO p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, 14593c62e87aSJun-ichiro itojun Hagino SADB_SATYPE_UNSPEC, 0, getpid()); 146033841545SHajimu UMEMOTO if (!p) { 146133841545SHajimu UMEMOTO free(newmsg); 146233841545SHajimu UMEMOTO return -1; 146333841545SHajimu UMEMOTO } 14643c62e87aSJun-ichiro itojun Hagino 146533841545SHajimu UMEMOTO if (p + sizeof(xpl) != ep) { 146633841545SHajimu UMEMOTO free(newmsg); 146733841545SHajimu UMEMOTO return -1; 146833841545SHajimu UMEMOTO } 14693c62e87aSJun-ichiro itojun Hagino memset(&xpl, 0, sizeof(xpl)); 1470bd9f52d5SHajimu UMEMOTO xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl)); 14713c62e87aSJun-ichiro itojun Hagino xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY; 14723c62e87aSJun-ichiro itojun Hagino xpl.sadb_x_policy_id = spid; 14733c62e87aSJun-ichiro itojun Hagino memcpy(p, &xpl, sizeof(xpl)); 14743c62e87aSJun-ichiro itojun Hagino 14753c62e87aSJun-ichiro itojun Hagino /* send message */ 14763c62e87aSJun-ichiro itojun Hagino len = pfkey_send(so, newmsg, len); 14773c62e87aSJun-ichiro itojun Hagino free(newmsg); 14783c62e87aSJun-ichiro itojun Hagino 14793c62e87aSJun-ichiro itojun Hagino if (len < 0) 14803c62e87aSJun-ichiro itojun Hagino return -1; 14813c62e87aSJun-ichiro itojun Hagino 14823c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 14839a4365d0SYoshinobu Inoue return len; 14849a4365d0SYoshinobu Inoue } 14859a4365d0SYoshinobu Inoue 14869a4365d0SYoshinobu Inoue /* 14879a4365d0SYoshinobu Inoue * open a socket. 14889a4365d0SYoshinobu Inoue * OUT: 14899a4365d0SYoshinobu Inoue * -1: fail. 14909a4365d0SYoshinobu Inoue * others : success and return value of socket. 14919a4365d0SYoshinobu Inoue */ 14929a4365d0SYoshinobu Inoue int 1493d570044cSAndrey V. Elsukov pfkey_open(void) 14949a4365d0SYoshinobu Inoue { 14959a4365d0SYoshinobu Inoue int so; 1496d570044cSAndrey V. Elsukov int bufsiz_current, bufsiz_wanted; 1497d570044cSAndrey V. Elsukov int ret; 1498d570044cSAndrey V. Elsukov socklen_t len; 14999a4365d0SYoshinobu Inoue 15009a4365d0SYoshinobu Inoue if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { 15013c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 15029a4365d0SYoshinobu Inoue return -1; 15039a4365d0SYoshinobu Inoue } 15049a4365d0SYoshinobu Inoue 15059a4365d0SYoshinobu Inoue /* 15069a4365d0SYoshinobu Inoue * This is a temporary workaround for KAME PR 154. 15079a4365d0SYoshinobu Inoue * Don't really care even if it fails. 15089a4365d0SYoshinobu Inoue */ 1509d570044cSAndrey V. Elsukov /* Try to have 128k. If we have more, do not lower it. */ 1510d570044cSAndrey V. Elsukov bufsiz_wanted = 128 * 1024; 1511d570044cSAndrey V. Elsukov len = sizeof(bufsiz_current); 1512d570044cSAndrey V. Elsukov ret = getsockopt(so, SOL_SOCKET, SO_SNDBUF, 1513d570044cSAndrey V. Elsukov &bufsiz_current, &len); 1514d570044cSAndrey V. Elsukov if ((ret < 0) || (bufsiz_current < bufsiz_wanted)) 1515d570044cSAndrey V. Elsukov (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, 1516d570044cSAndrey V. Elsukov &bufsiz_wanted, sizeof(bufsiz_wanted)); 1517d570044cSAndrey V. Elsukov 1518d570044cSAndrey V. Elsukov /* Try to have have at least 2MB. If we have more, do not lower it. */ 1519d570044cSAndrey V. Elsukov bufsiz_wanted = 2 * 1024 * 1024; 1520d570044cSAndrey V. Elsukov len = sizeof(bufsiz_current); 1521d570044cSAndrey V. Elsukov ret = getsockopt(so, SOL_SOCKET, SO_RCVBUF, 1522d570044cSAndrey V. Elsukov &bufsiz_current, &len); 1523d570044cSAndrey V. Elsukov if (ret < 0) 1524d570044cSAndrey V. Elsukov bufsiz_current = 128 * 1024; 1525d570044cSAndrey V. Elsukov 1526d570044cSAndrey V. Elsukov for (; bufsiz_wanted > bufsiz_current; bufsiz_wanted /= 2) { 1527d570044cSAndrey V. Elsukov if (setsockopt(so, SOL_SOCKET, SO_RCVBUF, 1528d570044cSAndrey V. Elsukov &bufsiz_wanted, sizeof(bufsiz_wanted)) == 0) 1529d570044cSAndrey V. Elsukov break; 1530d570044cSAndrey V. Elsukov } 15319a4365d0SYoshinobu Inoue 15323c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 15339a4365d0SYoshinobu Inoue return so; 15349a4365d0SYoshinobu Inoue } 15359a4365d0SYoshinobu Inoue 15369a4365d0SYoshinobu Inoue /* 15379a4365d0SYoshinobu Inoue * close a socket. 15389a4365d0SYoshinobu Inoue * OUT: 15399a4365d0SYoshinobu Inoue * 0: success. 15409a4365d0SYoshinobu Inoue * -1: fail. 15419a4365d0SYoshinobu Inoue */ 15429a4365d0SYoshinobu Inoue void 1543650d6cc1SKonstantin Belousov pfkey_close(int so) 15449a4365d0SYoshinobu Inoue { 15459a4365d0SYoshinobu Inoue (void)close(so); 15469a4365d0SYoshinobu Inoue 15473c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 15489a4365d0SYoshinobu Inoue return; 15499a4365d0SYoshinobu Inoue } 15509a4365d0SYoshinobu Inoue 15519a4365d0SYoshinobu Inoue /* 15529a4365d0SYoshinobu Inoue * receive sadb_msg data, and return pointer to new buffer allocated. 15539a4365d0SYoshinobu Inoue * Must free this buffer later. 15549a4365d0SYoshinobu Inoue * OUT: 15555666643aSGordon Bergling * NULL : error occurred. 15569a4365d0SYoshinobu Inoue * others : a pointer to sadb_msg structure. 155733841545SHajimu UMEMOTO * 155833841545SHajimu UMEMOTO * XXX should be rewritten to pass length explicitly 15599a4365d0SYoshinobu Inoue */ 15609a4365d0SYoshinobu Inoue struct sadb_msg * 1561650d6cc1SKonstantin Belousov pfkey_recv(int so) 15629a4365d0SYoshinobu Inoue { 15639a4365d0SYoshinobu Inoue struct sadb_msg buf, *newmsg; 15649a4365d0SYoshinobu Inoue int len, reallen; 15659a4365d0SYoshinobu Inoue 15669a4365d0SYoshinobu Inoue while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) { 156733841545SHajimu UMEMOTO if (errno == EINTR) 156833841545SHajimu UMEMOTO continue; 15693c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 15709a4365d0SYoshinobu Inoue return NULL; 15719a4365d0SYoshinobu Inoue } 15729a4365d0SYoshinobu Inoue 15739a4365d0SYoshinobu Inoue if (len < sizeof(buf)) { 15749a4365d0SYoshinobu Inoue recv(so, (caddr_t)&buf, sizeof(buf), 0); 15753c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_MAX; 15769a4365d0SYoshinobu Inoue return NULL; 15779a4365d0SYoshinobu Inoue } 15789a4365d0SYoshinobu Inoue 15799a4365d0SYoshinobu Inoue /* read real message */ 15809a4365d0SYoshinobu Inoue reallen = PFKEY_UNUNIT64(buf.sadb_msg_len); 15819929cc5dSPedro F. Giffuni if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == NULL) { 15823c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 15839a4365d0SYoshinobu Inoue return NULL; 15849a4365d0SYoshinobu Inoue } 15859a4365d0SYoshinobu Inoue 15869a4365d0SYoshinobu Inoue while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) { 158733841545SHajimu UMEMOTO if (errno == EINTR) 158833841545SHajimu UMEMOTO continue; 15893c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 15909a4365d0SYoshinobu Inoue free(newmsg); 15919a4365d0SYoshinobu Inoue return NULL; 15929a4365d0SYoshinobu Inoue } 15939a4365d0SYoshinobu Inoue 15949a4365d0SYoshinobu Inoue if (len != reallen) { 15953c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_SYSTEM_ERROR; 15969a4365d0SYoshinobu Inoue free(newmsg); 15979a4365d0SYoshinobu Inoue return NULL; 15989a4365d0SYoshinobu Inoue } 15999a4365d0SYoshinobu Inoue 160033841545SHajimu UMEMOTO /* don't trust what the kernel says, validate! */ 160133841545SHajimu UMEMOTO if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) { 160233841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_SYSTEM_ERROR; 160333841545SHajimu UMEMOTO free(newmsg); 160433841545SHajimu UMEMOTO return NULL; 160533841545SHajimu UMEMOTO } 160633841545SHajimu UMEMOTO 16073c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 16089a4365d0SYoshinobu Inoue return newmsg; 16099a4365d0SYoshinobu Inoue } 16109a4365d0SYoshinobu Inoue 16119a4365d0SYoshinobu Inoue /* 16129a4365d0SYoshinobu Inoue * send message to a socket. 16139a4365d0SYoshinobu Inoue * OUT: 16149a4365d0SYoshinobu Inoue * others: success and return length sent. 16159a4365d0SYoshinobu Inoue * -1 : fail. 16169a4365d0SYoshinobu Inoue */ 16179a4365d0SYoshinobu Inoue int 1618650d6cc1SKonstantin Belousov pfkey_send(int so, struct sadb_msg *msg, int len) 16199a4365d0SYoshinobu Inoue { 16209a4365d0SYoshinobu Inoue if ((len = send(so, (caddr_t)msg, len, 0)) < 0) { 16213c62e87aSJun-ichiro itojun Hagino __ipsec_set_strerror(strerror(errno)); 16229a4365d0SYoshinobu Inoue return -1; 16239a4365d0SYoshinobu Inoue } 16249a4365d0SYoshinobu Inoue 16253c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 16269a4365d0SYoshinobu Inoue return len; 16279a4365d0SYoshinobu Inoue } 16289a4365d0SYoshinobu Inoue 16299a4365d0SYoshinobu Inoue /* 16309a4365d0SYoshinobu Inoue * %%% Utilities 16319a4365d0SYoshinobu Inoue * NOTE: These functions are derived from netkey/key.c in KAME. 16329a4365d0SYoshinobu Inoue */ 16339a4365d0SYoshinobu Inoue /* 16349a4365d0SYoshinobu Inoue * set the pointer to each header in this message buffer. 16359a4365d0SYoshinobu Inoue * IN: msg: pointer to message buffer. 16369a4365d0SYoshinobu Inoue * mhp: pointer to the buffer initialized like below: 16379a4365d0SYoshinobu Inoue * caddr_t mhp[SADB_EXT_MAX + 1]; 16389a4365d0SYoshinobu Inoue * OUT: -1: invalid. 16399a4365d0SYoshinobu Inoue * 0: valid. 164033841545SHajimu UMEMOTO * 164133841545SHajimu UMEMOTO * XXX should be rewritten to obtain length explicitly 16429a4365d0SYoshinobu Inoue */ 16439a4365d0SYoshinobu Inoue int 1644650d6cc1SKonstantin Belousov pfkey_align(struct sadb_msg *msg, caddr_t *mhp) 16459a4365d0SYoshinobu Inoue { 16469a4365d0SYoshinobu Inoue struct sadb_ext *ext; 16479a4365d0SYoshinobu Inoue int i; 164833841545SHajimu UMEMOTO caddr_t p; 164933841545SHajimu UMEMOTO caddr_t ep; /* XXX should be passed from upper layer */ 16509a4365d0SYoshinobu Inoue 16519a4365d0SYoshinobu Inoue /* validity check */ 16529a4365d0SYoshinobu Inoue if (msg == NULL || mhp == NULL) { 16533c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 16549a4365d0SYoshinobu Inoue return -1; 16559a4365d0SYoshinobu Inoue } 16569a4365d0SYoshinobu Inoue 16579a4365d0SYoshinobu Inoue /* initialize */ 16589a4365d0SYoshinobu Inoue for (i = 0; i < SADB_EXT_MAX + 1; i++) 16599a4365d0SYoshinobu Inoue mhp[i] = NULL; 16609a4365d0SYoshinobu Inoue 16619a4365d0SYoshinobu Inoue mhp[0] = (caddr_t)msg; 16629a4365d0SYoshinobu Inoue 166333841545SHajimu UMEMOTO /* initialize */ 166433841545SHajimu UMEMOTO p = (caddr_t) msg; 166533841545SHajimu UMEMOTO ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len); 16669a4365d0SYoshinobu Inoue 166733841545SHajimu UMEMOTO /* skip base header */ 166833841545SHajimu UMEMOTO p += sizeof(struct sadb_msg); 166933841545SHajimu UMEMOTO 167033841545SHajimu UMEMOTO while (p < ep) { 167133841545SHajimu UMEMOTO ext = (struct sadb_ext *)p; 167233841545SHajimu UMEMOTO if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) || 167333841545SHajimu UMEMOTO ep < p + PFKEY_EXTLEN(ext)) { 167433841545SHajimu UMEMOTO /* invalid format */ 167533841545SHajimu UMEMOTO break; 167633841545SHajimu UMEMOTO } 167733841545SHajimu UMEMOTO 16789a4365d0SYoshinobu Inoue /* duplicate check */ 16799a4365d0SYoshinobu Inoue /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/ 1680*3d95e9e3SKonstantin Belousov if (mhp[ext->sadb_ext_type] != NULL && 1681*3d95e9e3SKonstantin Belousov ext->sadb_ext_type != SADB_X_EXT_IF_HW_OFFL /* XXXKIB */) { 16823c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; 16839a4365d0SYoshinobu Inoue return -1; 16849a4365d0SYoshinobu Inoue } 16859a4365d0SYoshinobu Inoue 16869a4365d0SYoshinobu Inoue /* set pointer */ 16879a4365d0SYoshinobu Inoue switch (ext->sadb_ext_type) { 16889a4365d0SYoshinobu Inoue case SADB_EXT_SA: 16899a4365d0SYoshinobu Inoue case SADB_EXT_LIFETIME_CURRENT: 16909a4365d0SYoshinobu Inoue case SADB_EXT_LIFETIME_HARD: 16919a4365d0SYoshinobu Inoue case SADB_EXT_LIFETIME_SOFT: 16929a4365d0SYoshinobu Inoue case SADB_EXT_ADDRESS_SRC: 16939a4365d0SYoshinobu Inoue case SADB_EXT_ADDRESS_DST: 16949a4365d0SYoshinobu Inoue case SADB_EXT_ADDRESS_PROXY: 16959a4365d0SYoshinobu Inoue case SADB_EXT_KEY_AUTH: 16969a4365d0SYoshinobu Inoue /* XXX should to be check weak keys. */ 16979a4365d0SYoshinobu Inoue case SADB_EXT_KEY_ENCRYPT: 16989a4365d0SYoshinobu Inoue /* XXX should to be check weak keys. */ 16999a4365d0SYoshinobu Inoue case SADB_EXT_IDENTITY_SRC: 17009a4365d0SYoshinobu Inoue case SADB_EXT_IDENTITY_DST: 17019a4365d0SYoshinobu Inoue case SADB_EXT_SENSITIVITY: 17029a4365d0SYoshinobu Inoue case SADB_EXT_PROPOSAL: 17039a4365d0SYoshinobu Inoue case SADB_EXT_SUPPORTED_AUTH: 17049a4365d0SYoshinobu Inoue case SADB_EXT_SUPPORTED_ENCRYPT: 17059a4365d0SYoshinobu Inoue case SADB_EXT_SPIRANGE: 17069a4365d0SYoshinobu Inoue case SADB_X_EXT_POLICY: 17073c62e87aSJun-ichiro itojun Hagino case SADB_X_EXT_SA2: 1708fb53b9cfSBjoern A. Zeeb case SADB_X_EXT_NAT_T_TYPE: 1709fb53b9cfSBjoern A. Zeeb case SADB_X_EXT_NAT_T_SPORT: 1710fb53b9cfSBjoern A. Zeeb case SADB_X_EXT_NAT_T_DPORT: 1711fb53b9cfSBjoern A. Zeeb case SADB_X_EXT_NAT_T_OAI: 1712fb53b9cfSBjoern A. Zeeb case SADB_X_EXT_NAT_T_OAR: 1713fb53b9cfSBjoern A. Zeeb case SADB_X_EXT_NAT_T_FRAG: 1714fcf59617SAndrey V. Elsukov case SADB_X_EXT_SA_REPLAY: 1715fcf59617SAndrey V. Elsukov case SADB_X_EXT_NEW_ADDRESS_SRC: 1716fcf59617SAndrey V. Elsukov case SADB_X_EXT_NEW_ADDRESS_DST: 17171b1cd327SKonstantin Belousov case SADB_X_EXT_LFT_CUR_SW_OFFL: 17181b1cd327SKonstantin Belousov case SADB_X_EXT_LFT_CUR_HW_OFFL: 1719*3d95e9e3SKonstantin Belousov case SADB_X_EXT_IF_HW_OFFL: 1720fb53b9cfSBjoern A. Zeeb mhp[ext->sadb_ext_type] = (caddr_t)ext; 1721fb53b9cfSBjoern A. Zeeb break; 17229a4365d0SYoshinobu Inoue default: 17233c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; 17249a4365d0SYoshinobu Inoue return -1; 17259a4365d0SYoshinobu Inoue } 17269a4365d0SYoshinobu Inoue 172733841545SHajimu UMEMOTO p += PFKEY_EXTLEN(ext); 172833841545SHajimu UMEMOTO } 172933841545SHajimu UMEMOTO 173033841545SHajimu UMEMOTO if (p != ep) { 173133841545SHajimu UMEMOTO __ipsec_errcode = EIPSEC_INVAL_SADBMSG; 173233841545SHajimu UMEMOTO return -1; 17339a4365d0SYoshinobu Inoue } 17349a4365d0SYoshinobu Inoue 17353c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 17369a4365d0SYoshinobu Inoue return 0; 17379a4365d0SYoshinobu Inoue } 17389a4365d0SYoshinobu Inoue 17399a4365d0SYoshinobu Inoue /* 17409a4365d0SYoshinobu Inoue * check basic usage for sadb_msg, 17419a4365d0SYoshinobu Inoue * NOTE: This routine is derived from netkey/key.c in KAME. 17429a4365d0SYoshinobu Inoue * IN: msg: pointer to message buffer. 17439a4365d0SYoshinobu Inoue * mhp: pointer to the buffer initialized like below: 17449a4365d0SYoshinobu Inoue * 17459a4365d0SYoshinobu Inoue * caddr_t mhp[SADB_EXT_MAX + 1]; 17469a4365d0SYoshinobu Inoue * 17479a4365d0SYoshinobu Inoue * OUT: -1: invalid. 17489a4365d0SYoshinobu Inoue * 0: valid. 17499a4365d0SYoshinobu Inoue */ 17509a4365d0SYoshinobu Inoue int 1751650d6cc1SKonstantin Belousov pfkey_check(caddr_t *mhp) 17529a4365d0SYoshinobu Inoue { 17539a4365d0SYoshinobu Inoue struct sadb_msg *msg; 17549a4365d0SYoshinobu Inoue 17559a4365d0SYoshinobu Inoue /* validity check */ 17569a4365d0SYoshinobu Inoue if (mhp == NULL || mhp[0] == NULL) { 17573c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; 17589a4365d0SYoshinobu Inoue return -1; 17599a4365d0SYoshinobu Inoue } 17609a4365d0SYoshinobu Inoue 17619a4365d0SYoshinobu Inoue msg = (struct sadb_msg *)mhp[0]; 17629a4365d0SYoshinobu Inoue 17639a4365d0SYoshinobu Inoue /* check version */ 17649a4365d0SYoshinobu Inoue if (msg->sadb_msg_version != PF_KEY_V2) { 17653c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_VERSION; 17669a4365d0SYoshinobu Inoue return -1; 17679a4365d0SYoshinobu Inoue } 17689a4365d0SYoshinobu Inoue 17699a4365d0SYoshinobu Inoue /* check type */ 17709a4365d0SYoshinobu Inoue if (msg->sadb_msg_type > SADB_MAX) { 17713c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_MSGTYPE; 17729a4365d0SYoshinobu Inoue return -1; 17739a4365d0SYoshinobu Inoue } 17749a4365d0SYoshinobu Inoue 17759a4365d0SYoshinobu Inoue /* check SA type */ 17769a4365d0SYoshinobu Inoue switch (msg->sadb_msg_satype) { 17779a4365d0SYoshinobu Inoue case SADB_SATYPE_UNSPEC: 17789a4365d0SYoshinobu Inoue switch (msg->sadb_msg_type) { 17799a4365d0SYoshinobu Inoue case SADB_GETSPI: 17809a4365d0SYoshinobu Inoue case SADB_UPDATE: 17819a4365d0SYoshinobu Inoue case SADB_ADD: 17829a4365d0SYoshinobu Inoue case SADB_DELETE: 17839a4365d0SYoshinobu Inoue case SADB_GET: 17849a4365d0SYoshinobu Inoue case SADB_ACQUIRE: 17859a4365d0SYoshinobu Inoue case SADB_EXPIRE: 17863c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 17879a4365d0SYoshinobu Inoue return -1; 17889a4365d0SYoshinobu Inoue } 17899a4365d0SYoshinobu Inoue break; 17909a4365d0SYoshinobu Inoue case SADB_SATYPE_ESP: 17919a4365d0SYoshinobu Inoue case SADB_SATYPE_AH: 17929a4365d0SYoshinobu Inoue case SADB_X_SATYPE_IPCOMP: 17931922fd12SBruce M Simpson case SADB_X_SATYPE_TCPSIGNATURE: 17949a4365d0SYoshinobu Inoue switch (msg->sadb_msg_type) { 17959a4365d0SYoshinobu Inoue case SADB_X_SPDADD: 17969a4365d0SYoshinobu Inoue case SADB_X_SPDDELETE: 17979a4365d0SYoshinobu Inoue case SADB_X_SPDGET: 17989a4365d0SYoshinobu Inoue case SADB_X_SPDDUMP: 17999a4365d0SYoshinobu Inoue case SADB_X_SPDFLUSH: 18003c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 18019a4365d0SYoshinobu Inoue return -1; 18029a4365d0SYoshinobu Inoue } 18039a4365d0SYoshinobu Inoue break; 18049a4365d0SYoshinobu Inoue case SADB_SATYPE_RSVP: 18059a4365d0SYoshinobu Inoue case SADB_SATYPE_OSPFV2: 18069a4365d0SYoshinobu Inoue case SADB_SATYPE_RIPV2: 18079a4365d0SYoshinobu Inoue case SADB_SATYPE_MIP: 18083c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NOT_SUPPORTED; 18099a4365d0SYoshinobu Inoue return -1; 18109a4365d0SYoshinobu Inoue case 1: /* XXX: What does it do ? */ 18119a4365d0SYoshinobu Inoue if (msg->sadb_msg_type == SADB_X_PROMISC) 18129a4365d0SYoshinobu Inoue break; 18139a4365d0SYoshinobu Inoue /*FALLTHROUGH*/ 18149a4365d0SYoshinobu Inoue default: 18153c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_SATYPE; 18169a4365d0SYoshinobu Inoue return -1; 18179a4365d0SYoshinobu Inoue } 18189a4365d0SYoshinobu Inoue 18199a4365d0SYoshinobu Inoue /* check field of upper layer protocol and address family */ 18209a4365d0SYoshinobu Inoue if (mhp[SADB_EXT_ADDRESS_SRC] != NULL 18219a4365d0SYoshinobu Inoue && mhp[SADB_EXT_ADDRESS_DST] != NULL) { 18229a4365d0SYoshinobu Inoue struct sadb_address *src0, *dst0; 18239a4365d0SYoshinobu Inoue 18249a4365d0SYoshinobu Inoue src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]); 18259a4365d0SYoshinobu Inoue dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]); 18269a4365d0SYoshinobu Inoue 18279a4365d0SYoshinobu Inoue if (src0->sadb_address_proto != dst0->sadb_address_proto) { 18283c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_PROTO_MISMATCH; 18299a4365d0SYoshinobu Inoue return -1; 18309a4365d0SYoshinobu Inoue } 18319a4365d0SYoshinobu Inoue 18329a4365d0SYoshinobu Inoue if (PFKEY_ADDR_SADDR(src0)->sa_family 18339a4365d0SYoshinobu Inoue != PFKEY_ADDR_SADDR(dst0)->sa_family) { 18343c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; 18359a4365d0SYoshinobu Inoue return -1; 18369a4365d0SYoshinobu Inoue } 18379a4365d0SYoshinobu Inoue 18389a4365d0SYoshinobu Inoue switch (PFKEY_ADDR_SADDR(src0)->sa_family) { 18399a4365d0SYoshinobu Inoue case AF_INET: 18409a4365d0SYoshinobu Inoue case AF_INET6: 18419a4365d0SYoshinobu Inoue break; 18429a4365d0SYoshinobu Inoue default: 18433c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_INVAL_FAMILY; 18449a4365d0SYoshinobu Inoue return -1; 18459a4365d0SYoshinobu Inoue } 18469a4365d0SYoshinobu Inoue 18479a4365d0SYoshinobu Inoue /* 18489a4365d0SYoshinobu Inoue * prefixlen == 0 is valid because there must be the case 18499a4365d0SYoshinobu Inoue * all addresses are matched. 18509a4365d0SYoshinobu Inoue */ 18519a4365d0SYoshinobu Inoue } 18529a4365d0SYoshinobu Inoue 18533c62e87aSJun-ichiro itojun Hagino __ipsec_errcode = EIPSEC_NO_ERROR; 18549a4365d0SYoshinobu Inoue return 0; 18559a4365d0SYoshinobu Inoue } 18569a4365d0SYoshinobu Inoue 18579a4365d0SYoshinobu Inoue /* 18589a4365d0SYoshinobu Inoue * set data into sadb_msg. 18599a4365d0SYoshinobu Inoue * `buf' must has been allocated sufficiently. 18609a4365d0SYoshinobu Inoue */ 18619a4365d0SYoshinobu Inoue static caddr_t 1862650d6cc1SKonstantin Belousov pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen, 1863650d6cc1SKonstantin Belousov u_int satype, u_int32_t seq, pid_t pid) 18649a4365d0SYoshinobu Inoue { 18659a4365d0SYoshinobu Inoue struct sadb_msg *p; 18669a4365d0SYoshinobu Inoue u_int len; 18679a4365d0SYoshinobu Inoue 18689a4365d0SYoshinobu Inoue p = (struct sadb_msg *)buf; 18693c62e87aSJun-ichiro itojun Hagino len = sizeof(struct sadb_msg); 18709a4365d0SYoshinobu Inoue 187133841545SHajimu UMEMOTO if (buf + len > lim) 187233841545SHajimu UMEMOTO return NULL; 187333841545SHajimu UMEMOTO 18749a4365d0SYoshinobu Inoue memset(p, 0, len); 18759a4365d0SYoshinobu Inoue p->sadb_msg_version = PF_KEY_V2; 18769a4365d0SYoshinobu Inoue p->sadb_msg_type = type; 18779a4365d0SYoshinobu Inoue p->sadb_msg_errno = 0; 18789a4365d0SYoshinobu Inoue p->sadb_msg_satype = satype; 18799a4365d0SYoshinobu Inoue p->sadb_msg_len = PFKEY_UNIT64(tlen); 18809a4365d0SYoshinobu Inoue p->sadb_msg_reserved = 0; 18819a4365d0SYoshinobu Inoue p->sadb_msg_seq = seq; 18829a4365d0SYoshinobu Inoue p->sadb_msg_pid = (u_int32_t)pid; 18839a4365d0SYoshinobu Inoue 18849a4365d0SYoshinobu Inoue return(buf + len); 18859a4365d0SYoshinobu Inoue } 18869a4365d0SYoshinobu Inoue 18879a4365d0SYoshinobu Inoue /* 18889a4365d0SYoshinobu Inoue * copy secasvar data into sadb_address. 18899a4365d0SYoshinobu Inoue * `buf' must has been allocated sufficiently. 18909a4365d0SYoshinobu Inoue */ 18919a4365d0SYoshinobu Inoue static caddr_t 1892650d6cc1SKonstantin Belousov pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize, 1893650d6cc1SKonstantin Belousov u_int auth, u_int enc, u_int32_t flags) 18949a4365d0SYoshinobu Inoue { 18959a4365d0SYoshinobu Inoue struct sadb_sa *p; 18969a4365d0SYoshinobu Inoue u_int len; 18979a4365d0SYoshinobu Inoue 18989a4365d0SYoshinobu Inoue p = (struct sadb_sa *)buf; 18999a4365d0SYoshinobu Inoue len = sizeof(struct sadb_sa); 19009a4365d0SYoshinobu Inoue 190133841545SHajimu UMEMOTO if (buf + len > lim) 190233841545SHajimu UMEMOTO return NULL; 190333841545SHajimu UMEMOTO 19049a4365d0SYoshinobu Inoue memset(p, 0, len); 19059a4365d0SYoshinobu Inoue p->sadb_sa_len = PFKEY_UNIT64(len); 19069a4365d0SYoshinobu Inoue p->sadb_sa_exttype = SADB_EXT_SA; 19079a4365d0SYoshinobu Inoue p->sadb_sa_spi = spi; 19084e0e8f31SAndrey V. Elsukov p->sadb_sa_replay = wsize > UINT8_MAX ? UINT8_MAX: wsize; 19099a4365d0SYoshinobu Inoue p->sadb_sa_state = SADB_SASTATE_LARVAL; 19109a4365d0SYoshinobu Inoue p->sadb_sa_auth = auth; 19119a4365d0SYoshinobu Inoue p->sadb_sa_encrypt = enc; 19129a4365d0SYoshinobu Inoue p->sadb_sa_flags = flags; 19139a4365d0SYoshinobu Inoue 19149a4365d0SYoshinobu Inoue return(buf + len); 19159a4365d0SYoshinobu Inoue } 19169a4365d0SYoshinobu Inoue 19179a4365d0SYoshinobu Inoue /* 19184e0e8f31SAndrey V. Elsukov * Set data into sadb_x_sa_replay. 19194e0e8f31SAndrey V. Elsukov * `buf' must has been allocated sufficiently. 19204e0e8f31SAndrey V. Elsukov */ 19214e0e8f31SAndrey V. Elsukov static caddr_t 19224e0e8f31SAndrey V. Elsukov pfkey_setsadbxreplay(caddr_t buf, caddr_t lim, uint32_t wsize) 19234e0e8f31SAndrey V. Elsukov { 19244e0e8f31SAndrey V. Elsukov struct sadb_x_sa_replay *p; 19254e0e8f31SAndrey V. Elsukov u_int len; 19264e0e8f31SAndrey V. Elsukov 19274e0e8f31SAndrey V. Elsukov p = (struct sadb_x_sa_replay *)buf; 19284e0e8f31SAndrey V. Elsukov len = sizeof(struct sadb_x_sa_replay); 19294e0e8f31SAndrey V. Elsukov 19304e0e8f31SAndrey V. Elsukov if (buf + len > lim) 19314e0e8f31SAndrey V. Elsukov return (NULL); 19324e0e8f31SAndrey V. Elsukov 19334e0e8f31SAndrey V. Elsukov memset(p, 0, len); 19344e0e8f31SAndrey V. Elsukov p->sadb_x_sa_replay_len = PFKEY_UNIT64(len); 19354e0e8f31SAndrey V. Elsukov p->sadb_x_sa_replay_exttype = SADB_X_EXT_SA_REPLAY; 19364e0e8f31SAndrey V. Elsukov /* Convert wsize from bytes to number of packets. */ 19374e0e8f31SAndrey V. Elsukov p->sadb_x_sa_replay_replay = wsize << 3; 19384e0e8f31SAndrey V. Elsukov 19394e0e8f31SAndrey V. Elsukov return (buf + len); 19404e0e8f31SAndrey V. Elsukov } 19414e0e8f31SAndrey V. Elsukov 19424e0e8f31SAndrey V. Elsukov /* 19439a4365d0SYoshinobu Inoue * set data into sadb_address. 19449a4365d0SYoshinobu Inoue * `buf' must has been allocated sufficiently. 19459a4365d0SYoshinobu Inoue * prefixlen is in bits. 19469a4365d0SYoshinobu Inoue */ 19479a4365d0SYoshinobu Inoue static caddr_t 1948650d6cc1SKonstantin Belousov pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype, 1949650d6cc1SKonstantin Belousov struct sockaddr *saddr, u_int prefixlen, u_int ul_proto) 19509a4365d0SYoshinobu Inoue { 19519a4365d0SYoshinobu Inoue struct sadb_address *p; 19529a4365d0SYoshinobu Inoue u_int len; 19539a4365d0SYoshinobu Inoue 19549a4365d0SYoshinobu Inoue p = (struct sadb_address *)buf; 19559a4365d0SYoshinobu Inoue len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len); 19569a4365d0SYoshinobu Inoue 195733841545SHajimu UMEMOTO if (buf + len > lim) 195833841545SHajimu UMEMOTO return NULL; 195933841545SHajimu UMEMOTO 19609a4365d0SYoshinobu Inoue memset(p, 0, len); 19619a4365d0SYoshinobu Inoue p->sadb_address_len = PFKEY_UNIT64(len); 19629a4365d0SYoshinobu Inoue p->sadb_address_exttype = exttype & 0xffff; 19639a4365d0SYoshinobu Inoue p->sadb_address_proto = ul_proto & 0xff; 19649a4365d0SYoshinobu Inoue p->sadb_address_prefixlen = prefixlen; 19659a4365d0SYoshinobu Inoue p->sadb_address_reserved = 0; 19669a4365d0SYoshinobu Inoue 19679a4365d0SYoshinobu Inoue memcpy(p + 1, saddr, saddr->sa_len); 19689a4365d0SYoshinobu Inoue 19699a4365d0SYoshinobu Inoue return(buf + len); 19709a4365d0SYoshinobu Inoue } 19719a4365d0SYoshinobu Inoue 19729a4365d0SYoshinobu Inoue /* 19739a4365d0SYoshinobu Inoue * set sadb_key structure after clearing buffer with zero. 19749a4365d0SYoshinobu Inoue * OUT: the pointer of buf + len. 19759a4365d0SYoshinobu Inoue */ 19769a4365d0SYoshinobu Inoue static caddr_t 1977650d6cc1SKonstantin Belousov pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key, u_int keylen) 19789a4365d0SYoshinobu Inoue { 19799a4365d0SYoshinobu Inoue struct sadb_key *p; 19809a4365d0SYoshinobu Inoue u_int len; 19819a4365d0SYoshinobu Inoue 19829a4365d0SYoshinobu Inoue p = (struct sadb_key *)buf; 19839a4365d0SYoshinobu Inoue len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); 19849a4365d0SYoshinobu Inoue 198533841545SHajimu UMEMOTO if (buf + len > lim) 198633841545SHajimu UMEMOTO return NULL; 198733841545SHajimu UMEMOTO 19889a4365d0SYoshinobu Inoue memset(p, 0, len); 19899a4365d0SYoshinobu Inoue p->sadb_key_len = PFKEY_UNIT64(len); 19909a4365d0SYoshinobu Inoue p->sadb_key_exttype = type; 19919a4365d0SYoshinobu Inoue p->sadb_key_bits = keylen << 3; 19929a4365d0SYoshinobu Inoue p->sadb_key_reserved = 0; 19939a4365d0SYoshinobu Inoue 19949a4365d0SYoshinobu Inoue memcpy(p + 1, key, keylen); 19959a4365d0SYoshinobu Inoue 19969a4365d0SYoshinobu Inoue return buf + len; 19979a4365d0SYoshinobu Inoue } 19989a4365d0SYoshinobu Inoue 19999a4365d0SYoshinobu Inoue /* 20009a4365d0SYoshinobu Inoue * set sadb_lifetime structure after clearing buffer with zero. 20019a4365d0SYoshinobu Inoue * OUT: the pointer of buf + len. 20029a4365d0SYoshinobu Inoue */ 20039a4365d0SYoshinobu Inoue static caddr_t 2004650d6cc1SKonstantin Belousov pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc, 2005650d6cc1SKonstantin Belousov u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime) 20069a4365d0SYoshinobu Inoue { 20079a4365d0SYoshinobu Inoue struct sadb_lifetime *p; 20089a4365d0SYoshinobu Inoue u_int len; 20099a4365d0SYoshinobu Inoue 20109a4365d0SYoshinobu Inoue p = (struct sadb_lifetime *)buf; 20119a4365d0SYoshinobu Inoue len = sizeof(struct sadb_lifetime); 20129a4365d0SYoshinobu Inoue 201333841545SHajimu UMEMOTO if (buf + len > lim) 201433841545SHajimu UMEMOTO return NULL; 201533841545SHajimu UMEMOTO 20169a4365d0SYoshinobu Inoue memset(p, 0, len); 20179a4365d0SYoshinobu Inoue p->sadb_lifetime_len = PFKEY_UNIT64(len); 20189a4365d0SYoshinobu Inoue p->sadb_lifetime_exttype = type; 20199a4365d0SYoshinobu Inoue 20209a4365d0SYoshinobu Inoue switch (type) { 20219a4365d0SYoshinobu Inoue case SADB_EXT_LIFETIME_SOFT: 20229a4365d0SYoshinobu Inoue p->sadb_lifetime_allocations 20239a4365d0SYoshinobu Inoue = (l_alloc * soft_lifetime_allocations_rate) /100; 20249a4365d0SYoshinobu Inoue p->sadb_lifetime_bytes 20253c62e87aSJun-ichiro itojun Hagino = (l_bytes * soft_lifetime_bytes_rate) /100; 20269a4365d0SYoshinobu Inoue p->sadb_lifetime_addtime 20279a4365d0SYoshinobu Inoue = (l_addtime * soft_lifetime_addtime_rate) /100; 20289a4365d0SYoshinobu Inoue p->sadb_lifetime_usetime 20299a4365d0SYoshinobu Inoue = (l_usetime * soft_lifetime_usetime_rate) /100; 20309a4365d0SYoshinobu Inoue break; 20319a4365d0SYoshinobu Inoue case SADB_EXT_LIFETIME_HARD: 20329a4365d0SYoshinobu Inoue p->sadb_lifetime_allocations = l_alloc; 20333c62e87aSJun-ichiro itojun Hagino p->sadb_lifetime_bytes = l_bytes; 20349a4365d0SYoshinobu Inoue p->sadb_lifetime_addtime = l_addtime; 20359a4365d0SYoshinobu Inoue p->sadb_lifetime_usetime = l_usetime; 20369a4365d0SYoshinobu Inoue break; 20379a4365d0SYoshinobu Inoue } 20389a4365d0SYoshinobu Inoue 20399a4365d0SYoshinobu Inoue return buf + len; 20409a4365d0SYoshinobu Inoue } 20419a4365d0SYoshinobu Inoue 20423c62e87aSJun-ichiro itojun Hagino /* 20433c62e87aSJun-ichiro itojun Hagino * copy secasvar data into sadb_address. 20443c62e87aSJun-ichiro itojun Hagino * `buf' must has been allocated sufficiently. 20453c62e87aSJun-ichiro itojun Hagino */ 20463c62e87aSJun-ichiro itojun Hagino static caddr_t 2047650d6cc1SKonstantin Belousov pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid) 20483c62e87aSJun-ichiro itojun Hagino { 20493c62e87aSJun-ichiro itojun Hagino struct sadb_x_sa2 *p; 20503c62e87aSJun-ichiro itojun Hagino u_int8_t mode = mode0 & 0xff; 20513c62e87aSJun-ichiro itojun Hagino u_int len; 20523c62e87aSJun-ichiro itojun Hagino 20533c62e87aSJun-ichiro itojun Hagino p = (struct sadb_x_sa2 *)buf; 20543c62e87aSJun-ichiro itojun Hagino len = sizeof(struct sadb_x_sa2); 20553c62e87aSJun-ichiro itojun Hagino 205633841545SHajimu UMEMOTO if (buf + len > lim) 205733841545SHajimu UMEMOTO return NULL; 205833841545SHajimu UMEMOTO 20593c62e87aSJun-ichiro itojun Hagino memset(p, 0, len); 20603c62e87aSJun-ichiro itojun Hagino p->sadb_x_sa2_len = PFKEY_UNIT64(len); 20613c62e87aSJun-ichiro itojun Hagino p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; 20623c62e87aSJun-ichiro itojun Hagino p->sadb_x_sa2_mode = mode; 20633c62e87aSJun-ichiro itojun Hagino p->sadb_x_sa2_reqid = reqid; 20643c62e87aSJun-ichiro itojun Hagino 20653c62e87aSJun-ichiro itojun Hagino return(buf + len); 20663c62e87aSJun-ichiro itojun Hagino } 2067