diff options
Diffstat (limited to 'net/ipv4/devinet.c')
-rw-r--r-- | net/ipv4/devinet.c | 246 |
1 files changed, 163 insertions, 83 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index a6cc31d911eb..8e8d1f17d77a 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/in.h> | 43 | #include <linux/in.h> |
44 | #include <linux/errno.h> | 44 | #include <linux/errno.h> |
45 | #include <linux/interrupt.h> | 45 | #include <linux/interrupt.h> |
46 | #include <linux/if_addr.h> | ||
46 | #include <linux/if_ether.h> | 47 | #include <linux/if_ether.h> |
47 | #include <linux/inet.h> | 48 | #include <linux/inet.h> |
48 | #include <linux/netdevice.h> | 49 | #include <linux/netdevice.h> |
@@ -62,6 +63,7 @@ | |||
62 | #include <net/ip.h> | 63 | #include <net/ip.h> |
63 | #include <net/route.h> | 64 | #include <net/route.h> |
64 | #include <net/ip_fib.h> | 65 | #include <net/ip_fib.h> |
66 | #include <net/netlink.h> | ||
65 | 67 | ||
66 | struct ipv4_devconf ipv4_devconf = { | 68 | struct ipv4_devconf ipv4_devconf = { |
67 | .accept_redirects = 1, | 69 | .accept_redirects = 1, |
@@ -78,7 +80,15 @@ static struct ipv4_devconf ipv4_devconf_dflt = { | |||
78 | .accept_source_route = 1, | 80 | .accept_source_route = 1, |
79 | }; | 81 | }; |
80 | 82 | ||
81 | 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); | ||
82 | 92 | ||
83 | static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); | 93 | static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); |
84 | 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, |
@@ -229,8 +239,8 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b) | |||
229 | return 0; | 239 | return 0; |
230 | } | 240 | } |
231 | 241 | ||
232 | 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, |
233 | int destroy) | 243 | int destroy, struct nlmsghdr *nlh, u32 pid) |
234 | { | 244 | { |
235 | struct in_ifaddr *promote = NULL; | 245 | struct in_ifaddr *promote = NULL; |
236 | struct in_ifaddr *ifa, *ifa1 = *ifap; | 246 | struct in_ifaddr *ifa, *ifa1 = *ifap; |
@@ -263,7 +273,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
263 | if (!do_promote) { | 273 | if (!do_promote) { |
264 | *ifap1 = ifa->ifa_next; | 274 | *ifap1 = ifa->ifa_next; |
265 | 275 | ||
266 | rtmsg_ifa(RTM_DELADDR, ifa); | 276 | rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid); |
267 | blocking_notifier_call_chain(&inetaddr_chain, | 277 | blocking_notifier_call_chain(&inetaddr_chain, |
268 | NETDEV_DOWN, ifa); | 278 | NETDEV_DOWN, ifa); |
269 | inet_free_ifa(ifa); | 279 | inet_free_ifa(ifa); |
@@ -288,7 +298,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
288 | is valid, it will try to restore deleted routes... Grr. | 298 | is valid, it will try to restore deleted routes... Grr. |
289 | So that, this order is correct. | 299 | So that, this order is correct. |
290 | */ | 300 | */ |
291 | rtmsg_ifa(RTM_DELADDR, ifa1); | 301 | rtmsg_ifa(RTM_DELADDR, ifa1, nlh, pid); |
292 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); | 302 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); |
293 | 303 | ||
294 | if (promote) { | 304 | if (promote) { |
@@ -300,7 +310,7 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
300 | } | 310 | } |
301 | 311 | ||
302 | promote->ifa_flags &= ~IFA_F_SECONDARY; | 312 | promote->ifa_flags &= ~IFA_F_SECONDARY; |
303 | rtmsg_ifa(RTM_NEWADDR, promote); | 313 | rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid); |
304 | blocking_notifier_call_chain(&inetaddr_chain, | 314 | blocking_notifier_call_chain(&inetaddr_chain, |
305 | NETDEV_UP, promote); | 315 | NETDEV_UP, promote); |
306 | for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { | 316 | for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { |
@@ -319,7 +329,14 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
319 | } | 329 | } |
320 | } | 330 | } |
321 | 331 | ||
322 | 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) | ||
323 | { | 340 | { |
324 | struct in_device *in_dev = ifa->ifa_dev; | 341 | struct in_device *in_dev = ifa->ifa_dev; |
325 | struct in_ifaddr *ifa1, **ifap, **last_primary; | 342 | struct in_ifaddr *ifa1, **ifap, **last_primary; |
@@ -364,12 +381,17 @@ static int inet_insert_ifa(struct in_ifaddr *ifa) | |||
364 | /* Send message first, then call notifier. | 381 | /* Send message first, then call notifier. |
365 | Notifier will trigger FIB update, so that | 382 | Notifier will trigger FIB update, so that |
366 | listeners of netlink will know about new ifaddr */ | 383 | listeners of netlink will know about new ifaddr */ |
367 | rtmsg_ifa(RTM_NEWADDR, ifa); | 384 | rtmsg_ifa(RTM_NEWADDR, ifa, nlh, pid); |
368 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); | 385 | blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); |
369 | 386 | ||
370 | return 0; | 387 | return 0; |
371 | } | 388 | } |
372 | 389 | ||
390 | static int inet_insert_ifa(struct in_ifaddr *ifa) | ||
391 | { | ||
392 | return __inet_insert_ifa(ifa, NULL, 0); | ||
393 | } | ||
394 | |||
373 | 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) |
374 | { | 396 | { |
375 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 397 | struct in_device *in_dev = __in_dev_get_rtnl(dev); |
@@ -421,87 +443,134 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, | |||
421 | 443 | ||
422 | 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) |
423 | { | 445 | { |
424 | struct rtattr **rta = arg; | 446 | struct nlattr *tb[IFA_MAX+1]; |
425 | struct in_device *in_dev; | 447 | struct in_device *in_dev; |
426 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); | 448 | struct ifaddrmsg *ifm; |
427 | struct in_ifaddr *ifa, **ifap; | 449 | struct in_ifaddr *ifa, **ifap; |
450 | int err = -EINVAL; | ||
428 | 451 | ||
429 | ASSERT_RTNL(); | 452 | ASSERT_RTNL(); |
430 | 453 | ||
431 | if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL) | 454 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); |
432 | 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 | |||
433 | __in_dev_put(in_dev); | 465 | __in_dev_put(in_dev); |
434 | 466 | ||
435 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; | 467 | for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; |
436 | ifap = &ifa->ifa_next) { | 468 | ifap = &ifa->ifa_next) { |
437 | if ((rta[IFA_LOCAL - 1] && | 469 | if (tb[IFA_LOCAL] && |
438 | memcmp(RTA_DATA(rta[IFA_LOCAL - 1]), | 470 | ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL])) |
439 | &ifa->ifa_local, 4)) || | 471 | continue; |
440 | (rta[IFA_LABEL - 1] && | 472 | |
441 | rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) || | 473 | if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label)) |
442 | (rta[IFA_ADDRESS - 1] && | 474 | continue; |
443 | (ifm->ifa_prefixlen != ifa->ifa_prefixlen || | 475 | |
444 | !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]), | 476 | if (tb[IFA_ADDRESS] && |
445 | ifa)))) | 477 | (ifm->ifa_prefixlen != ifa->ifa_prefixlen || |
478 | !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa))) | ||
446 | continue; | 479 | continue; |
447 | inet_del_ifa(in_dev, ifap, 1); | 480 | |
481 | __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid); | ||
448 | return 0; | 482 | return 0; |
449 | } | 483 | } |
450 | out: | 484 | |
451 | return -EADDRNOTAVAIL; | 485 | err = -EADDRNOTAVAIL; |
486 | errout: | ||
487 | return err; | ||
452 | } | 488 | } |
453 | 489 | ||
454 | 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) |
455 | { | 491 | { |
456 | struct rtattr **rta = arg; | 492 | struct nlattr *tb[IFA_MAX+1]; |
493 | struct in_ifaddr *ifa; | ||
494 | struct ifaddrmsg *ifm; | ||
457 | struct net_device *dev; | 495 | struct net_device *dev; |
458 | struct in_device *in_dev; | 496 | struct in_device *in_dev; |
459 | struct ifaddrmsg *ifm = NLMSG_DATA(nlh); | 497 | int err = -EINVAL; |
460 | struct in_ifaddr *ifa; | ||
461 | int rc = -EINVAL; | ||
462 | 498 | ||
463 | ASSERT_RTNL(); | 499 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); |
500 | if (err < 0) | ||
501 | goto errout; | ||
464 | 502 | ||
465 | if (ifm->ifa_prefixlen > 32 || !rta[IFA_LOCAL - 1]) | 503 | ifm = nlmsg_data(nlh); |
466 | goto out; | 504 | if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) |
505 | goto errout; | ||
467 | 506 | ||
468 | rc = -ENODEV; | 507 | dev = __dev_get_by_index(ifm->ifa_index); |
469 | if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL) | 508 | if (dev == NULL) { |
470 | goto out; | 509 | err = -ENODEV; |
510 | goto errout; | ||
511 | } | ||
471 | 512 | ||
472 | rc = -ENOBUFS; | 513 | in_dev = __in_dev_get_rtnl(dev); |
473 | if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) { | 514 | if (in_dev == NULL) { |
474 | in_dev = inetdev_init(dev); | 515 | in_dev = inetdev_init(dev); |
475 | if (!in_dev) | 516 | if (in_dev == NULL) { |
476 | goto out; | 517 | err = -ENOBUFS; |
518 | goto errout; | ||
519 | } | ||
477 | } | 520 | } |
478 | 521 | ||
479 | if ((ifa = inet_alloc_ifa()) == NULL) | 522 | ifa = inet_alloc_ifa(); |
480 | 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]; | ||
481 | 536 | ||
482 | if (!rta[IFA_ADDRESS - 1]) | ||
483 | rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1]; | ||
484 | memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL - 1]), 4); | ||
485 | memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS - 1]), 4); | ||
486 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; | 537 | ifa->ifa_prefixlen = ifm->ifa_prefixlen; |
487 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); | 538 | ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); |
488 | if (rta[IFA_BROADCAST - 1]) | ||
489 | memcpy(&ifa->ifa_broadcast, | ||
490 | RTA_DATA(rta[IFA_BROADCAST - 1]), 4); | ||
491 | if (rta[IFA_ANYCAST - 1]) | ||
492 | memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST - 1]), 4); | ||
493 | ifa->ifa_flags = ifm->ifa_flags; | 539 | ifa->ifa_flags = ifm->ifa_flags; |
494 | ifa->ifa_scope = ifm->ifa_scope; | 540 | ifa->ifa_scope = ifm->ifa_scope; |
495 | in_dev_hold(in_dev); | 541 | ifa->ifa_dev = in_dev; |
496 | ifa->ifa_dev = in_dev; | 542 | |
497 | if (rta[IFA_LABEL - 1]) | 543 | ifa->ifa_local = nla_get_u32(tb[IFA_LOCAL]); |
498 | rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ); | 544 | ifa->ifa_address = nla_get_u32(tb[IFA_ADDRESS]); |
545 | |||
546 | if (tb[IFA_BROADCAST]) | ||
547 | ifa->ifa_broadcast = nla_get_u32(tb[IFA_BROADCAST]); | ||
548 | |||
549 | if (tb[IFA_ANYCAST]) | ||
550 | ifa->ifa_anycast = nla_get_u32(tb[IFA_ANYCAST]); | ||
551 | |||
552 | if (tb[IFA_LABEL]) | ||
553 | nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ); | ||
499 | else | 554 | else |
500 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); | 555 | memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); |
501 | 556 | ||
502 | rc = inet_insert_ifa(ifa); | 557 | return ifa; |
503 | out: | 558 | |
504 | 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); | ||
505 | } | 574 | } |
506 | 575 | ||
507 | /* | 576 | /* |
@@ -1056,32 +1125,37 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, | |||
1056 | { | 1125 | { |
1057 | struct ifaddrmsg *ifm; | 1126 | struct ifaddrmsg *ifm; |
1058 | struct nlmsghdr *nlh; | 1127 | struct nlmsghdr *nlh; |
1059 | unsigned char *b = skb->tail; | ||
1060 | 1128 | ||
1061 | nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); | 1129 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags); |
1062 | ifm = NLMSG_DATA(nlh); | 1130 | if (nlh == NULL) |
1131 | return -ENOBUFS; | ||
1132 | |||
1133 | ifm = nlmsg_data(nlh); | ||
1063 | ifm->ifa_family = AF_INET; | 1134 | ifm->ifa_family = AF_INET; |
1064 | ifm->ifa_prefixlen = ifa->ifa_prefixlen; | 1135 | ifm->ifa_prefixlen = ifa->ifa_prefixlen; |
1065 | ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT; | 1136 | ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT; |
1066 | ifm->ifa_scope = ifa->ifa_scope; | 1137 | ifm->ifa_scope = ifa->ifa_scope; |
1067 | ifm->ifa_index = ifa->ifa_dev->dev->ifindex; | 1138 | ifm->ifa_index = ifa->ifa_dev->dev->ifindex; |
1139 | |||
1068 | if (ifa->ifa_address) | 1140 | if (ifa->ifa_address) |
1069 | RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address); | 1141 | NLA_PUT_U32(skb, IFA_ADDRESS, ifa->ifa_address); |
1142 | |||
1070 | if (ifa->ifa_local) | 1143 | if (ifa->ifa_local) |
1071 | RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local); | 1144 | NLA_PUT_U32(skb, IFA_LOCAL, ifa->ifa_local); |
1145 | |||
1072 | if (ifa->ifa_broadcast) | 1146 | if (ifa->ifa_broadcast) |
1073 | RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast); | 1147 | NLA_PUT_U32(skb, IFA_BROADCAST, ifa->ifa_broadcast); |
1148 | |||
1074 | if (ifa->ifa_anycast) | 1149 | if (ifa->ifa_anycast) |
1075 | RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast); | 1150 | NLA_PUT_U32(skb, IFA_ANYCAST, ifa->ifa_anycast); |
1151 | |||
1076 | if (ifa->ifa_label[0]) | 1152 | if (ifa->ifa_label[0]) |
1077 | RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label); | 1153 | NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label); |
1078 | nlh->nlmsg_len = skb->tail - b; | ||
1079 | return skb->len; | ||
1080 | 1154 | ||
1081 | nlmsg_failure: | 1155 | return nlmsg_end(skb, nlh); |
1082 | rtattr_failure: | 1156 | |
1083 | skb_trim(skb, b - skb->data); | 1157 | nla_put_failure: |
1084 | return -1; | 1158 | return nlmsg_cancel(skb, nlh); |
1085 | } | 1159 | } |
1086 | 1160 | ||
1087 | 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) |
@@ -1127,19 +1201,27 @@ done: | |||
1127 | return skb->len; | 1201 | return skb->len; |
1128 | } | 1202 | } |
1129 | 1203 | ||
1130 | 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) | ||
1131 | { | 1206 | { |
1132 | int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128); | 1207 | struct sk_buff *skb; |
1133 | 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; | ||
1134 | 1214 | ||
1135 | if (!skb) | 1215 | err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); |
1136 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); | 1216 | if (err < 0) { |
1137 | else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { | ||
1138 | kfree_skb(skb); | 1217 | kfree_skb(skb); |
1139 | netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); | 1218 | goto errout; |
1140 | } else { | ||
1141 | netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL); | ||
1142 | } | 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); | ||
1143 | } | 1225 | } |
1144 | 1226 | ||
1145 | static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { | 1227 | static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { |
@@ -1151,9 +1233,7 @@ static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { | |||
1151 | [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute, | 1233 | [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute, |
1152 | .dumpit = inet_dump_fib, }, | 1234 | .dumpit = inet_dump_fib, }, |
1153 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 1235 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
1154 | [RTM_NEWRULE - RTM_BASE] = { .doit = inet_rtm_newrule, }, | 1236 | [RTM_GETRULE - RTM_BASE] = { .dumpit = fib4_rules_dump, }, |
1155 | [RTM_DELRULE - RTM_BASE] = { .doit = inet_rtm_delrule, }, | ||
1156 | [RTM_GETRULE - RTM_BASE] = { .dumpit = inet_dump_rules, }, | ||
1157 | #endif | 1237 | #endif |
1158 | }; | 1238 | }; |
1159 | 1239 | ||