Esempio n. 1
0
static int ip_tun_build_state(struct nlattr *attr,
			      unsigned int family, const void *cfg,
			      struct lwtunnel_state **ts,
			      struct netlink_ext_ack *extack)
{
	struct ip_tunnel_info *tun_info;
	struct lwtunnel_state *new_state;
	struct nlattr *tb[LWTUNNEL_IP_MAX + 1];
	int err;

	err = nla_parse_nested_deprecated(tb, LWTUNNEL_IP_MAX, attr,
					  ip_tun_policy, extack);
	if (err < 0)
		return err;

	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
	if (!new_state)
		return -ENOMEM;

	new_state->type = LWTUNNEL_ENCAP_IP;

	tun_info = lwt_tun_info(new_state);

#ifdef CONFIG_DST_CACHE
	err = dst_cache_init(&tun_info->dst_cache, GFP_KERNEL);
	if (err) {
		lwtstate_free(new_state);
		return err;
	}
#endif

	if (tb[LWTUNNEL_IP_ID])
		tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP_ID]);

	if (tb[LWTUNNEL_IP_DST])
		tun_info->key.u.ipv4.dst = nla_get_in_addr(tb[LWTUNNEL_IP_DST]);

	if (tb[LWTUNNEL_IP_SRC])
		tun_info->key.u.ipv4.src = nla_get_in_addr(tb[LWTUNNEL_IP_SRC]);

	if (tb[LWTUNNEL_IP_TTL])
		tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP_TTL]);

	if (tb[LWTUNNEL_IP_TOS])
		tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP_TOS]);

	if (tb[LWTUNNEL_IP_FLAGS])
		tun_info->key.tun_flags = nla_get_be16(tb[LWTUNNEL_IP_FLAGS]);

	tun_info->mode = IP_TUNNEL_INFO_TX;
	tun_info->options_len = 0;

	*ts = new_state;

	return 0;
}
Esempio n. 2
0
static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
			      struct lwtunnel_state **ts)
{
	struct ip_tunnel_info *tun_info;
	struct lwtunnel_state *new_state;
	struct nlattr *tb[IP_TUN_MAX + 1];
	int err;

	err = nla_parse_nested(tb, IP_TUN_MAX, attr, ip_tun_policy);
	if (err < 0)
		return err;

	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
	if (!new_state)
		return -ENOMEM;

	new_state->type = LWTUNNEL_ENCAP_IP;

	tun_info = lwt_tun_info(new_state);

	if (tb[IP_TUN_ID])
		tun_info->key.tun_id = nla_get_u64(tb[IP_TUN_ID]);

	if (tb[IP_TUN_DST])
		tun_info->key.ipv4_dst = nla_get_be32(tb[IP_TUN_DST]);

	if (tb[IP_TUN_SRC])
		tun_info->key.ipv4_src = nla_get_be32(tb[IP_TUN_SRC]);

	if (tb[IP_TUN_TTL])
		tun_info->key.ipv4_ttl = nla_get_u8(tb[IP_TUN_TTL]);

	if (tb[IP_TUN_TOS])
		tun_info->key.ipv4_tos = nla_get_u8(tb[IP_TUN_TOS]);

	if (tb[IP_TUN_SPORT])
		tun_info->key.tp_src = nla_get_be16(tb[IP_TUN_SPORT]);

	if (tb[IP_TUN_DPORT])
		tun_info->key.tp_dst = nla_get_be16(tb[IP_TUN_DPORT]);

	if (tb[IP_TUN_FLAGS])
		tun_info->key.tun_flags = nla_get_u16(tb[IP_TUN_FLAGS]);

	tun_info->mode = IP_TUNNEL_INFO_TX;
	tun_info->options = NULL;
	tun_info->options_len = 0;

	*ts = new_state;

	return 0;
}
Esempio n. 3
0
static int ip6_tun_build_state(struct nlattr *attr,
			       unsigned int family, const void *cfg,
			       struct lwtunnel_state **ts,
			       struct netlink_ext_ack *extack)
{
	struct ip_tunnel_info *tun_info;
	struct lwtunnel_state *new_state;
	struct nlattr *tb[LWTUNNEL_IP6_MAX + 1];
	int err;

	err = nla_parse_nested_deprecated(tb, LWTUNNEL_IP6_MAX, attr,
					  ip6_tun_policy, extack);
	if (err < 0)
		return err;

	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
	if (!new_state)
		return -ENOMEM;

	new_state->type = LWTUNNEL_ENCAP_IP6;

	tun_info = lwt_tun_info(new_state);

	if (tb[LWTUNNEL_IP6_ID])
		tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP6_ID]);

	if (tb[LWTUNNEL_IP6_DST])
		tun_info->key.u.ipv6.dst = nla_get_in6_addr(tb[LWTUNNEL_IP6_DST]);

	if (tb[LWTUNNEL_IP6_SRC])
		tun_info->key.u.ipv6.src = nla_get_in6_addr(tb[LWTUNNEL_IP6_SRC]);

	if (tb[LWTUNNEL_IP6_HOPLIMIT])
		tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP6_HOPLIMIT]);

	if (tb[LWTUNNEL_IP6_TC])
		tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP6_TC]);

	if (tb[LWTUNNEL_IP6_FLAGS])
		tun_info->key.tun_flags = nla_get_be16(tb[LWTUNNEL_IP6_FLAGS]);

	tun_info->mode = IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6;
	tun_info->options_len = 0;

	*ts = new_state;

	return 0;
}
Esempio n. 4
0
static int ip_tun_build_state(struct net_device *dev, struct nlattr *attr,
			      unsigned int family, const void *cfg,
			      struct lwtunnel_state **ts)
{
	struct ip_tunnel_info *tun_info;
	struct lwtunnel_state *new_state;
	struct nlattr *tb[LWTUNNEL_IP_MAX + 1];
	int err;

	err = nla_parse_nested(tb, LWTUNNEL_IP_MAX, attr, ip_tun_policy);
	if (err < 0)
		return err;

	new_state = lwtunnel_state_alloc(sizeof(*tun_info));
	if (!new_state)
		return -ENOMEM;

	new_state->type = LWTUNNEL_ENCAP_IP;

	tun_info = lwt_tun_info(new_state);

	if (tb[LWTUNNEL_IP_ID])
		tun_info->key.tun_id = nla_get_be64(tb[LWTUNNEL_IP_ID]);

	if (tb[LWTUNNEL_IP_DST])
		tun_info->key.u.ipv4.dst = nla_get_be32(tb[LWTUNNEL_IP_DST]);

	if (tb[LWTUNNEL_IP_SRC])
		tun_info->key.u.ipv4.src = nla_get_be32(tb[LWTUNNEL_IP_SRC]);

	if (tb[LWTUNNEL_IP_TTL])
		tun_info->key.ttl = nla_get_u8(tb[LWTUNNEL_IP_TTL]);

	if (tb[LWTUNNEL_IP_TOS])
		tun_info->key.tos = nla_get_u8(tb[LWTUNNEL_IP_TOS]);

	if (tb[LWTUNNEL_IP_FLAGS])
		tun_info->key.tun_flags = nla_get_be16(tb[LWTUNNEL_IP_FLAGS]);

	tun_info->mode = IP_TUNNEL_INFO_TX;
	tun_info->options_len = 0;

	*ts = new_state;

	return 0;
}
Esempio n. 5
0
static int mpls_build_state(struct net_device *dev, struct nlattr *nla,
			    unsigned int family, const void *cfg,
			    struct lwtunnel_state **ts)
{
	struct mpls_iptunnel_encap *tun_encap_info;
	struct nlattr *tb[MPLS_IPTUNNEL_MAX + 1];
	struct lwtunnel_state *newts;
	int tun_encap_info_len;
	int ret;

	ret = nla_parse_nested(tb, MPLS_IPTUNNEL_MAX, nla,
			       mpls_iptunnel_policy);
	if (ret < 0)
		return ret;

	if (!tb[MPLS_IPTUNNEL_DST])
		return -EINVAL;

	tun_encap_info_len = sizeof(*tun_encap_info);

	newts = lwtunnel_state_alloc(tun_encap_info_len);
	if (!newts)
		return -ENOMEM;

	newts->len = tun_encap_info_len;
	tun_encap_info = mpls_lwtunnel_encap(newts);
	ret = nla_get_labels(tb[MPLS_IPTUNNEL_DST], MAX_NEW_LABELS,
			     &tun_encap_info->labels, tun_encap_info->label);
	if (ret)
		goto errout;
	newts->type = LWTUNNEL_ENCAP_MPLS;
	newts->flags |= LWTUNNEL_STATE_XMIT_REDIRECT;
	newts->headroom = mpls_encap_size(tun_encap_info);

	*ts = newts;

	return 0;

errout:
	kfree(newts);
	*ts = NULL;

	return ret;
}
Esempio n. 6
0
static int ila_build_state(struct nlattr *nla,
			   unsigned int family, const void *cfg,
			   struct lwtunnel_state **ts,
			   struct netlink_ext_ack *extack)
{
	struct ila_lwt *ilwt;
	struct ila_params *p;
	struct nlattr *tb[ILA_ATTR_MAX + 1];
	struct lwtunnel_state *newts;
	const struct fib6_config *cfg6 = cfg;
	struct ila_addr *iaddr;
	int ret;

	if (family != AF_INET6)
		return -EINVAL;

	if (cfg6->fc_dst_len < 8 * sizeof(struct ila_locator) + 3) {
		/* Need to have full locator and at least type field
		 * included in destination
		 */
		return -EINVAL;
	}

	iaddr = (struct ila_addr *)&cfg6->fc_dst;

	if (!ila_addr_is_ila(iaddr) || ila_csum_neutral_set(iaddr->ident)) {
		/* Don't allow translation for a non-ILA address or checksum
		 * neutral flag to be set.
		 */
		return -EINVAL;
	}

	ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla, ila_nl_policy, extack);
	if (ret < 0)
		return ret;

	if (!tb[ILA_ATTR_LOCATOR])
		return -EINVAL;

	newts = lwtunnel_state_alloc(sizeof(*ilwt));
	if (!newts)
		return -ENOMEM;

	ilwt = ila_lwt_lwtunnel(newts);
	ret = dst_cache_init(&ilwt->dst_cache, GFP_ATOMIC);
	if (ret) {
		kfree(newts);
		return ret;
	}

	p = ila_params_lwtunnel(newts);

	p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);

	/* Precompute checksum difference for translation since we
	 * know both the old locator and the new one.
	 */
	p->locator_match = iaddr->loc;
	p->csum_diff = compute_csum_diff8(
		(__be32 *)&p->locator_match, (__be32 *)&p->locator);

	if (tb[ILA_ATTR_CSUM_MODE])
		p->csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);

	ila_init_saved_csum(p);

	newts->type = LWTUNNEL_ENCAP_ILA;
	newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
			LWTUNNEL_STATE_INPUT_REDIRECT;

	if (cfg6->fc_dst_len == 8 * sizeof(struct in6_addr))
		ilwt->connected = 1;

	*ts = newts;

	return 0;
}