Blame src/xfrm.c

Packit c5a612
/*
Packit c5a612
 * XFRM (ipsec) expression
Packit c5a612
 *
Packit c5a612
 * This program is free software; you can redistribute it and/or modify
Packit c5a612
 * it under the terms of the GNU General Public License version 2 as
Packit c5a612
 * published by the Free Software Foundation.
Packit c5a612
 */
Packit c5a612
Packit c5a612
#include <nftables.h>
Packit c5a612
#include <erec.h>
Packit c5a612
#include <expression.h>
Packit c5a612
#include <xfrm.h>
Packit c5a612
#include <datatype.h>
Packit c5a612
#include <gmputil.h>
Packit c5a612
#include <utils.h>
Packit c5a612
#include <string.h>
Packit c5a612
Packit c5a612
#include <netinet/ip.h>
Packit c5a612
#include <linux/netfilter.h>
Packit c5a612
#include <linux/xfrm.h>
Packit c5a612
Packit c5a612
#define XFRM_TEMPLATE_BE(__token, __dtype, __len) {	\
Packit c5a612
	.token		= (__token),			\
Packit c5a612
	.dtype		= (__dtype),			\
Packit c5a612
	.len		= (__len),			\
Packit c5a612
	.byteorder	= BYTEORDER_BIG_ENDIAN,		\
Packit c5a612
}
Packit c5a612
Packit c5a612
#define XFRM_TEMPLATE_HE(__token, __dtype, __len) {	\
Packit c5a612
	.token		= (__token),			\
Packit c5a612
	.dtype		= (__dtype),			\
Packit c5a612
	.len		= (__len),			\
Packit c5a612
	.byteorder	= BYTEORDER_HOST_ENDIAN,	\
Packit c5a612
}
Packit c5a612
Packit c5a612
const struct xfrm_template xfrm_templates[] = {
Packit c5a612
	[NFT_XFRM_KEY_DADDR_IP4]	= XFRM_TEMPLATE_BE("daddr", &ipaddr_type, 4 * BITS_PER_BYTE),
Packit c5a612
	[NFT_XFRM_KEY_SADDR_IP4]	= XFRM_TEMPLATE_BE("saddr", &ipaddr_type, 4 * BITS_PER_BYTE),
Packit c5a612
	[NFT_XFRM_KEY_DADDR_IP6]	= XFRM_TEMPLATE_BE("daddr", &ip6addr_type, 16 * BITS_PER_BYTE),
Packit c5a612
	[NFT_XFRM_KEY_SADDR_IP6]	= XFRM_TEMPLATE_BE("saddr", &ip6addr_type, 16 * BITS_PER_BYTE),
Packit c5a612
	[NFT_XFRM_KEY_REQID]		= XFRM_TEMPLATE_HE("reqid", &integer_type, 4 * BITS_PER_BYTE),
Packit Service 1227cd
	[NFT_XFRM_KEY_SPI]		= XFRM_TEMPLATE_HE("spi", &integer_type, 4 * BITS_PER_BYTE),
Packit c5a612
};
Packit c5a612
Packit c5a612
static void xfrm_expr_print(const struct expr *expr, struct output_ctx *octx)
Packit c5a612
{
Packit c5a612
	switch (expr->xfrm.direction) {
Packit c5a612
	case XFRM_POLICY_IN:
Packit c5a612
		nft_print(octx, "ipsec in");
Packit c5a612
		break;
Packit c5a612
	case XFRM_POLICY_OUT:
Packit c5a612
		nft_print(octx, "ipsec out");
Packit c5a612
		break;
Packit c5a612
	default:
Packit c5a612
		nft_print(octx, "ipsec (unknown dir %d)", expr->xfrm.direction);
Packit c5a612
		break;
Packit c5a612
	}
Packit c5a612
Packit c5a612
	if (expr->xfrm.spnum)
Packit c5a612
		nft_print(octx, " spnum %u", expr->xfrm.spnum);
Packit c5a612
Packit c5a612
	switch (expr->xfrm.key) {
Packit c5a612
	case NFT_XFRM_KEY_DADDR_IP4:
Packit c5a612
	case NFT_XFRM_KEY_SADDR_IP4:
Packit c5a612
		 nft_print(octx, " ip");
Packit c5a612
		 break;
Packit c5a612
	case NFT_XFRM_KEY_DADDR_IP6:
Packit c5a612
	case NFT_XFRM_KEY_SADDR_IP6:
Packit c5a612
		 nft_print(octx, " ip6");
Packit c5a612
		 break;
Packit c5a612
	case NFT_XFRM_KEY_REQID:
Packit c5a612
	case NFT_XFRM_KEY_SPI:
Packit c5a612
		 break;
Packit c5a612
	default:
Packit c5a612
		 nft_print(octx, " (unknown key 0x%x)", expr->xfrm.key);
Packit c5a612
		 return;
Packit c5a612
	}
Packit c5a612
Packit c5a612
	nft_print(octx, " %s", xfrm_templates[expr->xfrm.key].token);
Packit c5a612
}
Packit c5a612
Packit c5a612
static bool xfrm_expr_cmp(const struct expr *e1, const struct expr *e2)
Packit c5a612
{
Packit c5a612
	return e1->xfrm.key == e2->xfrm.key &&
Packit c5a612
	       e1->xfrm.direction == e2->xfrm.direction &&
Packit c5a612
	       e1->xfrm.spnum == e2->xfrm.spnum;
Packit c5a612
}
Packit c5a612
Packit c5a612
static void xfrm_expr_clone(struct expr *new, const struct expr *expr)
Packit c5a612
{
Packit c5a612
	memcpy(&new->xfrm, &expr->xfrm, sizeof(new->xfrm));
Packit c5a612
}
Packit c5a612
Packit c5a612
const struct expr_ops xfrm_expr_ops = {
Packit c5a612
	.type		= EXPR_XFRM,
Packit c5a612
	.name		= "xfrm",
Packit c5a612
	.print		= xfrm_expr_print,
Packit c5a612
	.json		= xfrm_expr_json,
Packit c5a612
	.cmp		= xfrm_expr_cmp,
Packit c5a612
	.clone		= xfrm_expr_clone,
Packit c5a612
};
Packit c5a612
Packit c5a612
struct expr *xfrm_expr_alloc(const struct location *loc,
Packit c5a612
			     uint8_t direction,
Packit c5a612
			     uint8_t spnum,
Packit c5a612
			     enum nft_xfrm_keys key)
Packit c5a612
{
Packit c5a612
	struct expr *expr;
Packit c5a612
Packit c5a612
	expr = expr_alloc(loc, EXPR_XFRM,
Packit c5a612
			  xfrm_templates[key].dtype,
Packit c5a612
			  xfrm_templates[key].byteorder,
Packit c5a612
			  xfrm_templates[key].len);
Packit c5a612
Packit c5a612
	expr->xfrm.direction = direction;
Packit c5a612
	expr->xfrm.spnum = spnum;
Packit c5a612
	expr->xfrm.key = key;
Packit c5a612
Packit c5a612
	return expr;
Packit c5a612
}