addrlabel.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * IPv6 Address Label subsystem
  4. * for the IPv6 "Default" Source Address Selection
  5. *
  6. * Copyright (C)2007 USAGI/WIDE Project
  7. */
  8. /*
  9. * Author:
  10. * YOSHIFUJI Hideaki @ USAGI/WIDE Project <[email protected]>
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/list.h>
  14. #include <linux/rcupdate.h>
  15. #include <linux/in6.h>
  16. #include <linux/slab.h>
  17. #include <net/addrconf.h>
  18. #include <linux/if_addrlabel.h>
  19. #include <linux/netlink.h>
  20. #include <linux/rtnetlink.h>
  21. #if 0
  22. #define ADDRLABEL(x...) printk(x)
  23. #else
  24. #define ADDRLABEL(x...) do { ; } while (0)
  25. #endif
  26. /*
  27. * Policy Table
  28. */
  29. struct ip6addrlbl_entry {
  30. struct in6_addr prefix;
  31. int prefixlen;
  32. int ifindex;
  33. int addrtype;
  34. u32 label;
  35. struct hlist_node list;
  36. struct rcu_head rcu;
  37. };
  38. /*
  39. * Default policy table (RFC6724 + extensions)
  40. *
  41. * prefix addr_type label
  42. * -------------------------------------------------------------------------
  43. * ::1/128 LOOPBACK 0
  44. * ::/0 N/A 1
  45. * 2002::/16 N/A 2
  46. * ::/96 COMPATv4 3
  47. * ::ffff:0:0/96 V4MAPPED 4
  48. * fc00::/7 N/A 5 ULA (RFC 4193)
  49. * 2001::/32 N/A 6 Teredo (RFC 4380)
  50. * 2001:10::/28 N/A 7 ORCHID (RFC 4843)
  51. * fec0::/10 N/A 11 Site-local
  52. * (deprecated by RFC3879)
  53. * 3ffe::/16 N/A 12 6bone
  54. *
  55. * Note: 0xffffffff is used if we do not have any policies.
  56. * Note: Labels for ULA and 6to4 are different from labels listed in RFC6724.
  57. */
  58. #define IPV6_ADDR_LABEL_DEFAULT 0xffffffffUL
  59. static const __net_initconst struct ip6addrlbl_init_table
  60. {
  61. const struct in6_addr *prefix;
  62. int prefixlen;
  63. u32 label;
  64. } ip6addrlbl_init_table[] = {
  65. { /* ::/0 */
  66. .prefix = &in6addr_any,
  67. .label = 1,
  68. }, { /* fc00::/7 */
  69. .prefix = &(struct in6_addr){ { { 0xfc } } } ,
  70. .prefixlen = 7,
  71. .label = 5,
  72. }, { /* fec0::/10 */
  73. .prefix = &(struct in6_addr){ { { 0xfe, 0xc0 } } },
  74. .prefixlen = 10,
  75. .label = 11,
  76. }, { /* 2002::/16 */
  77. .prefix = &(struct in6_addr){ { { 0x20, 0x02 } } },
  78. .prefixlen = 16,
  79. .label = 2,
  80. }, { /* 3ffe::/16 */
  81. .prefix = &(struct in6_addr){ { { 0x3f, 0xfe } } },
  82. .prefixlen = 16,
  83. .label = 12,
  84. }, { /* 2001::/32 */
  85. .prefix = &(struct in6_addr){ { { 0x20, 0x01 } } },
  86. .prefixlen = 32,
  87. .label = 6,
  88. }, { /* 2001:10::/28 */
  89. .prefix = &(struct in6_addr){ { { 0x20, 0x01, 0x00, 0x10 } } },
  90. .prefixlen = 28,
  91. .label = 7,
  92. }, { /* ::ffff:0:0 */
  93. .prefix = &(struct in6_addr){ { { [10] = 0xff, [11] = 0xff } } },
  94. .prefixlen = 96,
  95. .label = 4,
  96. }, { /* ::/96 */
  97. .prefix = &in6addr_any,
  98. .prefixlen = 96,
  99. .label = 3,
  100. }, { /* ::1/128 */
  101. .prefix = &in6addr_loopback,
  102. .prefixlen = 128,
  103. .label = 0,
  104. }
  105. };
  106. /* Find label */
  107. static bool __ip6addrlbl_match(const struct ip6addrlbl_entry *p,
  108. const struct in6_addr *addr,
  109. int addrtype, int ifindex)
  110. {
  111. if (p->ifindex && p->ifindex != ifindex)
  112. return false;
  113. if (p->addrtype && p->addrtype != addrtype)
  114. return false;
  115. if (!ipv6_prefix_equal(addr, &p->prefix, p->prefixlen))
  116. return false;
  117. return true;
  118. }
  119. static struct ip6addrlbl_entry *__ipv6_addr_label(struct net *net,
  120. const struct in6_addr *addr,
  121. int type, int ifindex)
  122. {
  123. struct ip6addrlbl_entry *p;
  124. hlist_for_each_entry_rcu(p, &net->ipv6.ip6addrlbl_table.head, list) {
  125. if (__ip6addrlbl_match(p, addr, type, ifindex))
  126. return p;
  127. }
  128. return NULL;
  129. }
  130. u32 ipv6_addr_label(struct net *net,
  131. const struct in6_addr *addr, int type, int ifindex)
  132. {
  133. u32 label;
  134. struct ip6addrlbl_entry *p;
  135. type &= IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK;
  136. rcu_read_lock();
  137. p = __ipv6_addr_label(net, addr, type, ifindex);
  138. label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT;
  139. rcu_read_unlock();
  140. ADDRLABEL(KERN_DEBUG "%s(addr=%pI6, type=%d, ifindex=%d) => %08x\n",
  141. __func__, addr, type, ifindex, label);
  142. return label;
  143. }
  144. /* allocate one entry */
  145. static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix,
  146. int prefixlen, int ifindex,
  147. u32 label)
  148. {
  149. struct ip6addrlbl_entry *newp;
  150. int addrtype;
  151. ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d, label=%u)\n",
  152. __func__, prefix, prefixlen, ifindex, (unsigned int)label);
  153. addrtype = ipv6_addr_type(prefix) & (IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK);
  154. switch (addrtype) {
  155. case IPV6_ADDR_MAPPED:
  156. if (prefixlen > 96)
  157. return ERR_PTR(-EINVAL);
  158. if (prefixlen < 96)
  159. addrtype = 0;
  160. break;
  161. case IPV6_ADDR_COMPATv4:
  162. if (prefixlen != 96)
  163. addrtype = 0;
  164. break;
  165. case IPV6_ADDR_LOOPBACK:
  166. if (prefixlen != 128)
  167. addrtype = 0;
  168. break;
  169. }
  170. newp = kmalloc(sizeof(*newp), GFP_KERNEL);
  171. if (!newp)
  172. return ERR_PTR(-ENOMEM);
  173. ipv6_addr_prefix(&newp->prefix, prefix, prefixlen);
  174. newp->prefixlen = prefixlen;
  175. newp->ifindex = ifindex;
  176. newp->addrtype = addrtype;
  177. newp->label = label;
  178. INIT_HLIST_NODE(&newp->list);
  179. return newp;
  180. }
  181. /* add a label */
  182. static int __ip6addrlbl_add(struct net *net, struct ip6addrlbl_entry *newp,
  183. int replace)
  184. {
  185. struct ip6addrlbl_entry *last = NULL, *p = NULL;
  186. struct hlist_node *n;
  187. int ret = 0;
  188. ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp,
  189. replace);
  190. hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) {
  191. if (p->prefixlen == newp->prefixlen &&
  192. p->ifindex == newp->ifindex &&
  193. ipv6_addr_equal(&p->prefix, &newp->prefix)) {
  194. if (!replace) {
  195. ret = -EEXIST;
  196. goto out;
  197. }
  198. hlist_replace_rcu(&p->list, &newp->list);
  199. kfree_rcu(p, rcu);
  200. goto out;
  201. } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) ||
  202. (p->prefixlen < newp->prefixlen)) {
  203. hlist_add_before_rcu(&newp->list, &p->list);
  204. goto out;
  205. }
  206. last = p;
  207. }
  208. if (last)
  209. hlist_add_behind_rcu(&newp->list, &last->list);
  210. else
  211. hlist_add_head_rcu(&newp->list, &net->ipv6.ip6addrlbl_table.head);
  212. out:
  213. if (!ret)
  214. net->ipv6.ip6addrlbl_table.seq++;
  215. return ret;
  216. }
  217. /* add a label */
  218. static int ip6addrlbl_add(struct net *net,
  219. const struct in6_addr *prefix, int prefixlen,
  220. int ifindex, u32 label, int replace)
  221. {
  222. struct ip6addrlbl_entry *newp;
  223. int ret = 0;
  224. ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n",
  225. __func__, prefix, prefixlen, ifindex, (unsigned int)label,
  226. replace);
  227. newp = ip6addrlbl_alloc(prefix, prefixlen, ifindex, label);
  228. if (IS_ERR(newp))
  229. return PTR_ERR(newp);
  230. spin_lock(&net->ipv6.ip6addrlbl_table.lock);
  231. ret = __ip6addrlbl_add(net, newp, replace);
  232. spin_unlock(&net->ipv6.ip6addrlbl_table.lock);
  233. if (ret)
  234. kfree(newp);
  235. return ret;
  236. }
  237. /* remove a label */
  238. static int __ip6addrlbl_del(struct net *net,
  239. const struct in6_addr *prefix, int prefixlen,
  240. int ifindex)
  241. {
  242. struct ip6addrlbl_entry *p = NULL;
  243. struct hlist_node *n;
  244. int ret = -ESRCH;
  245. ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d)\n",
  246. __func__, prefix, prefixlen, ifindex);
  247. hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) {
  248. if (p->prefixlen == prefixlen &&
  249. p->ifindex == ifindex &&
  250. ipv6_addr_equal(&p->prefix, prefix)) {
  251. hlist_del_rcu(&p->list);
  252. kfree_rcu(p, rcu);
  253. ret = 0;
  254. break;
  255. }
  256. }
  257. return ret;
  258. }
  259. static int ip6addrlbl_del(struct net *net,
  260. const struct in6_addr *prefix, int prefixlen,
  261. int ifindex)
  262. {
  263. struct in6_addr prefix_buf;
  264. int ret;
  265. ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d)\n",
  266. __func__, prefix, prefixlen, ifindex);
  267. ipv6_addr_prefix(&prefix_buf, prefix, prefixlen);
  268. spin_lock(&net->ipv6.ip6addrlbl_table.lock);
  269. ret = __ip6addrlbl_del(net, &prefix_buf, prefixlen, ifindex);
  270. spin_unlock(&net->ipv6.ip6addrlbl_table.lock);
  271. return ret;
  272. }
  273. /* add default label */
  274. static int __net_init ip6addrlbl_net_init(struct net *net)
  275. {
  276. struct ip6addrlbl_entry *p = NULL;
  277. struct hlist_node *n;
  278. int err;
  279. int i;
  280. ADDRLABEL(KERN_DEBUG "%s\n", __func__);
  281. spin_lock_init(&net->ipv6.ip6addrlbl_table.lock);
  282. INIT_HLIST_HEAD(&net->ipv6.ip6addrlbl_table.head);
  283. for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) {
  284. err = ip6addrlbl_add(net,
  285. ip6addrlbl_init_table[i].prefix,
  286. ip6addrlbl_init_table[i].prefixlen,
  287. 0,
  288. ip6addrlbl_init_table[i].label, 0);
  289. if (err)
  290. goto err_ip6addrlbl_add;
  291. }
  292. return 0;
  293. err_ip6addrlbl_add:
  294. hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) {
  295. hlist_del_rcu(&p->list);
  296. kfree_rcu(p, rcu);
  297. }
  298. return err;
  299. }
  300. static void __net_exit ip6addrlbl_net_exit(struct net *net)
  301. {
  302. struct ip6addrlbl_entry *p = NULL;
  303. struct hlist_node *n;
  304. /* Remove all labels belonging to the exiting net */
  305. spin_lock(&net->ipv6.ip6addrlbl_table.lock);
  306. hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) {
  307. hlist_del_rcu(&p->list);
  308. kfree_rcu(p, rcu);
  309. }
  310. spin_unlock(&net->ipv6.ip6addrlbl_table.lock);
  311. }
  312. static struct pernet_operations ipv6_addr_label_ops = {
  313. .init = ip6addrlbl_net_init,
  314. .exit = ip6addrlbl_net_exit,
  315. };
  316. int __init ipv6_addr_label_init(void)
  317. {
  318. return register_pernet_subsys(&ipv6_addr_label_ops);
  319. }
  320. void ipv6_addr_label_cleanup(void)
  321. {
  322. unregister_pernet_subsys(&ipv6_addr_label_ops);
  323. }
  324. static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
  325. [IFAL_ADDRESS] = { .len = sizeof(struct in6_addr), },
  326. [IFAL_LABEL] = { .len = sizeof(u32), },
  327. };
  328. static bool addrlbl_ifindex_exists(struct net *net, int ifindex)
  329. {
  330. struct net_device *dev;
  331. rcu_read_lock();
  332. dev = dev_get_by_index_rcu(net, ifindex);
  333. rcu_read_unlock();
  334. return dev != NULL;
  335. }
  336. static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
  337. struct netlink_ext_ack *extack)
  338. {
  339. struct net *net = sock_net(skb->sk);
  340. struct ifaddrlblmsg *ifal;
  341. struct nlattr *tb[IFAL_MAX+1];
  342. struct in6_addr *pfx;
  343. u32 label;
  344. int err = 0;
  345. err = nlmsg_parse_deprecated(nlh, sizeof(*ifal), tb, IFAL_MAX,
  346. ifal_policy, extack);
  347. if (err < 0)
  348. return err;
  349. ifal = nlmsg_data(nlh);
  350. if (ifal->ifal_family != AF_INET6 ||
  351. ifal->ifal_prefixlen > 128)
  352. return -EINVAL;
  353. if (!tb[IFAL_ADDRESS])
  354. return -EINVAL;
  355. pfx = nla_data(tb[IFAL_ADDRESS]);
  356. if (!tb[IFAL_LABEL])
  357. return -EINVAL;
  358. label = nla_get_u32(tb[IFAL_LABEL]);
  359. if (label == IPV6_ADDR_LABEL_DEFAULT)
  360. return -EINVAL;
  361. switch (nlh->nlmsg_type) {
  362. case RTM_NEWADDRLABEL:
  363. if (ifal->ifal_index &&
  364. !addrlbl_ifindex_exists(net, ifal->ifal_index))
  365. return -EINVAL;
  366. err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen,
  367. ifal->ifal_index, label,
  368. nlh->nlmsg_flags & NLM_F_REPLACE);
  369. break;
  370. case RTM_DELADDRLABEL:
  371. err = ip6addrlbl_del(net, pfx, ifal->ifal_prefixlen,
  372. ifal->ifal_index);
  373. break;
  374. default:
  375. err = -EOPNOTSUPP;
  376. }
  377. return err;
  378. }
  379. static void ip6addrlbl_putmsg(struct nlmsghdr *nlh,
  380. int prefixlen, int ifindex, u32 lseq)
  381. {
  382. struct ifaddrlblmsg *ifal = nlmsg_data(nlh);
  383. ifal->ifal_family = AF_INET6;
  384. ifal->__ifal_reserved = 0;
  385. ifal->ifal_prefixlen = prefixlen;
  386. ifal->ifal_flags = 0;
  387. ifal->ifal_index = ifindex;
  388. ifal->ifal_seq = lseq;
  389. };
  390. static int ip6addrlbl_fill(struct sk_buff *skb,
  391. struct ip6addrlbl_entry *p,
  392. u32 lseq,
  393. u32 portid, u32 seq, int event,
  394. unsigned int flags)
  395. {
  396. struct nlmsghdr *nlh = nlmsg_put(skb, portid, seq, event,
  397. sizeof(struct ifaddrlblmsg), flags);
  398. if (!nlh)
  399. return -EMSGSIZE;
  400. ip6addrlbl_putmsg(nlh, p->prefixlen, p->ifindex, lseq);
  401. if (nla_put_in6_addr(skb, IFAL_ADDRESS, &p->prefix) < 0 ||
  402. nla_put_u32(skb, IFAL_LABEL, p->label) < 0) {
  403. nlmsg_cancel(skb, nlh);
  404. return -EMSGSIZE;
  405. }
  406. nlmsg_end(skb, nlh);
  407. return 0;
  408. }
  409. static int ip6addrlbl_valid_dump_req(const struct nlmsghdr *nlh,
  410. struct netlink_ext_ack *extack)
  411. {
  412. struct ifaddrlblmsg *ifal;
  413. if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifal))) {
  414. NL_SET_ERR_MSG_MOD(extack, "Invalid header for address label dump request");
  415. return -EINVAL;
  416. }
  417. ifal = nlmsg_data(nlh);
  418. if (ifal->__ifal_reserved || ifal->ifal_prefixlen ||
  419. ifal->ifal_flags || ifal->ifal_index || ifal->ifal_seq) {
  420. NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address label dump request");
  421. return -EINVAL;
  422. }
  423. if (nlmsg_attrlen(nlh, sizeof(*ifal))) {
  424. NL_SET_ERR_MSG_MOD(extack, "Invalid data after header for address label dump request");
  425. return -EINVAL;
  426. }
  427. return 0;
  428. }
  429. static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb)
  430. {
  431. const struct nlmsghdr *nlh = cb->nlh;
  432. struct net *net = sock_net(skb->sk);
  433. struct ip6addrlbl_entry *p;
  434. int idx = 0, s_idx = cb->args[0];
  435. int err;
  436. if (cb->strict_check) {
  437. err = ip6addrlbl_valid_dump_req(nlh, cb->extack);
  438. if (err < 0)
  439. return err;
  440. }
  441. rcu_read_lock();
  442. hlist_for_each_entry_rcu(p, &net->ipv6.ip6addrlbl_table.head, list) {
  443. if (idx >= s_idx) {
  444. err = ip6addrlbl_fill(skb, p,
  445. net->ipv6.ip6addrlbl_table.seq,
  446. NETLINK_CB(cb->skb).portid,
  447. nlh->nlmsg_seq,
  448. RTM_NEWADDRLABEL,
  449. NLM_F_MULTI);
  450. if (err < 0)
  451. break;
  452. }
  453. idx++;
  454. }
  455. rcu_read_unlock();
  456. cb->args[0] = idx;
  457. return skb->len;
  458. }
  459. static inline int ip6addrlbl_msgsize(void)
  460. {
  461. return NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))
  462. + nla_total_size(16) /* IFAL_ADDRESS */
  463. + nla_total_size(4); /* IFAL_LABEL */
  464. }
  465. static int ip6addrlbl_valid_get_req(struct sk_buff *skb,
  466. const struct nlmsghdr *nlh,
  467. struct nlattr **tb,
  468. struct netlink_ext_ack *extack)
  469. {
  470. struct ifaddrlblmsg *ifal;
  471. int i, err;
  472. if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifal))) {
  473. NL_SET_ERR_MSG_MOD(extack, "Invalid header for addrlabel get request");
  474. return -EINVAL;
  475. }
  476. if (!netlink_strict_get_check(skb))
  477. return nlmsg_parse_deprecated(nlh, sizeof(*ifal), tb,
  478. IFAL_MAX, ifal_policy, extack);
  479. ifal = nlmsg_data(nlh);
  480. if (ifal->__ifal_reserved || ifal->ifal_flags || ifal->ifal_seq) {
  481. NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for addrlabel get request");
  482. return -EINVAL;
  483. }
  484. err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifal), tb, IFAL_MAX,
  485. ifal_policy, extack);
  486. if (err)
  487. return err;
  488. for (i = 0; i <= IFAL_MAX; i++) {
  489. if (!tb[i])
  490. continue;
  491. switch (i) {
  492. case IFAL_ADDRESS:
  493. break;
  494. default:
  495. NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in addrlabel get request");
  496. return -EINVAL;
  497. }
  498. }
  499. return 0;
  500. }
  501. static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
  502. struct netlink_ext_ack *extack)
  503. {
  504. struct net *net = sock_net(in_skb->sk);
  505. struct ifaddrlblmsg *ifal;
  506. struct nlattr *tb[IFAL_MAX+1];
  507. struct in6_addr *addr;
  508. u32 lseq;
  509. int err = 0;
  510. struct ip6addrlbl_entry *p;
  511. struct sk_buff *skb;
  512. err = ip6addrlbl_valid_get_req(in_skb, nlh, tb, extack);
  513. if (err < 0)
  514. return err;
  515. ifal = nlmsg_data(nlh);
  516. if (ifal->ifal_family != AF_INET6 ||
  517. ifal->ifal_prefixlen != 128)
  518. return -EINVAL;
  519. if (ifal->ifal_index &&
  520. !addrlbl_ifindex_exists(net, ifal->ifal_index))
  521. return -EINVAL;
  522. if (!tb[IFAL_ADDRESS])
  523. return -EINVAL;
  524. addr = nla_data(tb[IFAL_ADDRESS]);
  525. skb = nlmsg_new(ip6addrlbl_msgsize(), GFP_KERNEL);
  526. if (!skb)
  527. return -ENOBUFS;
  528. err = -ESRCH;
  529. rcu_read_lock();
  530. p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index);
  531. lseq = net->ipv6.ip6addrlbl_table.seq;
  532. if (p)
  533. err = ip6addrlbl_fill(skb, p, lseq,
  534. NETLINK_CB(in_skb).portid,
  535. nlh->nlmsg_seq,
  536. RTM_NEWADDRLABEL, 0);
  537. rcu_read_unlock();
  538. if (err < 0) {
  539. WARN_ON(err == -EMSGSIZE);
  540. kfree_skb(skb);
  541. } else {
  542. err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
  543. }
  544. return err;
  545. }
  546. int __init ipv6_addr_label_rtnl_register(void)
  547. {
  548. int ret;
  549. ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_NEWADDRLABEL,
  550. ip6addrlbl_newdel,
  551. NULL, RTNL_FLAG_DOIT_UNLOCKED);
  552. if (ret < 0)
  553. return ret;
  554. ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_DELADDRLABEL,
  555. ip6addrlbl_newdel,
  556. NULL, RTNL_FLAG_DOIT_UNLOCKED);
  557. if (ret < 0)
  558. return ret;
  559. ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETADDRLABEL,
  560. ip6addrlbl_get,
  561. ip6addrlbl_dump, RTNL_FLAG_DOIT_UNLOCKED);
  562. return ret;
  563. }