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