diff options
-rw-r--r-- | net/ipv4/arp.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 54a76b8b803a..04e0ecdd07be 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -952,37 +952,45 @@ out_of_mem: | |||
952 | * Set (create) an ARP cache entry. | 952 | * Set (create) an ARP cache entry. |
953 | */ | 953 | */ |
954 | 954 | ||
955 | static int arp_req_set_public(struct arpreq *r, struct net_device *dev) | ||
956 | { | ||
957 | __be32 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; | ||
958 | __be32 mask = ((struct sockaddr_in *)&r->arp_netmask)->sin_addr.s_addr; | ||
959 | |||
960 | if (mask && mask != htonl(0xFFFFFFFF)) | ||
961 | return -EINVAL; | ||
962 | if (!dev && (r->arp_flags & ATF_COM)) { | ||
963 | dev = dev_getbyhwaddr(&init_net, r->arp_ha.sa_family, | ||
964 | r->arp_ha.sa_data); | ||
965 | if (!dev) | ||
966 | return -ENODEV; | ||
967 | } | ||
968 | if (mask) { | ||
969 | if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL) | ||
970 | return -ENOBUFS; | ||
971 | return 0; | ||
972 | } | ||
973 | if (dev == NULL) { | ||
974 | IPV4_DEVCONF_ALL(PROXY_ARP) = 1; | ||
975 | return 0; | ||
976 | } | ||
977 | if (__in_dev_get_rtnl(dev)) { | ||
978 | IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1); | ||
979 | return 0; | ||
980 | } | ||
981 | return -ENXIO; | ||
982 | } | ||
983 | |||
955 | static int arp_req_set(struct arpreq *r, struct net_device * dev) | 984 | static int arp_req_set(struct arpreq *r, struct net_device * dev) |
956 | { | 985 | { |
957 | __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; | 986 | __be32 ip; |
958 | struct neighbour *neigh; | 987 | struct neighbour *neigh; |
959 | int err; | 988 | int err; |
960 | 989 | ||
961 | if (r->arp_flags&ATF_PUBL) { | 990 | if (r->arp_flags & ATF_PUBL) |
962 | __be32 mask = ((struct sockaddr_in *) &r->arp_netmask)->sin_addr.s_addr; | 991 | return arp_req_set_public(r, dev); |
963 | if (mask && mask != htonl(0xFFFFFFFF)) | ||
964 | return -EINVAL; | ||
965 | if (!dev && (r->arp_flags & ATF_COM)) { | ||
966 | dev = dev_getbyhwaddr(&init_net, r->arp_ha.sa_family, r->arp_ha.sa_data); | ||
967 | if (!dev) | ||
968 | return -ENODEV; | ||
969 | } | ||
970 | if (mask) { | ||
971 | if (pneigh_lookup(&arp_tbl, &ip, dev, 1) == NULL) | ||
972 | return -ENOBUFS; | ||
973 | return 0; | ||
974 | } | ||
975 | if (dev == NULL) { | ||
976 | IPV4_DEVCONF_ALL(PROXY_ARP) = 1; | ||
977 | return 0; | ||
978 | } | ||
979 | if (__in_dev_get_rtnl(dev)) { | ||
980 | IN_DEV_CONF_SET(__in_dev_get_rtnl(dev), PROXY_ARP, 1); | ||
981 | return 0; | ||
982 | } | ||
983 | return -ENXIO; | ||
984 | } | ||
985 | 992 | ||
993 | ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; | ||
986 | if (r->arp_flags & ATF_PERM) | 994 | if (r->arp_flags & ATF_PERM) |
987 | r->arp_flags |= ATF_COM; | 995 | r->arp_flags |= ATF_COM; |
988 | if (dev == NULL) { | 996 | if (dev == NULL) { |