Пример #1
0
static int br_nf_dev_queue_xmit(struct sk_buff *skb)
{
	int ret;

	if (skb->nfct != NULL && skb->protocol == htons(ETH_P_IP) &&
	    skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu &&
	    !skb_is_gso(skb)) {
		if (br_parse_ip_options(skb))
			/* Drop invalid packet */
			return NF_DROP;
		ret = ip_fragment(skb, br_dev_queue_push_xmit);
	} else
		ret = br_dev_queue_push_xmit(skb);

	return ret;
}
Пример #2
0
static int br_nf_dev_queue_xmit(struct sk_buff *skb)
{
	int ret;

	if (!skb_is_gso(skb) &&
	    skb->protocol == htons(ETH_P_IP) &&
	    skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu) {
		if (br_parse_ip_options(skb))
			/* Drop invalid packet */
			goto drop;
		ret = ip_fragment(skb, br_dev_queue_push_xmit);
	} else
		ret = br_dev_queue_push_xmit(skb);

	return ret;
drop:
	kfree_skb(skb);
	return 0;
}
Пример #3
0
static int br_nf_dev_queue_xmit(struct sk_buff *skb)
{
	int ret;
	int frag_max_size;

	/* This is wrong! We should preserve the original fragment
	 * boundaries by preserving frag_list rather than refragmenting.
	 */
	if (skb->protocol == htons(ETH_P_IP) &&
	    skb->len + nf_bridge_mtu_reduction(skb) > skb->dev->mtu &&
	    !skb_is_gso(skb)) {
		frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
		if (br_parse_ip_options(skb))
			/* Drop invalid packet */
			return NF_DROP;
		IPCB(skb)->frag_max_size = frag_max_size;
		ret = ip_fragment(skb, br_dev_queue_push_xmit);
	} else
		ret = br_dev_queue_push_xmit(skb);

	return ret;
}
Пример #4
0
static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb)
{
    int ret;
    int frag_max_size;
    unsigned int mtu_reserved;

    if (skb_is_gso(skb) || skb->protocol != htons(ETH_P_IP))
        return br_dev_queue_push_xmit(sk, skb);

    mtu_reserved = nf_bridge_mtu_reduction(skb);
    /* This is wrong! We should preserve the original fragment
     * boundaries by preserving frag_list rather than refragmenting.
     */
    if (skb->len + mtu_reserved > skb->dev->mtu) {
        struct brnf_frag_data *data;

        frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
        if (br_parse_ip_options(skb))
            /* Drop invalid packet */
            return NF_DROP;
        IPCB(skb)->frag_max_size = frag_max_size;

        nf_bridge_update_protocol(skb);

        data = this_cpu_ptr(&brnf_frag_data_storage);
        data->encap_size = nf_bridge_encap_header_len(skb);
        data->size = ETH_HLEN + data->encap_size;

        skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
                                         data->size);

        ret = ip_fragment(sk, skb, br_nf_push_frag_xmit);
    } else {
        ret = br_dev_queue_push_xmit(sk, skb);
    }

    return ret;
}
Пример #5
0
static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	struct nf_bridge_info *nf_bridge;
	unsigned int mtu_reserved;

	mtu_reserved = nf_bridge_mtu_reduction(skb);

	if (skb_is_gso(skb) || skb->len + mtu_reserved <= skb->dev->mtu) {
		nf_bridge_info_free(skb);
		return br_dev_queue_push_xmit(net, sk, skb);
	}

	nf_bridge = nf_bridge_info_get(skb);

	/* This is wrong! We should preserve the original fragment
	 * boundaries by preserving frag_list rather than refragmenting.
	 */
	if (IS_ENABLED(CONFIG_NF_DEFRAG_IPV4) &&
	    skb->protocol == htons(ETH_P_IP)) {
		struct brnf_frag_data *data;

		if (br_validate_ipv4(net, skb))
			goto drop;

		IPCB(skb)->frag_max_size = nf_bridge->frag_max_size;

		nf_bridge_update_protocol(skb);

		data = this_cpu_ptr(&brnf_frag_data_storage);

		data->vlan_tci = skb->vlan_tci;
		data->vlan_proto = skb->vlan_proto;
		data->encap_size = nf_bridge_encap_header_len(skb);
		data->size = ETH_HLEN + data->encap_size;

		skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
						 data->size);

		return br_nf_ip_fragment(net, sk, skb, br_nf_push_frag_xmit);
	}
	if (IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) &&
	    skb->protocol == htons(ETH_P_IPV6)) {
		const struct nf_ipv6_ops *v6ops = nf_get_ipv6_ops();
		struct brnf_frag_data *data;

		if (br_validate_ipv6(net, skb))
			goto drop;

		IP6CB(skb)->frag_max_size = nf_bridge->frag_max_size;

		nf_bridge_update_protocol(skb);

		data = this_cpu_ptr(&brnf_frag_data_storage);
		data->encap_size = nf_bridge_encap_header_len(skb);
		data->size = ETH_HLEN + data->encap_size;

		skb_copy_from_linear_data_offset(skb, -data->size, data->mac,
						 data->size);

		if (v6ops)
			return v6ops->fragment(net, sk, skb, br_nf_push_frag_xmit);

		kfree_skb(skb);
		return -EMSGSIZE;
	}
	nf_bridge_info_free(skb);
	return br_dev_queue_push_xmit(net, sk, skb);
 drop:
	kfree_skb(skb);
	return 0;
}