Ejemplo n.º 1
0
int sadb_msg_send_expire(struct ipsec_sa *sa)
{
	int i=0, error = 0;
	struct sadb_msg *msg = NULL;
	struct sadb_ext *ext_msgs[SADB_EXT_MAX+1];
	struct socket_list *pfkey_socketsp = NULL;

	if (!sa) {
		PFKEY_DEBUG("sa is null\n");
		return -EINVAL;
	}

	memset(ext_msgs, 0, sizeof(ext_msgs));

	error = pfkey_msg_hdr_build(&ext_msgs[0],
				    SADB_EXPIRE,
				    sa->ipsec_proto,
				    0,
				    0,
				    0);
	if (error) {
		PFKEY_DEBUG("pfkey_msg_hdr_build is failed\n");
		goto free_ext_finish;
	}

	error = pfkey_sa_build(&ext_msgs[SADB_EXT_SA],
				   SADB_EXT_SA,
				   sa->spi,
				   64,
				   sa->state,
				   sa->auth_algo.algo,
				   sa->esp_algo.algo,
				   0); /* TODO: add pfs flag to struct ipsec_sa */
	if (error) {
		PFKEY_DEBUG("pfkey_sa_build is failed\n");
		goto free_ext_finish;
	}

	error = pfkey_lifetime_build(&ext_msgs[SADB_EXT_LIFETIME_CURRENT],
					 SADB_EXT_LIFETIME_CURRENT,
					 sa->lifetime_c.allocations,
					 sa->lifetime_c.bytes,
					 sa->lifetime_c.addtime,
					 sa->lifetime_c.usetime);
	if (error) {
		PFKEY_DEBUG("pfkey_lifetime_build is failed\n");
		goto free_ext_finish;
	}

	switch(sa->state) {
	case SADB_SASTATE_DEAD:
		error = pfkey_lifetime_build(&ext_msgs[SADB_EXT_LIFETIME_HARD],
						 SADB_EXT_LIFETIME_HARD,
						 sa->lifetime_h.allocations,
						 sa->lifetime_h.bytes,
						 sa->lifetime_h.addtime,
						 sa->lifetime_h.usetime);
		if (error) {
			PFKEY_DEBUG("pfkey_liftime_build(hard) is failed\n");
			goto free_ext_finish;
		}
		break;

	case SADB_SASTATE_DYING:
		error = pfkey_lifetime_build(&ext_msgs[SADB_EXT_LIFETIME_SOFT],
						 SADB_EXT_LIFETIME_SOFT,
						 sa->lifetime_s.allocations,
						 sa->lifetime_s.bytes,
						 sa->lifetime_s.addtime,
						 sa->lifetime_s.usetime);
		if (error) {
			PFKEY_DEBUG("pfkey_lifetime_build(soft) is failed\n");
			goto free_ext_finish;
		}
		break;

	case SADB_SASTATE_LARVAL:
	case SADB_SASTATE_MATURE:
	default:
		error = -EINVAL;
		goto free_ext_finish;

	}
	
	error = pfkey_address_build(&ext_msgs[SADB_EXT_ADDRESS_SRC],
					SADB_EXT_ADDRESS_SRC,
					sa->proto,
					sa->prefixlen_s,
					(struct sockaddr*)&sa->src);
	if (error) goto free_ext_finish;

	error = pfkey_address_build(&ext_msgs[SADB_EXT_ADDRESS_DST],
					SADB_EXT_ADDRESS_DST,
					sa->proto,
					sa->prefixlen_d,
					(struct sockaddr*)&sa->dst);
	if (error) goto free_ext_finish;

	error = pfkey_msg_build(&msg, ext_msgs, EXT_BITS_OUT);

	write_lock(&pfkey_sk_lock);
	for (pfkey_socketsp = pfkey_open_sockets;
		pfkey_socketsp;
			pfkey_socketsp = pfkey_socketsp->next)
	{
		pfkey_upmsg(pfkey_socketsp->socketp, msg);
	}
	write_unlock(&pfkey_sk_lock);

	kfree(msg);

free_ext_finish:
	for(i=0; i<SADB_MAX+1; i++) {
		if (ext_msgs[i]) {
			kfree(ext_msgs[i]);
		}
	}

	return 0;

}
Ejemplo n.º 2
0
int sadb_msg_send_acquire(struct ipsec_sa *sa)
{
	int i=0, error = 0;
	uint  comb_num = 0;
	struct sadb_comb combs[4];
	struct digest_implementation *di = NULL;
	struct cipher_implementation *ci = NULL;
	struct sadb_msg *msg = NULL;
	struct sadb_ext *ext_msgs[SADB_EXT_MAX+1];
	struct socket_list *pfkey_socketsp = NULL;

	memset(ext_msgs, 0, sizeof(ext_msgs));
	memset(combs, 0, sizeof(combs));

	if (sa->ipsec_proto == SADB_SATYPE_AH || sa->ipsec_proto == SADB_SATYPE_ESP) {
		di = find_digest_by_name("md5", 0 /* atomic */);
		if (di) {
			combs[comb_num].sadb_comb_auth = SADB_AALG_MD5HMAC;
			combs[comb_num].sadb_comb_auth_minbits = AUTH_MD5HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_auth_maxbits = AUTH_MD5HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			di = NULL;	
		}
	
		di = find_digest_by_name("sha1", 0 /* atomic */);
		if (di) {
			combs[comb_num].sadb_comb_auth = SADB_AALG_SHA1HMAC;
			combs[comb_num].sadb_comb_auth_minbits = AUTH_SHA1HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_auth_maxbits = AUTH_SHA1HMAC_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			di = NULL;
		}
	}

	if (sa->ipsec_proto == SADB_SATYPE_ESP) {
		ci = find_cipher_by_name("des-cbc", 1 /* atomic */);
		if (ci) {
			combs[comb_num].sadb_comb_encrypt = SADB_EALG_DESCBC;
			combs[comb_num].sadb_comb_encrypt_minbits = ESP_DES_KEY_BITS;
			combs[comb_num].sadb_comb_encrypt_maxbits = ESP_DES_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			ci = NULL;
		}

		ci = find_cipher_by_name("des_ede3-cbc", 1 /* atomic */);
		if (ci) {
			combs[comb_num].sadb_comb_encrypt = SADB_EALG_3DESCBC;
			combs[comb_num].sadb_comb_encrypt_minbits = ESP_3DES_KEY_BITS;
			combs[comb_num].sadb_comb_encrypt_maxbits = ESP_3DES_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			ci = NULL;
		}

		ci = find_cipher_by_name("aes-cbc", 1 /* atomic */);
		if (ci) {
			combs[comb_num].sadb_comb_encrypt = SADB_EALG_AES;
			combs[comb_num].sadb_comb_encrypt_minbits = ESP_AES_KEY_BITS;
			combs[comb_num].sadb_comb_encrypt_maxbits = ESP_AES_KEY_BITS;
			combs[comb_num].sadb_comb_reserved = 0;
			combs[comb_num].sadb_comb_soft_allocations = 0;
			combs[comb_num].sadb_comb_hard_allocations = 0;
			combs[comb_num].sadb_comb_soft_bytes = 0;
			combs[comb_num].sadb_comb_hard_bytes = 0;
			combs[comb_num].sadb_comb_soft_addtime = 57600;
			combs[comb_num].sadb_comb_hard_addtime = 86400;
			combs[comb_num].sadb_comb_soft_usetime = 57600;
			combs[comb_num].sadb_comb_hard_usetime = 86400;
			comb_num++;
			ci = NULL;
		}
	}

	error = pfkey_msg_hdr_build(&ext_msgs[0],
				    SADB_ACQUIRE,
				    sa->ipsec_proto,
				    0,
				    0,
				    0);
	if (error) {
		PFKEY_DEBUG("pfkey_msg_hdr_build is failed\n");
		goto free_ext_finish;
	}

	error = pfkey_address_build(&ext_msgs[SADB_EXT_ADDRESS_SRC],
					SADB_EXT_ADDRESS_SRC,
					sa->proto,
					sa->prefixlen_s,
					(struct sockaddr*)&sa->src);
	if (error) goto free_ext_finish;

	error = pfkey_address_build(&ext_msgs[SADB_EXT_ADDRESS_DST],
					SADB_EXT_ADDRESS_DST,
					sa->proto,
					sa->prefixlen_d,
					(struct sockaddr*)&sa->dst);
	if (error) goto free_ext_finish;

	error = pfkey_prop_build(&ext_msgs[SADB_EXT_PROPOSAL],
					64,
					comb_num,
					combs);
	if (error) goto free_ext_finish;


	error = pfkey_msg_build(&msg, ext_msgs, EXT_BITS_OUT);

	write_lock(&pfkey_sk_lock);
	for (pfkey_socketsp = pfkey_registered_sockets[sa->ipsec_proto];
		pfkey_socketsp;
			pfkey_socketsp = pfkey_socketsp->next)
	{
		pfkey_upmsg(pfkey_socketsp->socketp, msg);
	}
	write_unlock(&pfkey_sk_lock);

	kfree(msg);
free_ext_finish:

	for(i=0; i<SADB_MAX+1; i++) {
		if (ext_msgs[i]) {
			kfree(ext_msgs[i]);
		}
	}

	return 0;
}
/* derived from FreeS/WAN-1.9 pfkey_v2_parse.c (mk) */
int
pfkey_msg_interp(struct sock *sk, struct sadb_msg *pfkey_msg)
{
	int error = 0;
	struct sadb_msg *pfkey_reply = NULL;
	struct sadb_ext *reply_ext_msgs[SADB_EXT_MAX+1];
	struct socket_list *pfkey_socketsp = 0;

	if (pfkey_msg->sadb_msg_satype > SADB_SATYPE_MAX) {
		return -EINVAL;
	}
	
	memset(reply_ext_msgs, 0, SADB_EXT_MAX+1);

	switch (pfkey_msg->sadb_msg_type) {
	case SADB_GETSPI:
		error = sadb_msg_add_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PF_KEY:interp: SADB_GETSPI\n");
		break;
	case SADB_UPDATE:
		error = -EINVAL;/* XXX */
		PFKEY_DEBUG("PF_KEY:interp: SADB_UPDATE\n");
		break;
	case SADB_ADD:
		error = sadb_msg_add_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PF_KEY:interp: SADB_ADD\n");
		break;
	case SADB_DELETE:
		error = sadb_msg_delete_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PF_KEY:interp: SADB_DELETE\n");
		break;
	case SADB_FLUSH:
		error = sadb_msg_flush_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PF_KEY:interp: SADB_FLUSH\n");
		break;
	case SADB_REGISTER:
		error = sadb_msg_register_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PF_KEY:interp: SADB_REGISTER\n");
		break;
	case SADB_X_GRPSA:
		error =  -EINVAL;/* XXX */
		PFKEY_DEBUG("PF_KEY:interp: SADB_X_GRPSA\n");
		break;
	case SADB_X_ADDFLOW:
		error = sadb_msg_addflow_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PF_KEY:interp: SADB_ADDFLOW\n");
		break;
	case SADB_X_DELFLOW:
		error = sadb_msg_delflow_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PF_KEY:interp: SADB_DELFLOW\n");
		break;

	case SADB_X_FLUSH_SP:
		error = sadb_msg_flush_sp_parse(sk, pfkey_msg, &pfkey_reply);
		PFKEY_DEBUG("PFKEY:interp: SADB_X_FLUSH_SP\n");
		break;
	default:
		error = -EINVAL;
		break;
	}
	
	if (error) {
		PFKEY_DEBUG("PFKEY:interp: parse routine return error=%d\n", error);
		goto err;
	}

	switch (pfkey_msg->sadb_msg_type) {

	case SADB_GETSPI:
	case SADB_UPDATE:
	case SADB_ADD:
	case SADB_DELETE:
	case SADB_FLUSH:
	case SADB_X_ADDFLOW:
	case SADB_X_DELFLOW:
	case SADB_X_FLUSH_SP:
		write_lock_bh(&pfkey_sk_lock);
		for (pfkey_socketsp = pfkey_open_sockets;
	    		pfkey_socketsp;
	    			pfkey_socketsp = pfkey_socketsp->next)
		{
			pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply);
		}
		write_unlock_bh(&pfkey_sk_lock);
		break;

	case SADB_GET:
	case SADB_DUMP:
	case SADB_REGISTER:
		write_lock_bh(&pfkey_sk_lock);
		pfkey_upmsg(sk->socket, pfkey_reply);
		write_unlock_bh(&pfkey_sk_lock);
		break;

	case SADB_ACQUIRE:
		write_lock_bh(&pfkey_sk_lock);
		for (pfkey_socketsp = pfkey_registered_sockets[pfkey_msg->sadb_msg_satype];
			pfkey_socketsp;
				pfkey_socketsp = pfkey_socketsp->next)
		{
			pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply);
		}
		write_unlock_bh(&pfkey_sk_lock);
		break;

	default:
		error = -EINVAL;
		goto err;
	}

	if (pfkey_reply)
		kfree(pfkey_reply);

	return 0;
err:
	if (pfkey_reply)
		kfree(pfkey_reply);

	pfkey_reply = kmalloc(sizeof(struct sadb_msg), GFP_KERNEL);
	if (!pfkey_reply){
		return -ENOMEM;
	}
	memcpy(pfkey_reply, pfkey_msg, sizeof(pfkey_reply));
	pfkey_reply->sadb_msg_errno = error;

	write_lock_bh(&pfkey_sk_lock);
	pfkey_upmsg(sk->socket, pfkey_reply);
	for (pfkey_socketsp = pfkey_registered_sockets[pfkey_msg->sadb_msg_satype];
		pfkey_socketsp;
			pfkey_socketsp = pfkey_socketsp->next)
	{
		pfkey_upmsg(pfkey_socketsp->socketp, pfkey_reply);
	}
	write_unlock_bh(&pfkey_sk_lock);

	if (pfkey_reply) {
		kfree(pfkey_reply);
	}

	return error;
}