Re: [PATCH] IP masq csum fix for 2.1.127

Chip Salzenberg (chip@perlsupport.com)
Mon, 9 Nov 1998 02:02:26 -0500


--SUOF0GtieIMvvwua
Content-Type: text/plain; charset=us-ascii

According to Juanjo Ciarlante:
> This patch fixes incorrect ip_masq csuming when faced with corrupted pkts.

I've attached my adaptation of this patch for 2.1.127.

Is it still useful, though, I wonder? I don't know the IP
masquerading code that well.

-- 
Chip Salzenberg        - a.k.a. -        <chip@perlsupport.com>
      "There -- we made them swerve slightly!"   //MST3K

--SUOF0GtieIMvvwua Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=patch

Index: net/ipv4/ip_masq.c *************** static spinlock_t masq_port_lock = SPIN_ *** 338,341 **** --- 338,344 ---- #endif + /* + * At the moment, hardcore in sync with masq_proto_num + */ atomic_t ip_masq_free_ports[3] = { ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* UDP */ *************** mport_nono: *** 961,973 **** } ! static __inline__ unsigned proto_doff(unsigned proto, char *th) { switch (proto) { case IPPROTO_UDP: ! return sizeof(struct udphdr); case IPPROTO_TCP: ! return ((struct tcphdr*)th)->doff << 2; } ! return 0; } --- 964,1000 ---- } ! /* ! * Get transport protocol data offset, check against size ! */ ! static __inline__ int proto_doff(unsigned proto, char *th, unsigned size) { + int ret = -1; switch (proto) { + case IPPROTO_ICMP: + if (size >= sizeof(struct icmphdr)) + ret = sizeof(struct icmphdr); + break; case IPPROTO_UDP: ! if (size >= sizeof(struct udphdr)) ! ret = sizeof(struct udphdr); ! break; case IPPROTO_TCP: ! /* ! * Is this case, this check _also_ avoids ! * touching an invalid pointer if ! * size is invalid ! */ ! if (size >= sizeof(struct tcphdr)) { ! ret = ((struct tcphdr*)th)->doff << 2; ! if (ret > size) ! ret = -1; ! } ! ! break; } ! if (ret < 0) ! IP_MASQ_DEBUG(0, "mess proto_doff for proto=%d, size =%d\n", ! proto, size); ! return ret; } *************** int ip_fw_masquerade(struct sk_buff **sk *** 981,990 **** /* ! * Magic "doff" csum semantics ! * !0: saved payload csum IS valid, doff is correct ! * 0: csum not valid */ ! unsigned doff = 0; int csum = 0; /* --- 1008,1018 ---- /* ! * doff holds transport protocol data offset ! * csum holds its checksum ! * csum_ok says if csum is valid */ ! int doff = 0; int csum = 0; + int csum_ok = 0; /* *************** int ip_fw_masquerade(struct sk_buff **sk *** 993,997 **** --- 1021,1031 ---- h.raw = (char*) iph + iph->ihl * 4; + size = ntohs(iph->tot_len) - (iph->ihl * 4); + doff = proto_doff(iph->protocol, h.raw, size); + if (doff < 0) { + IP_MASQ_DEBUG(0, "O-pkt invalid packet data size\n"); + return -1; + } switch (iph->protocol) { case IPPROTO_ICMP: *************** int ip_fw_masquerade(struct sk_buff **sk *** 1003,1007 **** case IPPROTO_TCP: /* Make sure packet is in the masq range */ - size = ntohs(iph->tot_len) - (iph->ihl * 4); IP_MASQ_DEBUG(3, "O-pkt: %s size=%d\n", masq_proto_name(iph->protocol), --- 1037,1040 ---- *************** int ip_fw_masquerade(struct sk_buff **sk *** 1014,1022 **** { int datasz; - doff = proto_doff(iph->protocol, h.raw); datasz = size - doff; if (datasz < 0) return -1; csum = csum_partial(h.raw + doff, datasz, 0); IP_MASQ_DEBUG(3, "O-pkt: %s I-datacsum=%d\n", masq_proto_name(iph->protocol), --- 1047,1055 ---- { int datasz; datasz = size - doff; if (datasz < 0) return -1; csum = csum_partial(h.raw + doff, datasz, 0); + csum_ok++; IP_MASQ_DEBUG(3, "O-pkt: %s I-datacsum=%d\n", masq_proto_name(iph->protocol), *************** int ip_fw_masquerade(struct sk_buff **sk *** 1139,1143 **** if (ms->app) ! doff = 0; /* --- 1172,1176 ---- if (ms->app) ! csum_ok = 0; /* *************** int ip_fw_masquerade(struct sk_buff **sk *** 1153,1157 **** iph = skb->nh.iph; h.raw = (char*) iph + iph->ihl *4; ! size = skb->len - (h.raw - skb->nh.raw); } --- 1186,1191 ---- iph = skb->nh.iph; h.raw = (char*) iph + iph->ihl *4; ! size = skb->len - (h.raw - skb->nh.raw); ! /* doff should have not changed */ } *************** int ip_fw_masquerade(struct sk_buff **sk *** 1164,1169 **** */ ! if (!doff) { ! doff = proto_doff(iph->protocol, h.raw); csum = csum_partial(h.raw + doff, size - doff, 0); } --- 1198,1202 ---- */ ! if (!csum_ok) { csum = csum_partial(h.raw + doff, size - doff, 0); } *************** int ip_fw_demasquerade(struct sk_buff ** *** 1716,1721 **** struct ip_masq *ms; unsigned short size; ! unsigned doff = 0; int csum = 0; __u32 maddr; --- 1749,1755 ---- struct ip_masq *ms; unsigned short size; ! int doff = 0; int csum = 0; + int csum_ok = 0; __u32 maddr; *************** int ip_fw_demasquerade(struct sk_buff ** *** 1733,1738 **** } - maddr = iph->daddr; h.raw = (char*) iph + iph->ihl * 4; switch (iph->protocol) { --- 1767,1783 ---- } h.raw = (char*) iph + iph->ihl * 4; + /* + * IP payload size + */ + size = ntohs(iph->tot_len) - (iph->ihl * 4); + + doff = proto_doff(iph->protocol, h.raw, size); + if (doff < 0) { + IP_MASQ_DEBUG(0, "I-pkt invalid packet data size\n"); + return -1; + } + + maddr = iph->daddr; switch (iph->protocol) { *************** int ip_fw_demasquerade(struct sk_buff ** *** 1755,1759 **** /* Check that the checksum is OK */ - size = ntohs(iph->tot_len) - (iph->ihl * 4); if ((iph->protocol == IPPROTO_UDP) && (h.uh->check == 0)) /* No UDP checksum */ --- 1800,1803 ---- *************** int ip_fw_demasquerade(struct sk_buff ** *** 1763,1768 **** { case CHECKSUM_NONE: - doff = proto_doff(iph->protocol, h.raw); csum = csum_partial(h.raw + doff, size - doff, 0); skb->csum = csum_partial(h.raw , doff, csum); --- 1807,1812 ---- { case CHECKSUM_NONE: csum = csum_partial(h.raw + doff, size - doff, 0); + csum_ok++; skb->csum = csum_partial(h.raw , doff, csum); *************** int ip_fw_demasquerade(struct sk_buff ** *** 1852,1856 **** if (ms->app) ! doff = 0; /* --- 1896,1900 ---- if (ms->app) ! csum_ok = 0; /* *************** int ip_fw_demasquerade(struct sk_buff ** *** 1879,1884 **** */ ! if (!doff) { ! doff = proto_doff(iph->protocol, h.raw); csum = csum_partial(h.raw + doff, size - doff, 0); } --- 1923,1927 ---- */ ! if (!csum_ok) { csum = csum_partial(h.raw + doff, size - doff, 0); }

--SUOF0GtieIMvvwua--

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/