aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_gre.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2018-11-08 06:19:21 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-08 20:13:08 -0500
commit32bbd8793f24b0d5beb1cdb33c45c75ad1140e4b (patch)
tree69b7c7f0348e063bd81215058130c1b1800410db /net/ipv4/ip_gre.c
parentce7336610ca950cda131293def57a0178d860121 (diff)
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>
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r--net/ipv4/ip_gre.c48
1 files changed, 25 insertions, 23 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 2c67af644e64..76a9a5f7a40e 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -121,8 +121,8 @@ static unsigned int ipgre_net_id __read_mostly;
121static unsigned int gre_tap_net_id __read_mostly; 121static unsigned int gre_tap_net_id __read_mostly;
122static unsigned int erspan_net_id __read_mostly; 122static unsigned int erspan_net_id __read_mostly;
123 123
124static void ipgre_err(struct sk_buff *skb, u32 info, 124static int ipgre_err(struct sk_buff *skb, u32 info,
125 const struct tnl_ptk_info *tpi) 125 const struct tnl_ptk_info *tpi)
126{ 126{
127 127
128 /* All the routers (except for Linux) return only 128 /* All the routers (except for Linux) return only
@@ -146,17 +146,32 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
146 unsigned int data_len = 0; 146 unsigned int data_len = 0;
147 struct ip_tunnel *t; 147 struct ip_tunnel *t;
148 148
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
149 switch (type) { 164 switch (type) {
150 default: 165 default:
151 case ICMP_PARAMETERPROB: 166 case ICMP_PARAMETERPROB:
152 return; 167 return 0;
153 168
154 case ICMP_DEST_UNREACH: 169 case ICMP_DEST_UNREACH:
155 switch (code) { 170 switch (code) {
156 case ICMP_SR_FAILED: 171 case ICMP_SR_FAILED:
157 case ICMP_PORT_UNREACH: 172 case ICMP_PORT_UNREACH:
158 /* Impossible event. */ 173 /* Impossible event. */
159 return; 174 return 0;
160 default: 175 default:
161 /* All others are translated to HOST_UNREACH. 176 /* All others are translated to HOST_UNREACH.
162 rfc2003 contains "deep thoughts" about NET_UNREACH, 177 rfc2003 contains "deep thoughts" about NET_UNREACH,
@@ -168,7 +183,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
168 183
169 case ICMP_TIME_EXCEEDED: 184 case ICMP_TIME_EXCEEDED:
170 if (code != ICMP_EXC_TTL) 185 if (code != ICMP_EXC_TTL)
171 return; 186 return 0;
172 data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */ 187 data_len = icmp_hdr(skb)->un.reserved[1] * 4; /* RFC 4884 4.1 */
173 break; 188 break;
174 189
@@ -176,40 +191,27 @@ static void ipgre_err(struct sk_buff *skb, u32 info,
176 break; 191 break;
177 } 192 }
178 193
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
194#if IS_ENABLED(CONFIG_IPV6) 194#if IS_ENABLED(CONFIG_IPV6)
195 if (tpi->proto == htons(ETH_P_IPV6) && 195 if (tpi->proto == htons(ETH_P_IPV6) &&
196 !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len, 196 !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4 + tpi->hdr_len,
197 type, data_len)) 197 type, data_len))
198 return; 198 return 0;
199#endif 199#endif
200 200
201 if (t->parms.iph.daddr == 0 || 201 if (t->parms.iph.daddr == 0 ||
202 ipv4_is_multicast(t->parms.iph.daddr)) 202 ipv4_is_multicast(t->parms.iph.daddr))
203 return; 203 return 0;
204 204
205 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED) 205 if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
206 return; 206 return 0;
207 207
208 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO)) 208 if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
209 t->err_count++; 209 t->err_count++;
210 else 210 else
211 t->err_count = 1; 211 t->err_count = 1;
212 t->err_time = jiffies; 212 t->err_time = jiffies;
213
214 return 0;
213} 215}
214 216
215static void gre_err(struct sk_buff *skb, u32 info) 217static void gre_err(struct sk_buff *skb, u32 info)