Esempio n. 1
0
static void lro_update_tcp_ip_header(struct net_lro_desc *lro_desc)
{
	struct iphdr *iph = lro_desc->iph;
	struct tcphdr *tcph = lro_desc->tcph;
	__be32 *p;
	__wsum tcp_hdr_csum;

	tcph->ack_seq = lro_desc->tcp_ack;
	tcph->window = lro_desc->tcp_window;

	if (lro_desc->tcp_saw_tstamp) {
		p = (__be32 *)(tcph + 1);
		*(p+2) = lro_desc->tcp_rcv_tsecr;
	}

	csum_replace2(&iph->check, iph->tot_len, htons(lro_desc->ip_tot_len));
	iph->tot_len = htons(lro_desc->ip_tot_len);

	tcph->check = 0;
	tcp_hdr_csum = csum_partial((u8 *)tcph, TCP_HDR_LEN(tcph), 0);
	lro_desc->data_csum = csum_add(lro_desc->data_csum, tcp_hdr_csum);
	tcph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
					lro_desc->ip_tot_len -
					IP_HDR_LEN(iph), IPPROTO_TCP,
					lro_desc->data_csum);
}
Esempio n. 2
0
static void udpencap_fix4(struct sk_buff *skb, const struct xt_udpencap_tginfo *info)
{
	struct iphdr *iph = ip_hdr(skb);
	bool fix_csum = (skb->ip_summed == CHECKSUM_COMPLETE && !info->encap);
	__be16 newlen = htons(ntohs(iph->tot_len) + (info->encap ? 1 : -1) * sizeof(struct udphdr));
	if (fix_csum) {
		skb->csum = csum_sub(skb->csum, csum_partial(&iph->tot_len, 2, 0));
		skb->csum = csum_sub(skb->csum, csum_partial(&iph->protocol, 3, 0));
	}
	csum_replace2(&iph->check, iph->tot_len, newlen);
	iph->tot_len = newlen;
	if (iph->protocol != info->proto) {
		csum_replace2(&iph->check, htons(iph->protocol), htons(info->proto));
		iph->protocol = info->proto;
	}
	if (fix_csum) {
		skb->csum = csum_add(skb->csum, csum_partial(&iph->tot_len, 2, 0));
		skb->csum = csum_add(skb->csum, csum_partial(&iph->protocol, 3, 0));
	}
}
Esempio n. 3
0
File: af_mpls.c Progetto: 3bsa/linux
static bool mpls_egress(struct mpls_route *rt, struct sk_buff *skb,
			struct mpls_entry_decoded dec)
{
	/* RFC4385 and RFC5586 encode other packets in mpls such that
	 * they don't conflict with the ip version number, making
	 * decoding by examining the ip version correct in everything
	 * except for the strangest cases.
	 *
	 * The strange cases if we choose to support them will require
	 * manual configuration.
	 */
	struct iphdr *hdr4;
	bool success = true;

	/* The IPv4 code below accesses through the IPv4 header
	 * checksum, which is 12 bytes into the packet.
	 * The IPv6 code below accesses through the IPv6 hop limit
	 * which is 8 bytes into the packet.
	 *
	 * For all supported cases there should always be at least 12
	 * bytes of packet data present.  The IPv4 header is 20 bytes
	 * without options and the IPv6 header is always 40 bytes
	 * long.
	 */
	if (!pskb_may_pull(skb, 12))
		return false;

	/* Use ip_hdr to find the ip protocol version */
	hdr4 = ip_hdr(skb);
	if (hdr4->version == 4) {
		skb->protocol = htons(ETH_P_IP);
		csum_replace2(&hdr4->check,
			      htons(hdr4->ttl << 8),
			      htons(dec.ttl << 8));
		hdr4->ttl = dec.ttl;
	}
	else if (hdr4->version == 6) {
		struct ipv6hdr *hdr6 = ipv6_hdr(skb);
		skb->protocol = htons(ETH_P_IPV6);
		hdr6->hop_limit = dec.ttl;
	}
	else
		/* version 0 and version 1 are used by pseudo wires */
		success = false;
	return success;
}
/* set ECT codepoint from IP header.
 * 	return false if there was an error. */
static inline bool
set_ect_ip(struct sk_buff *skb, const struct ipt_ECN_info *einfo)
{
	struct iphdr *iph = ip_hdr(skb);

	if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
		__u8 oldtos;
		if (!skb_make_writable(skb, sizeof(struct iphdr)))
			return false;
		iph = ip_hdr(skb);
		oldtos = iph->tos;
		iph->tos &= ~IPT_ECN_IP_MASK;
		iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK);
		csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
	}
	return true;
}
Esempio n. 5
0
static void cvsw_apply_set_nw_tos(struct sk_buff *skb, const __u8 tos)
{
    __u8 *nw;

    nw = skb_util_get_network_header(skb);
    if (unlikely(! nw)) {
	return ;
    }

    if (((struct iphdr*)nw)->version == 4) {
	off_t off;
	struct iphdr *ip4;
	ip4 = (struct iphdr*)nw;
	off = offsetof(struct iphdr, tos);
	/* Update L3 checksum */
	csum_replace2(&ip4->check, htons(*((__u16*)&ip4->tos)), tos << 8 | nw[off + 1]);
	/* Set ToS */
	ip4->tos = tos;
    } else if (((struct ipv6hdr*)nw)->version == 6) {
Esempio n. 6
0
static unsigned int
ttl_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
	struct iphdr *iph;
	const struct ipt_TTL_info *info = par->targinfo;
	int new_ttl;

	if (!skb_make_writable(skb, skb->len))
		return NF_DROP;

	iph = ip_hdr(skb);

	switch (info->mode) {
	case IPT_TTL_SET:
		new_ttl = info->ttl;
		break;
	case IPT_TTL_INC:
		new_ttl = iph->ttl + info->ttl;
		if (new_ttl > 255)
			new_ttl = 255;
		break;
	case IPT_TTL_DEC:
		new_ttl = iph->ttl - info->ttl;
		if (new_ttl < 0)
			new_ttl = 0;
		break;
	default:
		new_ttl = iph->ttl;
		break;
	}

	if (new_ttl != iph->ttl) {
		csum_replace2(&iph->check, htons(iph->ttl << 8),
					   htons(new_ttl << 8));
		iph->ttl = new_ttl;
	}

	return XT_CONTINUE;
}
Esempio n. 7
0
static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl)
{
	csum_replace2(&nh->check, htons(nh->ttl << 8), htons(new_ttl << 8));
	nh->ttl = new_ttl;
}