diff options
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r-- | net/ipv4/arp.c | 31 |
1 files changed, 16 insertions, 15 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index d8e540c5b071..a2fc7b961dbc 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -433,8 +433,8 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip) | |||
433 | 433 | ||
434 | static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) | 434 | static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) |
435 | { | 435 | { |
436 | struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip, | 436 | struct flowi fl = { .fl4_dst = sip, |
437 | .saddr = tip } } }; | 437 | .fl4_src = tip }; |
438 | struct rtable *rt; | 438 | struct rtable *rt; |
439 | int flag = 0; | 439 | int flag = 0; |
440 | /*unsigned long now; */ | 440 | /*unsigned long now; */ |
@@ -883,7 +883,7 @@ static int arp_process(struct sk_buff *skb) | |||
883 | 883 | ||
884 | dont_send = arp_ignore(in_dev, sip, tip); | 884 | dont_send = arp_ignore(in_dev, sip, tip); |
885 | if (!dont_send && IN_DEV_ARPFILTER(in_dev)) | 885 | if (!dont_send && IN_DEV_ARPFILTER(in_dev)) |
886 | dont_send |= arp_filter(sip, tip, dev); | 886 | dont_send = arp_filter(sip, tip, dev); |
887 | if (!dont_send) { | 887 | if (!dont_send) { |
888 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); | 888 | n = neigh_event_ns(&arp_tbl, sha, &sip, dev); |
889 | if (n) { | 889 | if (n) { |
@@ -1017,13 +1017,14 @@ static int arp_req_set_proxy(struct net *net, struct net_device *dev, int on) | |||
1017 | IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; | 1017 | IPV4_DEVCONF_ALL(net, PROXY_ARP) = on; |
1018 | return 0; | 1018 | return 0; |
1019 | } | 1019 | } |
1020 | if (__in_dev_get_rtnl(dev)) { | 1020 | if (__in_dev_get_rcu(dev)) { |
1021 | IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, on); | 1021 | IN_DEV_CONF_SET(__in_dev_get_rcu(dev), PROXY_ARP, on); |
1022 | return 0; | 1022 | return 0; |
1023 | } | 1023 | } |
1024 | return -ENXIO; | 1024 | return -ENXIO; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | /* must be called with rcu_read_lock() */ | ||
1027 | static int arp_req_set_public(struct net *net, struct arpreq *r, | 1028 | static int arp_req_set_public(struct net *net, struct arpreq *r, |
1028 | struct net_device *dev) | 1029 | struct net_device *dev) |
1029 | { | 1030 | { |
@@ -1033,7 +1034,7 @@ static int arp_req_set_public(struct net *net, struct arpreq *r, | |||
1033 | if (mask && mask != htonl(0xFFFFFFFF)) | 1034 | if (mask && mask != htonl(0xFFFFFFFF)) |
1034 | return -EINVAL; | 1035 | return -EINVAL; |
1035 | if (!dev && (r->arp_flags & ATF_COM)) { | 1036 | if (!dev && (r->arp_flags & ATF_COM)) { |
1036 | dev = dev_getbyhwaddr(net, r->arp_ha.sa_family, | 1037 | dev = dev_getbyhwaddr_rcu(net, r->arp_ha.sa_family, |
1037 | r->arp_ha.sa_data); | 1038 | r->arp_ha.sa_data); |
1038 | if (!dev) | 1039 | if (!dev) |
1039 | return -ENODEV; | 1040 | return -ENODEV; |
@@ -1061,8 +1062,8 @@ static int arp_req_set(struct net *net, struct arpreq *r, | |||
1061 | if (r->arp_flags & ATF_PERM) | 1062 | if (r->arp_flags & ATF_PERM) |
1062 | r->arp_flags |= ATF_COM; | 1063 | r->arp_flags |= ATF_COM; |
1063 | if (dev == NULL) { | 1064 | if (dev == NULL) { |
1064 | struct flowi fl = { .nl_u.ip4_u = { .daddr = ip, | 1065 | struct flowi fl = { .fl4_dst = ip, |
1065 | .tos = RTO_ONLINK } }; | 1066 | .fl4_tos = RTO_ONLINK }; |
1066 | struct rtable *rt; | 1067 | struct rtable *rt; |
1067 | err = ip_route_output_key(net, &rt, &fl); | 1068 | err = ip_route_output_key(net, &rt, &fl); |
1068 | if (err != 0) | 1069 | if (err != 0) |
@@ -1169,8 +1170,8 @@ static int arp_req_delete(struct net *net, struct arpreq *r, | |||
1169 | 1170 | ||
1170 | ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; | 1171 | ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; |
1171 | if (dev == NULL) { | 1172 | if (dev == NULL) { |
1172 | struct flowi fl = { .nl_u.ip4_u = { .daddr = ip, | 1173 | struct flowi fl = { .fl4_dst = ip, |
1173 | .tos = RTO_ONLINK } }; | 1174 | .fl4_tos = RTO_ONLINK }; |
1174 | struct rtable *rt; | 1175 | struct rtable *rt; |
1175 | err = ip_route_output_key(net, &rt, &fl); | 1176 | err = ip_route_output_key(net, &rt, &fl); |
1176 | if (err != 0) | 1177 | if (err != 0) |
@@ -1225,10 +1226,10 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
1225 | if (!(r.arp_flags & ATF_NETMASK)) | 1226 | if (!(r.arp_flags & ATF_NETMASK)) |
1226 | ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = | 1227 | ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = |
1227 | htonl(0xFFFFFFFFUL); | 1228 | htonl(0xFFFFFFFFUL); |
1228 | rtnl_lock(); | 1229 | rcu_read_lock(); |
1229 | if (r.arp_dev[0]) { | 1230 | if (r.arp_dev[0]) { |
1230 | err = -ENODEV; | 1231 | err = -ENODEV; |
1231 | dev = __dev_get_by_name(net, r.arp_dev); | 1232 | dev = dev_get_by_name_rcu(net, r.arp_dev); |
1232 | if (dev == NULL) | 1233 | if (dev == NULL) |
1233 | goto out; | 1234 | goto out; |
1234 | 1235 | ||
@@ -1252,12 +1253,12 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
1252 | break; | 1253 | break; |
1253 | case SIOCGARP: | 1254 | case SIOCGARP: |
1254 | err = arp_req_get(&r, dev); | 1255 | err = arp_req_get(&r, dev); |
1255 | if (!err && copy_to_user(arg, &r, sizeof(r))) | ||
1256 | err = -EFAULT; | ||
1257 | break; | 1256 | break; |
1258 | } | 1257 | } |
1259 | out: | 1258 | out: |
1260 | rtnl_unlock(); | 1259 | rcu_read_unlock(); |
1260 | if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r))) | ||
1261 | err = -EFAULT; | ||
1261 | return err; | 1262 | return err; |
1262 | } | 1263 | } |
1263 | 1264 | ||