aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r--net/ipv4/arp.c60
1 files changed, 34 insertions, 26 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index d8e540c5b071..04c8b69fd426 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
434static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev) 434static 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() */
1027static int arp_req_set_public(struct net *net, struct arpreq *r, 1028static 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)
@@ -1142,6 +1143,23 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
1142 return err; 1143 return err;
1143} 1144}
1144 1145
1146int arp_invalidate(struct net_device *dev, __be32 ip)
1147{
1148 struct neighbour *neigh = neigh_lookup(&arp_tbl, &ip, dev);
1149 int err = -ENXIO;
1150
1151 if (neigh) {
1152 if (neigh->nud_state & ~NUD_NOARP)
1153 err = neigh_update(neigh, NULL, NUD_FAILED,
1154 NEIGH_UPDATE_F_OVERRIDE|
1155 NEIGH_UPDATE_F_ADMIN);
1156 neigh_release(neigh);
1157 }
1158
1159 return err;
1160}
1161EXPORT_SYMBOL(arp_invalidate);
1162
1145static int arp_req_delete_public(struct net *net, struct arpreq *r, 1163static int arp_req_delete_public(struct net *net, struct arpreq *r,
1146 struct net_device *dev) 1164 struct net_device *dev)
1147{ 1165{
@@ -1162,15 +1180,14 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
1162{ 1180{
1163 int err; 1181 int err;
1164 __be32 ip; 1182 __be32 ip;
1165 struct neighbour *neigh;
1166 1183
1167 if (r->arp_flags & ATF_PUBL) 1184 if (r->arp_flags & ATF_PUBL)
1168 return arp_req_delete_public(net, r, dev); 1185 return arp_req_delete_public(net, r, dev);
1169 1186
1170 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; 1187 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
1171 if (dev == NULL) { 1188 if (dev == NULL) {
1172 struct flowi fl = { .nl_u.ip4_u = { .daddr = ip, 1189 struct flowi fl = { .fl4_dst = ip,
1173 .tos = RTO_ONLINK } }; 1190 .fl4_tos = RTO_ONLINK };
1174 struct rtable *rt; 1191 struct rtable *rt;
1175 err = ip_route_output_key(net, &rt, &fl); 1192 err = ip_route_output_key(net, &rt, &fl);
1176 if (err != 0) 1193 if (err != 0)
@@ -1180,16 +1197,7 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
1180 if (!dev) 1197 if (!dev)
1181 return -EINVAL; 1198 return -EINVAL;
1182 } 1199 }
1183 err = -ENXIO; 1200 return arp_invalidate(dev, ip);
1184 neigh = neigh_lookup(&arp_tbl, &ip, dev);
1185 if (neigh) {
1186 if (neigh->nud_state & ~NUD_NOARP)
1187 err = neigh_update(neigh, NULL, NUD_FAILED,
1188 NEIGH_UPDATE_F_OVERRIDE|
1189 NEIGH_UPDATE_F_ADMIN);
1190 neigh_release(neigh);
1191 }
1192 return err;
1193} 1201}
1194 1202
1195/* 1203/*
@@ -1225,10 +1233,10 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1225 if (!(r.arp_flags & ATF_NETMASK)) 1233 if (!(r.arp_flags & ATF_NETMASK))
1226 ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr = 1234 ((struct sockaddr_in *)&r.arp_netmask)->sin_addr.s_addr =
1227 htonl(0xFFFFFFFFUL); 1235 htonl(0xFFFFFFFFUL);
1228 rtnl_lock(); 1236 rcu_read_lock();
1229 if (r.arp_dev[0]) { 1237 if (r.arp_dev[0]) {
1230 err = -ENODEV; 1238 err = -ENODEV;
1231 dev = __dev_get_by_name(net, r.arp_dev); 1239 dev = dev_get_by_name_rcu(net, r.arp_dev);
1232 if (dev == NULL) 1240 if (dev == NULL)
1233 goto out; 1241 goto out;
1234 1242
@@ -1252,12 +1260,12 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
1252 break; 1260 break;
1253 case SIOCGARP: 1261 case SIOCGARP:
1254 err = arp_req_get(&r, dev); 1262 err = arp_req_get(&r, dev);
1255 if (!err && copy_to_user(arg, &r, sizeof(r)))
1256 err = -EFAULT;
1257 break; 1263 break;
1258 } 1264 }
1259out: 1265out:
1260 rtnl_unlock(); 1266 rcu_read_unlock();
1267 if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r)))
1268 err = -EFAULT;
1261 return err; 1269 return err;
1262} 1270}
1263 1271