mirror of
https://github.com/torvalds/linux.git
synced 2026-09-14 16:10:02 +02:00
net: Use helpers to get/set UDP len tree-wide
Since BIG TCP for UDP tunnels will start using len=0 in the UDP header as an indicator of a GSO packet bigger than 65535 bytes, this commit introduces the following getter and setters to use tree-wide, in order to explicitly mark places where len=0 may be expected, and handle them properly: 1. udp_set_len() sets uh->len to its real value if it's not bigger than 65535, and to 0 otherwise: to be used in GSO context with aggregated packets. 2. udp_set_len_short() is to be used when the length is known to fit 16 bits. It WARNs when the caller tries to assign a bigger value if CONFIG_DEBUG_NET=y. 3. udp_get_len_short() returns len in host byte order: to be used on the RX side to deal with non-aggregated packets, or to access the raw value of the len field. 4. udp_get_len() decodes uh->len set by udp_set_len(). It checks whether the packet is GSO to guard from malformed packets. At the moment udp_set_len() is not used, a following commit will start using it after enabling len>65535 for GSO. Raw uh->len (in network byte order) is still accessed in a few places for checksum calculation purposes, and to decode len=0 in udpv6_rcv for jumbograms. udp_rcv and udpv6_rcv will be addressed by the commit that starts using udp_set_len() to set UDP len=0 for BIG TCP packets in UDP tunnels. Signed-off-by: Alice Mikityanska <alice@isovalent.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Acked-by: Jason A. Donenfeld <Jason@zx2c4.com> Link: https://patch.msgid.link/20260710134242.216538-2-alice.kernel@fastmail.im Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
ba520084dc
commit
5329647dad
|
|
@ -36,7 +36,7 @@ static struct sk_buff *rdma_build_skb(struct net_device *netdev,
|
|||
uh->source =
|
||||
htons(rdma_flow_label_to_udp_sport(ah_attr->grh.flow_label));
|
||||
uh->dest = htons(ROCE_V2_UDP_DPORT);
|
||||
uh->len = htons(sizeof(struct udphdr));
|
||||
udp_set_len_short(uh, sizeof(struct udphdr));
|
||||
|
||||
if (is_ipv4) {
|
||||
skb_push(skb, sizeof(struct iphdr));
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ static int rxe_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
|||
pkt->port_num = 1;
|
||||
pkt->hdr = (u8 *)(udph + 1);
|
||||
pkt->mask = RXE_GRH_MASK;
|
||||
pkt->paylen = be16_to_cpu(udph->len) - sizeof(*udph);
|
||||
pkt->paylen = udp_get_len_short(udph) - sizeof(*udph);
|
||||
|
||||
/* remove udp header */
|
||||
skb_pull(skb, sizeof(struct udphdr));
|
||||
|
|
@ -305,7 +305,7 @@ static void prepare_udp_hdr(struct sk_buff *skb, __be16 src_port,
|
|||
|
||||
udph->dest = dst_port;
|
||||
udph->source = src_port;
|
||||
udph->len = htons(skb->len);
|
||||
udp_set_len_short(udph, skb->len);
|
||||
udph->check = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -667,7 +667,7 @@ static void amt_send_discovery(struct amt_dev *amt)
|
|||
udph = udp_hdr(skb);
|
||||
udph->source = amt->gw_port;
|
||||
udph->dest = amt->relay_port;
|
||||
udph->len = htons(sizeof(*udph) + sizeof(*amtd));
|
||||
udp_set_len_short(udph, sizeof(*udph) + sizeof(*amtd));
|
||||
udph->check = 0;
|
||||
offset = skb_transport_offset(skb);
|
||||
skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
|
||||
|
|
@ -760,7 +760,7 @@ static void amt_send_request(struct amt_dev *amt, bool v6)
|
|||
udph = udp_hdr(skb);
|
||||
udph->source = amt->gw_port;
|
||||
udph->dest = amt->relay_port;
|
||||
udph->len = htons(sizeof(*amtrh) + sizeof(*udph));
|
||||
udp_set_len_short(udph, sizeof(*amtrh) + sizeof(*udph));
|
||||
udph->check = 0;
|
||||
offset = skb_transport_offset(skb);
|
||||
skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
|
||||
|
|
@ -2611,7 +2611,7 @@ static void amt_send_advertisement(struct amt_dev *amt, __be32 nonce,
|
|||
udph = udp_hdr(skb);
|
||||
udph->source = amt->relay_port;
|
||||
udph->dest = dport;
|
||||
udph->len = htons(sizeof(*amta) + sizeof(*udph));
|
||||
udp_set_len_short(udph, sizeof(*amta) + sizeof(*udph));
|
||||
udph->check = 0;
|
||||
offset = skb_transport_offset(skb);
|
||||
skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
|
||||
|
|
|
|||
|
|
@ -3129,7 +3129,7 @@ static int i40e_tso(struct i40e_tx_buffer *first, u8 *hdr_len,
|
|||
SKB_GSO_UDP_TUNNEL_CSUM)) {
|
||||
if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
|
||||
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
|
||||
l4.udp->len = 0;
|
||||
udp_set_len_short(l4.udp, 0);
|
||||
|
||||
/* determine offset of outer transport header */
|
||||
l4_offset = l4.hdr - skb->data;
|
||||
|
|
|
|||
|
|
@ -1774,7 +1774,7 @@ static int iavf_tso(struct iavf_tx_buffer *first, u8 *hdr_len,
|
|||
SKB_GSO_UDP_TUNNEL_CSUM)) {
|
||||
if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
|
||||
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
|
||||
l4.udp->len = 0;
|
||||
udp_set_len_short(l4.udp, 0);
|
||||
|
||||
/* determine offset of outer transport header */
|
||||
l4_offset = l4.hdr - skb->data;
|
||||
|
|
|
|||
|
|
@ -1893,7 +1893,7 @@ int ice_tso(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
|
|||
SKB_GSO_UDP_TUNNEL_CSUM)) {
|
||||
if (!(skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) &&
|
||||
(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM)) {
|
||||
l4.udp->len = 0;
|
||||
udp_set_len_short(l4.udp, 0);
|
||||
|
||||
/* determine offset of outer transport header */
|
||||
l4_start = (u8)(l4.hdr - skb->data);
|
||||
|
|
|
|||
|
|
@ -2871,7 +2871,7 @@ int idpf_tso(struct sk_buff *skb, struct idpf_tx_offload_params *off)
|
|||
(__force __wsum)htonl(paylen));
|
||||
/* compute length of segmentation header */
|
||||
off->tso_hdr_len = sizeof(struct udphdr) + l4_start;
|
||||
l4.udp->len = htons(shinfo->gso_size + sizeof(struct udphdr));
|
||||
udp_set_len_short(l4.udp, shinfo->gso_size + sizeof(struct udphdr));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -750,7 +750,7 @@ static void otx2_sqe_add_ext(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
|
|||
ext->lso_format = pfvf->hw.lso_udpv6_idx;
|
||||
}
|
||||
|
||||
udph->len = htons(sizeof(struct udphdr));
|
||||
udp_set_len_short(udph, sizeof(struct udphdr));
|
||||
}
|
||||
} else if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
|
||||
ext->tstmp = 1;
|
||||
|
|
|
|||
|
|
@ -1081,7 +1081,7 @@ static void mlx5e_shampo_update_ipv4_udp_hdr(struct mlx5e_rq *rq, struct iphdr *
|
|||
struct udphdr *uh;
|
||||
|
||||
uh = (struct udphdr *)(skb->data + udp_off);
|
||||
uh->len = htons(skb->len - udp_off);
|
||||
udp_set_len_short(uh, skb->len - udp_off);
|
||||
|
||||
if (uh->check)
|
||||
uh->check = ~udp_v4_check(skb->len - udp_off, ipv4->saddr,
|
||||
|
|
@ -1100,7 +1100,7 @@ static void mlx5e_shampo_update_ipv6_udp_hdr(struct mlx5e_rq *rq, struct ipv6hdr
|
|||
struct udphdr *uh;
|
||||
|
||||
uh = (struct udphdr *)(skb->data + udp_off);
|
||||
uh->len = htons(skb->len - udp_off);
|
||||
udp_set_len_short(uh, skb->len - udp_off);
|
||||
|
||||
if (uh->check)
|
||||
uh->check = ~udp_v6_check(skb->len - udp_off, &ipv6->saddr,
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
|
|||
/* Fill UDP header */
|
||||
udph->source = htons(9);
|
||||
udph->dest = htons(9); /* Discard Protocol */
|
||||
udph->len = htons(sizeof(struct mlx5ehdr) + sizeof(struct udphdr));
|
||||
udp_set_len_short(udph, sizeof(struct mlx5ehdr) + sizeof(struct udphdr));
|
||||
udph->check = 0;
|
||||
|
||||
/* Fill IP header */
|
||||
|
|
|
|||
|
|
@ -401,8 +401,8 @@ static void ef4_iterate_state(struct ef4_nic *efx)
|
|||
|
||||
/* Initialise udp header */
|
||||
payload->udp.source = 0;
|
||||
payload->udp.len = htons(sizeof(*payload) -
|
||||
offsetof(struct ef4_loopback_payload, udp));
|
||||
udp_set_len_short(&payload->udp, sizeof(*payload) -
|
||||
offsetof(struct ef4_loopback_payload, udp));
|
||||
payload->udp.check = 0; /* checksum ignored */
|
||||
|
||||
/* Fill out payload */
|
||||
|
|
|
|||
|
|
@ -398,8 +398,8 @@ static void efx_iterate_state(struct efx_nic *efx)
|
|||
|
||||
/* Initialise udp header */
|
||||
payload->udp.source = 0;
|
||||
payload->udp.len = htons(sizeof(*payload) -
|
||||
offsetof(struct efx_loopback_payload, udp));
|
||||
udp_set_len_short(&payload->udp, sizeof(*payload) -
|
||||
offsetof(struct efx_loopback_payload, udp));
|
||||
payload->udp.check = 0; /* checksum ignored */
|
||||
|
||||
/* Fill out payload */
|
||||
|
|
|
|||
|
|
@ -399,8 +399,8 @@ static void efx_iterate_state(struct efx_nic *efx)
|
|||
|
||||
/* Initialise udp header */
|
||||
payload->udp.source = 0;
|
||||
payload->udp.len = htons(sizeof(*payload) -
|
||||
offsetof(struct efx_loopback_payload, udp));
|
||||
udp_set_len_short(&payload->udp, sizeof(*payload) -
|
||||
offsetof(struct efx_loopback_payload, udp));
|
||||
payload->udp.check = 0; /* checksum ignored */
|
||||
|
||||
/* Fill out payload */
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ static void efx_gen_tun_header_udp(struct efx_tc_encap_action *encap, u8 len)
|
|||
encap->encap_hdr_len += sizeof(*udp);
|
||||
|
||||
udp->dest = key->tp_dst;
|
||||
udp->len = cpu_to_be16(sizeof(*udp) + len);
|
||||
udp_set_len_short(udp, sizeof(*udp) + len);
|
||||
}
|
||||
|
||||
static void efx_gen_tun_header_vxlan(struct efx_tc_encap_action *encap)
|
||||
|
|
|
|||
|
|
@ -154,9 +154,9 @@ static struct sk_buff *stmmac_test_get_udp_skb(struct stmmac_priv *priv,
|
|||
} else {
|
||||
uhdr->source = htons(attr->sport);
|
||||
uhdr->dest = htons(attr->dport);
|
||||
uhdr->len = htons(sizeof(*shdr) + sizeof(*uhdr) + attr->size);
|
||||
udp_set_len_short(uhdr, sizeof(*shdr) + sizeof(*uhdr) + attr->size);
|
||||
if (attr->max_size)
|
||||
uhdr->len = htons(attr->max_size -
|
||||
udp_set_len_short(uhdr, attr->max_size -
|
||||
(sizeof(*ihdr) + sizeof(*ehdr)));
|
||||
uhdr->check = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -631,7 +631,7 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb,
|
|||
|
||||
/* Adjust the nested UDP header len and checksum. */
|
||||
uh = udp_hdr(skb);
|
||||
uh->len = htons(skb->len - gro_hint->nested_tp_offset);
|
||||
udp_set_len_short(uh, skb->len - gro_hint->nested_tp_offset);
|
||||
if (uh->check) {
|
||||
len = skb->len - gro_hint->nested_tp_offset;
|
||||
skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL_CSUM;
|
||||
|
|
|
|||
|
|
@ -1876,7 +1876,7 @@ static void push_udp(struct netpoll *np, struct sk_buff *skb, int len)
|
|||
udph = udp_hdr(skb);
|
||||
udph->source = htons(np->local_port);
|
||||
udph->dest = htons(np->remote_port);
|
||||
udph->len = htons(udp_len);
|
||||
udp_set_len_short(udph, udp_len);
|
||||
|
||||
netpoll_udp_checksum(np, skb, len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -845,7 +845,7 @@ static struct sk_buff *nsim_dev_trap_skb_build(void)
|
|||
udph = skb_put_zero(skb, sizeof(struct udphdr) + data_len);
|
||||
get_random_bytes(&udph->source, sizeof(u16));
|
||||
get_random_bytes(&udph->dest, sizeof(u16));
|
||||
udph->len = htons(sizeof(struct udphdr) + data_len);
|
||||
udp_set_len_short(udph, sizeof(struct udphdr) + data_len);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ static struct sk_buff *nsim_dev_psample_skb_build(void)
|
|||
udph = skb_put_zero(skb, sizeof(struct udphdr) + data_len);
|
||||
get_random_bytes(&udph->source, sizeof(u16));
|
||||
get_random_bytes(&udph->dest, sizeof(u16));
|
||||
udph->len = htons(sizeof(struct udphdr) + data_len);
|
||||
udp_set_len_short(udph, sizeof(struct udphdr) + data_len);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
|
|||
struct iphdr *iph;
|
||||
struct udphdr *uh;
|
||||
__wsum csum;
|
||||
int udplen;
|
||||
|
||||
/* Do not decapsulate. Receive the skb with the udp and psp
|
||||
* headers still there as if this is a normal udp packet.
|
||||
|
|
@ -91,19 +92,20 @@ nsim_do_psp(struct sk_buff *skb, struct netdevsim *ns,
|
|||
* provide a valid checksum here, so the skb isn't dropped.
|
||||
*/
|
||||
uh = udp_hdr(skb);
|
||||
udplen = udp_get_len(skb, uh, skb_transport_offset(skb));
|
||||
csum = skb_checksum(skb, skb_transport_offset(skb),
|
||||
ntohs(uh->len), 0);
|
||||
udplen, 0);
|
||||
|
||||
switch (skb->protocol) {
|
||||
case htons(ETH_P_IP):
|
||||
iph = ip_hdr(skb);
|
||||
uh->check = udp_v4_check(ntohs(uh->len), iph->saddr,
|
||||
uh->check = udp_v4_check(udplen, iph->saddr,
|
||||
iph->daddr, csum);
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
case htons(ETH_P_IPV6):
|
||||
ip6h = ipv6_hdr(skb);
|
||||
uh->check = udp_v6_check(ntohs(uh->len), &ip6h->saddr,
|
||||
uh->check = udp_v6_check(udplen, &ip6h->saddr,
|
||||
&ip6h->daddr, csum);
|
||||
break;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ static int prepare_skb_header(struct sk_buff *skb, struct wg_device *wg)
|
|||
* to have UDP fields.
|
||||
*/
|
||||
return -EINVAL;
|
||||
data_len = ntohs(udp->len);
|
||||
data_len = udp_get_len_short(udp);
|
||||
if (unlikely(data_len < sizeof(struct udphdr) ||
|
||||
data_len > skb->len - data_offset))
|
||||
/* UDP packet is reporting too small of a size or lying about
|
||||
|
|
|
|||
|
|
@ -23,6 +23,33 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
|
|||
return (struct udphdr *)skb_transport_header(skb);
|
||||
}
|
||||
|
||||
static inline unsigned int udp_get_len(const struct sk_buff *skb,
|
||||
const struct udphdr *uh,
|
||||
unsigned int dataoff)
|
||||
{
|
||||
if (uh->len)
|
||||
return ntohs(uh->len);
|
||||
if (skb_is_gso(skb)) /* BIG TCP */
|
||||
return skb->len - dataoff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int udp_get_len_short(const struct udphdr *uh)
|
||||
{
|
||||
return ntohs(uh->len);
|
||||
}
|
||||
|
||||
static inline void udp_set_len(struct udphdr *uh, unsigned int len)
|
||||
{
|
||||
uh->len = len < GRO_LEGACY_MAX_SIZE ? htons(len) : 0;
|
||||
}
|
||||
|
||||
static inline void udp_set_len_short(struct udphdr *uh, unsigned int len)
|
||||
{
|
||||
DEBUG_NET_WARN_ON_ONCE(len >= GRO_LEGACY_MAX_SIZE);
|
||||
uh->len = htons(len);
|
||||
}
|
||||
|
||||
#define UDP_HTABLE_SIZE_MIN_PERNET 128
|
||||
#define UDP_HTABLE_SIZE_MIN (IS_ENABLED(CONFIG_BASE_SMALL) ? 128 : 256)
|
||||
#define UDP_HTABLE_SIZE_MAX 65536
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ TRACE_EVENT(icmp_send,
|
|||
} else {
|
||||
__entry->sport = ntohs(uh->source);
|
||||
__entry->dport = ntohs(uh->dest);
|
||||
__entry->ulen = ntohs(uh->len);
|
||||
__entry->ulen = udp_get_len_short(uh);
|
||||
}
|
||||
|
||||
p32 = (__be32 *) __entry->saddr;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ static void test_blackholedev(struct kunit *test)
|
|||
uh = (struct udphdr *)skb_push(skb, sizeof(struct udphdr));
|
||||
skb_set_transport_header(skb, 0);
|
||||
uh->source = uh->dest = htons(UDP_PORT);
|
||||
uh->len = htons(data_len);
|
||||
udp_set_len_short(uh, data_len);
|
||||
uh->check = 0;
|
||||
/* (Network) IPv6 */
|
||||
ip6h = (struct ipv6hdr *)skb_push(skb, sizeof(struct ipv6hdr));
|
||||
|
|
|
|||
|
|
@ -88,16 +88,16 @@ static int udp_uncompress(struct sk_buff *skb, size_t needed)
|
|||
switch (lowpan_dev(skb->dev)->lltype) {
|
||||
case LOWPAN_LLTYPE_IEEE802154:
|
||||
if (lowpan_802154_cb(skb)->d_size)
|
||||
uh.len = htons(lowpan_802154_cb(skb)->d_size -
|
||||
sizeof(struct ipv6hdr));
|
||||
udp_set_len_short(&uh, lowpan_802154_cb(skb)->d_size -
|
||||
sizeof(struct ipv6hdr));
|
||||
else
|
||||
uh.len = htons(skb->len + sizeof(struct udphdr));
|
||||
udp_set_len_short(&uh, skb->len + sizeof(struct udphdr));
|
||||
break;
|
||||
default:
|
||||
uh.len = htons(skb->len + sizeof(struct udphdr));
|
||||
udp_set_len_short(&uh, skb->len + sizeof(struct udphdr));
|
||||
break;
|
||||
}
|
||||
pr_debug("uncompressed UDP length: src = %d", ntohs(uh.len));
|
||||
pr_debug("uncompressed UDP length: src = %d", udp_get_len_short(&uh));
|
||||
|
||||
/* replace the compressed UDP head by the uncompressed UDP
|
||||
* header
|
||||
|
|
|
|||
|
|
@ -3005,7 +3005,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
|
|||
|
||||
udph->source = htons(pkt_dev->cur_udp_src);
|
||||
udph->dest = htons(pkt_dev->cur_udp_dst);
|
||||
udph->len = htons(datalen + 8); /* DATA + udphdr */
|
||||
udp_set_len_short(udph, datalen + 8); /* DATA + udphdr */
|
||||
udph->check = 0;
|
||||
|
||||
iph->ihl = 5;
|
||||
|
|
@ -3138,7 +3138,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
|
|||
udplen = datalen + sizeof(struct udphdr);
|
||||
udph->source = htons(pkt_dev->cur_udp_src);
|
||||
udph->dest = htons(pkt_dev->cur_udp_dst);
|
||||
udph->len = htons(udplen);
|
||||
udp_set_len_short(udph, udplen);
|
||||
udph->check = 0;
|
||||
|
||||
*(__be32 *) iph = htonl(0x60000000); /* Version + flow */
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ struct sk_buff *net_test_get_skb(struct net_device *ndev, u8 id,
|
|||
} else {
|
||||
uhdr->source = htons(attr->sport);
|
||||
uhdr->dest = htons(attr->dport);
|
||||
uhdr->len = htons(sizeof(*shdr) + sizeof(*uhdr) + attr->size);
|
||||
udp_set_len_short(uhdr, sizeof(*shdr) + sizeof(*uhdr) + attr->size);
|
||||
if (attr->max_size)
|
||||
uhdr->len = htons(attr->max_size -
|
||||
udp_set_len_short(uhdr, attr->max_size -
|
||||
(sizeof(*ihdr) + sizeof(*ehdr)));
|
||||
uhdr->check = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ void tso_build_hdr(const struct sk_buff *skb, char *hdr, struct tso_t *tso,
|
|||
} else {
|
||||
struct udphdr *uh = (struct udphdr *)hdr;
|
||||
|
||||
uh->len = htons(sizeof(*uh) + size);
|
||||
/* size is after segmentation. */
|
||||
udp_set_len_short(uh, sizeof(*uh) + size);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(tso_build_hdr);
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ static struct ip_esp_hdr *esp_output_udp_encap(struct sk_buff *skb,
|
|||
uh = (struct udphdr *)esp->esph;
|
||||
uh->source = sport;
|
||||
uh->dest = dport;
|
||||
uh->len = htons(len);
|
||||
udp_set_len_short(uh, len);
|
||||
uh->check = 0;
|
||||
|
||||
/* For IPv4 ESP with UDP encapsulation, if xo is not null, the skb is in the crypto offload
|
||||
|
|
|
|||
|
|
@ -1040,7 +1040,7 @@ static void fou_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
|
|||
|
||||
uh->dest = e->dport;
|
||||
uh->source = sport;
|
||||
uh->len = htons(skb->len);
|
||||
udp_set_len_short(uh, skb->len);
|
||||
udp_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM), skb,
|
||||
fl4->saddr, fl4->daddr, skb->len);
|
||||
|
||||
|
|
|
|||
|
|
@ -847,7 +847,7 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d
|
|||
/* Construct UDP header */
|
||||
b->udph.source = htons(68);
|
||||
b->udph.dest = htons(67);
|
||||
b->udph.len = htons(sizeof(struct bootp_pkt) - sizeof(struct iphdr));
|
||||
udp_set_len_short(&b->udph, sizeof(struct bootp_pkt) - sizeof(struct iphdr));
|
||||
/* UDP checksum not calculated -- explicitly allowed in BOOTP RFC */
|
||||
|
||||
/* Construct DHCP/BOOTP header */
|
||||
|
|
@ -1025,10 +1025,10 @@ static int __init ic_bootp_recv(struct sk_buff *skb, struct net_device *dev, str
|
|||
if (b->udph.source != htons(67) || b->udph.dest != htons(68))
|
||||
goto drop;
|
||||
|
||||
if (ntohs(h->tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr))
|
||||
if (ntohs(h->tot_len) < udp_get_len_short(&b->udph) + sizeof(struct iphdr))
|
||||
goto drop;
|
||||
|
||||
len = ntohs(b->udph.len) - sizeof(struct udphdr);
|
||||
len = udp_get_len_short(&b->udph) - sizeof(struct udphdr);
|
||||
ext_len = len - (sizeof(*b) -
|
||||
sizeof(struct iphdr) -
|
||||
sizeof(struct udphdr) -
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ static int snmp_translate(struct nf_conn *ct, int dir, struct sk_buff *skb)
|
|||
{
|
||||
struct iphdr *iph = ip_hdr(skb);
|
||||
struct udphdr *udph = (struct udphdr *)((__be32 *)iph + iph->ihl);
|
||||
u16 datalen = ntohs(udph->len) - sizeof(struct udphdr);
|
||||
u16 datalen = udp_get_len_short(udph) - sizeof(struct udphdr);
|
||||
char *data = (unsigned char *)udph + sizeof(struct udphdr);
|
||||
struct snmp_ctx ctx;
|
||||
int ret;
|
||||
|
|
@ -181,7 +181,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
|
|||
* enough room for a UDP header. Just verify the UDP length field so we
|
||||
* can mess around with the payload.
|
||||
*/
|
||||
if (ntohs(udph->len) != skb->len - (iph->ihl << 2)) {
|
||||
if (udp_get_len_short(udph) != skb->len - (iph->ihl << 2)) {
|
||||
nf_ct_helper_log(skb, ct, "dropping malformed packet\n");
|
||||
return NF_DROP;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3187,7 +3187,7 @@ static struct sk_buff *inet_rtm_getroute_build_skb(__be32 src, __be32 dst,
|
|||
udph = skb_put_zero(skb, sizeof(struct udphdr));
|
||||
udph->source = sport;
|
||||
udph->dest = dport;
|
||||
udph->len = htons(sizeof(struct udphdr));
|
||||
udp_set_len_short(udph, sizeof(struct udphdr));
|
||||
udph->check = 0;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1108,7 +1108,8 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
|
|||
uh = udp_hdr(skb);
|
||||
uh->source = inet_sk(sk)->inet_sport;
|
||||
uh->dest = fl4->fl4_dport;
|
||||
uh->len = htons(len);
|
||||
/* Datagram length checked in udp_sendmsg. */
|
||||
udp_set_len_short(uh, len);
|
||||
uh->check = 0;
|
||||
|
||||
if (cork->gso_size) {
|
||||
|
|
|
|||
|
|
@ -279,11 +279,11 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
|||
* segment instead of the entire frame.
|
||||
*/
|
||||
if (gso_partial && skb_is_gso(skb)) {
|
||||
uh->len = htons(skb_shinfo(skb)->gso_size +
|
||||
SKB_GSO_CB(skb)->data_offset +
|
||||
skb->head - (unsigned char *)uh);
|
||||
udp_set_len_short(uh, skb_shinfo(skb)->gso_size +
|
||||
SKB_GSO_CB(skb)->data_offset +
|
||||
skb->head - (unsigned char *)uh);
|
||||
} else {
|
||||
uh->len = htons(len);
|
||||
udp_set_len_short(uh, len);
|
||||
}
|
||||
|
||||
if (!need_csum)
|
||||
|
|
@ -468,7 +468,7 @@ static struct sk_buff *__udp_gso_segment_list(struct sk_buff *skb,
|
|||
if (IS_ERR(skb))
|
||||
return skb;
|
||||
|
||||
udp_hdr(skb)->len = htons(sizeof(struct udphdr) + mss);
|
||||
udp_set_len_short(udp_hdr(skb), sizeof(struct udphdr) + mss);
|
||||
|
||||
if (is_ipv6)
|
||||
return __udpv6_gso_segment_list_csum(skb);
|
||||
|
|
@ -486,8 +486,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
|||
unsigned int mss;
|
||||
bool copy_dtor;
|
||||
__sum16 check;
|
||||
__be16 newlen;
|
||||
int ret = 0;
|
||||
u16 newlen;
|
||||
|
||||
mss = skb_shinfo(gso_skb)->gso_size;
|
||||
if (gso_skb->len <= sizeof(*uh) + mss)
|
||||
|
|
@ -564,8 +564,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
|||
(skb_shinfo(gso_skb)->tx_flags & SKBTX_ANY_TSTAMP);
|
||||
|
||||
/* compute checksum adjustment based on old length versus new */
|
||||
newlen = htons(sizeof(*uh) + mss);
|
||||
check = csum16_add(csum16_sub(uh->check, uh->len), newlen);
|
||||
newlen = sizeof(*uh) + mss;
|
||||
check = csum16_add(csum16_sub(uh->check, uh->len), htons(newlen));
|
||||
|
||||
for (;;) {
|
||||
if (copy_dtor) {
|
||||
|
|
@ -577,7 +577,7 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
|||
if (!seg->next)
|
||||
break;
|
||||
|
||||
uh->len = newlen;
|
||||
udp_set_len_short(uh, newlen);
|
||||
uh->check = check;
|
||||
|
||||
if (seg->ip_summed == CHECKSUM_PARTIAL)
|
||||
|
|
@ -594,11 +594,10 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
|||
* segment may not be full MSS, account for that in the checksum
|
||||
*/
|
||||
if (!skb_is_gso(seg))
|
||||
newlen = htons(skb_tail_pointer(seg) -
|
||||
skb_transport_header(seg) + seg->data_len);
|
||||
check = csum16_add(csum16_sub(uh->check, uh->len), newlen);
|
||||
newlen = skb_tail_pointer(seg) - skb_transport_header(seg) + seg->data_len;
|
||||
check = csum16_add(csum16_sub(uh->check, uh->len), htons(newlen));
|
||||
|
||||
uh->len = newlen;
|
||||
udp_set_len_short(uh, newlen);
|
||||
uh->check = check;
|
||||
|
||||
if (seg->ip_summed == CHECKSUM_PARTIAL)
|
||||
|
|
@ -709,7 +708,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
|
|||
}
|
||||
|
||||
/* Do not deal with padded or malicious packets, sorry ! */
|
||||
ulen = ntohs(uh->len);
|
||||
ulen = udp_get_len_short(uh);
|
||||
if (ulen <= sizeof(*uh) || ulen != skb_gro_len(skb)) {
|
||||
NAPI_GRO_CB(skb)->flush = 1;
|
||||
return NULL;
|
||||
|
|
@ -742,7 +741,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
|
|||
* On len mismatch merge the first packet shorter than gso_size,
|
||||
* otherwise complete the GRO packet.
|
||||
*/
|
||||
if (ulen > ntohs(uh2->len) || flush) {
|
||||
if (ulen > udp_get_len_short(uh2) || flush) {
|
||||
pp = p;
|
||||
} else {
|
||||
if (NAPI_GRO_CB(skb)->is_flist) {
|
||||
|
|
@ -765,7 +764,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
|
|||
}
|
||||
}
|
||||
|
||||
if (ret || ulen != ntohs(uh2->len) ||
|
||||
if (ret || ulen != udp_get_len_short(uh2) ||
|
||||
NAPI_GRO_CB(p)->count >= UDP_GRO_CNT_MAX)
|
||||
pp = p;
|
||||
|
||||
|
|
@ -915,12 +914,12 @@ static int udp_gro_complete_segment(struct sk_buff *skb)
|
|||
int udp_gro_complete(struct sk_buff *skb, int nhoff,
|
||||
udp_lookup_t lookup)
|
||||
{
|
||||
__be16 newlen = htons(skb->len - nhoff);
|
||||
struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
|
||||
unsigned int newlen = skb->len - nhoff;
|
||||
struct sock *sk;
|
||||
int err;
|
||||
|
||||
uh->len = newlen;
|
||||
udp_set_len_short(uh, newlen);
|
||||
|
||||
sk = INDIRECT_CALL_INET(lookup, udp6_lib_lookup_skb,
|
||||
udp4_lib_lookup_skb, skb, uh->source, uh->dest);
|
||||
|
|
@ -957,7 +956,7 @@ INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff)
|
|||
|
||||
/* do fraglist only if there is no outer UDP encap (or we already processed it) */
|
||||
if (NAPI_GRO_CB(skb)->is_flist && !NAPI_GRO_CB(skb)->encap_mark) {
|
||||
uh->len = htons(skb->len - nhoff);
|
||||
udp_set_len_short(uh, skb->len - nhoff);
|
||||
|
||||
skb_shinfo(skb)->gso_type |= (SKB_GSO_FRAGLIST|SKB_GSO_UDP_L4);
|
||||
skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb
|
|||
|
||||
uh->dest = dst_port;
|
||||
uh->source = src_port;
|
||||
uh->len = htons(skb->len);
|
||||
udp_set_len_short(uh, skb->len);
|
||||
|
||||
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
||||
|
||||
|
|
|
|||
|
|
@ -230,7 +230,8 @@ static void esp_output_encap_csum(struct sk_buff *skb)
|
|||
if (*skb_mac_header(skb) == IPPROTO_UDP) {
|
||||
struct udphdr *uh = udp_hdr(skb);
|
||||
struct ipv6hdr *ip6h = ipv6_hdr(skb);
|
||||
int len = ntohs(uh->len);
|
||||
/* esp6_output_udp_encap limits len to U16_MAX. */
|
||||
int len = udp_get_len_short(uh);
|
||||
unsigned int offset = skb_transport_offset(skb);
|
||||
__wsum csum = skb_checksum(skb, offset, skb->len - offset, 0);
|
||||
|
||||
|
|
@ -358,7 +359,7 @@ static struct ip_esp_hdr *esp6_output_udp_encap(struct sk_buff *skb,
|
|||
uh = (struct udphdr *)esp->esph;
|
||||
uh->source = sport;
|
||||
uh->dest = dport;
|
||||
uh->len = htons(len);
|
||||
udp_set_len_short(uh, len);
|
||||
uh->check = 0;
|
||||
|
||||
*skb_mac_header(skb) = IPPROTO_UDP;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ static void fou6_build_udp(struct sk_buff *skb, struct ip_tunnel_encap *e,
|
|||
|
||||
uh->dest = e->dport;
|
||||
uh->source = sport;
|
||||
uh->len = htons(skb->len);
|
||||
udp_set_len_short(uh, skb->len);
|
||||
udp6_set_csum(!(e->flags & TUNNEL_ENCAP_FLAG_CSUM6), skb,
|
||||
&fl6->saddr, &fl6->daddr, skb->len);
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ void udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk,
|
|||
uh->dest = dst_port;
|
||||
uh->source = src_port;
|
||||
|
||||
uh->len = htons(skb->len);
|
||||
udp_set_len_short(uh, skb->len);
|
||||
|
||||
skb_dst_set(skb, dst);
|
||||
|
||||
|
|
|
|||
|
|
@ -1369,7 +1369,8 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
|
|||
uh = udp_hdr(skb);
|
||||
uh->source = fl6->fl6_sport;
|
||||
uh->dest = fl6->fl6_dport;
|
||||
uh->len = htons(len);
|
||||
/* Datagram length checked in udpv6_sendmsg. */
|
||||
udp_set_len_short(uh, len);
|
||||
uh->check = 0;
|
||||
|
||||
if (cork->gso_size) {
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ int udp6_gro_complete(struct sk_buff *skb, int nhoff)
|
|||
|
||||
/* do fraglist only if there is no outer UDP encap (or we already processed it) */
|
||||
if (NAPI_GRO_CB(skb)->is_flist && !NAPI_GRO_CB(skb)->encap_mark) {
|
||||
uh->len = htons(skb->len - nhoff);
|
||||
udp_set_len_short(uh, skb->len - nhoff);
|
||||
|
||||
skb_shinfo(skb)->gso_type |= (SKB_GSO_FRAGLIST|SKB_GSO_UDP_L4);
|
||||
skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
|
||||
|
|
|
|||
|
|
@ -1296,7 +1296,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
|
|||
ret = NET_XMIT_DROP;
|
||||
goto out_unlock;
|
||||
}
|
||||
uh->len = htons(udp_len);
|
||||
udp_set_len_short(uh, udp_len);
|
||||
|
||||
/* Calculate UDP checksum if configured to do so */
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
|
|
|
|||
|
|
@ -1100,7 +1100,7 @@ ipvs_gue_encap(struct net *net, struct sk_buff *skb,
|
|||
dport = cp->dest->tun_port;
|
||||
udph->dest = dport;
|
||||
udph->source = sport;
|
||||
udph->len = htons(skb->len);
|
||||
udp_set_len_short(udph, skb->len);
|
||||
udph->check = 0;
|
||||
|
||||
*next_protocol = IPPROTO_UDP;
|
||||
|
|
|
|||
|
|
@ -41,11 +41,22 @@ static void udp_error_log(const struct sk_buff *skb,
|
|||
nf_l4proto_log_invalid(skb, state, IPPROTO_UDP, "%s", msg);
|
||||
}
|
||||
|
||||
static bool udp_validate_len(struct sk_buff *skb,
|
||||
const struct udphdr *hdr,
|
||||
unsigned int dataoff)
|
||||
{
|
||||
unsigned int udplen = udp_get_len_short(hdr);
|
||||
unsigned int skblen = skb->len - dataoff;
|
||||
|
||||
if (udplen > skblen || udplen < sizeof(*hdr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool udp_error(struct sk_buff *skb,
|
||||
unsigned int dataoff,
|
||||
const struct nf_hook_state *state)
|
||||
{
|
||||
unsigned int udplen = skb->len - dataoff;
|
||||
const struct udphdr *hdr;
|
||||
struct udphdr _hdr;
|
||||
|
||||
|
|
@ -57,7 +68,7 @@ static bool udp_error(struct sk_buff *skb,
|
|||
}
|
||||
|
||||
/* Truncated/malformed packets */
|
||||
if (ntohs(hdr->len) > udplen || ntohs(hdr->len) < sizeof(*hdr)) {
|
||||
if (!udp_validate_len(skb, hdr, dataoff)) {
|
||||
udp_error_log(skb, state, "truncated/malformed packet");
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ nf_log_dump_udp_header(struct nf_log_buf *m,
|
|||
|
||||
/* Max length: 20 "SPT=65535 DPT=65535 " */
|
||||
nf_log_buf_add(m, "SPT=%u DPT=%u LEN=%u ",
|
||||
ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len));
|
||||
ntohs(uh->source), ntohs(uh->dest), udp_get_len_short(uh));
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb,
|
|||
|
||||
/* update the length of the UDP packet */
|
||||
datalen = skb->len - protoff;
|
||||
udph->len = htons(datalen);
|
||||
udp_set_len_short(udph, datalen);
|
||||
|
||||
/* fix udp checksum if udp checksum was previously calculated */
|
||||
if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL)
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ static void psp_write_headers(struct net *net, struct sk_buff *skb, __be32 spi,
|
|||
uh->source = udp_flow_src_port(net, skb, 0, 0, false);
|
||||
}
|
||||
uh->check = 0;
|
||||
uh->len = htons(udp_len);
|
||||
udp_set_len_short(uh, udp_len);
|
||||
|
||||
psph->nexthdr = IPPROTO_TCP;
|
||||
psph->hdrlen = PSP_HDRLEN_NOOPT;
|
||||
|
|
|
|||
|
|
@ -276,7 +276,7 @@ static int tcf_csum_ipv4_udp(struct sk_buff *skb, unsigned int ihl,
|
|||
return 0;
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
ul = ntohs(udph->len);
|
||||
ul = udp_get_len_short(udph);
|
||||
|
||||
if (udplite || udph->check) {
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ static int tcf_csum_ipv6_udp(struct sk_buff *skb, unsigned int ihl,
|
|||
return 0;
|
||||
|
||||
ip6h = ipv6_hdr(skb);
|
||||
ul = ntohs(udph->len);
|
||||
ul = udp_get_len_short(udph);
|
||||
|
||||
udph->check = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ static void nat_keepalive_send(struct nat_keepalive *ka)
|
|||
uh = skb_push(skb, sizeof(*uh));
|
||||
uh->source = ka->encap_sport;
|
||||
uh->dest = ka->encap_dport;
|
||||
uh->len = htons(skb->len);
|
||||
udp_set_len_short(uh, skb->len);
|
||||
uh->check = 0;
|
||||
|
||||
skb->mark = ka->smark;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user