aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp.c')
-rw-r--r--net/ipv4/udp.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index ef29df8648e4..5676237d2b0f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2221,9 +2221,10 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,
2221 return NULL; 2221 return NULL;
2222} 2222}
2223 2223
2224void udp_v4_early_demux(struct sk_buff *skb) 2224int udp_v4_early_demux(struct sk_buff *skb)
2225{ 2225{
2226 struct net *net = dev_net(skb->dev); 2226 struct net *net = dev_net(skb->dev);
2227 struct in_device *in_dev = NULL;
2227 const struct iphdr *iph; 2228 const struct iphdr *iph;
2228 const struct udphdr *uh; 2229 const struct udphdr *uh;
2229 struct sock *sk = NULL; 2230 struct sock *sk = NULL;
@@ -2234,24 +2235,24 @@ void udp_v4_early_demux(struct sk_buff *skb)
2234 2235
2235 /* validate the packet */ 2236 /* validate the packet */
2236 if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) 2237 if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr)))
2237 return; 2238 return 0;
2238 2239
2239 iph = ip_hdr(skb); 2240 iph = ip_hdr(skb);
2240 uh = udp_hdr(skb); 2241 uh = udp_hdr(skb);
2241 2242
2242 if (skb->pkt_type == PACKET_BROADCAST || 2243 if (skb->pkt_type == PACKET_BROADCAST ||
2243 skb->pkt_type == PACKET_MULTICAST) { 2244 skb->pkt_type == PACKET_MULTICAST) {
2244 struct in_device *in_dev = __in_dev_get_rcu(skb->dev); 2245 in_dev = __in_dev_get_rcu(skb->dev);
2245 2246
2246 if (!in_dev) 2247 if (!in_dev)
2247 return; 2248 return 0;
2248 2249
2249 /* we are supposed to accept bcast packets */ 2250 /* we are supposed to accept bcast packets */
2250 if (skb->pkt_type == PACKET_MULTICAST) { 2251 if (skb->pkt_type == PACKET_MULTICAST) {
2251 ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, 2252 ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
2252 iph->protocol); 2253 iph->protocol);
2253 if (!ours) 2254 if (!ours)
2254 return; 2255 return 0;
2255 } 2256 }
2256 2257
2257 sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr, 2258 sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
@@ -2263,7 +2264,7 @@ void udp_v4_early_demux(struct sk_buff *skb)
2263 } 2264 }
2264 2265
2265 if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt)) 2266 if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt))
2266 return; 2267 return 0;
2267 2268
2268 skb->sk = sk; 2269 skb->sk = sk;
2269 skb->destructor = sock_efree; 2270 skb->destructor = sock_efree;
@@ -2272,12 +2273,23 @@ void udp_v4_early_demux(struct sk_buff *skb)
2272 if (dst) 2273 if (dst)
2273 dst = dst_check(dst, 0); 2274 dst = dst_check(dst, 0);
2274 if (dst) { 2275 if (dst) {
2276 u32 itag = 0;
2277
2275 /* set noref for now. 2278 /* set noref for now.
2276 * any place which wants to hold dst has to call 2279 * any place which wants to hold dst has to call
2277 * dst_hold_safe() 2280 * dst_hold_safe()
2278 */ 2281 */
2279 skb_dst_set_noref(skb, dst); 2282 skb_dst_set_noref(skb, dst);
2283
2284 /* for unconnected multicast sockets we need to validate
2285 * the source on each packet
2286 */
2287 if (!inet_sk(sk)->inet_daddr && in_dev)
2288 return ip_mc_validate_source(skb, iph->daddr,
2289 iph->saddr, iph->tos,
2290 skb->dev, in_dev, &itag);
2280 } 2291 }
2292 return 0;
2281} 2293}
2282 2294
2283int udp_rcv(struct sk_buff *skb) 2295int udp_rcv(struct sk_buff *skb)