diff options
Diffstat (limited to 'net/ipv4/devinet.c')
| -rw-r--r-- | net/ipv4/devinet.c | 275 |
1 files changed, 176 insertions, 99 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 54419b27686f..7602c79a389b 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | * if no match found. | 27 | * if no match found. |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <linux/config.h> | ||
| 31 | 30 | ||
| 32 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
| 33 | #include <asm/system.h> | 32 | #include <asm/system.h> |
| @@ -44,6 +43,7 @@ | |||
| 44 | #include <linux/in.h> | 43 | #include <linux/in.h> |
| 45 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
| 46 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
| 46 | #include <linux/if_addr.h> | ||
| 47 | #include <linux/if_ether.h> | 47 | #include <linux/if_ether.h> |
| 48 | #include <linux/inet.h> | 48 | #include <linux/inet.h> |
| 49 | #include <linux/netdevice.h> | 49 | #include <linux/netdevice.h> |
| @@ -63,6 +63,7 @@ | |||
| 63 | #include <net/ip.h> | 63 | #include <net/ip.h> |
| 64 | #include <net/route.h> | 64 | #include <net/route.h> |
| 65 | #include <net/ip_fib.h> | 65 | #include <net/ip_fib.h> |
| 66 | #include <net/netlink.h> | ||
| 66 | 67 | ||
| 67 | struct ipv4_devconf ipv4_devconf = { | 68 | struct ipv4_devconf ipv4_devconf = { |
| 68 | .accept_redirects = 1, | 69 | .accept_redirects = 1, |
| @@ -79,7 +80,15 @@ static struct ipv4_devconf ipv4_devconf_dflt = { | |||
| 79 | .accept_source_route = 1, | 80 | .accept_source_route = 1, |
| 80 | }; | 81 | }; |
| 81 | 82 | ||
| 82 | static void rtmsg_ifa(int event, struct in_ifaddr *); | 83 | static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = { |
| 84 | [IFA_LOCAL] = { .type = NLA_U32 }, | ||
| 85 | [IFA_ADDRESS] = { .type = NLA_U32 }, | ||
| 86 | [IFA_BROADCAST] = { .type = NLA_U32 }, | ||
| 87 | [IFA_ANYCAST] = { .type = NLA_U32 }, | ||
| 88 | [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, | ||
| 89 | }; | ||
| 90 | |||
| 91 | static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); | ||
| 83 | 92 | ||
| 84 | static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); | 93 | static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); |
| 85 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | 94 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, |
| @@ -94,10 +103,9 @@ static void devinet_sysctl_unregister(struct ipv4_devconf *p); | |||
| 94 | 103 | ||
| 95 | static struct in_ifaddr *inet_alloc_ifa(void) | 104 | static struct in_ifaddr *inet_alloc_ifa(void) |
| 96 | { | 105 | { |
| 97 | struct in_ifaddr *ifa = kmalloc(sizeof(*ifa), GFP_KERNEL); | 106 | struct in_ifaddr *ifa = kzalloc(sizeof(*ifa), GFP_KERNEL); |
| 98 | 107 | ||
| 99 | if (ifa) { | 108 | if (ifa) { |
| 100 | memset(ifa, 0, sizeof(*ifa)); | ||
| 101 | INIT_RCU_HEAD(&ifa->rcu_head); | 109 | INIT_RCU_HEAD(&ifa->rcu_head); |
| 102 | } | 110 | } |
| 103 | 111 | ||
| @@ -141,10 +149,9 @@ struct in_device *inetdev_init(struct net_device *dev) | |||
| 141 | 149 | ||
| 142 | ASSERT_RTNL(); | 150 | ASSERT_RTNL(); |
| 143 | 151 | ||
| 144 | in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL); | 152 | in_dev = kzalloc(sizeof(*in_dev), GFP_KERNEL); |
| 145 | if (!in_dev) | 153 | if (!in_dev) |
| 146 | goto out; | 154 | goto out; |
| 147 | memset(in_dev, 0, sizeof(*in_dev)); | ||
| 148 | INIT_RCU_HEAD(&in_dev->rcu_head); | 155 | INIT_RCU_HEAD(&in_dev->rcu_head); |
| 149 | memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf)); | 156 | memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf)); |
| 150 | in_dev->cnf.sysctl = NULL; | 157 | in_dev->cnf.sysctl = NULL; |
| @@ -217,7 +224,7 @@ static void inetdev_destroy(struct in_device *in_dev) | |||
| 217 | call_rcu(&in_dev->rcu_head, in_dev_rcu_put); | 224 | call_rcu(&in_dev->rcu_head, in_dev_rcu_put); |
| 218 | } | 225 | } |
| 219 | 226 | ||
| 220 | int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b) | 227 | int inet_addr_onlink(struct in_device *in_dev, __be32 a, __be32 b) |
| 221 | { | 228 | { |
| 222 | rcu_read_lock(); | 229 | rcu_read_lock(); |
| 223 | for_primary_ifa(in_dev) { | 230 | for_primary_ifa(in_dev) { |
| @@ -232,8 +239,8 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b) | |||
| 232 | return 0; | 239 | return 0; |
| 233 | } | 240 | } |
| 234 | 241 | ||
| 235 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | 242 | static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, |
| 236 | int destroy) | 243 | int destroy, struct nlmsghdr *nlh, u32 pid) |
| 237 | { | 244 | { |
| 238 | struct in_ifaddr *promote = NULL; | 245 | struct in_ifaddr *promote = NULL; |
| 239 | struct in_ifaddr *ifa, *ifa1 = *ifap; | 246 | struct in_ifaddr *ifa, *ifa1 = *ifap; |
| @@ -266,7 +273,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
| 266 | if (!do_promote) { | 273 | if (!do_promote) { |
| 267 | *ifap1 = ifa->ifa_next; | 274 | *ifap1 = ifa->ifa_next; |
| 268 | 275 | ||
| 269 | rtmsg_ifa(RTM_DELADDR, ifa); | 276 | rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid); |
| 270 | blocking_notifier_call_chain(&inetaddr_chain, | 277 | blocking_notifier_call_chain(&inetaddr_chain, |
| 271 | NETDEV_DOWN, ifa); | 278 | NETDEV_DOWN, ifa); |
| 272 | inet_free_ifa(ifa); | 279 | inet_free_ifa(ifa); |
| @@ -291,7 +298,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
| 291 | is valid, it will try to restore deleted routes... Grr. | 298 | is valid, it will try to restore deleted routes... Grr. |
| 292 | So that, this order is correct. | 299 | So that, this order is correct. |
| 293 | */ | 300 | */ |
| 294 | rtmsg_ifa(RTM_DELADDR, ifa1); | 301 | rtmsg_ifa(RTM_DELADDR, ifa1, nlh, pid); |
| 295 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); | 302 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); |
| 296 | 303 | ||
| 297 | if (promote) { | 304 | if (promote) { |
| @@ -303,7 +310,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
| 303 | } | 310 | } |
| 304 | 311 | ||
| 305 | promote->ifa_flags &= ~IFA_F_SECONDARY; | 312 | promote->ifa_flags &= ~IFA_F_SECONDARY; |
| 306 | rtmsg_ifa(RTM_NEWADDR, promote); | 313 | rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid); |
| 307 | blocking_notifier_call_chain(&inetaddr_chain, | 314 | blocking_notifier_call_chain(&inetaddr_chain, |
| 308 | NETDEV_UP, promote); | 315 | NETDEV_UP, promote); |
| 309 | for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { | 316 | for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { |
| @@ -322,7 +329,14 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
| 322 | } | 329 | } |
| 323 | } | 330 | } |
| 324 | 331 | ||
| 325 | static int inet_insert_ifa(struct in_ifaddr *ifa) | 332 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, |
| 333 | int destroy) | ||
| 334 | { | ||
| 335 | __inet_del_ifa(in_dev, ifap, destroy, NULL, 0); | ||
| 336 | } | ||
| 337 | |||
| 338 | static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, | ||
| 339 | u32 pid) | ||
| 326 | { | 340 | { |
| 327 | struct in_device *in_dev = ifa->ifa_dev; | 341 | struct in_device *in_dev = ifa->ifa_dev; |
| 328 | struct in_ifaddr *ifa1, **ifap, **last_primary; | 342 | struct in_ifaddr *ifa1, **ifap, **last_primary; |
| @@ -367,12 +381,17 @@ static int inet_insert_ifa(struct in_ifaddr *ifa) | |||
| 367 | /* Send message first, then call notifier. | 381 | /* Send message first, then call notifier. |
| 368 | Notifier will trigger FIB update, so that | 382 | Notifier will trigger FIB update, so that |
| 369 | listeners of netlink will know about new ifaddr */ | 383 | listeners of netlink will know about new ifaddr */ |
| 370 | rtmsg_ifa(RTM_NEWADDR, ifa); | 384 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, pid); |
| 371 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); | 385 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); |
| 372 | 386 | ||
| 373 | return 0; | 387 | return 0; |
| 374 | } | 388 | } |
| 375 | 389 | ||
| 390 | static int inet_insert_ifa(struct in_ifaddr *ifa) | ||
| 391 | { | ||
| 392 | return __inet_insert_ifa(ifa, NULL, 0); | ||
| 393 | } | ||
| 394 | |||
| 376 | static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) | 395 | static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) |
| 377 | { | 396 | { |
| 378 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 397 | struct in_device *in_dev = __in_dev_get_rtnl(dev); |
| @@ -410,8 +429,8 @@ struct in_device *inetdev_by_index(int ifindex) | |||
| 410 | 429 | ||
| 411 | /* Called only from RTNL semaphored context. No locks. */ | 430 | /* Called only from RTNL semaphored context. No locks. */ |
| 412 | 431 | ||
| 413 | struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, | 432 | struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, __be32 prefix, |
| 414 | u32 mask) | 433 | __be32 mask) |
| 415 | { | 434 | { |
| 416 | ASSERT_RTNL(); | 435 | ASSERT_RTNL(); |
| 417 | 436 | ||
| @@ -424,87 +443,134 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, | |||
| 424 | 443 | ||
| 425 | static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 444 | static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
| 426 | { | 445 | { |
| 427 | struct rtattr **rta = arg; | 446 | struct nlattr *tb[IFA_MAX+1]; |
| 428 | struct in_device *in_dev; | 447 | struct in_device *in_dev; |
| 429 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); | 448 | struct ifaddrmsg *ifm; |
| 430 | struct in_ifaddr *ifa, **ifap; | 449 | struct in_ifaddr *ifa, **ifap; |
| 450 | int err = -EINVAL; | ||
| 431 | 451 | ||
| 432 | ASSERT_RTNL(); | 452 | ASSERT_RTNL(); |
| 433 | 453 | ||
| 434 | if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL) | 454 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); |
| 435 | goto out; | 455 | if (err < 0) |
| 456 | goto errout; | ||
| 457 | |||
| 458 | ifm = nlmsg_data(nlh); | ||
| 459 | in_dev = inetdev_by_index(ifm->ifa_index); | ||
| 460 | if (in_dev == NULL) { | ||
| 461 | err = -ENODEV; | ||
| 462 | goto errout; | ||
| 463 | } | ||
| 464 | |||
| 436 | __in_dev_put(in_dev); | 465 | __in_dev_put(in_dev); |
| 437 | 466 | ||
| 438 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; | 467 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; |
| 439 | ifap = &ifa->ifa_next) { | 468 | ifap = &ifa->ifa_next) { |
| 440 | if ((rta[IFA_LOCAL - 1] && | 469 | if (tb[IFA_LOCAL] && |
| 441 | memcmp(RTA_DATA(rta[IFA_LOCAL - 1]), | 470 | ifa->ifa_local != nla_get_be32(tb[IFA_LOCAL])) |
| 442 | &ifa->ifa_local, 4)) || | 471 | continue; |
| 443 | (rta[IFA_LABEL - 1] && | 472 | |
| 444 | rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) || | 473 | if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label)) |
| 445 | (rta[IFA_ADDRESS - 1] && | 474 | continue; |
| 446 | (ifm->ifa_prefixlen != ifa->ifa_prefixlen || | 475 | |
| 447 | !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]), | 476 | if (tb[IFA_ADDRESS] && |
| 448 | ifa)))) | 477 | (ifm->ifa_prefixlen != ifa->ifa_prefixlen || |
| 478 | !inet_ifa_match(nla_get_be32(tb[IFA_ADDRESS]), ifa))) | ||
| 449 | continue; | 479 | continue; |
| 450 | inet_del_ifa(in_dev, ifap, 1); | 480 | |
| 481 | __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid); | ||
| 451 | return 0; | 482 | return 0; |
| 452 | } | 483 | } |
| 453 | out: | 484 | |
| 454 | return -EADDRNOTAVAIL; | 485 | err = -EADDRNOTAVAIL; |
| 486 | errout: | ||
| 487 | return err; | ||
| 455 | } | 488 | } |
| 456 | 489 | ||
| 457 | static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 490 | static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) |
| 458 | { | 491 | { |
| 459 | struct rtattr **rta = arg; | 492 | struct nlattr *tb[IFA_MAX+1]; |
| 493 | struct in_ifaddr *ifa; | ||
| 494 | struct ifaddrmsg *ifm; | ||
| 460 | struct net_device *dev; | 495 | struct net_device *dev; |
| 461 | struct in_device *in_dev; | 496 | struct in_device *in_dev; |
| 462 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); | 497 | int err = -EINVAL; |
| 463 | struct in_ifaddr *ifa; | ||
| 464 | int rc = -EINVAL; | ||
| 465 | 498 | ||
| 466 | ASSERT_RTNL(); | 499 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); |
| 500 | if (err < 0) | ||
| 501 | goto errout; | ||
| 467 | 502 | ||
| 468 | if (ifm->ifa_prefixlen > 32 || !rta[IFA_LOCAL - 1]) | 503 | ifm = nlmsg_data(nlh); |
| 469 | goto out; | 504 | if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) |
| 505 | goto errout; | ||
| 470 | 506 | ||
| 471 | rc = -ENODEV; | 507 | dev = __dev_get_by_index(ifm->ifa_index); |
| 472 | if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL) | 508 | if (dev == NULL) { |
| 473 | goto out; | 509 | err = -ENODEV; |
| 510 | goto errout; | ||
| 511 | } | ||
| 474 | 512 | ||
| 475 | rc = -ENOBUFS; | 513 | in_dev = __in_dev_get_rtnl(dev); |
| 476 | if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) { | 514 | if (in_dev == NULL) { |
| 477 | in_dev = inetdev_init(dev); | 515 | in_dev = inetdev_init(dev); |
| 478 | if (!in_dev) | 516 | if (in_dev == NULL) { |
| 479 | goto out; | 517 | err = -ENOBUFS; |
| 518 | goto errout; | ||
| 519 | } | ||
| 480 | } | 520 | } |
| 481 | 521 | ||
| 482 | if ((ifa = inet_alloc_ifa()) == NULL) | 522 | ifa = inet_alloc_ifa(); |
| 483 | goto out; | 523 | if (ifa == NULL) { |
| 524 | /* | ||
| 525 | * A potential indev allocation can be left alive, it stays | ||
| 526 | * assigned to its device and is destroy with it. | ||
| 527 | */ | ||
| 528 | err = -ENOBUFS; | ||
| 529 | goto errout; | ||
| 530 | } | ||
| 531 | |||
| 532 | in_dev_hold(in_dev); | ||
| 533 | |||
| 534 | if (tb[IFA_ADDRESS] == NULL) | ||
| 535 | tb[IFA_ADDRESS] = tb[IFA_LOCAL]; | ||
| 484 | 536 | ||
| 485 | if (!rta[IFA_ADDRESS - 1]) | ||
| 486 | rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1]; | ||
| 487 | memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL - 1]), 4); | ||
| 488 | memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS - 1]), 4); | ||
| 489 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; | 537 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; |
| 490 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); | 538 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); |
| 491 | if (rta[IFA_BROADCAST - 1]) | ||
| 492 | memcpy(&ifa->ifa_broadcast, | ||
| 493 | RTA_DATA(rta[IFA_BROADCAST - 1]), 4); | ||
| 494 | if (rta[IFA_ANYCAST - 1]) | ||
| 495 | memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST - 1]), 4); | ||
| 496 | ifa->ifa_flags = ifm->ifa_flags; | 539 | ifa->ifa_flags = ifm->ifa_flags; |
| 497 | ifa->ifa_scope = ifm->ifa_scope; | 540 | ifa->ifa_scope = ifm->ifa_scope; |
| 498 | in_dev_hold(in_dev); | 541 | ifa->ifa_dev = in_dev; |
| 499 | ifa->ifa_dev = in_dev; | 542 | |
| 500 | if (rta[IFA_LABEL - 1]) | 543 | ifa->ifa_local = nla_get_be32(tb[IFA_LOCAL]); |
| 501 | rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ); | 544 | ifa->ifa_address = nla_get_be32(tb[IFA_ADDRESS]); |
| 545 | |||
| 546 | if (tb[IFA_BROADCAST]) | ||
| 547 | ifa->ifa_broadcast = nla_get_be32(tb[IFA_BROADCAST]); | ||
| 548 | |||
| 549 | if (tb[IFA_ANYCAST]) | ||
| 550 | ifa->ifa_anycast = nla_get_be32(tb[IFA_ANYCAST]); | ||
| 551 | |||
| 552 | if (tb[IFA_LABEL]) | ||
| 553 | nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ); | ||
| 502 | else | 554 | else |
| 503 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); | 555 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); |
| 504 | 556 | ||
| 505 | rc = inet_insert_ifa(ifa); | 557 | return ifa; |
| 506 | out: | 558 | |
| 507 | return rc; | 559 | errout: |
| 560 | return ERR_PTR(err); | ||
| 561 | } | ||
| 562 | |||
| 563 | static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
| 564 | { | ||
| 565 | struct in_ifaddr *ifa; | ||
| 566 | |||
| 567 | ASSERT_RTNL(); | ||
| 568 | |||
| 569 | ifa = rtm_to_ifaddr(nlh); | ||
| 570 | if (IS_ERR(ifa)) | ||
| 571 | return PTR_ERR(ifa); | ||
| 572 | |||
| 573 | return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).pid); | ||
| 508 | } | 574 | } |
| 509 | 575 | ||
| 510 | /* | 576 | /* |
| @@ -739,7 +805,7 @@ int devinet_ioctl(unsigned int cmd, void __user *arg) | |||
| 739 | break; | 805 | break; |
| 740 | ret = 0; | 806 | ret = 0; |
| 741 | if (ifa->ifa_mask != sin->sin_addr.s_addr) { | 807 | if (ifa->ifa_mask != sin->sin_addr.s_addr) { |
| 742 | u32 old_mask = ifa->ifa_mask; | 808 | __be32 old_mask = ifa->ifa_mask; |
| 743 | inet_del_ifa(in_dev, ifap, 0); | 809 | inet_del_ifa(in_dev, ifap, 0); |
| 744 | ifa->ifa_mask = sin->sin_addr.s_addr; | 810 | ifa->ifa_mask = sin->sin_addr.s_addr; |
| 745 | ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); | 811 | ifa->ifa_prefixlen = inet_mask_len(ifa->ifa_mask); |
| @@ -810,9 +876,9 @@ out: | |||
| 810 | return done; | 876 | return done; |
| 811 | } | 877 | } |
| 812 | 878 | ||
| 813 | u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope) | 879 | __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) |
| 814 | { | 880 | { |
| 815 | u32 addr = 0; | 881 | __be32 addr = 0; |
| 816 | struct in_device *in_dev; | 882 | struct in_device *in_dev; |
| 817 | 883 | ||
| 818 | rcu_read_lock(); | 884 | rcu_read_lock(); |
| @@ -861,11 +927,11 @@ out: | |||
| 861 | return addr; | 927 | return addr; |
| 862 | } | 928 | } |
| 863 | 929 | ||
| 864 | static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst, | 930 | static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, |
| 865 | u32 local, int scope) | 931 | __be32 local, int scope) |
| 866 | { | 932 | { |
| 867 | int same = 0; | 933 | int same = 0; |
| 868 | u32 addr = 0; | 934 | __be32 addr = 0; |
| 869 | 935 | ||
| 870 | for_ifa(in_dev) { | 936 | for_ifa(in_dev) { |
| 871 | if (!addr && | 937 | if (!addr && |
| @@ -905,9 +971,9 @@ static u32 confirm_addr_indev(struct in_device *in_dev, u32 dst, | |||
| 905 | * - local: address, 0=autoselect the local address | 971 | * - local: address, 0=autoselect the local address |
| 906 | * - scope: maximum allowed scope value for the local address | 972 | * - scope: maximum allowed scope value for the local address |
| 907 | */ | 973 | */ |
| 908 | u32 inet_confirm_addr(const struct net_device *dev, u32 dst, u32 local, int scope) | 974 | __be32 inet_confirm_addr(const struct net_device *dev, __be32 dst, __be32 local, int scope) |
| 909 | { | 975 | { |
| 910 | u32 addr = 0; | 976 | __be32 addr = 0; |
| 911 | struct in_device *in_dev; | 977 | struct in_device *in_dev; |
| 912 | 978 | ||
| 913 | if (dev) { | 979 | if (dev) { |
| @@ -1059,32 +1125,37 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, | |||
| 1059 | { | 1125 | { |
| 1060 | struct ifaddrmsg *ifm; | 1126 | struct ifaddrmsg *ifm; |
| 1061 | struct nlmsghdr *nlh; | 1127 | struct nlmsghdr *nlh; |
| 1062 | unsigned char *b = skb->tail; | ||
| 1063 | 1128 | ||
| 1064 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); | 1129 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags); |
| 1065 | ifm = NLMSG_DATA(nlh); | 1130 | if (nlh == NULL) |
| 1131 | return -ENOBUFS; | ||
| 1132 | |||
| 1133 | ifm = nlmsg_data(nlh); | ||
| 1066 | ifm->ifa_family = AF_INET; | 1134 | ifm->ifa_family = AF_INET; |
| 1067 | ifm->ifa_prefixlen = ifa->ifa_prefixlen; | 1135 | ifm->ifa_prefixlen = ifa->ifa_prefixlen; |
| 1068 | ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT; | 1136 | ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT; |
| 1069 | ifm->ifa_scope = ifa->ifa_scope; | 1137 | ifm->ifa_scope = ifa->ifa_scope; |
| 1070 | ifm->ifa_index = ifa->ifa_dev->dev->ifindex; | 1138 | ifm->ifa_index = ifa->ifa_dev->dev->ifindex; |
| 1139 | |||
| 1071 | if (ifa->ifa_address) | 1140 | if (ifa->ifa_address) |
| 1072 | RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address); | 1141 | NLA_PUT_BE32(skb, IFA_ADDRESS, ifa->ifa_address); |
| 1142 | |||
| 1073 | if (ifa->ifa_local) | 1143 | if (ifa->ifa_local) |
| 1074 | RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local); | 1144 | NLA_PUT_BE32(skb, IFA_LOCAL, ifa->ifa_local); |
| 1145 | |||
| 1075 | if (ifa->ifa_broadcast) | 1146 | if (ifa->ifa_broadcast) |
| 1076 | RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast); | 1147 | NLA_PUT_BE32(skb, IFA_BROADCAST, ifa->ifa_broadcast); |
| 1148 | |||
| 1077 | if (ifa->ifa_anycast) | 1149 | if (ifa->ifa_anycast) |
| 1078 | RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast); | 1150 | NLA_PUT_BE32(skb, IFA_ANYCAST, ifa->ifa_anycast); |
| 1151 | |||
| 1079 | if (ifa->ifa_label[0]) | 1152 | if (ifa->ifa_label[0]) |
| 1080 | RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label); | 1153 | NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label); |
| 1081 | nlh->nlmsg_len = skb->tail - b; | ||
| 1082 | return skb->len; | ||
| 1083 | 1154 | ||
| 1084 | nlmsg_failure: | 1155 | return nlmsg_end(skb, nlh); |
| 1085 | rtattr_failure: | 1156 | |
| 1086 | skb_trim(skb, b - skb->data); | 1157 | nla_put_failure: |
| 1087 | return -1; | 1158 | return nlmsg_cancel(skb, nlh); |
| 1088 | } | 1159 | } |
| 1089 | 1160 | ||
| 1090 | static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | 1161 | static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) |
| @@ -1130,19 +1201,27 @@ done: | |||
| 1130 | return skb->len; | 1201 | return skb->len; |
| 1131 | } | 1202 | } |
| 1132 | 1203 | ||
| 1133 | static void rtmsg_ifa(int event, struct in_ifaddr* ifa) | 1204 | static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh, |
| 1205 | u32 pid) | ||
| 1134 | { | 1206 | { |
| 1135 | int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128); | 1207 | struct sk_buff *skb; |
| 1136 | struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); | 1208 | u32 seq = nlh ? nlh->nlmsg_seq : 0; |
| 1209 | int err = -ENOBUFS; | ||
| 1210 | |||
| 1211 | skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
| 1212 | if (skb == NULL) | ||
| 1213 | goto errout; | ||
| 1137 | 1214 | ||
| 1138 | if (!skb) | 1215 | err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); |
| 1139 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); | 1216 | if (err < 0) { |
| 1140 | else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { | ||
| 1141 | kfree_skb(skb); | 1217 | kfree_skb(skb); |
| 1142 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); | 1218 | goto errout; |
| 1143 | } else { | ||
| 1144 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL); | ||
| 1145 | } | 1219 | } |
| 1220 | |||
| 1221 | err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); | ||
| 1222 | errout: | ||
| 1223 | if (err < 0) | ||
| 1224 | rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err); | ||
| 1146 | } | 1225 | } |
| 1147 | 1226 | ||
| 1148 | static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { | 1227 | static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { |
| @@ -1154,9 +1233,7 @@ static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { | |||
| 1154 | [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute, | 1233 | [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute, |
| 1155 | .dumpit = inet_dump_fib, }, | 1234 | .dumpit = inet_dump_fib, }, |
| 1156 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 1235 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
| 1157 | [RTM_NEWRULE - RTM_BASE] = { .doit = inet_rtm_newrule, }, | 1236 | [RTM_GETRULE - RTM_BASE] = { .dumpit = fib4_rules_dump, }, |
| 1158 | [RTM_DELRULE - RTM_BASE] = { .doit = inet_rtm_delrule, }, | ||
| 1159 | [RTM_GETRULE - RTM_BASE] = { .dumpit = inet_dump_rules, }, | ||
| 1160 | #endif | 1237 | #endif |
| 1161 | }; | 1238 | }; |
| 1162 | 1239 | ||
