addrlabel.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  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 <yoshfuji@linux-ipv6.org>
  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. int err = 0;
  277. int i;
  278. ADDRLABEL(KERN_DEBUG "%s\n", __func__);
  279. spin_lock_init(&net->ipv6.ip6addrlbl_table.lock);
  280. INIT_HLIST_HEAD(&net->ipv6.ip6addrlbl_table.head);
  281. for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) {
  282. int ret = ip6addrlbl_add(net,
  283. ip6addrlbl_init_table[i].prefix,
  284. ip6addrlbl_init_table[i].prefixlen,
  285. 0,
  286. ip6addrlbl_init_table[i].label, 0);
  287. /* XXX: should we free all rules when we catch an error? */
  288. if (ret && (!err || err != -ENOMEM))
  289. err = ret;
  290. }
  291. return err;
  292. }
  293. static void __net_exit ip6addrlbl_net_exit(struct net *net)
  294. {
  295. struct ip6addrlbl_entry *p = NULL;
  296. struct hlist_node *n;
  297. /* Remove all labels belonging to the exiting net */
  298. spin_lock(&net->ipv6.ip6addrlbl_table.lock);
  299. hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) {
  300. hlist_del_rcu(&p->list);
  301. kfree_rcu(p, rcu);
  302. }
  303. spin_unlock(&net->ipv6.ip6addrlbl_table.lock);
  304. }
  305. static struct pernet_operations ipv6_addr_label_ops = {
  306. .init = ip6addrlbl_net_init,
  307. .exit = ip6addrlbl_net_exit,
  308. };
  309. int __init ipv6_addr_label_init(void)
  310. {
  311. return register_pernet_subsys(&ipv6_addr_label_ops);
  312. }
  313. void ipv6_addr_label_cleanup(void)
  314. {
  315. unregister_pernet_subsys(&ipv6_addr_label_ops);
  316. }
  317. static const struct nla_policy ifal_policy[IFAL_MAX+1] = {
  318. [IFAL_ADDRESS] = { .len = sizeof(struct in6_addr), },
  319. [IFAL_LABEL] = { .len = sizeof(u32), },
  320. };
  321. static bool addrlbl_ifindex_exists(struct net *net, int ifindex)
  322. {
  323. struct net_device *dev;
  324. rcu_read_lock();
  325. dev = dev_get_by_index_rcu(net, ifindex);
  326. rcu_read_unlock();
  327. return dev != NULL;
  328. }
  329. static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,
  330. struct netlink_ext_ack *extack)
  331. {
  332. struct net *net = sock_net(skb->sk);
  333. struct ifaddrlblmsg *ifal;
  334. struct nlattr *tb[IFAL_MAX+1];
  335. struct in6_addr *pfx;
  336. u32 label;
  337. int err = 0;
  338. err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy,
  339. extack);
  340. if (err < 0)
  341. return err;
  342. ifal = nlmsg_data(nlh);
  343. if (ifal->ifal_family != AF_INET6 ||
  344. ifal->ifal_prefixlen > 128)
  345. return -EINVAL;
  346. if (!tb[IFAL_ADDRESS])
  347. return -EINVAL;
  348. pfx = nla_data(tb[IFAL_ADDRESS]);
  349. if (!tb[IFAL_LABEL])
  350. return -EINVAL;
  351. label = nla_get_u32(tb[IFAL_LABEL]);
  352. if (label == IPV6_ADDR_LABEL_DEFAULT)
  353. return -EINVAL;
  354. switch (nlh->nlmsg_type) {
  355. case RTM_NEWADDRLABEL:
  356. if (ifal->ifal_index &&
  357. !addrlbl_ifindex_exists(net, ifal->ifal_index))
  358. return -EINVAL;
  359. err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen,
  360. ifal->ifal_index, label,
  361. nlh->nlmsg_flags & NLM_F_REPLACE);
  362. break;
  363. case RTM_DELADDRLABEL:
  364. err = ip6addrlbl_del(net, pfx, ifal->ifal_prefixlen,
  365. ifal->ifal_index);
  366. break;
  367. default:
  368. err = -EOPNOTSUPP;
  369. }
  370. return err;
  371. }
  372. static void ip6addrlbl_putmsg(struct nlmsghdr *nlh,
  373. int prefixlen, int ifindex, u32 lseq)
  374. {
  375. struct ifaddrlblmsg *ifal = nlmsg_data(nlh);
  376. ifal->ifal_family = AF_INET6;
  377. ifal->ifal_prefixlen = prefixlen;
  378. ifal->ifal_flags = 0;
  379. ifal->ifal_index = ifindex;
  380. ifal->ifal_seq = lseq;
  381. };
  382. static int ip6addrlbl_fill(struct sk_buff *skb,
  383. struct ip6addrlbl_entry *p,
  384. u32 lseq,
  385. u32 portid, u32 seq, int event,
  386. unsigned int flags)
  387. {
  388. struct nlmsghdr *nlh = nlmsg_put(skb, portid, seq, event,
  389. sizeof(struct ifaddrlblmsg), flags);
  390. if (!nlh)
  391. return -EMSGSIZE;
  392. ip6addrlbl_putmsg(nlh, p->prefixlen, p->ifindex, lseq);
  393. if (nla_put_in6_addr(skb, IFAL_ADDRESS, &p->prefix) < 0 ||
  394. nla_put_u32(skb, IFAL_LABEL, p->label) < 0) {
  395. nlmsg_cancel(skb, nlh);
  396. return -EMSGSIZE;
  397. }
  398. nlmsg_end(skb, nlh);
  399. return 0;
  400. }
  401. static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb)
  402. {
  403. struct net *net = sock_net(skb->sk);
  404. struct ip6addrlbl_entry *p;
  405. int idx = 0, s_idx = cb->args[0];
  406. int err;
  407. rcu_read_lock();
  408. hlist_for_each_entry_rcu(p, &net->ipv6.ip6addrlbl_table.head, list) {
  409. if (idx >= s_idx) {
  410. err = ip6addrlbl_fill(skb, p,
  411. net->ipv6.ip6addrlbl_table.seq,
  412. NETLINK_CB(cb->skb).portid,
  413. cb->nlh->nlmsg_seq,
  414. RTM_NEWADDRLABEL,
  415. NLM_F_MULTI);
  416. if (err < 0)
  417. break;
  418. }
  419. idx++;
  420. }
  421. rcu_read_unlock();
  422. cb->args[0] = idx;
  423. return skb->len;
  424. }
  425. static inline int ip6addrlbl_msgsize(void)
  426. {
  427. return NLMSG_ALIGN(sizeof(struct ifaddrlblmsg))
  428. + nla_total_size(16) /* IFAL_ADDRESS */
  429. + nla_total_size(4); /* IFAL_LABEL */
  430. }
  431. static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
  432. struct netlink_ext_ack *extack)
  433. {
  434. struct net *net = sock_net(in_skb->sk);
  435. struct ifaddrlblmsg *ifal;
  436. struct nlattr *tb[IFAL_MAX+1];
  437. struct in6_addr *addr;
  438. u32 lseq;
  439. int err = 0;
  440. struct ip6addrlbl_entry *p;
  441. struct sk_buff *skb;
  442. err = nlmsg_parse(nlh, sizeof(*ifal), tb, IFAL_MAX, ifal_policy,
  443. extack);
  444. if (err < 0)
  445. return err;
  446. ifal = nlmsg_data(nlh);
  447. if (ifal->ifal_family != AF_INET6 ||
  448. ifal->ifal_prefixlen != 128)
  449. return -EINVAL;
  450. if (ifal->ifal_index &&
  451. !addrlbl_ifindex_exists(net, ifal->ifal_index))
  452. return -EINVAL;
  453. if (!tb[IFAL_ADDRESS])
  454. return -EINVAL;
  455. addr = nla_data(tb[IFAL_ADDRESS]);
  456. skb = nlmsg_new(ip6addrlbl_msgsize(), GFP_KERNEL);
  457. if (!skb)
  458. return -ENOBUFS;
  459. err = -ESRCH;
  460. rcu_read_lock();
  461. p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index);
  462. lseq = net->ipv6.ip6addrlbl_table.seq;
  463. if (p)
  464. err = ip6addrlbl_fill(skb, p, lseq,
  465. NETLINK_CB(in_skb).portid,
  466. nlh->nlmsg_seq,
  467. RTM_NEWADDRLABEL, 0);
  468. rcu_read_unlock();
  469. if (err < 0) {
  470. WARN_ON(err == -EMSGSIZE);
  471. kfree_skb(skb);
  472. } else {
  473. err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
  474. }
  475. return err;
  476. }
  477. int __init ipv6_addr_label_rtnl_register(void)
  478. {
  479. int ret;
  480. ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_NEWADDRLABEL,
  481. ip6addrlbl_newdel,
  482. NULL, RTNL_FLAG_DOIT_UNLOCKED);
  483. if (ret < 0)
  484. return ret;
  485. ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_DELADDRLABEL,
  486. ip6addrlbl_newdel,
  487. NULL, RTNL_FLAG_DOIT_UNLOCKED);
  488. if (ret < 0)
  489. return ret;
  490. ret = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETADDRLABEL,
  491. ip6addrlbl_get,
  492. ip6addrlbl_dump, RTNL_FLAG_DOIT_UNLOCKED);
  493. return ret;
  494. }