struct net_device *dev = skb->dev;
        struct in_device *in_dev;
        struct fib_result res;
+       struct rtable *rt;
        struct flowi4 fl4;
        struct net *net;
+       int scope;
 
-       if (skb->pkt_type != PACKET_BROADCAST &&
-           skb->pkt_type != PACKET_MULTICAST)
+       rt = skb_rtable(skb);
+       if (!(rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)))
                return ip_hdr(skb)->daddr;
 
        in_dev = __in_dev_get_rcu(dev);
        BUG_ON(!in_dev);
-       fl4.flowi4_oif = 0;
-       fl4.flowi4_iif = 0;
-       fl4.daddr = ip_hdr(skb)->saddr;
-       fl4.saddr = ip_hdr(skb)->daddr;
-       fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
-       fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
-       fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
 
        net = dev_net(dev);
-       if (!fib_lookup(net, &fl4, &res))
-               return FIB_RES_PREFSRC(net, res);
-       else
-               return inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
+
+       scope = RT_SCOPE_UNIVERSE;
+       if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) {
+               fl4.flowi4_oif = 0;
+               fl4.flowi4_iif = net->loopback_dev->ifindex;
+               fl4.daddr = ip_hdr(skb)->saddr;
+               fl4.saddr = 0;
+               fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
+               fl4.flowi4_scope = scope;
+               fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
+               if (!fib_lookup(net, &fl4, &res))
+                       return FIB_RES_PREFSRC(net, res);
+       } else {
+               scope = RT_SCOPE_LINK;
+       }
+
+       return inet_select_addr(dev, ip_hdr(skb)->saddr, scope);
 }
 
 /* Given (packet source, input interface) and optional (dst, oif, tos):