Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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