Skip to content

Commit cafbe18

Browse files
edumazetdavem330
authored andcommitted
inet: move inet->hdrincl to inet->inet_flags
IP_HDRINCL socket option can now be set/read without locking the socket. Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Soheil Hassas Yeganeh <soheil@google.com> Reviewed-by: Simon Horman <horms@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3f7e753 commit cafbe18

File tree

10 files changed

+31
-41
lines changed

10 files changed

+31
-41
lines changed

include/net/inet_sock.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ struct inet_sock {
231231
__u8 mc_ttl;
232232
__u8 pmtudisc;
233233
__u8 is_icsk:1,
234-
hdrincl:1,
235234
mc_loop:1,
236235
transparent:1,
237236
mc_all:1,
@@ -271,6 +270,7 @@ enum {
271270
INET_FLAGS_RECVERR = 9,
272271
INET_FLAGS_RECVERR_RFC4884 = 10,
273272
INET_FLAGS_FREEBIND = 11,
273+
INET_FLAGS_HDRINCL = 12,
274274
};
275275

276276
/* cmsg flags for inet */
@@ -397,7 +397,7 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
397397
{
398398
__u8 flags = 0;
399399

400-
if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl)
400+
if (inet_sk(sk)->transparent || inet_test_bit(HDRINCL, sk))
401401
flags |= FLOWI_FLAG_ANYSRC;
402402
return flags;
403403
}

net/ipv4/af_inet.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
338338
if (SOCK_RAW == sock->type) {
339339
inet->inet_num = protocol;
340340
if (IPPROTO_RAW == protocol)
341-
inet->hdrincl = 1;
341+
inet_set_bit(HDRINCL, sk);
342342
}
343343

344344
if (READ_ONCE(net->ipv4.sysctl_ip_no_pmtu_disc))

net/ipv4/inet_diag.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
185185
inet_sockopt.recverr = inet_test_bit(RECVERR, sk);
186186
inet_sockopt.is_icsk = inet->is_icsk;
187187
inet_sockopt.freebind = inet_test_bit(FREEBIND, sk);
188-
inet_sockopt.hdrincl = inet->hdrincl;
188+
inet_sockopt.hdrincl = inet_test_bit(HDRINCL, sk);
189189
inet_sockopt.mc_loop = inet->mc_loop;
190190
inet_sockopt.transparent = inet->transparent;
191191
inet_sockopt.mc_all = inet->mc_all;

net/ipv4/ip_output.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,7 +1039,7 @@ static int __ip_append_data(struct sock *sk,
10391039
}
10401040
}
10411041
} else if ((flags & MSG_SPLICE_PAGES) && length) {
1042-
if (inet->hdrincl)
1042+
if (inet_test_bit(HDRINCL, sk))
10431043
return -EPERM;
10441044
if (rt->dst.dev->features & NETIF_F_SG &&
10451045
getfrag == ip_generic_getfrag)
@@ -1467,7 +1467,8 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
14671467
* so icmphdr does not in skb linear region and can not get icmp_type
14681468
* by icmp_hdr(skb)->type.
14691469
*/
1470-
if (sk->sk_type == SOCK_RAW && !inet_sk(sk)->hdrincl)
1470+
if (sk->sk_type == SOCK_RAW &&
1471+
!inet_test_bit(HDRINCL, sk))
14711472
icmp_type = fl4->fl4_icmp_type;
14721473
else
14731474
icmp_type = icmp_hdr(skb)->type;

net/ipv4/ip_sockglue.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -988,6 +988,11 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
988988
return -EINVAL;
989989
inet_assign_bit(FREEBIND, sk, val);
990990
return 0;
991+
case IP_HDRINCL:
992+
if (sk->sk_type != SOCK_RAW)
993+
return -ENOPROTOOPT;
994+
inet_assign_bit(HDRINCL, sk, val);
995+
return 0;
991996
}
992997

993998
err = 0;
@@ -1052,13 +1057,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
10521057
goto e_inval;
10531058
inet->uc_ttl = val;
10541059
break;
1055-
case IP_HDRINCL:
1056-
if (sk->sk_type != SOCK_RAW) {
1057-
err = -ENOPROTOOPT;
1058-
break;
1059-
}
1060-
inet->hdrincl = val ? 1 : 0;
1061-
break;
10621060
case IP_NODEFRAG:
10631061
if (sk->sk_type != SOCK_RAW) {
10641062
err = -ENOPROTOOPT;
@@ -1578,6 +1576,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
15781576
case IP_FREEBIND:
15791577
val = inet_test_bit(FREEBIND, sk);
15801578
goto copyval;
1579+
case IP_HDRINCL:
1580+
val = inet_test_bit(HDRINCL, sk);
1581+
goto copyval;
15811582
}
15821583

15831584
if (needs_rtnl)
@@ -1625,9 +1626,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
16251626
inet->uc_ttl);
16261627
break;
16271628
}
1628-
case IP_HDRINCL:
1629-
val = inet->hdrincl;
1630-
break;
16311629
case IP_NODEFRAG:
16321630
val = inet->nodefrag;
16331631
break;

net/ipv4/raw.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
251251
const struct iphdr *iph = (const struct iphdr *)skb->data;
252252
u8 *payload = skb->data + (iph->ihl << 2);
253253

254-
if (inet->hdrincl)
254+
if (inet_test_bit(HDRINCL, sk))
255255
payload = skb->data;
256256
ip_icmp_error(sk, skb, err, 0, info, payload);
257257
}
@@ -491,12 +491,8 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
491491
if (len > 0xFFFF)
492492
goto out;
493493

494-
/* hdrincl should be READ_ONCE(inet->hdrincl)
495-
* but READ_ONCE() doesn't work with bit fields.
496-
* Doing this indirectly yields the same result.
497-
*/
498-
hdrincl = inet->hdrincl;
499-
hdrincl = READ_ONCE(hdrincl);
494+
hdrincl = inet_test_bit(HDRINCL, sk);
495+
500496
/*
501497
* Check the flags.
502498
*/

net/ipv4/route.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,13 +515,12 @@ static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
515515
__u8 scope = RT_SCOPE_UNIVERSE;
516516

517517
if (sk) {
518-
const struct inet_sock *inet = inet_sk(sk);
519-
520518
oif = sk->sk_bound_dev_if;
521519
mark = READ_ONCE(sk->sk_mark);
522520
tos = ip_sock_rt_tos(sk);
523521
scope = ip_sock_rt_scope(sk);
524-
prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol;
522+
prot = inet_test_bit(HDRINCL, sk) ? IPPROTO_RAW :
523+
sk->sk_protocol;
525524
}
526525

527526
flowi4_init_output(fl4, oif, mark, tos & IPTOS_RT_MASK, scope,
@@ -555,7 +554,8 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
555554
flowi4_init_output(fl4, sk->sk_bound_dev_if, READ_ONCE(sk->sk_mark),
556555
ip_sock_rt_tos(sk) & IPTOS_RT_MASK,
557556
ip_sock_rt_scope(sk),
558-
inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
557+
inet_test_bit(HDRINCL, sk) ?
558+
IPPROTO_RAW : sk->sk_protocol,
559559
inet_sk_flowi_flags(sk),
560560
daddr, inet->inet_saddr, 0, 0, sk->sk_uid);
561561
rcu_read_unlock();

net/ipv6/af_inet6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
205205
if (SOCK_RAW == sock->type) {
206206
inet->inet_num = protocol;
207207
if (IPPROTO_RAW == protocol)
208-
inet->hdrincl = 1;
208+
inet_set_bit(HDRINCL, sk);
209209
}
210210

211211
sk->sk_destruct = inet6_sock_destruct;

net/ipv6/ip6_output.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,7 +1591,7 @@ static int __ip6_append_data(struct sock *sk,
15911591
}
15921592
}
15931593
} else if ((flags & MSG_SPLICE_PAGES) && length) {
1594-
if (inet_sk(sk)->hdrincl)
1594+
if (inet_test_bit(HDRINCL, sk))
15951595
return -EPERM;
15961596
if (rt->dst.dev->features & NETIF_F_SG &&
15971597
getfrag == ip_generic_getfrag)
@@ -1995,7 +1995,8 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
19951995
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
19961996
u8 icmp6_type;
19971997

1998-
if (sk->sk_socket->type == SOCK_RAW && !inet_sk(sk)->hdrincl)
1998+
if (sk->sk_socket->type == SOCK_RAW &&
1999+
!inet_test_bit(HDRINCL, sk))
19992000
icmp6_type = fl6->fl6_icmp_type;
20002001
else
20012002
icmp6_type = icmp6_hdr(skb)->icmp6_type;

net/ipv6/raw.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,
291291
struct inet6_skb_parm *opt,
292292
u8 type, u8 code, int offset, __be32 info)
293293
{
294-
struct inet_sock *inet = inet_sk(sk);
295294
struct ipv6_pinfo *np = inet6_sk(sk);
296295
int err;
297296
int harderr;
@@ -315,7 +314,7 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb,
315314
}
316315
if (np->recverr) {
317316
u8 *payload = skb->data;
318-
if (!inet->hdrincl)
317+
if (!inet_test_bit(HDRINCL, sk))
319318
payload += offset;
320319
ipv6_icmp_error(sk, skb, err, 0, ntohl(info), payload);
321320
}
@@ -406,7 +405,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
406405
skb->len,
407406
inet->inet_num, 0));
408407

409-
if (inet->hdrincl) {
408+
if (inet_test_bit(HDRINCL, sk)) {
410409
if (skb_checksum_complete(skb)) {
411410
atomic_inc(&sk->sk_drops);
412411
kfree_skb_reason(skb, SKB_DROP_REASON_SKB_CSUM);
@@ -762,12 +761,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
762761
if (msg->msg_flags & MSG_OOB)
763762
return -EOPNOTSUPP;
764763

765-
/* hdrincl should be READ_ONCE(inet->hdrincl)
766-
* but READ_ONCE() doesn't work with bit fields.
767-
* Doing this indirectly yields the same result.
768-
*/
769-
hdrincl = inet->hdrincl;
770-
hdrincl = READ_ONCE(hdrincl);
764+
hdrincl = inet_test_bit(HDRINCL, sk);
771765

772766
/*
773767
* Get and verify the address.
@@ -1000,7 +994,7 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname,
1000994
case IPV6_HDRINCL:
1001995
if (sk->sk_type != SOCK_RAW)
1002996
return -EINVAL;
1003-
inet_sk(sk)->hdrincl = !!val;
997+
inet_assign_bit(HDRINCL, sk, val);
1004998
return 0;
1005999
case IPV6_CHECKSUM:
10061000
if (inet_sk(sk)->inet_num == IPPROTO_ICMPV6 &&
@@ -1068,7 +1062,7 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname,
10681062

10691063
switch (optname) {
10701064
case IPV6_HDRINCL:
1071-
val = inet_sk(sk)->hdrincl;
1065+
val = inet_test_bit(HDRINCL, sk);
10721066
break;
10731067
case IPV6_CHECKSUM:
10741068
/*

0 commit comments

Comments
 (0)