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