📄 pfkey_v2_parser.c
字号:
/* * @(#) RFC2367 PF_KEYv2 Key management API message parser * Copyright (C) 1999, 2000, 2001 Richard Guy Briggs <rgb@freeswan.org> * * 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_parser.c,v 1.134.2.1 2006/05/01 14:37:25 mcr Exp $ *//* * Template from klips/net/ipsec/ipsec/ipsec_netlink.c. */char pfkey_v2_parser_c_version[] = "$Id: pfkey_v2_parser.c,v 1.134.2.1 2006/05/01 14:37:25 mcr Exp $";#include <linux/config.h>#include <linux/version.h>#include <linux/kernel.h> /* printk() */#include "openswan/ipsec_param.h"#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 */#include <linux/skbuff.h>#include <openswan.h>#include <crypto/des.h>#ifdef SPINLOCK# ifdef SPINLOCK_23# include <linux/spinlock.h> /* *lock* */# else /* SPINLOCK_23 */# include <asm/spinlock.h> /* *lock* */# endif /* SPINLOCK_23 */#endif /* SPINLOCK */#include <linux/in6.h>#include <net/route.h>#include <net/ip.h>#ifdef NETLINK_SOCK# include <linux/netlink.h>#else# include <net/netlink.h>#endif#include <linux/random.h> /* get_random_bytes() */#include "openswan/radij.h"#include "openswan/ipsec_encap.h"#include "openswan/ipsec_sa.h"#include "openswan/ipsec_radij.h"#include "openswan/ipsec_xform.h"#include "openswan/ipsec_ah.h"#include "openswan/ipsec_esp.h"#include "openswan/ipsec_tunnel.h"#include "openswan/ipsec_rcv.h"#include "openswan/ipcomp.h"#include <pfkeyv2.h>#include <pfkey.h>#include "openswan/ipsec_proto.h"#include "openswan/ipsec_alg.h"#include "openswan/ipsec_kern24.h"#define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)struct sklist_t { struct socket *sk; struct sklist_t* next;} pfkey_sklist_head, *pfkey_sklist, *pfkey_sklist_prev;__u32 pfkey_msg_seq = 0;#if 0#define DUMP_SAID dump_said(&extr->ips->ips_said, __LINE__)#define DUMP_SAID2 dump_said(&extr.ips->ips_said, __LINE__)static void dump_said(ip_said *s, int line){ char msa[SATOT_BUF]; size_t msa_len; msa_len = satot(s, 0, msa, sizeof(msa)); printk("line: %d msa: %s\n", line, msa);}#endifintpfkey_alloc_eroute(struct eroute** eroute){ int error = 0; if(*eroute) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "eroute struct already allocated\n"); SENDERR(EEXIST); } if((*eroute = kmalloc(sizeof(**eroute), GFP_ATOMIC) ) == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "memory allocation error\n"); SENDERR(ENOMEM); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_alloc_eroute: " "allocating %lu bytes for an eroute at 0p%p\n", (unsigned long) sizeof(**eroute), *eroute); memset((caddr_t)*eroute, 0, sizeof(**eroute)); (*eroute)->er_eaddr.sen_len = (*eroute)->er_emask.sen_len = sizeof(struct sockaddr_encap); (*eroute)->er_eaddr.sen_family = (*eroute)->er_emask.sen_family = AF_ENCAP; (*eroute)->er_eaddr.sen_type = SENT_IP4; (*eroute)->er_emask.sen_type = 255; (*eroute)->er_pid = 0; (*eroute)->er_count = 0; (*eroute)->er_lasttime = jiffies/HZ; errlab: return(error);}DEBUG_NO_STATIC intpfkey_x_protocol_process(struct sadb_ext *pfkey_ext, struct pfkey_extracted_data *extr){ int error = 0; struct sadb_protocol * p = (struct sadb_protocol *)pfkey_ext; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: %p\n", extr); if (extr == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process:" "extr is NULL, fatal\n"); SENDERR(EINVAL); } if (extr->eroute == 0) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process:" "extr->eroute is NULL, fatal\n"); SENDERR(EINVAL); } extr->eroute->er_eaddr.sen_proto = p->sadb_protocol_proto; extr->eroute->er_emask.sen_proto = p->sadb_protocol_proto ? ~0:0; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_x_protocol_process: protocol = %d.\n", p->sadb_protocol_proto); errlab: return error;}DEBUG_NO_STATIC intpfkey_ipsec_sa_init(struct ipsec_sa *ipsp){ return ipsec_sa_init(ipsp);}intpfkey_safe_build(int error, struct sadb_ext *extensions[SADB_MAX+1]){ KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build: " "error=%d\n", error); if (!error) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" "success.\n"); return 1; } else { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_safe_build:" "caught error %d\n", error); pfkey_extensions_free(extensions); return 0; }}DEBUG_NO_STATIC intpfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr){ int error = 0; ipsec_spi_t minspi = htonl(256), maxspi = htonl(-1L); int found_avail = 0; struct ipsec_sa *ipsq; char sa[SATOT_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: .\n"); pfkey_extensions_init(extensions_reply); if(extr == NULL || extr->ips == NULL) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "error, extr or extr->ipsec_sa pointer NULL\n"); SENDERR(EINVAL); } if(extensions[SADB_EXT_SPIRANGE]) { minspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_min; maxspi = ((struct sadb_spirange *)extensions[SADB_EXT_SPIRANGE])->sadb_spirange_max; } if(maxspi == minspi) { extr->ips->ips_said.spi = maxspi; ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); if(ipsq != NULL) { sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); ipsec_sa_put(ipsq); KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } else { found_avail = 1; } } else { int i = 0; __u32 rand_val; __u32 spi_diff; while( ( i < (spi_diff = (ntohl(maxspi) - ntohl(minspi)))) && !found_avail ) { prng_bytes(&ipsec_prng, (char *) &(rand_val), ( (spi_diff < (2^8)) ? 1 : ( (spi_diff < (2^16)) ? 2 : ( (spi_diff < (2^24)) ? 3 : 4 ) ) ) ); extr->ips->ips_said.spi = htonl(ntohl(minspi) + (rand_val % (spi_diff + 1))); i++; ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said)); if(ipsq == NULL) { found_avail = 1; } else { ipsec_sa_put(ipsq); } } } sa_len = satot(&extr->ips->ips_said, 0, sa, sizeof(sa)); if (!found_avail) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "found an old ipsec_sa for SA: %s, delete it first.\n", sa_len ? sa : " (error)"); SENDERR(EEXIST); } if(inet_addr_type((unsigned long)extr->ips->ips_said.dst.u.v4.sin_addr.s_addr) == RTN_LOCAL) { extr->ips->ips_flags |= EMT_INBOUND; } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "existing ipsec_sa not found (this is good) for SA: %s, %s-bound, allocating.\n", sa_len ? sa : " (error)", extr->ips->ips_flags & EMT_INBOUND ? "in" : "out"); /* XXX extr->ips->ips_rcvif = &(enc_softc[em->em_if].enc_if);*/ extr->ips->ips_rcvif = NULL; extr->ips->ips_life.ipl_addtime.ipl_count = jiffies/HZ; extr->ips->ips_state = SADB_SASTATE_LARVAL; if(!extr->ips->ips_life.ipl_allocations.ipl_count) { extr->ips->ips_life.ipl_allocations.ipl_count += 1; } if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0], SADB_GETSPI, satype, 0, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_seq, ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_pid), extensions_reply) && pfkey_safe_build(error = pfkey_sa_ref_build(&extensions_reply[SADB_EXT_SA], SADB_EXT_SA, extr->ips->ips_said.spi, 0, SADB_SASTATE_LARVAL, 0, 0, 0, extr->ips->ips_ref), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_s), extensions_reply) && pfkey_safe_build(error = pfkey_address_build(&extensions_reply[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, /*extr->ips->ips_said.proto,*/ 0, extr->ips->ips_addr_d), extensions_reply) )) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to build the getspi reply message extensions\n"); goto errlab; } if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to build the getspi reply message\n"); SENDERR(-error); } for(pfkey_socketsp = pfkey_open_sockets; pfkey_socketsp; pfkey_socketsp = pfkey_socketsp->next) { if((error = pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "sending up getspi reply message for satype=%d(%s) to socket=0p%p failed with error=%d.\n", satype, satype2name(satype), pfkey_socketsp->socketp, error); SENDERR(-error); } KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "sending up getspi reply message for satype=%d(%s) to socket=0p%p succeeded.\n", satype, satype2name(satype), pfkey_socketsp->socketp); } if((error = ipsec_sa_add(extr->ips))) { KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "failed to add the larval SA=%s with error=%d.\n", sa_len ? sa : " (error)", error); SENDERR(-error); } extr->ips = NULL; KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_getspi_parse: " "successful for SA: %s\n", sa_len ? sa : " (error)"); errlab: if (pfkey_reply) { pfkey_msg_free(&pfkey_reply); } pfkey_extensions_free(extensions_reply); return error;}DEBUG_NO_STATIC intpfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extracted_data* extr){ int error = 0; struct ipsec_sa* ipsq; char sa[SATOT_BUF]; size_t sa_len; struct sadb_ext *extensions_reply[SADB_EXT_MAX+1]; struct sadb_msg *pfkey_reply = NULL; struct socket_list *pfkey_socketsp; uint8_t satype = ((struct sadb_msg*)extensions[SADB_EXT_RESERVED])->sadb_msg_satype;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -