📄 pfkey_v2_parse.c
字号:
/* * RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * RCSID $Id: pfkey_v2_parse.c,v 1.63 2004/10/28 22:54:10 mcr Exp $ *//* * Template from klips/net/ipsec/ipsec/ipsec_parser.c. */char pfkey_v2_parse_c_version[] = "$Id: pfkey_v2_parse.c,v 1.63 2004/10/28 22:54:10 mcr Exp $";/* * Some ugly stuff to allow consistent debugging code for use in the * kernel and in user space*/#ifdef __KERNEL__# include <linux/kernel.h> /* for printk */#include "openswan/ipsec_kversion.h" /* for malloc switch */# ifdef MALLOC_SLAB# include <linux/slab.h> /* kmalloc() */# else /* MALLOC_SLAB */# include <linux/malloc.h> /* kmalloc() */# endif /* MALLOC_SLAB */# include <linux/errno.h> /* error codes */# include <linux/types.h> /* size_t */# include <linux/interrupt.h> /* mark_bh */# include <linux/netdevice.h> /* struct device, and other headers */# include <linux/etherdevice.h> /* eth_type_trans */# include <linux/ip.h> /* struct iphdr */ # if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)# include <linux/ipv6.h> /* struct ipv6hdr */# endif /* if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */extern int debug_pfkey;# include <openswan.h>#include "openswan/ipsec_encap.h"#else /* __KERNEL__ */# include <sys/types.h># include <linux/types.h># include <linux/errno.h># include <openswan.h># include "constants.h" # include "programs/pluto/defs.h" /* for PRINTF_LIKE */#endif /* __KERNEL__ */#include <pfkeyv2.h>#include <pfkey.h>#include "openswan/ipsec_sa.h" /* IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_IDX_WIDTH *//* * how to handle debugging for pfkey. */#include <openswan/pfkey_debug.h>unsigned int pfkey_lib_debug = PF_KEY_DEBUG_PARSE_NONE;void (*pfkey_debug_func)(const char *message, ...) PRINTF_LIKE(1);void (*pfkey_error_func)(const char *message, ...) PRINTF_LIKE(1);#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)struct satype_tbl { uint8_t proto; uint8_t satype; char* name;} static satype_tbl[] = {#ifdef __KERNEL__ { IPPROTO_ESP, SADB_SATYPE_ESP, "ESP" }, { IPPROTO_AH, SADB_SATYPE_AH, "AH" }, { IPPROTO_IPIP, SADB_X_SATYPE_IPIP, "IPIP" },#ifdef CONFIG_KLIPS_IPCOMP { IPPROTO_COMP, SADB_X_SATYPE_COMP, "COMP" },#endif /* CONFIG_KLIPS_IPCOMP */ { IPPROTO_INT, SADB_X_SATYPE_INT, "INT" },#else /* __KERNEL__ */ { SA_ESP, SADB_SATYPE_ESP, "ESP" }, { SA_AH, SADB_SATYPE_AH, "AH" }, { SA_IPIP, SADB_X_SATYPE_IPIP, "IPIP" }, { SA_COMP, SADB_X_SATYPE_COMP, "COMP" }, { SA_INT, SADB_X_SATYPE_INT, "INT" },#endif /* __KERNEL__ */ { 0, 0, "UNKNOWN" }};uint8_tsatype2proto(uint8_t satype){ int i =0; while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { i++; } return satype_tbl[i].proto;}uint8_tproto2satype(uint8_t proto){ int i = 0; while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { i++; } return satype_tbl[i].satype;}char*satype2name(uint8_t satype){ int i = 0; while(satype_tbl[i].satype != satype && satype_tbl[i].satype != 0) { i++; } return satype_tbl[i].name;}char*proto2name(uint8_t proto){ int i = 0; while(satype_tbl[i].proto != proto && satype_tbl[i].proto != 0) { i++; } return satype_tbl[i].name;}/* Default extension parsers taken from the KLIPS code */DEBUG_NO_STATIC intpfkey_sa_parse(struct sadb_ext *pfkey_ext){ int error = 0; struct sadb_sa *pfkey_sa = (struct sadb_sa *)pfkey_ext;#if 0 struct sadb_sa sav2;#endif /* sanity checks... */ if(!pfkey_sa) { ERROR("pfkey_sa_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } #if 0 /* check if this structure is short, and if so, fix it up. * XXX this is NOT the way to do things. */ if(pfkey_sa->sadb_sa_len == sizeof(struct sadb_sa_v1)/IPSEC_PFKEYv2_ALIGN) { /* yes, so clear out a temporary structure, and copy first */ memset(&sav2, 0, sizeof(sav2)); memcpy(&sav2, pfkey_sa, sizeof(struct sadb_sa_v1)); sav2.sadb_x_sa_ref=-1; sav2.sadb_sa_len = sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN; pfkey_sa = &sav2; }#endif if(pfkey_sa->sadb_sa_len != sizeof(struct sadb_sa) / IPSEC_PFKEYv2_ALIGN) { ERROR( "pfkey_sa_parse: " "length wrong pfkey_sa->sadb_sa_len=%d sizeof(struct sadb_sa)=%d.\n", pfkey_sa->sadb_sa_len, (int)sizeof(struct sadb_sa)); SENDERR(EINVAL); }#if SADB_EALG_MAX < 255 if(pfkey_sa->sadb_sa_encrypt > SADB_EALG_MAX) { ERROR( "pfkey_sa_parse: " "pfkey_sa->sadb_sa_encrypt=%d > SADB_EALG_MAX=%d.\n", pfkey_sa->sadb_sa_encrypt, SADB_EALG_MAX); SENDERR(EINVAL); }#endif #if SADB_AALG_MAX < 255 if(pfkey_sa->sadb_sa_auth > SADB_AALG_MAX) { ERROR( "pfkey_sa_parse: " "pfkey_sa->sadb_sa_auth=%d > SADB_AALG_MAX=%d.\n", pfkey_sa->sadb_sa_auth, SADB_AALG_MAX); SENDERR(EINVAL); }#endif #if SADB_SASTATE_MAX < 255 if(pfkey_sa->sadb_sa_state > SADB_SASTATE_MAX) { ERROR( "pfkey_sa_parse: " "state=%d exceeds MAX=%d.\n", pfkey_sa->sadb_sa_state, SADB_SASTATE_MAX); SENDERR(EINVAL); }#endif if(pfkey_sa->sadb_sa_state == SADB_SASTATE_DEAD) { ERROR( "pfkey_sa_parse: " "state=%d is DEAD=%d.\n", pfkey_sa->sadb_sa_state, SADB_SASTATE_DEAD); SENDERR(EINVAL); } if(pfkey_sa->sadb_sa_replay > 64) { ERROR( "pfkey_sa_parse: " "replay window size: %d -- must be 0 <= size <= 64\n", pfkey_sa->sadb_sa_replay); SENDERR(EINVAL); } if(! ((pfkey_sa->sadb_sa_exttype == SADB_EXT_SA) || (pfkey_sa->sadb_sa_exttype == SADB_X_EXT_SA2))) { ERROR( "pfkey_sa_parse: " "unknown exttype=%d, expecting SADB_EXT_SA=%d or SADB_X_EXT_SA2=%d.\n", pfkey_sa->sadb_sa_exttype, SADB_EXT_SA, SADB_X_EXT_SA2); SENDERR(EINVAL); } if((IPSEC_SAREF_NULL != pfkey_sa->sadb_x_sa_ref) && (pfkey_sa->sadb_x_sa_ref >= (1 << IPSEC_SA_REF_TABLE_IDX_WIDTH))) { ERROR( "pfkey_sa_parse: " "SAref=%d must be (SAref == IPSEC_SAREF_NULL(%d) || SAref < IPSEC_SA_REF_TABLE_NUM_ENTRIES(%d)).\n", pfkey_sa->sadb_x_sa_ref, IPSEC_SAREF_NULL, IPSEC_SA_REF_TABLE_NUM_ENTRIES); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_sa_parse: " "successfully found len=%d exttype=%d(%s) spi=%08lx replay=%d state=%d auth=%d encrypt=%d flags=%d ref=%d.\n", pfkey_sa->sadb_sa_len, pfkey_sa->sadb_sa_exttype, pfkey_v2_sadb_ext_string(pfkey_sa->sadb_sa_exttype), (long unsigned int)ntohl(pfkey_sa->sadb_sa_spi), pfkey_sa->sadb_sa_replay, pfkey_sa->sadb_sa_state, pfkey_sa->sadb_sa_auth, pfkey_sa->sadb_sa_encrypt, pfkey_sa->sadb_sa_flags, pfkey_sa->sadb_x_sa_ref); errlab: return error;} DEBUG_NO_STATIC intpfkey_lifetime_parse(struct sadb_ext *pfkey_ext){ int error = 0; struct sadb_lifetime *pfkey_lifetime = (struct sadb_lifetime *)pfkey_ext; DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW, "pfkey_lifetime_parse:enter\n"); /* sanity checks... */ if(!pfkey_lifetime) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if(pfkey_lifetime->sadb_lifetime_len != sizeof(struct sadb_lifetime) / IPSEC_PFKEYv2_ALIGN) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "length wrong pfkey_lifetime->sadb_lifetime_len=%d sizeof(struct sadb_lifetime)=%d.\n", pfkey_lifetime->sadb_lifetime_len, (int)sizeof(struct sadb_lifetime)); SENDERR(EINVAL); } if((pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_HARD) && (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_SOFT) && (pfkey_lifetime->sadb_lifetime_exttype != SADB_EXT_LIFETIME_CURRENT)) { DEBUGGING(PF_KEY_DEBUG_PARSE_PROBLEM, "pfkey_lifetime_parse: " "unexpected ext_type=%d.\n", pfkey_lifetime->sadb_lifetime_exttype); SENDERR(EINVAL); } DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_lifetime_parse: " "life_type=%d(%s) alloc=%u bytes=%u add=%u use=%u pkts=%u.\n", pfkey_lifetime->sadb_lifetime_exttype, pfkey_v2_sadb_ext_string(pfkey_lifetime->sadb_lifetime_exttype), pfkey_lifetime->sadb_lifetime_allocations, (unsigned)pfkey_lifetime->sadb_lifetime_bytes, (unsigned)pfkey_lifetime->sadb_lifetime_addtime, (unsigned)pfkey_lifetime->sadb_lifetime_usetime, pfkey_lifetime->sadb_x_lifetime_packets); errlab: return error;}DEBUG_NO_STATIC intpfkey_address_parse(struct sadb_ext *pfkey_ext){ int error = 0; int saddr_len = 0; struct sadb_address *pfkey_address = (struct sadb_address *)pfkey_ext; struct sockaddr* s = (struct sockaddr*)((char*)pfkey_address + sizeof(*pfkey_address)); char ipaddr_txt[ADDRTOT_BUF]; /* sanity checks... */ if(!pfkey_address) { ERROR( "pfkey_address_parse: " "NULL pointer passed in.\n"); SENDERR(EINVAL); } if(pfkey_address->sadb_address_len < (sizeof(struct sadb_address) + sizeof(struct sockaddr))/ IPSEC_PFKEYv2_ALIGN) { ERROR("pfkey_address_parse: " "size wrong 1 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), (int)sizeof(struct sockaddr)); SENDERR(EINVAL); } if(pfkey_address->sadb_address_reserved) { ERROR("pfkey_address_parse: " "res=%d, must be zero.\n", pfkey_address->sadb_address_reserved); SENDERR(EINVAL); } switch(pfkey_address->sadb_address_exttype) { case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_EXT_ADDRESS_PROXY: case SADB_X_EXT_ADDRESS_DST2: case SADB_X_EXT_ADDRESS_SRC_FLOW: case SADB_X_EXT_ADDRESS_DST_FLOW: case SADB_X_EXT_ADDRESS_SRC_MASK: case SADB_X_EXT_ADDRESS_DST_MASK:#ifdef NAT_TRAVERSAL case SADB_X_EXT_NAT_T_OA:#endif break; default: ERROR( "pfkey_address_parse: " "unexpected ext_type=%d.\n", pfkey_address->sadb_address_exttype); SENDERR(EINVAL); } switch(s->sa_family) { case AF_INET: saddr_len = sizeof(struct sockaddr_in); sprintf(ipaddr_txt, "%d.%d.%d.%d" , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 0) & 0xFF , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 8) & 0xFF , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 16) & 0xFF , (((struct sockaddr_in*)s)->sin_addr.s_addr >> 24) & 0xFF); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ntohs(((struct sockaddr_in*)s)->sin_port)); break; case AF_INET6: saddr_len = sizeof(struct sockaddr_in6); sprintf(ipaddr_txt, "%x:%x:%x:%x:%x:%x:%x:%x" , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[0]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[1]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[2]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[3]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[4]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[5]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[6]) , ntohs(((struct sockaddr_in6*)s)->sin6_addr.s6_addr16[7])); DEBUGGING(PF_KEY_DEBUG_PARSE_STRUCT, "pfkey_address_parse: " "found exttype=%u(%s) family=%d(AF_INET6) address=%s proto=%u port=%u.\n", pfkey_address->sadb_address_exttype, pfkey_v2_sadb_ext_string(pfkey_address->sadb_address_exttype), s->sa_family, ipaddr_txt, pfkey_address->sadb_address_proto, ((struct sockaddr_in6*)s)->sin6_port); break; default: ERROR( "pfkey_address_parse: " "s->sa_family=%d not supported.\n", s->sa_family); SENDERR(EPFNOSUPPORT); } if(pfkey_address->sadb_address_len != DIVUP(sizeof(struct sadb_address) + saddr_len, IPSEC_PFKEYv2_ALIGN)) { ERROR( "pfkey_address_parse: " "size wrong 2 ext_len=%d, adr_ext_len=%d, saddr_len=%d.\n", pfkey_address->sadb_address_len, (int)sizeof(struct sadb_address), saddr_len); SENDERR(EINVAL); } if(pfkey_address->sadb_address_prefixlen != 0) { ERROR( "pfkey_address_parse: " "address prefixes not supported yet.\n"); SENDERR(EAFNOSUPPORT); /* not supported yet */ } /* XXX check if port!=0 */ DEBUGGING(PF_KEY_DEBUG_PARSE_FLOW,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -