kernel_pfkey.c

来自「ipsec vpn」· C语言 代码 · 共 1,018 行 · 第 1/2 页

C
1,018
字号
	    , description, text_said, error);	pfkey_extensions_free(extensions);	return FALSE;    }}/* pfkey_extensions_init + pfkey_build + pfkey_msg_hdr_build */static boolpfkey_msg_start(u_int8_t msg_type, u_int8_t satype, const char *description, const char *text_said, struct sadb_ext *extensions[SADB_EXT_MAX + 1]){    pfkey_extensions_init(extensions);    return pfkey_build(pfkey_msg_hdr_build(&extensions[0], msg_type	    , satype, 0, ++pfkey_seq, pid)	, description, text_said, extensions);}/* pfkey_build + pfkey_address_build */static boolpfkeyext_address(u_int16_t exttype, const ip_address *address, const char *description, const char *text_said, struct sadb_ext *extensions[SADB_EXT_MAX + 1]){    /* the following variable is only needed to silence     * a warning caused by the fact that the argument     * to sockaddrof is NOT pointer to const!     */    ip_address t = *address;    return pfkey_build(pfkey_address_build(extensions + exttype	    , exttype, 0, 0, sockaddrof(&t))	, description, text_said, extensions);}/* pfkey_build + pfkey_x_protocol_build */static boolpfkeyext_protocol(int transport_proto, const char *description, const char *text_said, struct sadb_ext *extensions[SADB_EXT_MAX + 1]){    return (transport_proto == 0)        ? TRUE        : pfkey_build(pfkey_x_protocol_build(extensions + SADB_X_EXT_PROTOCOL,                                             transport_proto),                      description, text_said, extensions);}/* Finish (building, sending, accepting response for) PF_KEY message. * If response isn't NULL, the response from the kernel will be * placed there (and its errno field will not be examined). * Returns TRUE iff all appears well. */static boolfinish_pfkey_msg(struct sadb_ext *extensions[SADB_EXT_MAX + 1], const char *description, const char *text_said, pfkey_buf *response){    struct sadb_msg *pfkey_msg;    bool success = TRUE;    int error;    error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN);    if (error != 0)    {	loglog(RC_LOG_SERIOUS, "pfkey_msg_build of %s %s failed, code %d"	    , description, text_said, error);	success = FALSE;    }    else    {	size_t len = pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN;	DBG(DBG_KLIPS,	    DBG_log("finish_pfkey_msg: %s message %u for %s %s"		, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)		, pfkey_msg->sadb_msg_seq		, description, text_said);	    DBG_dump(NULL, (void *) pfkey_msg, len));	if (kern_interface != NO_KERNEL)	{	    ssize_t r = write(pfkeyfd, pfkey_msg, len);	    int e1 = errno;	    if (r != (ssize_t)len)	    {		if (r < 0)		{		  switch(e1) {		  case ESRCH:		    if(pfkey_msg->sadb_msg_type == SADB_DELETE) {		      success=TRUE;		    }		    else {		      goto logerr;		    }		    break;		  case ENOENT:		    loglog(RC_LOG_SERIOUS, "requested algorithm is not available in the kernel");		    success=FALSE;		    break;		    		  default:		  logerr:		    log_errno_routine(e1, "pfkey write() of %s message %u"				      " for %s %s failed"				      , sparse_val_show(pfkey_type_names							, pfkey_msg->sadb_msg_type)				      , pfkey_msg->sadb_msg_seq				      , description, text_said);		    success = FALSE;		  }		}		else		{		    loglog(RC_LOG_SERIOUS			, "ERROR: pfkey write() of %s message %u"			  " for %s %s truncated: %ld instead of %ld"			, sparse_val_show(pfkey_type_names			    , pfkey_msg->sadb_msg_type)			, pfkey_msg->sadb_msg_seq			, description, text_said			, (long)r, (long)len);		    success = FALSE;		}		/* if we were compiled with debugging, but we haven't already		 * dumped the KLIPS command, do so.		 */#ifdef DEBUG		if ((cur_debugging & DBG_KLIPS) == 0)		    DBG_dump(NULL, (void *) pfkey_msg, len);#endif	    }	    else	    {		/* Check response from KLIPS.		 * It ought to be an echo, perhaps with additional info.		 * If the caller wants it, response will point to space.		 */		pfkey_buf b;		pfkey_buf *bp = response != NULL? response : &b;		if (!pfkey_get_response(bp, ((struct sadb_msg *) extensions[0])->sadb_msg_seq))		{		    loglog(RC_LOG_SERIOUS			, "ERROR: no response to our PF_KEY %s message for %s %s"			, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)			, description, text_said);		    success = FALSE;		}		else if (pfkey_msg->sadb_msg_type != bp->msg.sadb_msg_type)		{		    loglog(RC_LOG_SERIOUS			, "Openswan ERROR: response to our PF_KEY %s message for %s %s was of wrong type (%s)"			, sparse_name(pfkey_type_names, pfkey_msg->sadb_msg_type)			, description, text_said			, sparse_val_show(pfkey_type_names, bp->msg.sadb_msg_type));		    success = FALSE;		}		else if (response == NULL && bp->msg.sadb_msg_errno != 0)		{		    /* KLIPS is signalling a problem */		    loglog(RC_LOG_SERIOUS			, "ERROR: PF_KEY %s response for %s %s included errno %u: %s"			, sparse_val_show(pfkey_type_names, pfkey_msg->sadb_msg_type)			, description, text_said			, (unsigned) bp->msg.sadb_msg_errno			, strerror(bp->msg.sadb_msg_errno));		    success = FALSE;		}	    }	}    }    /* all paths must exit this way to free resources */    pfkey_extensions_free(extensions);    pfkey_msg_free(&pfkey_msg);    return success;}/*  register SA types that can be negotiated */voidpfkey_register_proto(unsigned satype, const char *satypename){    struct sadb_ext *extensions[SADB_EXT_MAX + 1];    pfkey_buf pfb;    if (!(pfkey_msg_start(SADB_REGISTER      , satype      , satypename, NULL, extensions)    && finish_pfkey_msg(extensions, satypename, "", &pfb)))    {	/* ??? should this be loglog */	plog("no KLIPS support for %s", satypename);    }    else    {	kernel_ops->pfkey_register_response(&pfb.msg);	DBG(DBG_KLIPS,	    DBG_log("%s registered with kernel.", satypename));    }}static voidklips_pfkey_register(void){    pfkey_register_proto(SADB_SATYPE_AH, "AH");    pfkey_register_proto(SADB_SATYPE_ESP, "ESP");    can_do_IPcomp = FALSE;  /* until we get a response from KLIPS */    pfkey_register_proto(SADB_X_SATYPE_COMP, "IPCOMP");    pfkey_register_proto(SADB_X_SATYPE_IPIP, "IPIP");}static boolpfkey_raw_eroute(const ip_address *this_host		 , const ip_subnet *this_client		 , const ip_address *that_host		 , const ip_subnet *that_client		 , ipsec_spi_t spi		 , unsigned int proto UNUSED		 , unsigned int transport_proto		 , unsigned int satype		 , const struct pfkey_proto_info *proto_info UNUSED		 , time_t use_lifetime UNUSED		 , unsigned int op		 , const char *text_said){    struct sadb_ext *extensions[SADB_EXT_MAX + 1];    ip_address	sflow_ska,	dflow_ska,	smask_ska,	dmask_ska;    int sport = ntohs(portof(&this_client->addr));    int dport = ntohs(portof(&that_client->addr));    networkof(this_client, &sflow_ska);    maskof(this_client, &smask_ska);    setportof(sport ? ~0:0, &smask_ska);    networkof(that_client, &dflow_ska);    maskof(that_client, &dmask_ska);    setportof(dport ? ~0:0, &dmask_ska);    if (!pfkey_msg_start(op & ERO_MASK, satype		       , "pfkey_msg_hdr flow", text_said, extensions))    {	return FALSE;    }    if (op != ERO_DELETE)    {	if (!(pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]					 , SADB_EXT_SA					 , spi	/* in network order */					 , 0, 0, 0, 0, op >> ERO_FLAG_SHIFT)			  , "pfkey_sa add flow", text_said, extensions)	    && pfkeyext_address(SADB_EXT_ADDRESS_SRC, this_host		, "pfkey_addr_s add flow", text_said, extensions)	    && pfkeyext_address(SADB_EXT_ADDRESS_DST, that_host				, "pfkey_addr_d add flow", text_said				, extensions)))	{	    return FALSE;	}    }    if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_FLOW, &sflow_ska			  , "pfkey_addr_sflow", text_said, extensions))    {	return FALSE;    }    if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_FLOW, &dflow_ska			, "pfkey_addr_dflow", text_said, extensions))    {	return FALSE;    }    if (!pfkeyext_address(SADB_X_EXT_ADDRESS_SRC_MASK, &smask_ska			, "pfkey_addr_smask", text_said, extensions))    {	return FALSE;    }    if (!pfkeyext_address(SADB_X_EXT_ADDRESS_DST_MASK, &dmask_ska			, "pfkey_addr_dmask", text_said, extensions))    {	return FALSE;    }    if (!pfkeyext_protocol(transport_proto			, "pfkey_x_protocol", text_said, extensions))    {	return FALSE;    }    return finish_pfkey_msg(extensions, "flow", text_said, NULL);}static boolpfkey_add_sa(const struct kernel_sa *sa, bool replace){    struct sadb_ext *extensions[SADB_EXT_MAX + 1];    bool success = FALSE;    success = pfkey_msg_start(replace ? SADB_UPDATE : SADB_ADD, sa->satype			      , "pfkey_msg_hdr Add SA"			      , sa->text_said, extensions);    if(!success) return FALSE;    success = pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]					 , SADB_EXT_SA					 , sa->spi	/* in network order */					 , sa->replay_window, SADB_SASTATE_MATURE					 , sa->authalg, sa->encalg, 0)			  , "pfkey_sa Add SA", sa->text_said, extensions);    if(!success) return FALSE;    success = pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src			       , "pfkey_addr_s Add SA"			       , sa->text_said, extensions);    if(!success) return FALSE;    success = pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst			       , "pfkey_addr_d Add SA", sa->text_said			       , extensions);    if(!success) return FALSE;    if(sa->authkeylen != 0) {	success = pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_AUTH]					      , SADB_EXT_KEY_AUTH					      , sa->authkeylen * BITS_PER_BYTE					      , sa->authkey)			      , "pfkey_key_a Add SA"			      , sa->text_said, extensions);	if(!success) return FALSE;    }	    if(sa->enckeylen != 0) {	success = pfkey_build(pfkey_key_build(&extensions[SADB_EXT_KEY_ENCRYPT]					      , SADB_EXT_KEY_ENCRYPT					      , sa->enckeylen * BITS_PER_BYTE					      , sa->enckey)			      , "pfkey_key_e Add SA"			      , sa->text_said, extensions);	if(!success) return FALSE;    }	#ifdef NAT_TRAVERSAL    if(sa->natt_type != 0) {	success = pfkey_build(pfkey_x_nat_t_type_build(				  &extensions[SADB_X_EXT_NAT_T_TYPE]				  , sa->natt_type),			      "pfkey_nat_t_type Add ESP SA"			      ,  sa->text_said, extensions);	DBG(DBG_KLIPS	    , DBG_log("setting natt_type to %d\n", sa->natt_type));	if(!success) return FALSE;	if(sa->natt_sport != 0) {	  success = pfkey_build(pfkey_x_nat_t_port_build(				  &extensions[SADB_X_EXT_NAT_T_SPORT]				  , SADB_X_EXT_NAT_T_SPORT,				  sa->natt_sport)			      , "pfkey_nat_t_sport Add ESP SA"			      , sa->text_said, extensions);	  DBG(DBG_KLIPS	      , DBG_log("setting natt_sport to %d\n", sa->natt_sport));	  if(!success) return FALSE;	}		if(sa->natt_dport != 0) {	  success = pfkey_build(pfkey_x_nat_t_port_build(				  &extensions[SADB_X_EXT_NAT_T_DPORT]				  , SADB_X_EXT_NAT_T_DPORT				  , sa->natt_dport)			      , "pfkey_nat_t_dport Add ESP SA"			      , sa->text_said, extensions);	  DBG(DBG_KLIPS	      , DBG_log("setting natt_dport to %d\n", sa->natt_dport));	  if(!success) return FALSE;	}		if(sa->natt_type!=0 && !isanyaddr(sa->natt_oa)) {	  success = pfkeyext_address(SADB_X_EXT_NAT_T_OA, sa->natt_oa				     , "pfkey_nat_t_oa Add ESP SA"				     , sa->text_said, extensions);	  DBG(DBG_KLIPS	      , DBG_log("setting nat_oa to %s\n", ip_str(sa->natt_oa)));	  if(!success) return FALSE;	}    }#endif    return finish_pfkey_msg(extensions, "Add SA", sa->text_said, NULL);}static boolpfkey_grp_sa(const struct kernel_sa *sa0, const struct kernel_sa *sa1){    struct sadb_ext *extensions[SADB_EXT_MAX + 1];    return pfkey_msg_start(SADB_X_GRPSA, sa1->satype	, "pfkey_msg_hdr group", sa1->text_said, extensions)    && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]	    , SADB_EXT_SA	    , sa1->spi	/* in network order */	    , 0, 0, 0, 0, 0)	, "pfkey_sa group", sa1->text_said, extensions)    && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa1->dst	, "pfkey_addr_d group", sa1->text_said, extensions)    && pfkey_build(pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2]	    , sa0->satype)	, "pfkey_satype group", sa0->text_said, extensions)    && pfkey_build(pfkey_sa_build(&extensions[SADB_X_EXT_SA2]	    , SADB_X_EXT_SA2	    , sa0->spi	/* in network order */	    , 0, 0, 0, 0, 0)	, "pfkey_sa2 group", sa0->text_said, extensions)    && pfkeyext_address(SADB_X_EXT_ADDRESS_DST2, sa0->dst	, "pfkey_addr_d2 group", sa0->text_said, extensions)    && finish_pfkey_msg(extensions, "group", sa1->text_said, NULL);}static boolpfkey_del_sa(const struct kernel_sa *sa){    struct sadb_ext *extensions[SADB_EXT_MAX + 1];    return pfkey_msg_start(SADB_DELETE, proto2satype(sa->proto)	, "pfkey_msg_hdr delete SA", sa->text_said, extensions)    && pfkey_build(pfkey_sa_build(&extensions[SADB_EXT_SA]	    , SADB_EXT_SA	    , sa->spi	/* in host order */	    , 0, SADB_SASTATE_MATURE, 0, 0, 0)	, "pfkey_sa delete SA", sa->text_said, extensions)    && pfkeyext_address(SADB_EXT_ADDRESS_SRC, sa->src	, "pfkey_addr_s delete SA", sa->text_said, extensions)    && pfkeyext_address(SADB_EXT_ADDRESS_DST, sa->dst	, "pfkey_addr_d delete SA", sa->text_said, extensions)    && finish_pfkey_msg(extensions, "Delete SA", sa->text_said, NULL);}voidpfkey_close(void){    while (pfkey_iq_head != NULL)    {	pfkey_item *it = pfkey_iq_head;	pfkey_iq_head = it->next;	pfree(it);    }    close(pfkeyfd);    pfkeyfd = NULL_FD;}const struct kernel_ops klips_kernel_ops = {	type: KERNEL_TYPE_KLIPS,	async_fdp: &pfkeyfd,	replay_window: 64,	pfkey_register: klips_pfkey_register,	pfkey_register_response: klips_pfkey_register_response,	process_queue: pfkey_dequeue,	process_msg: pfkey_event,	raw_eroute: pfkey_raw_eroute,	add_sa: pfkey_add_sa,	grp_sa: pfkey_grp_sa,	del_sa: pfkey_del_sa,	get_spi: NULL,        inbound_eroute: FALSE,	policy_lifetime: FALSE,	init: NULL,	docommand: do_command_linux,	opname: "pfkey"};#endif /* KLIPS */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?