Skip to content

Commit 32bbd87

Browse files
sbrivio-rhdavem330
authored andcommitted
net: Convert protocol error handlers from void to int
We'll need this to handle ICMP errors for tunnels without a sending socket (i.e. FoU and GUE). There, we might have to look up different types of IP tunnels, registered as network protocols, before we get a match, so we want this for the error handlers of IPPROTO_IPIP and IPPROTO_IPV6 in both inet_protos and inet6_protos. These error codes will be used in the next patch. For consistency, return sensible error codes in protocol error handlers whenever handlers can't handle errors because, even if valid, they don't match a protocol or any of its states. This has no effect on existing error handling paths. Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent ce73366 commit 32bbd87

27 files changed

+177
-121
lines changed

include/net/icmp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct net;
4141

4242
void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info);
4343
int icmp_rcv(struct sk_buff *skb);
44-
void icmp_err(struct sk_buff *skb, u32 info);
44+
int icmp_err(struct sk_buff *skb, u32 info);
4545
int icmp_init(void);
4646
void icmp_out_count(struct net *net, unsigned char type);
4747

include/net/protocol.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ struct net_protocol {
4242
int (*early_demux)(struct sk_buff *skb);
4343
int (*early_demux_handler)(struct sk_buff *skb);
4444
int (*handler)(struct sk_buff *skb);
45-
void (*err_handler)(struct sk_buff *skb, u32 info);
45+
46+
/* This returns an error if we weren't able to handle the error. */
47+
int (*err_handler)(struct sk_buff *skb, u32 info);
48+
4649
unsigned int no_policy:1,
4750
netns_ok:1,
4851
/* does the protocol do more stringent
@@ -58,10 +61,12 @@ struct inet6_protocol {
5861
void (*early_demux_handler)(struct sk_buff *skb);
5962
int (*handler)(struct sk_buff *skb);
6063

61-
void (*err_handler)(struct sk_buff *skb,
64+
/* This returns an error if we weren't able to handle the error. */
65+
int (*err_handler)(struct sk_buff *skb,
6266
struct inet6_skb_parm *opt,
6367
u8 type, u8 code, int offset,
6468
__be32 info);
69+
6570
unsigned int flags; /* INET6_PROTO_xxx */
6671
};
6772

include/net/sctp/sctp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ int sctp_primitive_RECONF(struct net *net, struct sctp_association *asoc,
151151
* sctp/input.c
152152
*/
153153
int sctp_rcv(struct sk_buff *skb);
154-
void sctp_v4_err(struct sk_buff *skb, u32 info);
154+
int sctp_v4_err(struct sk_buff *skb, u32 info);
155155
void sctp_hash_endpoint(struct sctp_endpoint *);
156156
void sctp_unhash_endpoint(struct sctp_endpoint *);
157157
struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *,

include/net/tcp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ extern struct proto tcp_prot;
313313

314314
void tcp_tasklet_init(void);
315315

316-
void tcp_v4_err(struct sk_buff *skb, u32);
316+
int tcp_v4_err(struct sk_buff *skb, u32);
317317

318318
void tcp_shutdown(struct sock *sk, int how);
319319

include/net/udp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ bool udp_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst);
283283
int udp_get_port(struct sock *sk, unsigned short snum,
284284
int (*saddr_cmp)(const struct sock *,
285285
const struct sock *));
286-
void udp_err(struct sk_buff *, u32);
286+
int udp_err(struct sk_buff *, u32);
287287
int udp_abort(struct sock *sk, int err);
288288
int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
289289
int udp_push_pending_frames(struct sock *sk);

net/dccp/ipv4.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ EXPORT_SYMBOL(dccp_req_err);
231231
* check at all. A more general error queue to queue errors for later handling
232232
* is probably better.
233233
*/
234-
static void dccp_v4_err(struct sk_buff *skb, u32 info)
234+
static int dccp_v4_err(struct sk_buff *skb, u32 info)
235235
{
236236
const struct iphdr *iph = (struct iphdr *)skb->data;
237237
const u8 offset = iph->ihl << 2;
@@ -259,16 +259,18 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
259259
inet_iif(skb), 0);
260260
if (!sk) {
261261
__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
262-
return;
262+
return -ENOENT;
263263
}
264264

265265
if (sk->sk_state == DCCP_TIME_WAIT) {
266266
inet_twsk_put(inet_twsk(sk));
267-
return;
267+
return 0;
268268
}
269269
seq = dccp_hdr_seq(dh);
270-
if (sk->sk_state == DCCP_NEW_SYN_RECV)
271-
return dccp_req_err(sk, seq);
270+
if (sk->sk_state == DCCP_NEW_SYN_RECV) {
271+
dccp_req_err(sk, seq);
272+
return 0;
273+
}
272274

273275
bh_lock_sock(sk);
274276
/* If too many ICMPs get dropped on busy
@@ -357,6 +359,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
357359
out:
358360
bh_unlock_sock(sk);
359361
sock_put(sk);
362+
return 0;
360363
}
361364

362365
static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb,

net/dccp/ipv6.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
6868

6969
}
7070

71-
static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
71+
static int dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
7272
u8 type, u8 code, int offset, __be32 info)
7373
{
7474
const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data;
@@ -96,16 +96,18 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
9696
if (!sk) {
9797
__ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
9898
ICMP6_MIB_INERRORS);
99-
return;
99+
return -ENOENT;
100100
}
101101

102102
if (sk->sk_state == DCCP_TIME_WAIT) {
103103
inet_twsk_put(inet_twsk(sk));
104-
return;
104+
return 0;
105105
}
106106
seq = dccp_hdr_seq(dh);
107-
if (sk->sk_state == DCCP_NEW_SYN_RECV)
108-
return dccp_req_err(sk, seq);
107+
if (sk->sk_state == DCCP_NEW_SYN_RECV) {
108+
dccp_req_err(sk, seq);
109+
return 0;
110+
}
109111

110112
bh_lock_sock(sk);
111113
if (sock_owned_by_user(sk))
@@ -183,6 +185,7 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
183185
out:
184186
bh_unlock_sock(sk);
185187
sock_put(sk);
188+
return 0;
186189
}
187190

188191

net/ipv4/gre_demux.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,25 @@ static int gre_rcv(struct sk_buff *skb)
151151
return NET_RX_DROP;
152152
}
153153

154-
static void gre_err(struct sk_buff *skb, u32 info)
154+
static int gre_err(struct sk_buff *skb, u32 info)
155155
{
156156
const struct gre_protocol *proto;
157157
const struct iphdr *iph = (const struct iphdr *)skb->data;
158158
u8 ver = skb->data[(iph->ihl<<2) + 1]&0x7f;
159+
int err = 0;
159160

160161
if (ver >= GREPROTO_MAX)
161-
return;
162+
return -EINVAL;
162163

163164
rcu_read_lock();
164165
proto = rcu_dereference(gre_proto[ver]);
165166
if (proto && proto->err_handler)
166167
proto->err_handler(skb, info);
168+
else
169+
err = -EPROTONOSUPPORT;
167170
rcu_read_unlock();
171+
172+
return err;
168173
}
169174

170175
static const struct net_protocol net_gre_protocol = {

net/ipv4/icmp.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ int icmp_rcv(struct sk_buff *skb)
10791079
goto drop;
10801080
}
10811081

1082-
void icmp_err(struct sk_buff *skb, u32 info)
1082+
int icmp_err(struct sk_buff *skb, u32 info)
10831083
{
10841084
struct iphdr *iph = (struct iphdr *)skb->data;
10851085
int offset = iph->ihl<<2;
@@ -1094,13 +1094,15 @@ void icmp_err(struct sk_buff *skb, u32 info)
10941094
*/
10951095
if (icmph->type != ICMP_ECHOREPLY) {
10961096
ping_err(skb, offset, info);
1097-
return;
1097+
return 0;
10981098
}
10991099

11001100
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
11011101
ipv4_update_pmtu(skb, net, info, 0, IPPROTO_ICMP);
11021102
else if (type == ICMP_REDIRECT)
11031103
ipv4_redirect(skb, net, 0, IPPROTO_ICMP);
1104+
1105+
return 0;
11041106
}
11051107

11061108
/*

net/ipv4/ip_gre.c

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ static unsigned int ipgre_net_id __read_mostly;
121121
static unsigned int gre_tap_net_id __read_mostly;
122122
static unsigned int erspan_net_id __read_mostly;
123123

124-
static void ipgre_err(struct sk_buff *skb, u32 info,
125-
const struct tnl_ptk_info *tpi)
124+
static int ipgre_err(struct sk_buff *skb, u32 info,
125+
const struct tnl_ptk_info *tpi)
126126
{
127127

128128
/* All the routers (except for Linux) return only
@@ -146,17 +146,32 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
146146
unsigned int data_len = 0;
147147
struct ip_tunnel *t;
148148

149+
if (tpi->proto == htons(ETH_P_TEB))
150+
itn = net_generic(net, gre_tap_net_id);
151+
else if (tpi->proto == htons(ETH_P_ERSPAN) ||
152+
tpi->proto == htons(ETH_P_ERSPAN2))
153+
itn = net_generic(net, erspan_net_id);
154+
else
155+
itn = net_generic(net, ipgre_net_id);
156+
157+
iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
158+
t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
159+
iph->daddr, iph->saddr, tpi->key);
160+
161+
if (!t)
162+
return -ENOENT;
163+
149164
switch (type) {
150165
default:
151166
case ICMP_PARAMETERPROB:
152-
return;
167+
return 0;
153168

154169
case ICMP_DEST_UNREACH:
155170
switch (code) {
156171
case ICMP_SR_FAILED:
157172
case ICMP_PORT_UNREACH:
158173
/* Impossible event. */
159-
return;
174+
return 0;
160175
default:
161176
/* All others are translated to HOST_UNREACH.
162177
rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -168,48 +183,35 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
168183

169184
case ICMP_TIME_EXCEEDED:
170185
if (code != ICMP_EXC_TTL)
171-
return;
186+
return 0;
172187
data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
173188
break;
174189

175190
case ICMP_REDIRECT:
176191
break;
177192
}
178193

179-
if (tpi->proto == htons(ETH_P_TEB))
180-
itn = net_generic(net, gre_tap_net_id);
181-
else if (tpi->proto == htons(ETH_P_ERSPAN) ||
182-
tpi->proto == htons(ETH_P_ERSPAN2))
183-
itn = net_generic(net, erspan_net_id);
184-
else
185-
itn = net_generic(net, ipgre_net_id);
186-
187-
iph = (const struct iphdr *)(icmp_hdr(skb) + 1);
188-
t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi->flags,
189-
iph->daddr, iph->saddr, tpi->key);
190-
191-
if (!t)
192-
return;
193-
194194
#if IS_ENABLED(CONFIG_IPV6)
195195
if (tpi->proto == htons(ETH_P_IPV6) &&
196196
!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
197197
type, data_len))
198-
return;
198+
return 0;
199199
#endif
200200

201201
if (t->parms.iph.daddr == 0 ||
202202
ipv4_is_multicast(t->parms.iph.daddr))
203-
return;
203+
return 0;
204204

205205
if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
206-
return;
206+
return 0;
207207

208208
if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
209209
t->err_count++;
210210
else
211211
t->err_count = 1;
212212
t->err_time = jiffies;
213+
214+
return 0;
213215
}
214216

215217
static void gre_err(struct sk_buff *skb, u32 info)

net/ipv4/ipip.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ static int ipip_err(struct sk_buff *skb, u32 info)
140140
struct ip_tunnel *t;
141141
int err = 0;
142142

143+
t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
144+
iph->daddr, iph->saddr, 0);
145+
if (!t) {
146+
err = -ENOENT;
147+
goto out;
148+
}
149+
143150
switch (type) {
144151
case ICMP_DEST_UNREACH:
145152
switch (code) {
@@ -167,13 +174,6 @@ static int ipip_err(struct sk_buff *skb, u32 info)
167174
goto out;
168175
}
169176

170-
t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
171-
iph->daddr, iph->saddr, 0);
172-
if (!t) {
173-
err = -ENOENT;
174-
goto out;
175-
}
176-
177177
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
178178
ipv4_update_pmtu(skb, net, info, t->parms.link, iph->protocol);
179179
goto out;

net/ipv4/tcp_ipv4.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ EXPORT_SYMBOL(tcp_req_err);
423423
*
424424
*/
425425

426-
void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
426+
int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
427427
{
428428
const struct iphdr *iph = (const struct iphdr *)icmp_skb->data;
429429
struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2));
@@ -446,20 +446,21 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
446446
inet_iif(icmp_skb), 0);
447447
if (!sk) {
448448
__ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
449-
return;
449+
return -ENOENT;
450450
}
451451
if (sk->sk_state == TCP_TIME_WAIT) {
452452
inet_twsk_put(inet_twsk(sk));
453-
return;
453+
return 0;
454454
}
455455
seq = ntohl(th->seq);
456-
if (sk->sk_state == TCP_NEW_SYN_RECV)
457-
return tcp_req_err(sk, seq,
458-
type == ICMP_PARAMETERPROB ||
459-
type == ICMP_TIME_EXCEEDED ||
460-
(type == ICMP_DEST_UNREACH &&
461-
(code == ICMP_NET_UNREACH ||
462-
code == ICMP_HOST_UNREACH)));
456+
if (sk->sk_state == TCP_NEW_SYN_RECV) {
457+
tcp_req_err(sk, seq, type == ICMP_PARAMETERPROB ||
458+
type == ICMP_TIME_EXCEEDED ||
459+
(type == ICMP_DEST_UNREACH &&
460+
(code == ICMP_NET_UNREACH ||
461+
code == ICMP_HOST_UNREACH)));
462+
return 0;
463+
}
463464

464465
bh_lock_sock(sk);
465466
/* If too many ICMPs get dropped on busy
@@ -613,6 +614,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
613614
out:
614615
bh_unlock_sock(sk);
615616
sock_put(sk);
617+
return 0;
616618
}
617619

618620
void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr)

0 commit comments

Comments
 (0)