diff options
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r-- | net/ipv4/devinet.c | 269 |
1 files changed, 103 insertions, 166 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5df2f6a0b0f0..5cdbc102a418 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -140,11 +140,11 @@ void in_dev_finish_destroy(struct in_device *idev) | |||
140 | #endif | 140 | #endif |
141 | dev_put(dev); | 141 | dev_put(dev); |
142 | if (!idev->dead) | 142 | if (!idev->dead) |
143 | printk("Freeing alive in_device %p\n", idev); | 143 | pr_err("Freeing alive in_device %p\n", idev); |
144 | else { | 144 | else |
145 | kfree(idev); | 145 | kfree(idev); |
146 | } | ||
147 | } | 146 | } |
147 | EXPORT_SYMBOL(in_dev_finish_destroy); | ||
148 | 148 | ||
149 | static struct in_device *inetdev_init(struct net_device *dev) | 149 | static struct in_device *inetdev_init(struct net_device *dev) |
150 | { | 150 | { |
@@ -159,7 +159,8 @@ static struct in_device *inetdev_init(struct net_device *dev) | |||
159 | sizeof(in_dev->cnf)); | 159 | sizeof(in_dev->cnf)); |
160 | in_dev->cnf.sysctl = NULL; | 160 | in_dev->cnf.sysctl = NULL; |
161 | in_dev->dev = dev; | 161 | in_dev->dev = dev; |
162 | if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL) | 162 | in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl); |
163 | if (!in_dev->arp_parms) | ||
163 | goto out_kfree; | 164 | goto out_kfree; |
164 | if (IPV4_DEVCONF(in_dev->cnf, FORWARDING)) | 165 | if (IPV4_DEVCONF(in_dev->cnf, FORWARDING)) |
165 | dev_disable_lro(dev); | 166 | dev_disable_lro(dev); |
@@ -405,13 +406,15 @@ struct in_device *inetdev_by_index(struct net *net, int ifindex) | |||
405 | { | 406 | { |
406 | struct net_device *dev; | 407 | struct net_device *dev; |
407 | struct in_device *in_dev = NULL; | 408 | struct in_device *in_dev = NULL; |
408 | read_lock(&dev_base_lock); | 409 | |
409 | dev = __dev_get_by_index(net, ifindex); | 410 | rcu_read_lock(); |
411 | dev = dev_get_by_index_rcu(net, ifindex); | ||
410 | if (dev) | 412 | if (dev) |
411 | in_dev = in_dev_get(dev); | 413 | in_dev = in_dev_get(dev); |
412 | read_unlock(&dev_base_lock); | 414 | rcu_read_unlock(); |
413 | return in_dev; | 415 | return in_dev; |
414 | } | 416 | } |
417 | EXPORT_SYMBOL(inetdev_by_index); | ||
415 | 418 | ||
416 | /* Called only from RTNL semaphored context. No locks. */ | 419 | /* Called only from RTNL semaphored context. No locks. */ |
417 | 420 | ||
@@ -557,7 +560,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg | |||
557 | * Determine a default network mask, based on the IP address. | 560 | * Determine a default network mask, based on the IP address. |
558 | */ | 561 | */ |
559 | 562 | ||
560 | static __inline__ int inet_abc_len(__be32 addr) | 563 | static inline int inet_abc_len(__be32 addr) |
561 | { | 564 | { |
562 | int rc = -1; /* Something else, probably a multicast. */ | 565 | int rc = -1; /* Something else, probably a multicast. */ |
563 | 566 | ||
@@ -646,13 +649,15 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
646 | rtnl_lock(); | 649 | rtnl_lock(); |
647 | 650 | ||
648 | ret = -ENODEV; | 651 | ret = -ENODEV; |
649 | if ((dev = __dev_get_by_name(net, ifr.ifr_name)) == NULL) | 652 | dev = __dev_get_by_name(net, ifr.ifr_name); |
653 | if (!dev) | ||
650 | goto done; | 654 | goto done; |
651 | 655 | ||
652 | if (colon) | 656 | if (colon) |
653 | *colon = ':'; | 657 | *colon = ':'; |
654 | 658 | ||
655 | if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { | 659 | in_dev = __in_dev_get_rtnl(dev); |
660 | if (in_dev) { | ||
656 | if (tryaddrmatch) { | 661 | if (tryaddrmatch) { |
657 | /* Matthias Andree */ | 662 | /* Matthias Andree */ |
658 | /* compare label and address (4.4BSD style) */ | 663 | /* compare label and address (4.4BSD style) */ |
@@ -720,7 +725,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
720 | 725 | ||
721 | if (!ifa) { | 726 | if (!ifa) { |
722 | ret = -ENOBUFS; | 727 | ret = -ENOBUFS; |
723 | if ((ifa = inet_alloc_ifa()) == NULL) | 728 | ifa = inet_alloc_ifa(); |
729 | if (!ifa) | ||
724 | break; | 730 | break; |
725 | if (colon) | 731 | if (colon) |
726 | memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); | 732 | memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); |
@@ -822,10 +828,10 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len) | |||
822 | struct ifreq ifr; | 828 | struct ifreq ifr; |
823 | int done = 0; | 829 | int done = 0; |
824 | 830 | ||
825 | if (!in_dev || (ifa = in_dev->ifa_list) == NULL) | 831 | if (!in_dev) |
826 | goto out; | 832 | goto out; |
827 | 833 | ||
828 | for (; ifa; ifa = ifa->ifa_next) { | 834 | for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { |
829 | if (!buf) { | 835 | if (!buf) { |
830 | done += sizeof(ifr); | 836 | done += sizeof(ifr); |
831 | continue; | 837 | continue; |
@@ -875,36 +881,33 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) | |||
875 | if (!addr) | 881 | if (!addr) |
876 | addr = ifa->ifa_local; | 882 | addr = ifa->ifa_local; |
877 | } endfor_ifa(in_dev); | 883 | } endfor_ifa(in_dev); |
878 | no_in_dev: | ||
879 | rcu_read_unlock(); | ||
880 | 884 | ||
881 | if (addr) | 885 | if (addr) |
882 | goto out; | 886 | goto out_unlock; |
887 | no_in_dev: | ||
883 | 888 | ||
884 | /* Not loopback addresses on loopback should be preferred | 889 | /* Not loopback addresses on loopback should be preferred |
885 | in this case. It is importnat that lo is the first interface | 890 | in this case. It is importnat that lo is the first interface |
886 | in dev_base list. | 891 | in dev_base list. |
887 | */ | 892 | */ |
888 | read_lock(&dev_base_lock); | 893 | for_each_netdev_rcu(net, dev) { |
889 | rcu_read_lock(); | 894 | in_dev = __in_dev_get_rcu(dev); |
890 | for_each_netdev(net, dev) { | 895 | if (!in_dev) |
891 | if ((in_dev = __in_dev_get_rcu(dev)) == NULL) | ||
892 | continue; | 896 | continue; |
893 | 897 | ||
894 | for_primary_ifa(in_dev) { | 898 | for_primary_ifa(in_dev) { |
895 | if (ifa->ifa_scope != RT_SCOPE_LINK && | 899 | if (ifa->ifa_scope != RT_SCOPE_LINK && |
896 | ifa->ifa_scope <= scope) { | 900 | ifa->ifa_scope <= scope) { |
897 | addr = ifa->ifa_local; | 901 | addr = ifa->ifa_local; |
898 | goto out_unlock_both; | 902 | goto out_unlock; |
899 | } | 903 | } |
900 | } endfor_ifa(in_dev); | 904 | } endfor_ifa(in_dev); |
901 | } | 905 | } |
902 | out_unlock_both: | 906 | out_unlock: |
903 | read_unlock(&dev_base_lock); | ||
904 | rcu_read_unlock(); | 907 | rcu_read_unlock(); |
905 | out: | ||
906 | return addr; | 908 | return addr; |
907 | } | 909 | } |
910 | EXPORT_SYMBOL(inet_select_addr); | ||
908 | 911 | ||
909 | static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, | 912 | static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, |
910 | __be32 local, int scope) | 913 | __be32 local, int scope) |
@@ -940,7 +943,7 @@ static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, | |||
940 | } | 943 | } |
941 | } endfor_ifa(in_dev); | 944 | } endfor_ifa(in_dev); |
942 | 945 | ||
943 | return same? addr : 0; | 946 | return same ? addr : 0; |
944 | } | 947 | } |
945 | 948 | ||
946 | /* | 949 | /* |
@@ -961,17 +964,16 @@ __be32 inet_confirm_addr(struct in_device *in_dev, | |||
961 | return confirm_addr_indev(in_dev, dst, local, scope); | 964 | return confirm_addr_indev(in_dev, dst, local, scope); |
962 | 965 | ||
963 | net = dev_net(in_dev->dev); | 966 | net = dev_net(in_dev->dev); |
964 | read_lock(&dev_base_lock); | ||
965 | rcu_read_lock(); | 967 | rcu_read_lock(); |
966 | for_each_netdev(net, dev) { | 968 | for_each_netdev_rcu(net, dev) { |
967 | if ((in_dev = __in_dev_get_rcu(dev))) { | 969 | in_dev = __in_dev_get_rcu(dev); |
970 | if (in_dev) { | ||
968 | addr = confirm_addr_indev(in_dev, dst, local, scope); | 971 | addr = confirm_addr_indev(in_dev, dst, local, scope); |
969 | if (addr) | 972 | if (addr) |
970 | break; | 973 | break; |
971 | } | 974 | } |
972 | } | 975 | } |
973 | rcu_read_unlock(); | 976 | rcu_read_unlock(); |
974 | read_unlock(&dev_base_lock); | ||
975 | 977 | ||
976 | return addr; | 978 | return addr; |
977 | } | 979 | } |
@@ -984,14 +986,16 @@ int register_inetaddr_notifier(struct notifier_block *nb) | |||
984 | { | 986 | { |
985 | return blocking_notifier_chain_register(&inetaddr_chain, nb); | 987 | return blocking_notifier_chain_register(&inetaddr_chain, nb); |
986 | } | 988 | } |
989 | EXPORT_SYMBOL(register_inetaddr_notifier); | ||
987 | 990 | ||
988 | int unregister_inetaddr_notifier(struct notifier_block *nb) | 991 | int unregister_inetaddr_notifier(struct notifier_block *nb) |
989 | { | 992 | { |
990 | return blocking_notifier_chain_unregister(&inetaddr_chain, nb); | 993 | return blocking_notifier_chain_unregister(&inetaddr_chain, nb); |
991 | } | 994 | } |
995 | EXPORT_SYMBOL(unregister_inetaddr_notifier); | ||
992 | 996 | ||
993 | /* Rename ifa_labels for a device name change. Make some effort to preserve existing | 997 | /* Rename ifa_labels for a device name change. Make some effort to preserve |
994 | * alias numbering and to create unique labels if possible. | 998 | * existing alias numbering and to create unique labels if possible. |
995 | */ | 999 | */ |
996 | static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) | 1000 | static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) |
997 | { | 1001 | { |
@@ -1010,11 +1014,10 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) | |||
1010 | sprintf(old, ":%d", named); | 1014 | sprintf(old, ":%d", named); |
1011 | dot = old; | 1015 | dot = old; |
1012 | } | 1016 | } |
1013 | if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) { | 1017 | if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) |
1014 | strcat(ifa->ifa_label, dot); | 1018 | strcat(ifa->ifa_label, dot); |
1015 | } else { | 1019 | else |
1016 | strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); | 1020 | strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); |
1017 | } | ||
1018 | skip: | 1021 | skip: |
1019 | rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); | 1022 | rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); |
1020 | } | 1023 | } |
@@ -1061,8 +1064,9 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1061 | if (!inetdev_valid_mtu(dev->mtu)) | 1064 | if (!inetdev_valid_mtu(dev->mtu)) |
1062 | break; | 1065 | break; |
1063 | if (dev->flags & IFF_LOOPBACK) { | 1066 | if (dev->flags & IFF_LOOPBACK) { |
1064 | struct in_ifaddr *ifa; | 1067 | struct in_ifaddr *ifa = inet_alloc_ifa(); |
1065 | if ((ifa = inet_alloc_ifa()) != NULL) { | 1068 | |
1069 | if (ifa) { | ||
1066 | ifa->ifa_local = | 1070 | ifa->ifa_local = |
1067 | ifa->ifa_address = htonl(INADDR_LOOPBACK); | 1071 | ifa->ifa_address = htonl(INADDR_LOOPBACK); |
1068 | ifa->ifa_prefixlen = 8; | 1072 | ifa->ifa_prefixlen = 8; |
@@ -1170,38 +1174,54 @@ nla_put_failure: | |||
1170 | static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | 1174 | static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) |
1171 | { | 1175 | { |
1172 | struct net *net = sock_net(skb->sk); | 1176 | struct net *net = sock_net(skb->sk); |
1173 | int idx, ip_idx; | 1177 | int h, s_h; |
1178 | int idx, s_idx; | ||
1179 | int ip_idx, s_ip_idx; | ||
1174 | struct net_device *dev; | 1180 | struct net_device *dev; |
1175 | struct in_device *in_dev; | 1181 | struct in_device *in_dev; |
1176 | struct in_ifaddr *ifa; | 1182 | struct in_ifaddr *ifa; |
1177 | int s_ip_idx, s_idx = cb->args[0]; | 1183 | struct hlist_head *head; |
1184 | struct hlist_node *node; | ||
1178 | 1185 | ||
1179 | s_ip_idx = ip_idx = cb->args[1]; | 1186 | s_h = cb->args[0]; |
1180 | idx = 0; | 1187 | s_idx = idx = cb->args[1]; |
1181 | for_each_netdev(net, dev) { | 1188 | s_ip_idx = ip_idx = cb->args[2]; |
1182 | if (idx < s_idx) | 1189 | |
1183 | goto cont; | 1190 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
1184 | if (idx > s_idx) | 1191 | idx = 0; |
1185 | s_ip_idx = 0; | 1192 | head = &net->dev_index_head[h]; |
1186 | if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) | 1193 | rcu_read_lock(); |
1187 | goto cont; | 1194 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { |
1188 | 1195 | if (idx < s_idx) | |
1189 | for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; | 1196 | goto cont; |
1190 | ifa = ifa->ifa_next, ip_idx++) { | 1197 | if (idx > s_idx) |
1191 | if (ip_idx < s_ip_idx) | 1198 | s_ip_idx = 0; |
1192 | continue; | 1199 | in_dev = __in_dev_get_rcu(dev); |
1193 | if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, | 1200 | if (!in_dev) |
1201 | goto cont; | ||
1202 | |||
1203 | for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; | ||
1204 | ifa = ifa->ifa_next, ip_idx++) { | ||
1205 | if (ip_idx < s_ip_idx) | ||
1206 | continue; | ||
1207 | if (inet_fill_ifaddr(skb, ifa, | ||
1208 | NETLINK_CB(cb->skb).pid, | ||
1194 | cb->nlh->nlmsg_seq, | 1209 | cb->nlh->nlmsg_seq, |
1195 | RTM_NEWADDR, NLM_F_MULTI) <= 0) | 1210 | RTM_NEWADDR, NLM_F_MULTI) <= 0) { |
1196 | goto done; | 1211 | rcu_read_unlock(); |
1197 | } | 1212 | goto done; |
1213 | } | ||
1214 | } | ||
1198 | cont: | 1215 | cont: |
1199 | idx++; | 1216 | idx++; |
1217 | } | ||
1218 | rcu_read_unlock(); | ||
1200 | } | 1219 | } |
1201 | 1220 | ||
1202 | done: | 1221 | done: |
1203 | cb->args[0] = idx; | 1222 | cb->args[0] = h; |
1204 | cb->args[1] = ip_idx; | 1223 | cb->args[1] = idx; |
1224 | cb->args[2] = ip_idx; | ||
1205 | 1225 | ||
1206 | return skb->len; | 1226 | return skb->len; |
1207 | } | 1227 | } |
@@ -1239,18 +1259,18 @@ static void devinet_copy_dflt_conf(struct net *net, int i) | |||
1239 | { | 1259 | { |
1240 | struct net_device *dev; | 1260 | struct net_device *dev; |
1241 | 1261 | ||
1242 | read_lock(&dev_base_lock); | 1262 | rcu_read_lock(); |
1243 | for_each_netdev(net, dev) { | 1263 | for_each_netdev_rcu(net, dev) { |
1244 | struct in_device *in_dev; | 1264 | struct in_device *in_dev; |
1245 | rcu_read_lock(); | 1265 | |
1246 | in_dev = __in_dev_get_rcu(dev); | 1266 | in_dev = __in_dev_get_rcu(dev); |
1247 | if (in_dev && !test_bit(i, in_dev->cnf.state)) | 1267 | if (in_dev && !test_bit(i, in_dev->cnf.state)) |
1248 | in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i]; | 1268 | in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i]; |
1249 | rcu_read_unlock(); | ||
1250 | } | 1269 | } |
1251 | read_unlock(&dev_base_lock); | 1270 | rcu_read_unlock(); |
1252 | } | 1271 | } |
1253 | 1272 | ||
1273 | /* called with RTNL locked */ | ||
1254 | static void inet_forward_change(struct net *net) | 1274 | static void inet_forward_change(struct net *net) |
1255 | { | 1275 | { |
1256 | struct net_device *dev; | 1276 | struct net_device *dev; |
@@ -1259,7 +1279,6 @@ static void inet_forward_change(struct net *net) | |||
1259 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; | 1279 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; |
1260 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; | 1280 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; |
1261 | 1281 | ||
1262 | read_lock(&dev_base_lock); | ||
1263 | for_each_netdev(net, dev) { | 1282 | for_each_netdev(net, dev) { |
1264 | struct in_device *in_dev; | 1283 | struct in_device *in_dev; |
1265 | if (on) | 1284 | if (on) |
@@ -1270,7 +1289,6 @@ static void inet_forward_change(struct net *net) | |||
1270 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); | 1289 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); |
1271 | rcu_read_unlock(); | 1290 | rcu_read_unlock(); |
1272 | } | 1291 | } |
1273 | read_unlock(&dev_base_lock); | ||
1274 | } | 1292 | } |
1275 | 1293 | ||
1276 | static int devinet_conf_proc(ctl_table *ctl, int write, | 1294 | static int devinet_conf_proc(ctl_table *ctl, int write, |
@@ -1293,58 +1311,6 @@ static int devinet_conf_proc(ctl_table *ctl, int write, | |||
1293 | return ret; | 1311 | return ret; |
1294 | } | 1312 | } |
1295 | 1313 | ||
1296 | static int devinet_conf_sysctl(ctl_table *table, | ||
1297 | void __user *oldval, size_t __user *oldlenp, | ||
1298 | void __user *newval, size_t newlen) | ||
1299 | { | ||
1300 | struct ipv4_devconf *cnf; | ||
1301 | struct net *net; | ||
1302 | int *valp = table->data; | ||
1303 | int new; | ||
1304 | int i; | ||
1305 | |||
1306 | if (!newval || !newlen) | ||
1307 | return 0; | ||
1308 | |||
1309 | if (newlen != sizeof(int)) | ||
1310 | return -EINVAL; | ||
1311 | |||
1312 | if (get_user(new, (int __user *)newval)) | ||
1313 | return -EFAULT; | ||
1314 | |||
1315 | if (new == *valp) | ||
1316 | return 0; | ||
1317 | |||
1318 | if (oldval && oldlenp) { | ||
1319 | size_t len; | ||
1320 | |||
1321 | if (get_user(len, oldlenp)) | ||
1322 | return -EFAULT; | ||
1323 | |||
1324 | if (len) { | ||
1325 | if (len > table->maxlen) | ||
1326 | len = table->maxlen; | ||
1327 | if (copy_to_user(oldval, valp, len)) | ||
1328 | return -EFAULT; | ||
1329 | if (put_user(len, oldlenp)) | ||
1330 | return -EFAULT; | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | *valp = new; | ||
1335 | |||
1336 | cnf = table->extra1; | ||
1337 | net = table->extra2; | ||
1338 | i = (int *)table->data - cnf->data; | ||
1339 | |||
1340 | set_bit(i, cnf->state); | ||
1341 | |||
1342 | if (cnf == net->ipv4.devconf_dflt) | ||
1343 | devinet_copy_dflt_conf(net, i); | ||
1344 | |||
1345 | return 1; | ||
1346 | } | ||
1347 | |||
1348 | static int devinet_sysctl_forward(ctl_table *ctl, int write, | 1314 | static int devinet_sysctl_forward(ctl_table *ctl, int write, |
1349 | void __user *buffer, | 1315 | void __user *buffer, |
1350 | size_t *lenp, loff_t *ppos) | 1316 | size_t *lenp, loff_t *ppos) |
@@ -1390,47 +1356,28 @@ int ipv4_doint_and_flush(ctl_table *ctl, int write, | |||
1390 | return ret; | 1356 | return ret; |
1391 | } | 1357 | } |
1392 | 1358 | ||
1393 | int ipv4_doint_and_flush_strategy(ctl_table *table, | 1359 | #define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc) \ |
1394 | void __user *oldval, size_t __user *oldlenp, | ||
1395 | void __user *newval, size_t newlen) | ||
1396 | { | ||
1397 | int ret = devinet_conf_sysctl(table, oldval, oldlenp, newval, newlen); | ||
1398 | struct net *net = table->extra2; | ||
1399 | |||
1400 | if (ret == 1) | ||
1401 | rt_cache_flush(net, 0); | ||
1402 | |||
1403 | return ret; | ||
1404 | } | ||
1405 | |||
1406 | |||
1407 | #define DEVINET_SYSCTL_ENTRY(attr, name, mval, proc, sysctl) \ | ||
1408 | { \ | 1360 | { \ |
1409 | .ctl_name = NET_IPV4_CONF_ ## attr, \ | ||
1410 | .procname = name, \ | 1361 | .procname = name, \ |
1411 | .data = ipv4_devconf.data + \ | 1362 | .data = ipv4_devconf.data + \ |
1412 | NET_IPV4_CONF_ ## attr - 1, \ | 1363 | NET_IPV4_CONF_ ## attr - 1, \ |
1413 | .maxlen = sizeof(int), \ | 1364 | .maxlen = sizeof(int), \ |
1414 | .mode = mval, \ | 1365 | .mode = mval, \ |
1415 | .proc_handler = proc, \ | 1366 | .proc_handler = proc, \ |
1416 | .strategy = sysctl, \ | ||
1417 | .extra1 = &ipv4_devconf, \ | 1367 | .extra1 = &ipv4_devconf, \ |
1418 | } | 1368 | } |
1419 | 1369 | ||
1420 | #define DEVINET_SYSCTL_RW_ENTRY(attr, name) \ | 1370 | #define DEVINET_SYSCTL_RW_ENTRY(attr, name) \ |
1421 | DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc, \ | 1371 | DEVINET_SYSCTL_ENTRY(attr, name, 0644, devinet_conf_proc) |
1422 | devinet_conf_sysctl) | ||
1423 | 1372 | ||
1424 | #define DEVINET_SYSCTL_RO_ENTRY(attr, name) \ | 1373 | #define DEVINET_SYSCTL_RO_ENTRY(attr, name) \ |
1425 | DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc, \ | 1374 | DEVINET_SYSCTL_ENTRY(attr, name, 0444, devinet_conf_proc) |
1426 | devinet_conf_sysctl) | ||
1427 | 1375 | ||
1428 | #define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc, sysctl) \ | 1376 | #define DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, proc) \ |
1429 | DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc, sysctl) | 1377 | DEVINET_SYSCTL_ENTRY(attr, name, 0644, proc) |
1430 | 1378 | ||
1431 | #define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \ | 1379 | #define DEVINET_SYSCTL_FLUSHING_ENTRY(attr, name) \ |
1432 | DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush, \ | 1380 | DEVINET_SYSCTL_COMPLEX_ENTRY(attr, name, ipv4_doint_and_flush) |
1433 | ipv4_doint_and_flush_strategy) | ||
1434 | 1381 | ||
1435 | static struct devinet_sysctl_table { | 1382 | static struct devinet_sysctl_table { |
1436 | struct ctl_table_header *sysctl_header; | 1383 | struct ctl_table_header *sysctl_header; |
@@ -1439,8 +1386,7 @@ static struct devinet_sysctl_table { | |||
1439 | } devinet_sysctl = { | 1386 | } devinet_sysctl = { |
1440 | .devinet_vars = { | 1387 | .devinet_vars = { |
1441 | DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding", | 1388 | DEVINET_SYSCTL_COMPLEX_ENTRY(FORWARDING, "forwarding", |
1442 | devinet_sysctl_forward, | 1389 | devinet_sysctl_forward), |
1443 | devinet_conf_sysctl), | ||
1444 | DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"), | 1390 | DEVINET_SYSCTL_RO_ENTRY(MC_FORWARDING, "mc_forwarding"), |
1445 | 1391 | ||
1446 | DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"), | 1392 | DEVINET_SYSCTL_RW_ENTRY(ACCEPT_REDIRECTS, "accept_redirects"), |
@@ -1450,6 +1396,7 @@ static struct devinet_sysctl_table { | |||
1450 | DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"), | 1396 | DEVINET_SYSCTL_RW_ENTRY(SEND_REDIRECTS, "send_redirects"), |
1451 | DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE, | 1397 | DEVINET_SYSCTL_RW_ENTRY(ACCEPT_SOURCE_ROUTE, |
1452 | "accept_source_route"), | 1398 | "accept_source_route"), |
1399 | DEVINET_SYSCTL_RW_ENTRY(ACCEPT_LOCAL, "accept_local"), | ||
1453 | DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"), | 1400 | DEVINET_SYSCTL_RW_ENTRY(PROXY_ARP, "proxy_arp"), |
1454 | DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"), | 1401 | DEVINET_SYSCTL_RW_ENTRY(MEDIUM_ID, "medium_id"), |
1455 | DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"), | 1402 | DEVINET_SYSCTL_RW_ENTRY(BOOTP_RELAY, "bootp_relay"), |
@@ -1471,7 +1418,7 @@ static struct devinet_sysctl_table { | |||
1471 | }; | 1418 | }; |
1472 | 1419 | ||
1473 | static int __devinet_sysctl_register(struct net *net, char *dev_name, | 1420 | static int __devinet_sysctl_register(struct net *net, char *dev_name, |
1474 | int ctl_name, struct ipv4_devconf *p) | 1421 | struct ipv4_devconf *p) |
1475 | { | 1422 | { |
1476 | int i; | 1423 | int i; |
1477 | struct devinet_sysctl_table *t; | 1424 | struct devinet_sysctl_table *t; |
@@ -1479,9 +1426,9 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, | |||
1479 | #define DEVINET_CTL_PATH_DEV 3 | 1426 | #define DEVINET_CTL_PATH_DEV 3 |
1480 | 1427 | ||
1481 | struct ctl_path devinet_ctl_path[] = { | 1428 | struct ctl_path devinet_ctl_path[] = { |
1482 | { .procname = "net", .ctl_name = CTL_NET, }, | 1429 | { .procname = "net", }, |
1483 | { .procname = "ipv4", .ctl_name = NET_IPV4, }, | 1430 | { .procname = "ipv4", }, |
1484 | { .procname = "conf", .ctl_name = NET_IPV4_CONF, }, | 1431 | { .procname = "conf", }, |
1485 | { /* to be set */ }, | 1432 | { /* to be set */ }, |
1486 | { }, | 1433 | { }, |
1487 | }; | 1434 | }; |
@@ -1506,7 +1453,6 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, | |||
1506 | goto free; | 1453 | goto free; |
1507 | 1454 | ||
1508 | devinet_ctl_path[DEVINET_CTL_PATH_DEV].procname = t->dev_name; | 1455 | devinet_ctl_path[DEVINET_CTL_PATH_DEV].procname = t->dev_name; |
1509 | devinet_ctl_path[DEVINET_CTL_PATH_DEV].ctl_name = ctl_name; | ||
1510 | 1456 | ||
1511 | t->sysctl_header = register_net_sysctl_table(net, devinet_ctl_path, | 1457 | t->sysctl_header = register_net_sysctl_table(net, devinet_ctl_path, |
1512 | t->devinet_vars); | 1458 | t->devinet_vars); |
@@ -1540,9 +1486,9 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | |||
1540 | static void devinet_sysctl_register(struct in_device *idev) | 1486 | static void devinet_sysctl_register(struct in_device *idev) |
1541 | { | 1487 | { |
1542 | neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4, | 1488 | neigh_sysctl_register(idev->dev, idev->arp_parms, NET_IPV4, |
1543 | NET_IPV4_NEIGH, "ipv4", NULL, NULL); | 1489 | NET_IPV4_NEIGH, "ipv4", NULL); |
1544 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, | 1490 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, |
1545 | idev->dev->ifindex, &idev->cnf); | 1491 | &idev->cnf); |
1546 | } | 1492 | } |
1547 | 1493 | ||
1548 | static void devinet_sysctl_unregister(struct in_device *idev) | 1494 | static void devinet_sysctl_unregister(struct in_device *idev) |
@@ -1553,14 +1499,12 @@ static void devinet_sysctl_unregister(struct in_device *idev) | |||
1553 | 1499 | ||
1554 | static struct ctl_table ctl_forward_entry[] = { | 1500 | static struct ctl_table ctl_forward_entry[] = { |
1555 | { | 1501 | { |
1556 | .ctl_name = NET_IPV4_FORWARD, | ||
1557 | .procname = "ip_forward", | 1502 | .procname = "ip_forward", |
1558 | .data = &ipv4_devconf.data[ | 1503 | .data = &ipv4_devconf.data[ |
1559 | NET_IPV4_CONF_FORWARDING - 1], | 1504 | NET_IPV4_CONF_FORWARDING - 1], |
1560 | .maxlen = sizeof(int), | 1505 | .maxlen = sizeof(int), |
1561 | .mode = 0644, | 1506 | .mode = 0644, |
1562 | .proc_handler = devinet_sysctl_forward, | 1507 | .proc_handler = devinet_sysctl_forward, |
1563 | .strategy = devinet_conf_sysctl, | ||
1564 | .extra1 = &ipv4_devconf, | 1508 | .extra1 = &ipv4_devconf, |
1565 | .extra2 = &init_net, | 1509 | .extra2 = &init_net, |
1566 | }, | 1510 | }, |
@@ -1568,8 +1512,8 @@ static struct ctl_table ctl_forward_entry[] = { | |||
1568 | }; | 1512 | }; |
1569 | 1513 | ||
1570 | static __net_initdata struct ctl_path net_ipv4_path[] = { | 1514 | static __net_initdata struct ctl_path net_ipv4_path[] = { |
1571 | { .procname = "net", .ctl_name = CTL_NET, }, | 1515 | { .procname = "net", }, |
1572 | { .procname = "ipv4", .ctl_name = NET_IPV4, }, | 1516 | { .procname = "ipv4", }, |
1573 | { }, | 1517 | { }, |
1574 | }; | 1518 | }; |
1575 | #endif | 1519 | #endif |
@@ -1587,7 +1531,7 @@ static __net_init int devinet_init_net(struct net *net) | |||
1587 | all = &ipv4_devconf; | 1531 | all = &ipv4_devconf; |
1588 | dflt = &ipv4_devconf_dflt; | 1532 | dflt = &ipv4_devconf_dflt; |
1589 | 1533 | ||
1590 | if (net != &init_net) { | 1534 | if (!net_eq(net, &init_net)) { |
1591 | all = kmemdup(all, sizeof(ipv4_devconf), GFP_KERNEL); | 1535 | all = kmemdup(all, sizeof(ipv4_devconf), GFP_KERNEL); |
1592 | if (all == NULL) | 1536 | if (all == NULL) |
1593 | goto err_alloc_all; | 1537 | goto err_alloc_all; |
@@ -1608,13 +1552,11 @@ static __net_init int devinet_init_net(struct net *net) | |||
1608 | } | 1552 | } |
1609 | 1553 | ||
1610 | #ifdef CONFIG_SYSCTL | 1554 | #ifdef CONFIG_SYSCTL |
1611 | err = __devinet_sysctl_register(net, "all", | 1555 | err = __devinet_sysctl_register(net, "all", all); |
1612 | NET_PROTO_CONF_ALL, all); | ||
1613 | if (err < 0) | 1556 | if (err < 0) |
1614 | goto err_reg_all; | 1557 | goto err_reg_all; |
1615 | 1558 | ||
1616 | err = __devinet_sysctl_register(net, "default", | 1559 | err = __devinet_sysctl_register(net, "default", dflt); |
1617 | NET_PROTO_CONF_DEFAULT, dflt); | ||
1618 | if (err < 0) | 1560 | if (err < 0) |
1619 | goto err_reg_dflt; | 1561 | goto err_reg_dflt; |
1620 | 1562 | ||
@@ -1680,8 +1622,3 @@ void __init devinet_init(void) | |||
1680 | rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr); | 1622 | rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr); |
1681 | } | 1623 | } |
1682 | 1624 | ||
1683 | EXPORT_SYMBOL(in_dev_finish_destroy); | ||
1684 | EXPORT_SYMBOL(inet_select_addr); | ||
1685 | EXPORT_SYMBOL(inetdev_by_index); | ||
1686 | EXPORT_SYMBOL(register_inetaddr_notifier); | ||
1687 | EXPORT_SYMBOL(unregister_inetaddr_notifier); | ||