xref: /aosp_15_r20/external/libnl/lib/addr.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1*4dc78e53SAndroid Build Coastguard Worker /* SPDX-License-Identifier: LGPL-2.1-only */
2*4dc78e53SAndroid Build Coastguard Worker /*
3*4dc78e53SAndroid Build Coastguard Worker  * Copyright (c) 2003-2013 Thomas Graf <[email protected]>
4*4dc78e53SAndroid Build Coastguard Worker  */
5*4dc78e53SAndroid Build Coastguard Worker 
6*4dc78e53SAndroid Build Coastguard Worker /**
7*4dc78e53SAndroid Build Coastguard Worker  * @ingroup core_types
8*4dc78e53SAndroid Build Coastguard Worker  * @defgroup addr Network Address
9*4dc78e53SAndroid Build Coastguard Worker  *
10*4dc78e53SAndroid Build Coastguard Worker  * Abstract data type representing any kind of network address
11*4dc78e53SAndroid Build Coastguard Worker  *
12*4dc78e53SAndroid Build Coastguard Worker  * Related sections in the development guide:
13*4dc78e53SAndroid Build Coastguard Worker  * - @core_doc{_abstract_address, Network Addresses}
14*4dc78e53SAndroid Build Coastguard Worker  *
15*4dc78e53SAndroid Build Coastguard Worker  * @{
16*4dc78e53SAndroid Build Coastguard Worker  *
17*4dc78e53SAndroid Build Coastguard Worker  * Header
18*4dc78e53SAndroid Build Coastguard Worker  * ------
19*4dc78e53SAndroid Build Coastguard Worker  * ~~~~{.c}
20*4dc78e53SAndroid Build Coastguard Worker  * #include <netlink/addr.h>
21*4dc78e53SAndroid Build Coastguard Worker  * ~~~~
22*4dc78e53SAndroid Build Coastguard Worker  */
23*4dc78e53SAndroid Build Coastguard Worker 
24*4dc78e53SAndroid Build Coastguard Worker #include "nl-default.h"
25*4dc78e53SAndroid Build Coastguard Worker 
26*4dc78e53SAndroid Build Coastguard Worker #include <linux/socket.h>
27*4dc78e53SAndroid Build Coastguard Worker 
28*4dc78e53SAndroid Build Coastguard Worker #include <netlink/netlink.h>
29*4dc78e53SAndroid Build Coastguard Worker #include <netlink/utils.h>
30*4dc78e53SAndroid Build Coastguard Worker #include <netlink/addr.h>
31*4dc78e53SAndroid Build Coastguard Worker #include <netlink/attr.h>
32*4dc78e53SAndroid Build Coastguard Worker 
33*4dc78e53SAndroid Build Coastguard Worker #include "mpls.h"
34*4dc78e53SAndroid Build Coastguard Worker #include "nl-priv-dynamic-core/nl-core.h"
35*4dc78e53SAndroid Build Coastguard Worker 
36*4dc78e53SAndroid Build Coastguard Worker /* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote
37*4dc78e53SAndroid Build Coastguard Worker  * this, probably Alexey. */
dn_ntohs(uint16_t addr)38*4dc78e53SAndroid Build Coastguard Worker static inline uint16_t dn_ntohs(uint16_t addr)
39*4dc78e53SAndroid Build Coastguard Worker {
40*4dc78e53SAndroid Build Coastguard Worker 	union {
41*4dc78e53SAndroid Build Coastguard Worker 		uint8_t byte[2];
42*4dc78e53SAndroid Build Coastguard Worker 		uint16_t word;
43*4dc78e53SAndroid Build Coastguard Worker 	} u = {
44*4dc78e53SAndroid Build Coastguard Worker 		.word = addr,
45*4dc78e53SAndroid Build Coastguard Worker 	};
46*4dc78e53SAndroid Build Coastguard Worker 
47*4dc78e53SAndroid Build Coastguard Worker 	return ((uint16_t) u.byte[0]) | (((uint16_t) u.byte[1]) << 8);
48*4dc78e53SAndroid Build Coastguard Worker }
49*4dc78e53SAndroid Build Coastguard Worker 
do_digit(char * str,uint16_t * addr,uint16_t scale,size_t * pos,size_t len,int * started)50*4dc78e53SAndroid Build Coastguard Worker static inline int do_digit(char *str, uint16_t *addr, uint16_t scale,
51*4dc78e53SAndroid Build Coastguard Worker 			   size_t *pos, size_t len, int *started)
52*4dc78e53SAndroid Build Coastguard Worker {
53*4dc78e53SAndroid Build Coastguard Worker 	uint16_t tmp = *addr / scale;
54*4dc78e53SAndroid Build Coastguard Worker 
55*4dc78e53SAndroid Build Coastguard Worker 	if (*pos == len)
56*4dc78e53SAndroid Build Coastguard Worker 		return 1;
57*4dc78e53SAndroid Build Coastguard Worker 
58*4dc78e53SAndroid Build Coastguard Worker 	if (((tmp) > 0) || *started || (scale == 1)) {
59*4dc78e53SAndroid Build Coastguard Worker 		*str = tmp + '0';
60*4dc78e53SAndroid Build Coastguard Worker 		*started = 1;
61*4dc78e53SAndroid Build Coastguard Worker 		(*pos)++;
62*4dc78e53SAndroid Build Coastguard Worker 		*addr -= (tmp * scale);
63*4dc78e53SAndroid Build Coastguard Worker 	}
64*4dc78e53SAndroid Build Coastguard Worker 
65*4dc78e53SAndroid Build Coastguard Worker 	return 0;
66*4dc78e53SAndroid Build Coastguard Worker }
67*4dc78e53SAndroid Build Coastguard Worker 
dnet_ntop(const char * addrbuf,size_t addrlen,char * str,size_t len)68*4dc78e53SAndroid Build Coastguard Worker static const char *dnet_ntop(const char *addrbuf, size_t addrlen, char *str,
69*4dc78e53SAndroid Build Coastguard Worker 			     size_t len)
70*4dc78e53SAndroid Build Coastguard Worker {
71*4dc78e53SAndroid Build Coastguard Worker 	uint16_t addr = dn_ntohs(*(uint16_t *)addrbuf);
72*4dc78e53SAndroid Build Coastguard Worker 	uint16_t area = addr >> 10;
73*4dc78e53SAndroid Build Coastguard Worker 	size_t pos = 0;
74*4dc78e53SAndroid Build Coastguard Worker 	int started = 0;
75*4dc78e53SAndroid Build Coastguard Worker 
76*4dc78e53SAndroid Build Coastguard Worker 	if (addrlen != 2)
77*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
78*4dc78e53SAndroid Build Coastguard Worker 
79*4dc78e53SAndroid Build Coastguard Worker 	addr &= 0x03ff;
80*4dc78e53SAndroid Build Coastguard Worker 
81*4dc78e53SAndroid Build Coastguard Worker 	if (len == 0)
82*4dc78e53SAndroid Build Coastguard Worker 		return str;
83*4dc78e53SAndroid Build Coastguard Worker 
84*4dc78e53SAndroid Build Coastguard Worker 	if (do_digit(str + pos, &area, 10, &pos, len, &started))
85*4dc78e53SAndroid Build Coastguard Worker 		return str;
86*4dc78e53SAndroid Build Coastguard Worker 
87*4dc78e53SAndroid Build Coastguard Worker 	if (do_digit(str + pos, &area, 1, &pos, len, &started))
88*4dc78e53SAndroid Build Coastguard Worker 		return str;
89*4dc78e53SAndroid Build Coastguard Worker 
90*4dc78e53SAndroid Build Coastguard Worker 	if (pos == len)
91*4dc78e53SAndroid Build Coastguard Worker 		return str;
92*4dc78e53SAndroid Build Coastguard Worker 
93*4dc78e53SAndroid Build Coastguard Worker 	*(str + pos) = '.';
94*4dc78e53SAndroid Build Coastguard Worker 	pos++;
95*4dc78e53SAndroid Build Coastguard Worker 	started = 0;
96*4dc78e53SAndroid Build Coastguard Worker 
97*4dc78e53SAndroid Build Coastguard Worker 	if (do_digit(str + pos, &addr, 1000, &pos, len, &started))
98*4dc78e53SAndroid Build Coastguard Worker 		return str;
99*4dc78e53SAndroid Build Coastguard Worker 
100*4dc78e53SAndroid Build Coastguard Worker 	if (do_digit(str + pos, &addr, 100, &pos, len, &started))
101*4dc78e53SAndroid Build Coastguard Worker 		return str;
102*4dc78e53SAndroid Build Coastguard Worker 
103*4dc78e53SAndroid Build Coastguard Worker 	if (do_digit(str + pos, &addr, 10, &pos, len, &started))
104*4dc78e53SAndroid Build Coastguard Worker 		return str;
105*4dc78e53SAndroid Build Coastguard Worker 
106*4dc78e53SAndroid Build Coastguard Worker 	if (do_digit(str + pos, &addr, 1, &pos, len, &started))
107*4dc78e53SAndroid Build Coastguard Worker 		return str;
108*4dc78e53SAndroid Build Coastguard Worker 
109*4dc78e53SAndroid Build Coastguard Worker 	if (pos == len)
110*4dc78e53SAndroid Build Coastguard Worker 		return str;
111*4dc78e53SAndroid Build Coastguard Worker 
112*4dc78e53SAndroid Build Coastguard Worker 	*(str + pos) = 0;
113*4dc78e53SAndroid Build Coastguard Worker 
114*4dc78e53SAndroid Build Coastguard Worker 	return str;
115*4dc78e53SAndroid Build Coastguard Worker }
116*4dc78e53SAndroid Build Coastguard Worker 
dnet_num(const char * src,uint16_t * dst)117*4dc78e53SAndroid Build Coastguard Worker static int dnet_num(const char *src, uint16_t * dst)
118*4dc78e53SAndroid Build Coastguard Worker {
119*4dc78e53SAndroid Build Coastguard Worker 	int rv = 0;
120*4dc78e53SAndroid Build Coastguard Worker 	int tmp;
121*4dc78e53SAndroid Build Coastguard Worker 	*dst = 0;
122*4dc78e53SAndroid Build Coastguard Worker 
123*4dc78e53SAndroid Build Coastguard Worker 	while ((tmp = *src++) != 0) {
124*4dc78e53SAndroid Build Coastguard Worker 		tmp -= '0';
125*4dc78e53SAndroid Build Coastguard Worker 		if ((tmp < 0) || (tmp > 9))
126*4dc78e53SAndroid Build Coastguard Worker 			return rv;
127*4dc78e53SAndroid Build Coastguard Worker 
128*4dc78e53SAndroid Build Coastguard Worker 		rv++;
129*4dc78e53SAndroid Build Coastguard Worker 		(*dst) *= 10;
130*4dc78e53SAndroid Build Coastguard Worker 		(*dst) += tmp;
131*4dc78e53SAndroid Build Coastguard Worker 	}
132*4dc78e53SAndroid Build Coastguard Worker 
133*4dc78e53SAndroid Build Coastguard Worker 	return rv;
134*4dc78e53SAndroid Build Coastguard Worker }
135*4dc78e53SAndroid Build Coastguard Worker 
dnet_pton(const char * src,char * addrbuf)136*4dc78e53SAndroid Build Coastguard Worker static inline int dnet_pton(const char *src, char *addrbuf)
137*4dc78e53SAndroid Build Coastguard Worker {
138*4dc78e53SAndroid Build Coastguard Worker 	uint16_t area = 0;
139*4dc78e53SAndroid Build Coastguard Worker 	uint16_t node = 0;
140*4dc78e53SAndroid Build Coastguard Worker 	int pos;
141*4dc78e53SAndroid Build Coastguard Worker 
142*4dc78e53SAndroid Build Coastguard Worker 	pos = dnet_num(src, &area);
143*4dc78e53SAndroid Build Coastguard Worker 	if ((pos == 0) || (area > 63) ||
144*4dc78e53SAndroid Build Coastguard Worker 	    ((*(src + pos) != '.') && (*(src + pos) != ',')))
145*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
146*4dc78e53SAndroid Build Coastguard Worker 
147*4dc78e53SAndroid Build Coastguard Worker 	pos = dnet_num(src + pos + 1, &node);
148*4dc78e53SAndroid Build Coastguard Worker 	if ((pos == 0) || (node > 1023))
149*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
150*4dc78e53SAndroid Build Coastguard Worker 
151*4dc78e53SAndroid Build Coastguard Worker 	*(uint16_t *)addrbuf = dn_ntohs((area << 10) | node);
152*4dc78e53SAndroid Build Coastguard Worker 
153*4dc78e53SAndroid Build Coastguard Worker 	return 1;
154*4dc78e53SAndroid Build Coastguard Worker }
155*4dc78e53SAndroid Build Coastguard Worker 
addr_destroy(struct nl_addr * addr)156*4dc78e53SAndroid Build Coastguard Worker static void addr_destroy(struct nl_addr *addr)
157*4dc78e53SAndroid Build Coastguard Worker {
158*4dc78e53SAndroid Build Coastguard Worker 	if (!addr)
159*4dc78e53SAndroid Build Coastguard Worker 		return;
160*4dc78e53SAndroid Build Coastguard Worker 
161*4dc78e53SAndroid Build Coastguard Worker 	if (addr->a_refcnt != 1)
162*4dc78e53SAndroid Build Coastguard Worker 		BUG();
163*4dc78e53SAndroid Build Coastguard Worker 
164*4dc78e53SAndroid Build Coastguard Worker 	free(addr);
165*4dc78e53SAndroid Build Coastguard Worker }
166*4dc78e53SAndroid Build Coastguard Worker 
167*4dc78e53SAndroid Build Coastguard Worker /**
168*4dc78e53SAndroid Build Coastguard Worker  * @name Creating Abstract Network Addresses
169*4dc78e53SAndroid Build Coastguard Worker  * @{
170*4dc78e53SAndroid Build Coastguard Worker  */
171*4dc78e53SAndroid Build Coastguard Worker 
172*4dc78e53SAndroid Build Coastguard Worker /**
173*4dc78e53SAndroid Build Coastguard Worker  * Allocate empty abstract address
174*4dc78e53SAndroid Build Coastguard Worker  * @arg maxsize		Upper limit of the binary address to be stored
175*4dc78e53SAndroid Build Coastguard Worker  *
176*4dc78e53SAndroid Build Coastguard Worker  * The new address object will be empty with a prefix length of 0 and will
177*4dc78e53SAndroid Build Coastguard Worker  * be capable of holding binary addresses up to the specified limit.
178*4dc78e53SAndroid Build Coastguard Worker  *
179*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_build()
180*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_parse()
181*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_put()
182*4dc78e53SAndroid Build Coastguard Worker  *
183*4dc78e53SAndroid Build Coastguard Worker  * @return Allocated address object or NULL upon failure.
184*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_alloc(size_t maxsize)185*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *nl_addr_alloc(size_t maxsize)
186*4dc78e53SAndroid Build Coastguard Worker {
187*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *addr;
188*4dc78e53SAndroid Build Coastguard Worker 
189*4dc78e53SAndroid Build Coastguard Worker 	addr = calloc(1, sizeof(*addr) + maxsize);
190*4dc78e53SAndroid Build Coastguard Worker 	if (!addr)
191*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
192*4dc78e53SAndroid Build Coastguard Worker 
193*4dc78e53SAndroid Build Coastguard Worker 	addr->a_refcnt = 1;
194*4dc78e53SAndroid Build Coastguard Worker 	addr->a_maxsize = maxsize;
195*4dc78e53SAndroid Build Coastguard Worker 
196*4dc78e53SAndroid Build Coastguard Worker 	return addr;
197*4dc78e53SAndroid Build Coastguard Worker }
198*4dc78e53SAndroid Build Coastguard Worker 
199*4dc78e53SAndroid Build Coastguard Worker /**
200*4dc78e53SAndroid Build Coastguard Worker  * Allocate abstract address based on a binary address.
201*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Address family
202*4dc78e53SAndroid Build Coastguard Worker  * @arg buf		Binary address
203*4dc78e53SAndroid Build Coastguard Worker  * @arg size		Length of binary address
204*4dc78e53SAndroid Build Coastguard Worker  *
205*4dc78e53SAndroid Build Coastguard Worker  * This function will allocate an abstract address capable of holding the
206*4dc78e53SAndroid Build Coastguard Worker  * binary address specified. The prefix length will be set to the full
207*4dc78e53SAndroid Build Coastguard Worker  * length of the binary address provided.
208*4dc78e53SAndroid Build Coastguard Worker  *
209*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_alloc()
210*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_alloc_attr()
211*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_parse()
212*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_put()
213*4dc78e53SAndroid Build Coastguard Worker  *
214*4dc78e53SAndroid Build Coastguard Worker  * @return Allocated address object or NULL upon failure.
215*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_build(int family,const void * buf,size_t size)216*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *nl_addr_build(int family, const void *buf, size_t size)
217*4dc78e53SAndroid Build Coastguard Worker {
218*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *addr;
219*4dc78e53SAndroid Build Coastguard Worker 
220*4dc78e53SAndroid Build Coastguard Worker 	addr = nl_addr_alloc(size);
221*4dc78e53SAndroid Build Coastguard Worker 	if (!addr)
222*4dc78e53SAndroid Build Coastguard Worker 		return NULL;
223*4dc78e53SAndroid Build Coastguard Worker 
224*4dc78e53SAndroid Build Coastguard Worker 	addr->a_family = family;
225*4dc78e53SAndroid Build Coastguard Worker 	addr->a_len = size;
226*4dc78e53SAndroid Build Coastguard Worker 	switch(family) {
227*4dc78e53SAndroid Build Coastguard Worker 	case AF_MPLS:
228*4dc78e53SAndroid Build Coastguard Worker 		addr->a_prefixlen = 20;  /* MPLS address is a 20-bit label */
229*4dc78e53SAndroid Build Coastguard Worker 		break;
230*4dc78e53SAndroid Build Coastguard Worker 	default:
231*4dc78e53SAndroid Build Coastguard Worker 		addr->a_prefixlen = size*8;
232*4dc78e53SAndroid Build Coastguard Worker 	}
233*4dc78e53SAndroid Build Coastguard Worker 
234*4dc78e53SAndroid Build Coastguard Worker 	if (size && buf)
235*4dc78e53SAndroid Build Coastguard Worker 		memcpy(addr->a_addr, buf, size);
236*4dc78e53SAndroid Build Coastguard Worker 
237*4dc78e53SAndroid Build Coastguard Worker 	return addr;
238*4dc78e53SAndroid Build Coastguard Worker }
239*4dc78e53SAndroid Build Coastguard Worker 
240*4dc78e53SAndroid Build Coastguard Worker /**
241*4dc78e53SAndroid Build Coastguard Worker  * Allocate abstract address based on Netlink attribute.
242*4dc78e53SAndroid Build Coastguard Worker  * @arg nla		Netlink attribute
243*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Address family.
244*4dc78e53SAndroid Build Coastguard Worker  *
245*4dc78e53SAndroid Build Coastguard Worker  * Allocates an abstract address based on the specified Netlink attribute
246*4dc78e53SAndroid Build Coastguard Worker  * by interpreting the payload of the Netlink attribute as the binary
247*4dc78e53SAndroid Build Coastguard Worker  * address.
248*4dc78e53SAndroid Build Coastguard Worker  *
249*4dc78e53SAndroid Build Coastguard Worker  * This function is identical to:
250*4dc78e53SAndroid Build Coastguard Worker  * @code
251*4dc78e53SAndroid Build Coastguard Worker  * nl_addr_build(family, nla_data(nla), nla_len(nla));
252*4dc78e53SAndroid Build Coastguard Worker  * @endcode
253*4dc78e53SAndroid Build Coastguard Worker  *
254*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_alloc()
255*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_build()
256*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_parse()
257*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_put()
258*4dc78e53SAndroid Build Coastguard Worker  *
259*4dc78e53SAndroid Build Coastguard Worker  * @return Allocated address object or NULL upon failure.
260*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_alloc_attr(const struct nlattr * nla,int family)261*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *nl_addr_alloc_attr(const struct nlattr *nla, int family)
262*4dc78e53SAndroid Build Coastguard Worker {
263*4dc78e53SAndroid Build Coastguard Worker 	return nl_addr_build(family, nla_data(nla), nla_len(nla));
264*4dc78e53SAndroid Build Coastguard Worker }
265*4dc78e53SAndroid Build Coastguard Worker 
266*4dc78e53SAndroid Build Coastguard Worker /**
267*4dc78e53SAndroid Build Coastguard Worker  * Allocate abstract address based on character string
268*4dc78e53SAndroid Build Coastguard Worker  * @arg addrstr		Address represented as character string.
269*4dc78e53SAndroid Build Coastguard Worker  * @arg hint		Address family hint or AF_UNSPEC.
270*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting address.
271*4dc78e53SAndroid Build Coastguard Worker  *
272*4dc78e53SAndroid Build Coastguard Worker  * Regognizes the following address formats:
273*4dc78e53SAndroid Build Coastguard Worker  * @code
274*4dc78e53SAndroid Build Coastguard Worker  *  Format                      Len                Family
275*4dc78e53SAndroid Build Coastguard Worker  *  ----------------------------------------------------------------
276*4dc78e53SAndroid Build Coastguard Worker  *  IPv6 address format         16                 AF_INET6
277*4dc78e53SAndroid Build Coastguard Worker  *  ddd.ddd.ddd.ddd             4                  AF_INET
278*4dc78e53SAndroid Build Coastguard Worker  *  HH:HH:HH:HH:HH:HH           6                  AF_LLC
279*4dc78e53SAndroid Build Coastguard Worker  *  AA{.|,}NNNN                 2                  AF_DECnet
280*4dc78e53SAndroid Build Coastguard Worker  *  HH:HH:HH:...                variable           AF_UNSPEC
281*4dc78e53SAndroid Build Coastguard Worker  * @endcode
282*4dc78e53SAndroid Build Coastguard Worker  *
283*4dc78e53SAndroid Build Coastguard Worker  *  Special values:
284*4dc78e53SAndroid Build Coastguard Worker  *    - none: All bits and length set to 0.
285*4dc78e53SAndroid Build Coastguard Worker  *    - {default|all|any}: All bits set to 0, length based on hint or
286*4dc78e53SAndroid Build Coastguard Worker  *                         AF_INET if no hint is given.
287*4dc78e53SAndroid Build Coastguard Worker  *
288*4dc78e53SAndroid Build Coastguard Worker  * The prefix length may be appened at the end prefixed with a
289*4dc78e53SAndroid Build Coastguard Worker  * slash, e.g. 10.0.0.0/8.
290*4dc78e53SAndroid Build Coastguard Worker  *
291*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_alloc()
292*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_build()
293*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_put()
294*4dc78e53SAndroid Build Coastguard Worker  *
295*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
296*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_parse(const char * addrstr,int hint,struct nl_addr ** result)297*4dc78e53SAndroid Build Coastguard Worker int nl_addr_parse(const char *addrstr, int hint, struct nl_addr **result)
298*4dc78e53SAndroid Build Coastguard Worker {
299*4dc78e53SAndroid Build Coastguard Worker 	int err, copy = 0, len = 0, family = AF_UNSPEC, plen = 0;
300*4dc78e53SAndroid Build Coastguard Worker 	char *str, *prefix = NULL, buf[256];
301*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *addr = NULL; /* gcc ain't that smart */
302*4dc78e53SAndroid Build Coastguard Worker 
303*4dc78e53SAndroid Build Coastguard Worker 	str = strdup(addrstr);
304*4dc78e53SAndroid Build Coastguard Worker 	if (!str) {
305*4dc78e53SAndroid Build Coastguard Worker 		err = -NLE_NOMEM;
306*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
307*4dc78e53SAndroid Build Coastguard Worker 	}
308*4dc78e53SAndroid Build Coastguard Worker 
309*4dc78e53SAndroid Build Coastguard Worker 	if (hint != AF_MPLS) {
310*4dc78e53SAndroid Build Coastguard Worker 		prefix = strchr(str, '/');
311*4dc78e53SAndroid Build Coastguard Worker 		if (prefix)
312*4dc78e53SAndroid Build Coastguard Worker 			*prefix = '\0';
313*4dc78e53SAndroid Build Coastguard Worker 	}
314*4dc78e53SAndroid Build Coastguard Worker 
315*4dc78e53SAndroid Build Coastguard Worker 	if (!strcasecmp(str, "none")) {
316*4dc78e53SAndroid Build Coastguard Worker 		family = hint;
317*4dc78e53SAndroid Build Coastguard Worker 		goto prefix;
318*4dc78e53SAndroid Build Coastguard Worker 	}
319*4dc78e53SAndroid Build Coastguard Worker 
320*4dc78e53SAndroid Build Coastguard Worker 	if (!strcasecmp(str, "default") ||
321*4dc78e53SAndroid Build Coastguard Worker 	    !strcasecmp(str, "all") ||
322*4dc78e53SAndroid Build Coastguard Worker 	    !strcasecmp(str, "any")) {
323*4dc78e53SAndroid Build Coastguard Worker 
324*4dc78e53SAndroid Build Coastguard Worker 		switch (hint) {
325*4dc78e53SAndroid Build Coastguard Worker 			case AF_INET:
326*4dc78e53SAndroid Build Coastguard Worker 			case AF_UNSPEC:
327*4dc78e53SAndroid Build Coastguard Worker 				/* Kind of a hack, we assume that if there is
328*4dc78e53SAndroid Build Coastguard Worker 				 * no hint given the user wants to have a IPv4
329*4dc78e53SAndroid Build Coastguard Worker 				 * address given back. */
330*4dc78e53SAndroid Build Coastguard Worker 				family = AF_INET;
331*4dc78e53SAndroid Build Coastguard Worker 				len = 4;
332*4dc78e53SAndroid Build Coastguard Worker 				goto prefix;
333*4dc78e53SAndroid Build Coastguard Worker 
334*4dc78e53SAndroid Build Coastguard Worker 			case AF_INET6:
335*4dc78e53SAndroid Build Coastguard Worker 				family = AF_INET6;
336*4dc78e53SAndroid Build Coastguard Worker 				len = 16;
337*4dc78e53SAndroid Build Coastguard Worker 				goto prefix;
338*4dc78e53SAndroid Build Coastguard Worker 
339*4dc78e53SAndroid Build Coastguard Worker 			case AF_LLC:
340*4dc78e53SAndroid Build Coastguard Worker 				family = AF_LLC;
341*4dc78e53SAndroid Build Coastguard Worker 				len = 6;
342*4dc78e53SAndroid Build Coastguard Worker 				goto prefix;
343*4dc78e53SAndroid Build Coastguard Worker 
344*4dc78e53SAndroid Build Coastguard Worker 			default:
345*4dc78e53SAndroid Build Coastguard Worker 				err = -NLE_AF_NOSUPPORT;
346*4dc78e53SAndroid Build Coastguard Worker 				goto errout;
347*4dc78e53SAndroid Build Coastguard Worker 		}
348*4dc78e53SAndroid Build Coastguard Worker 	}
349*4dc78e53SAndroid Build Coastguard Worker 
350*4dc78e53SAndroid Build Coastguard Worker 	copy = 1;
351*4dc78e53SAndroid Build Coastguard Worker 
352*4dc78e53SAndroid Build Coastguard Worker 	if (hint == AF_INET || hint == AF_UNSPEC) {
353*4dc78e53SAndroid Build Coastguard Worker 		if (inet_pton(AF_INET, str, buf) > 0) {
354*4dc78e53SAndroid Build Coastguard Worker 			family = AF_INET;
355*4dc78e53SAndroid Build Coastguard Worker 			len = 4;
356*4dc78e53SAndroid Build Coastguard Worker 			goto prefix;
357*4dc78e53SAndroid Build Coastguard Worker 		}
358*4dc78e53SAndroid Build Coastguard Worker 		if (hint == AF_INET) {
359*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_NOADDR;
360*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
361*4dc78e53SAndroid Build Coastguard Worker 		}
362*4dc78e53SAndroid Build Coastguard Worker 	}
363*4dc78e53SAndroid Build Coastguard Worker 
364*4dc78e53SAndroid Build Coastguard Worker 	if (hint == AF_INET6 || hint == AF_UNSPEC) {
365*4dc78e53SAndroid Build Coastguard Worker 		if (inet_pton(AF_INET6, str, buf) > 0) {
366*4dc78e53SAndroid Build Coastguard Worker 			family = AF_INET6;
367*4dc78e53SAndroid Build Coastguard Worker 			len = 16;
368*4dc78e53SAndroid Build Coastguard Worker 			goto prefix;
369*4dc78e53SAndroid Build Coastguard Worker 		}
370*4dc78e53SAndroid Build Coastguard Worker 		if (hint == AF_INET6) {
371*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_NOADDR;
372*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
373*4dc78e53SAndroid Build Coastguard Worker 		}
374*4dc78e53SAndroid Build Coastguard Worker 	}
375*4dc78e53SAndroid Build Coastguard Worker 
376*4dc78e53SAndroid Build Coastguard Worker 	if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) {
377*4dc78e53SAndroid Build Coastguard Worker 		unsigned int a, b, c, d, e, f;
378*4dc78e53SAndroid Build Coastguard Worker 
379*4dc78e53SAndroid Build Coastguard Worker 		if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
380*4dc78e53SAndroid Build Coastguard Worker 		    &a, &b, &c, &d, &e, &f) == 6) {
381*4dc78e53SAndroid Build Coastguard Worker 			family = AF_LLC;
382*4dc78e53SAndroid Build Coastguard Worker 			len = 6;
383*4dc78e53SAndroid Build Coastguard Worker 			buf[0] = (unsigned char) a;
384*4dc78e53SAndroid Build Coastguard Worker 			buf[1] = (unsigned char) b;
385*4dc78e53SAndroid Build Coastguard Worker 			buf[2] = (unsigned char) c;
386*4dc78e53SAndroid Build Coastguard Worker 			buf[3] = (unsigned char) d;
387*4dc78e53SAndroid Build Coastguard Worker 			buf[4] = (unsigned char) e;
388*4dc78e53SAndroid Build Coastguard Worker 			buf[5] = (unsigned char) f;
389*4dc78e53SAndroid Build Coastguard Worker 			goto prefix;
390*4dc78e53SAndroid Build Coastguard Worker 		}
391*4dc78e53SAndroid Build Coastguard Worker 
392*4dc78e53SAndroid Build Coastguard Worker 		if (hint == AF_LLC) {
393*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_NOADDR;
394*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
395*4dc78e53SAndroid Build Coastguard Worker 		}
396*4dc78e53SAndroid Build Coastguard Worker 	}
397*4dc78e53SAndroid Build Coastguard Worker 
398*4dc78e53SAndroid Build Coastguard Worker 	if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
399*4dc78e53SAndroid Build Coastguard Worker 	    (strchr(str, '.') || strchr(str, ','))) {
400*4dc78e53SAndroid Build Coastguard Worker 		if (dnet_pton(str, buf) > 0) {
401*4dc78e53SAndroid Build Coastguard Worker 			family = AF_DECnet;
402*4dc78e53SAndroid Build Coastguard Worker 			len = 2;
403*4dc78e53SAndroid Build Coastguard Worker 			goto prefix;
404*4dc78e53SAndroid Build Coastguard Worker 		}
405*4dc78e53SAndroid Build Coastguard Worker 		if (hint == AF_DECnet) {
406*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_NOADDR;
407*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
408*4dc78e53SAndroid Build Coastguard Worker 		}
409*4dc78e53SAndroid Build Coastguard Worker 	}
410*4dc78e53SAndroid Build Coastguard Worker 
411*4dc78e53SAndroid Build Coastguard Worker 	if (hint == AF_MPLS) {
412*4dc78e53SAndroid Build Coastguard Worker 		len = mpls_pton(AF_MPLS, str, buf, sizeof(buf));
413*4dc78e53SAndroid Build Coastguard Worker 		if (len <= 0) {
414*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_INVAL;
415*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
416*4dc78e53SAndroid Build Coastguard Worker 		}
417*4dc78e53SAndroid Build Coastguard Worker 		family = AF_MPLS;
418*4dc78e53SAndroid Build Coastguard Worker 		plen = 20;
419*4dc78e53SAndroid Build Coastguard Worker 		goto prefix;
420*4dc78e53SAndroid Build Coastguard Worker 	}
421*4dc78e53SAndroid Build Coastguard Worker 
422*4dc78e53SAndroid Build Coastguard Worker 	if (hint == AF_UNSPEC && strchr(str, ':')) {
423*4dc78e53SAndroid Build Coastguard Worker 		size_t i = 0;
424*4dc78e53SAndroid Build Coastguard Worker 		char *s = str, *p;
425*4dc78e53SAndroid Build Coastguard Worker 		for (;;) {
426*4dc78e53SAndroid Build Coastguard Worker 			long l = strtol(s, &p, 16);
427*4dc78e53SAndroid Build Coastguard Worker 
428*4dc78e53SAndroid Build Coastguard Worker 			if (s == p || l > 0xff || i >= sizeof(buf)) {
429*4dc78e53SAndroid Build Coastguard Worker 				err = -NLE_INVAL;
430*4dc78e53SAndroid Build Coastguard Worker 				goto errout;
431*4dc78e53SAndroid Build Coastguard Worker 			}
432*4dc78e53SAndroid Build Coastguard Worker 
433*4dc78e53SAndroid Build Coastguard Worker 			buf[i++] = (unsigned char) l;
434*4dc78e53SAndroid Build Coastguard Worker 			if (*p == '\0')
435*4dc78e53SAndroid Build Coastguard Worker 				break;
436*4dc78e53SAndroid Build Coastguard Worker 			s = ++p;
437*4dc78e53SAndroid Build Coastguard Worker 		}
438*4dc78e53SAndroid Build Coastguard Worker 
439*4dc78e53SAndroid Build Coastguard Worker 		len = i;
440*4dc78e53SAndroid Build Coastguard Worker 		family = AF_UNSPEC;
441*4dc78e53SAndroid Build Coastguard Worker 		goto prefix;
442*4dc78e53SAndroid Build Coastguard Worker 	}
443*4dc78e53SAndroid Build Coastguard Worker 
444*4dc78e53SAndroid Build Coastguard Worker 	err = -NLE_NOADDR;
445*4dc78e53SAndroid Build Coastguard Worker 	goto errout;
446*4dc78e53SAndroid Build Coastguard Worker 
447*4dc78e53SAndroid Build Coastguard Worker prefix:
448*4dc78e53SAndroid Build Coastguard Worker 	addr = nl_addr_alloc(len);
449*4dc78e53SAndroid Build Coastguard Worker 	if (!addr) {
450*4dc78e53SAndroid Build Coastguard Worker 		err = -NLE_NOMEM;
451*4dc78e53SAndroid Build Coastguard Worker 		goto errout;
452*4dc78e53SAndroid Build Coastguard Worker 	}
453*4dc78e53SAndroid Build Coastguard Worker 
454*4dc78e53SAndroid Build Coastguard Worker 	nl_addr_set_family(addr, family);
455*4dc78e53SAndroid Build Coastguard Worker 
456*4dc78e53SAndroid Build Coastguard Worker 	if (copy)
457*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_binary_addr(addr, buf, len);
458*4dc78e53SAndroid Build Coastguard Worker 	else
459*4dc78e53SAndroid Build Coastguard Worker 		addr->a_len = len;
460*4dc78e53SAndroid Build Coastguard Worker 
461*4dc78e53SAndroid Build Coastguard Worker 	if (prefix) {
462*4dc78e53SAndroid Build Coastguard Worker 		char *p;
463*4dc78e53SAndroid Build Coastguard Worker 		long pl = strtol(++prefix, &p, 0);
464*4dc78e53SAndroid Build Coastguard Worker 		if (p == prefix) {
465*4dc78e53SAndroid Build Coastguard Worker 			addr_destroy(addr);
466*4dc78e53SAndroid Build Coastguard Worker 			err = -NLE_INVAL;
467*4dc78e53SAndroid Build Coastguard Worker 			goto errout;
468*4dc78e53SAndroid Build Coastguard Worker 		}
469*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_prefixlen(addr, pl);
470*4dc78e53SAndroid Build Coastguard Worker 	} else {
471*4dc78e53SAndroid Build Coastguard Worker 		if (copy && !plen)
472*4dc78e53SAndroid Build Coastguard Worker 			plen = len * 8;
473*4dc78e53SAndroid Build Coastguard Worker 		nl_addr_set_prefixlen(addr, plen);
474*4dc78e53SAndroid Build Coastguard Worker 	}
475*4dc78e53SAndroid Build Coastguard Worker 	*result = addr;
476*4dc78e53SAndroid Build Coastguard Worker 	err = 0;
477*4dc78e53SAndroid Build Coastguard Worker errout:
478*4dc78e53SAndroid Build Coastguard Worker 	free(str);
479*4dc78e53SAndroid Build Coastguard Worker 
480*4dc78e53SAndroid Build Coastguard Worker 	return err;
481*4dc78e53SAndroid Build Coastguard Worker }
482*4dc78e53SAndroid Build Coastguard Worker 
483*4dc78e53SAndroid Build Coastguard Worker /**
484*4dc78e53SAndroid Build Coastguard Worker  * Clone existing abstract address object
485*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object
486*4dc78e53SAndroid Build Coastguard Worker  *
487*4dc78e53SAndroid Build Coastguard Worker  * Allocates new abstract address representing an identical clone of an
488*4dc78e53SAndroid Build Coastguard Worker  * existing address.
489*4dc78e53SAndroid Build Coastguard Worker  *
490*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_alloc()
491*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_put()
492*4dc78e53SAndroid Build Coastguard Worker  *
493*4dc78e53SAndroid Build Coastguard Worker  * @return Allocated abstract address or NULL upon failure.
494*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_clone(const struct nl_addr * addr)495*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *nl_addr_clone(const struct nl_addr *addr)
496*4dc78e53SAndroid Build Coastguard Worker {
497*4dc78e53SAndroid Build Coastguard Worker 	struct nl_addr *new;
498*4dc78e53SAndroid Build Coastguard Worker 
499*4dc78e53SAndroid Build Coastguard Worker 	new = nl_addr_build(addr->a_family, addr->a_addr, addr->a_len);
500*4dc78e53SAndroid Build Coastguard Worker 	if (new)
501*4dc78e53SAndroid Build Coastguard Worker 		new->a_prefixlen = addr->a_prefixlen;
502*4dc78e53SAndroid Build Coastguard Worker 
503*4dc78e53SAndroid Build Coastguard Worker 	return new;
504*4dc78e53SAndroid Build Coastguard Worker }
505*4dc78e53SAndroid Build Coastguard Worker 
506*4dc78e53SAndroid Build Coastguard Worker /** @} */
507*4dc78e53SAndroid Build Coastguard Worker 
508*4dc78e53SAndroid Build Coastguard Worker /**
509*4dc78e53SAndroid Build Coastguard Worker  * @name Managing Usage References
510*4dc78e53SAndroid Build Coastguard Worker  * @{
511*4dc78e53SAndroid Build Coastguard Worker  */
512*4dc78e53SAndroid Build Coastguard Worker 
513*4dc78e53SAndroid Build Coastguard Worker /**
514*4dc78e53SAndroid Build Coastguard Worker  * Increase the reference counter of an abstract address
515*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address
516*4dc78e53SAndroid Build Coastguard Worker  *
517*4dc78e53SAndroid Build Coastguard Worker  * Increases the reference counter of the address and thus prevents the
518*4dc78e53SAndroid Build Coastguard Worker  * release of the memory resources until the reference is given back
519*4dc78e53SAndroid Build Coastguard Worker  * using the function nl_addr_put().
520*4dc78e53SAndroid Build Coastguard Worker  *
521*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_put()
522*4dc78e53SAndroid Build Coastguard Worker  *
523*4dc78e53SAndroid Build Coastguard Worker  * @return Pointer to the existing abstract address
524*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_get(struct nl_addr * addr)525*4dc78e53SAndroid Build Coastguard Worker struct nl_addr *nl_addr_get(struct nl_addr *addr)
526*4dc78e53SAndroid Build Coastguard Worker {
527*4dc78e53SAndroid Build Coastguard Worker 	addr->a_refcnt++;
528*4dc78e53SAndroid Build Coastguard Worker 
529*4dc78e53SAndroid Build Coastguard Worker 	return addr;
530*4dc78e53SAndroid Build Coastguard Worker }
531*4dc78e53SAndroid Build Coastguard Worker 
532*4dc78e53SAndroid Build Coastguard Worker /**
533*4dc78e53SAndroid Build Coastguard Worker  * Decrease the reference counter of an abstract address
534*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract addr
535*4dc78e53SAndroid Build Coastguard Worker  *
536*4dc78e53SAndroid Build Coastguard Worker  * @note The resources of the abstract address will be freed after the
537*4dc78e53SAndroid Build Coastguard Worker  *       last reference to the address has been returned.
538*4dc78e53SAndroid Build Coastguard Worker  *
539*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_get()
540*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_put(struct nl_addr * addr)541*4dc78e53SAndroid Build Coastguard Worker void nl_addr_put(struct nl_addr *addr)
542*4dc78e53SAndroid Build Coastguard Worker {
543*4dc78e53SAndroid Build Coastguard Worker 	if (!addr)
544*4dc78e53SAndroid Build Coastguard Worker 		return;
545*4dc78e53SAndroid Build Coastguard Worker 
546*4dc78e53SAndroid Build Coastguard Worker 	if (addr->a_refcnt == 1)
547*4dc78e53SAndroid Build Coastguard Worker 		addr_destroy(addr);
548*4dc78e53SAndroid Build Coastguard Worker 	else
549*4dc78e53SAndroid Build Coastguard Worker 		addr->a_refcnt--;
550*4dc78e53SAndroid Build Coastguard Worker }
551*4dc78e53SAndroid Build Coastguard Worker 
552*4dc78e53SAndroid Build Coastguard Worker /**
553*4dc78e53SAndroid Build Coastguard Worker  * Check whether an abstract address is shared.
554*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
555*4dc78e53SAndroid Build Coastguard Worker  *
556*4dc78e53SAndroid Build Coastguard Worker  * @return Non-zero if the abstract address is shared, otherwise 0.
557*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_shared(const struct nl_addr * addr)558*4dc78e53SAndroid Build Coastguard Worker int nl_addr_shared(const struct nl_addr *addr)
559*4dc78e53SAndroid Build Coastguard Worker {
560*4dc78e53SAndroid Build Coastguard Worker 	return addr->a_refcnt > 1;
561*4dc78e53SAndroid Build Coastguard Worker }
562*4dc78e53SAndroid Build Coastguard Worker 
563*4dc78e53SAndroid Build Coastguard Worker /** @} */
564*4dc78e53SAndroid Build Coastguard Worker 
565*4dc78e53SAndroid Build Coastguard Worker /**
566*4dc78e53SAndroid Build Coastguard Worker  * @name Miscellaneous
567*4dc78e53SAndroid Build Coastguard Worker  * @{
568*4dc78e53SAndroid Build Coastguard Worker  */
569*4dc78e53SAndroid Build Coastguard Worker 
570*4dc78e53SAndroid Build Coastguard Worker /**
571*4dc78e53SAndroid Build Coastguard Worker  * Compare abstract addresses
572*4dc78e53SAndroid Build Coastguard Worker  * @arg a		An abstract address
573*4dc78e53SAndroid Build Coastguard Worker  * @arg b		Another abstract address
574*4dc78e53SAndroid Build Coastguard Worker  *
575*4dc78e53SAndroid Build Coastguard Worker  * Verifies whether the address family, address length, prefix length, and
576*4dc78e53SAndroid Build Coastguard Worker  * binary addresses of two abstract addresses matches.
577*4dc78e53SAndroid Build Coastguard Worker  *
578*4dc78e53SAndroid Build Coastguard Worker  * @note This function will *not* respect the prefix length in the sense
579*4dc78e53SAndroid Build Coastguard Worker  *       that only the actual prefix will be compared. Please refer to the
580*4dc78e53SAndroid Build Coastguard Worker  *       nl_addr_cmp_prefix() function if you require this functionality.
581*4dc78e53SAndroid Build Coastguard Worker  *
582*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_cmp_prefix()
583*4dc78e53SAndroid Build Coastguard Worker  *
584*4dc78e53SAndroid Build Coastguard Worker  * @return Integer less than, equal to or greather than zero if the two
585*4dc78e53SAndroid Build Coastguard Worker  *         addresses match.
586*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_cmp(const struct nl_addr * a,const struct nl_addr * b)587*4dc78e53SAndroid Build Coastguard Worker int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
588*4dc78e53SAndroid Build Coastguard Worker {
589*4dc78e53SAndroid Build Coastguard Worker 	int d;
590*4dc78e53SAndroid Build Coastguard Worker 
591*4dc78e53SAndroid Build Coastguard Worker 	if (a == b)
592*4dc78e53SAndroid Build Coastguard Worker 		return 0;
593*4dc78e53SAndroid Build Coastguard Worker 	if (!a)
594*4dc78e53SAndroid Build Coastguard Worker 		return -1;
595*4dc78e53SAndroid Build Coastguard Worker 	if (!b)
596*4dc78e53SAndroid Build Coastguard Worker 		return 1;
597*4dc78e53SAndroid Build Coastguard Worker 
598*4dc78e53SAndroid Build Coastguard Worker 	d = a->a_family - b->a_family;
599*4dc78e53SAndroid Build Coastguard Worker 	if (d == 0) {
600*4dc78e53SAndroid Build Coastguard Worker 		d = a->a_len - b->a_len;
601*4dc78e53SAndroid Build Coastguard Worker 
602*4dc78e53SAndroid Build Coastguard Worker 		if (a->a_len && d == 0) {
603*4dc78e53SAndroid Build Coastguard Worker 			d = memcmp(a->a_addr, b->a_addr, a->a_len);
604*4dc78e53SAndroid Build Coastguard Worker 
605*4dc78e53SAndroid Build Coastguard Worker 			if (d == 0)
606*4dc78e53SAndroid Build Coastguard Worker 				return (a->a_prefixlen - b->a_prefixlen);
607*4dc78e53SAndroid Build Coastguard Worker 		}
608*4dc78e53SAndroid Build Coastguard Worker 	}
609*4dc78e53SAndroid Build Coastguard Worker 
610*4dc78e53SAndroid Build Coastguard Worker 	return d;
611*4dc78e53SAndroid Build Coastguard Worker }
612*4dc78e53SAndroid Build Coastguard Worker 
613*4dc78e53SAndroid Build Coastguard Worker /**
614*4dc78e53SAndroid Build Coastguard Worker  * Compare the prefix of two abstract addresses
615*4dc78e53SAndroid Build Coastguard Worker  * @arg a		An abstract address
616*4dc78e53SAndroid Build Coastguard Worker  * @arg b		Another abstract address
617*4dc78e53SAndroid Build Coastguard Worker  *
618*4dc78e53SAndroid Build Coastguard Worker  * Verifies whether the address family and the binary address covered by
619*4dc78e53SAndroid Build Coastguard Worker  * the smaller prefix length of the two abstract addresses matches.
620*4dc78e53SAndroid Build Coastguard Worker  *
621*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_cmp()
622*4dc78e53SAndroid Build Coastguard Worker  *
623*4dc78e53SAndroid Build Coastguard Worker  * @return Integer less than, equal to or greather than zero if the two
624*4dc78e53SAndroid Build Coastguard Worker  *         addresses match.
625*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_cmp_prefix(const struct nl_addr * a,const struct nl_addr * b)626*4dc78e53SAndroid Build Coastguard Worker int nl_addr_cmp_prefix(const struct nl_addr *a, const struct nl_addr *b)
627*4dc78e53SAndroid Build Coastguard Worker {
628*4dc78e53SAndroid Build Coastguard Worker 	int d = a->a_family - b->a_family;
629*4dc78e53SAndroid Build Coastguard Worker 
630*4dc78e53SAndroid Build Coastguard Worker 	if (d == 0) {
631*4dc78e53SAndroid Build Coastguard Worker 		int len = _NL_MIN(a->a_prefixlen, b->a_prefixlen);
632*4dc78e53SAndroid Build Coastguard Worker 		int bytes = len / 8;
633*4dc78e53SAndroid Build Coastguard Worker 
634*4dc78e53SAndroid Build Coastguard Worker 		d = memcmp(a->a_addr, b->a_addr, bytes);
635*4dc78e53SAndroid Build Coastguard Worker 		if (d == 0 && (len % 8) != 0) {
636*4dc78e53SAndroid Build Coastguard Worker 			int mask = (0xFF00 >> (len % 8)) & 0xFF;
637*4dc78e53SAndroid Build Coastguard Worker 
638*4dc78e53SAndroid Build Coastguard Worker 			d = (a->a_addr[bytes] & mask) -
639*4dc78e53SAndroid Build Coastguard Worker 			    (b->a_addr[bytes] & mask);
640*4dc78e53SAndroid Build Coastguard Worker 		}
641*4dc78e53SAndroid Build Coastguard Worker 	}
642*4dc78e53SAndroid Build Coastguard Worker 
643*4dc78e53SAndroid Build Coastguard Worker 	return d;
644*4dc78e53SAndroid Build Coastguard Worker }
645*4dc78e53SAndroid Build Coastguard Worker 
646*4dc78e53SAndroid Build Coastguard Worker /**
647*4dc78e53SAndroid Build Coastguard Worker  * Returns true if the address consists of all zeros
648*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address
649*4dc78e53SAndroid Build Coastguard Worker  *
650*4dc78e53SAndroid Build Coastguard Worker  * @return 1 if the binary address consists of all zeros, 0 otherwise.
651*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_iszero(const struct nl_addr * addr)652*4dc78e53SAndroid Build Coastguard Worker int nl_addr_iszero(const struct nl_addr *addr)
653*4dc78e53SAndroid Build Coastguard Worker {
654*4dc78e53SAndroid Build Coastguard Worker 	unsigned int i;
655*4dc78e53SAndroid Build Coastguard Worker 
656*4dc78e53SAndroid Build Coastguard Worker 	for (i = 0; i < addr->a_len; i++)
657*4dc78e53SAndroid Build Coastguard Worker 		if (addr->a_addr[i])
658*4dc78e53SAndroid Build Coastguard Worker 			return 0;
659*4dc78e53SAndroid Build Coastguard Worker 
660*4dc78e53SAndroid Build Coastguard Worker 	return 1;
661*4dc78e53SAndroid Build Coastguard Worker }
662*4dc78e53SAndroid Build Coastguard Worker 
663*4dc78e53SAndroid Build Coastguard Worker /**
664*4dc78e53SAndroid Build Coastguard Worker  * Check if address string is parseable for a specific address family
665*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Address represented as character string.
666*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Desired address family.
667*4dc78e53SAndroid Build Coastguard Worker  *
668*4dc78e53SAndroid Build Coastguard Worker  * @return 1 if the address is parseable assuming the specified address family,
669*4dc78e53SAndroid Build Coastguard Worker  *         otherwise 0 is returned.
670*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_valid(const char * addr,int family)671*4dc78e53SAndroid Build Coastguard Worker int nl_addr_valid(const char *addr, int family)
672*4dc78e53SAndroid Build Coastguard Worker {
673*4dc78e53SAndroid Build Coastguard Worker 	int ret;
674*4dc78e53SAndroid Build Coastguard Worker 	char buf[256]; /* MPLS has N-labels at 4-bytes / label */
675*4dc78e53SAndroid Build Coastguard Worker 
676*4dc78e53SAndroid Build Coastguard Worker 	switch (family) {
677*4dc78e53SAndroid Build Coastguard Worker 	case AF_INET:
678*4dc78e53SAndroid Build Coastguard Worker 	case AF_INET6:
679*4dc78e53SAndroid Build Coastguard Worker 		ret = inet_pton(family, addr, buf);
680*4dc78e53SAndroid Build Coastguard Worker 		if (ret <= 0)
681*4dc78e53SAndroid Build Coastguard Worker 			return 0;
682*4dc78e53SAndroid Build Coastguard Worker 		break;
683*4dc78e53SAndroid Build Coastguard Worker 
684*4dc78e53SAndroid Build Coastguard Worker 	case AF_MPLS:
685*4dc78e53SAndroid Build Coastguard Worker 		ret = mpls_pton(family, addr, buf, sizeof(buf));
686*4dc78e53SAndroid Build Coastguard Worker 		if (ret <= 0)
687*4dc78e53SAndroid Build Coastguard Worker 			return 0;
688*4dc78e53SAndroid Build Coastguard Worker 		break;
689*4dc78e53SAndroid Build Coastguard Worker 
690*4dc78e53SAndroid Build Coastguard Worker 	case AF_DECnet:
691*4dc78e53SAndroid Build Coastguard Worker 		ret = dnet_pton(addr, buf);
692*4dc78e53SAndroid Build Coastguard Worker 		if (ret <= 0)
693*4dc78e53SAndroid Build Coastguard Worker 			return 0;
694*4dc78e53SAndroid Build Coastguard Worker 		break;
695*4dc78e53SAndroid Build Coastguard Worker 
696*4dc78e53SAndroid Build Coastguard Worker 	case AF_LLC:
697*4dc78e53SAndroid Build Coastguard Worker 		if (sscanf(addr, "%*02x:%*02x:%*02x:%*02x:%*02x:%*02x") != 6)
698*4dc78e53SAndroid Build Coastguard Worker 			return 0;
699*4dc78e53SAndroid Build Coastguard Worker 		break;
700*4dc78e53SAndroid Build Coastguard Worker 	}
701*4dc78e53SAndroid Build Coastguard Worker 
702*4dc78e53SAndroid Build Coastguard Worker 	return 1;
703*4dc78e53SAndroid Build Coastguard Worker }
704*4dc78e53SAndroid Build Coastguard Worker 
705*4dc78e53SAndroid Build Coastguard Worker /**
706*4dc78e53SAndroid Build Coastguard Worker  * Guess address family of abstract address based on address size
707*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
708*4dc78e53SAndroid Build Coastguard Worker  *
709*4dc78e53SAndroid Build Coastguard Worker  * @return Numeric address family or AF_UNSPEC
710*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_guess_family(const struct nl_addr * addr)711*4dc78e53SAndroid Build Coastguard Worker int nl_addr_guess_family(const struct nl_addr *addr)
712*4dc78e53SAndroid Build Coastguard Worker {
713*4dc78e53SAndroid Build Coastguard Worker 	switch (addr->a_len) {
714*4dc78e53SAndroid Build Coastguard Worker 		case 4:
715*4dc78e53SAndroid Build Coastguard Worker 			return AF_INET;
716*4dc78e53SAndroid Build Coastguard Worker 		case 6:
717*4dc78e53SAndroid Build Coastguard Worker 			return AF_LLC;
718*4dc78e53SAndroid Build Coastguard Worker 		case 16:
719*4dc78e53SAndroid Build Coastguard Worker 			return AF_INET6;
720*4dc78e53SAndroid Build Coastguard Worker 		default:
721*4dc78e53SAndroid Build Coastguard Worker 			return AF_UNSPEC;
722*4dc78e53SAndroid Build Coastguard Worker 	}
723*4dc78e53SAndroid Build Coastguard Worker }
724*4dc78e53SAndroid Build Coastguard Worker 
725*4dc78e53SAndroid Build Coastguard Worker /**
726*4dc78e53SAndroid Build Coastguard Worker  * Fill out sockaddr structure with values from abstract address object.
727*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
728*4dc78e53SAndroid Build Coastguard Worker  * @arg sa		Destination sockaddr structure buffer.
729*4dc78e53SAndroid Build Coastguard Worker  * @arg salen		Length of sockaddr structure buffer.
730*4dc78e53SAndroid Build Coastguard Worker  *
731*4dc78e53SAndroid Build Coastguard Worker  * Fills out the specified sockaddr structure with the data found in the
732*4dc78e53SAndroid Build Coastguard Worker  * specified abstract address. The salen argument needs to be set to the
733*4dc78e53SAndroid Build Coastguard Worker  * size of sa but will be modified to the actual size used during before
734*4dc78e53SAndroid Build Coastguard Worker  * the function exits.
735*4dc78e53SAndroid Build Coastguard Worker  *
736*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code
737*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_fill_sockaddr(const struct nl_addr * addr,struct sockaddr * sa,socklen_t * salen)738*4dc78e53SAndroid Build Coastguard Worker int nl_addr_fill_sockaddr(const struct nl_addr *addr, struct sockaddr *sa,
739*4dc78e53SAndroid Build Coastguard Worker 			  socklen_t *salen)
740*4dc78e53SAndroid Build Coastguard Worker {
741*4dc78e53SAndroid Build Coastguard Worker 	switch (addr->a_family) {
742*4dc78e53SAndroid Build Coastguard Worker 	case AF_INET: {
743*4dc78e53SAndroid Build Coastguard Worker 		struct sockaddr_in *sai = (struct sockaddr_in *) sa;
744*4dc78e53SAndroid Build Coastguard Worker 
745*4dc78e53SAndroid Build Coastguard Worker 		if (*salen < sizeof(*sai))
746*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
747*4dc78e53SAndroid Build Coastguard Worker 
748*4dc78e53SAndroid Build Coastguard Worker 		if (addr->a_len == 4)
749*4dc78e53SAndroid Build Coastguard Worker 			memcpy(&sai->sin_addr, addr->a_addr, 4);
750*4dc78e53SAndroid Build Coastguard Worker 		else if (addr->a_len != 0)
751*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
752*4dc78e53SAndroid Build Coastguard Worker 		else
753*4dc78e53SAndroid Build Coastguard Worker 			memset(&sai->sin_addr, 0, 4);
754*4dc78e53SAndroid Build Coastguard Worker 
755*4dc78e53SAndroid Build Coastguard Worker 		sai->sin_family = addr->a_family;
756*4dc78e53SAndroid Build Coastguard Worker 		*salen = sizeof(*sai);
757*4dc78e53SAndroid Build Coastguard Worker 	}
758*4dc78e53SAndroid Build Coastguard Worker 		break;
759*4dc78e53SAndroid Build Coastguard Worker 
760*4dc78e53SAndroid Build Coastguard Worker 	case AF_INET6: {
761*4dc78e53SAndroid Build Coastguard Worker 		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
762*4dc78e53SAndroid Build Coastguard Worker 
763*4dc78e53SAndroid Build Coastguard Worker 		if (*salen < sizeof(*sa6))
764*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
765*4dc78e53SAndroid Build Coastguard Worker 
766*4dc78e53SAndroid Build Coastguard Worker 		if (addr->a_len == 16)
767*4dc78e53SAndroid Build Coastguard Worker 			memcpy(&sa6->sin6_addr, addr->a_addr, 16);
768*4dc78e53SAndroid Build Coastguard Worker 		else if (addr->a_len != 0)
769*4dc78e53SAndroid Build Coastguard Worker 			return -NLE_INVAL;
770*4dc78e53SAndroid Build Coastguard Worker 		else
771*4dc78e53SAndroid Build Coastguard Worker 			memset(&sa6->sin6_addr, 0, 16);
772*4dc78e53SAndroid Build Coastguard Worker 
773*4dc78e53SAndroid Build Coastguard Worker 		sa6->sin6_family = addr->a_family;
774*4dc78e53SAndroid Build Coastguard Worker 		*salen = sizeof(*sa6);
775*4dc78e53SAndroid Build Coastguard Worker 	}
776*4dc78e53SAndroid Build Coastguard Worker 		break;
777*4dc78e53SAndroid Build Coastguard Worker 
778*4dc78e53SAndroid Build Coastguard Worker 	default:
779*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_INVAL;
780*4dc78e53SAndroid Build Coastguard Worker 	}
781*4dc78e53SAndroid Build Coastguard Worker 
782*4dc78e53SAndroid Build Coastguard Worker 	return 0;
783*4dc78e53SAndroid Build Coastguard Worker }
784*4dc78e53SAndroid Build Coastguard Worker 
785*4dc78e53SAndroid Build Coastguard Worker 
786*4dc78e53SAndroid Build Coastguard Worker /** @} */
787*4dc78e53SAndroid Build Coastguard Worker 
788*4dc78e53SAndroid Build Coastguard Worker /**
789*4dc78e53SAndroid Build Coastguard Worker  * @name Getting Information About Addresses
790*4dc78e53SAndroid Build Coastguard Worker  * @{
791*4dc78e53SAndroid Build Coastguard Worker  */
792*4dc78e53SAndroid Build Coastguard Worker 
793*4dc78e53SAndroid Build Coastguard Worker /**
794*4dc78e53SAndroid Build Coastguard Worker  * Call getaddrinfo() for an abstract address object.
795*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
796*4dc78e53SAndroid Build Coastguard Worker  * @arg result		Pointer to store resulting address list.
797*4dc78e53SAndroid Build Coastguard Worker  *
798*4dc78e53SAndroid Build Coastguard Worker  * Calls getaddrinfo() for the specified abstract address in AI_NUMERICHOST
799*4dc78e53SAndroid Build Coastguard Worker  * mode.
800*4dc78e53SAndroid Build Coastguard Worker  *
801*4dc78e53SAndroid Build Coastguard Worker  * @note The caller is responsible for freeing the linked list using the
802*4dc78e53SAndroid Build Coastguard Worker  *       interface provided by getaddrinfo(3).
803*4dc78e53SAndroid Build Coastguard Worker  *
804*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
805*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_info(const struct nl_addr * addr,struct addrinfo ** result)806*4dc78e53SAndroid Build Coastguard Worker int nl_addr_info(const struct nl_addr *addr, struct addrinfo **result)
807*4dc78e53SAndroid Build Coastguard Worker {
808*4dc78e53SAndroid Build Coastguard Worker 	int err;
809*4dc78e53SAndroid Build Coastguard Worker 	char buf[INET6_ADDRSTRLEN+5];
810*4dc78e53SAndroid Build Coastguard Worker 	struct addrinfo hint = {
811*4dc78e53SAndroid Build Coastguard Worker 		.ai_flags = AI_NUMERICHOST,
812*4dc78e53SAndroid Build Coastguard Worker 		.ai_family = addr->a_family,
813*4dc78e53SAndroid Build Coastguard Worker 	};
814*4dc78e53SAndroid Build Coastguard Worker 
815*4dc78e53SAndroid Build Coastguard Worker 	nl_addr2str(addr, buf, sizeof(buf));
816*4dc78e53SAndroid Build Coastguard Worker 
817*4dc78e53SAndroid Build Coastguard Worker 	err = getaddrinfo(buf, NULL, &hint, result);
818*4dc78e53SAndroid Build Coastguard Worker 	if (err != 0) {
819*4dc78e53SAndroid Build Coastguard Worker 		switch (err) {
820*4dc78e53SAndroid Build Coastguard Worker 		case EAI_ADDRFAMILY: return -NLE_AF_NOSUPPORT;
821*4dc78e53SAndroid Build Coastguard Worker 		case EAI_AGAIN: return -NLE_AGAIN;
822*4dc78e53SAndroid Build Coastguard Worker 		case EAI_BADFLAGS: return -NLE_INVAL;
823*4dc78e53SAndroid Build Coastguard Worker 		case EAI_FAIL: return -NLE_NOADDR;
824*4dc78e53SAndroid Build Coastguard Worker 		case EAI_FAMILY: return -NLE_AF_NOSUPPORT;
825*4dc78e53SAndroid Build Coastguard Worker 		case EAI_MEMORY: return -NLE_NOMEM;
826*4dc78e53SAndroid Build Coastguard Worker 		case EAI_NODATA: return -NLE_NOADDR;
827*4dc78e53SAndroid Build Coastguard Worker 		case EAI_NONAME: return -NLE_OBJ_NOTFOUND;
828*4dc78e53SAndroid Build Coastguard Worker 		case EAI_SERVICE: return -NLE_OPNOTSUPP;
829*4dc78e53SAndroid Build Coastguard Worker 		case EAI_SOCKTYPE: return -NLE_BAD_SOCK;
830*4dc78e53SAndroid Build Coastguard Worker 		default: return -NLE_FAILURE;
831*4dc78e53SAndroid Build Coastguard Worker 		}
832*4dc78e53SAndroid Build Coastguard Worker 	}
833*4dc78e53SAndroid Build Coastguard Worker 
834*4dc78e53SAndroid Build Coastguard Worker 	return 0;
835*4dc78e53SAndroid Build Coastguard Worker }
836*4dc78e53SAndroid Build Coastguard Worker 
837*4dc78e53SAndroid Build Coastguard Worker /**
838*4dc78e53SAndroid Build Coastguard Worker  * Resolve abstract address object to a name using getnameinfo().
839*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
840*4dc78e53SAndroid Build Coastguard Worker  * @arg host		Destination buffer for host name.
841*4dc78e53SAndroid Build Coastguard Worker  * @arg hostlen		Length of destination buffer.
842*4dc78e53SAndroid Build Coastguard Worker  *
843*4dc78e53SAndroid Build Coastguard Worker  * Resolves the abstract address to a name and writes the looked up result
844*4dc78e53SAndroid Build Coastguard Worker  * into the host buffer. getnameinfo() is used to perform the lookup and
845*4dc78e53SAndroid Build Coastguard Worker  * is put into NI_NAMEREQD mode so the function will fail if the lookup
846*4dc78e53SAndroid Build Coastguard Worker  * couldn't be performed.
847*4dc78e53SAndroid Build Coastguard Worker  *
848*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
849*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_resolve(const struct nl_addr * addr,char * host,size_t hostlen)850*4dc78e53SAndroid Build Coastguard Worker int nl_addr_resolve(const struct nl_addr *addr, char *host, size_t hostlen)
851*4dc78e53SAndroid Build Coastguard Worker {
852*4dc78e53SAndroid Build Coastguard Worker 	int err;
853*4dc78e53SAndroid Build Coastguard Worker 	struct sockaddr_in6 buf;
854*4dc78e53SAndroid Build Coastguard Worker 	socklen_t salen = sizeof(buf);
855*4dc78e53SAndroid Build Coastguard Worker 
856*4dc78e53SAndroid Build Coastguard Worker 	err = nl_addr_fill_sockaddr(addr, (struct sockaddr *) &buf, &salen);
857*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
858*4dc78e53SAndroid Build Coastguard Worker 		return err;
859*4dc78e53SAndroid Build Coastguard Worker 
860*4dc78e53SAndroid Build Coastguard Worker 	err = getnameinfo((struct sockaddr *) &buf, salen, host, hostlen,
861*4dc78e53SAndroid Build Coastguard Worker 			  NULL, 0, NI_NAMEREQD);
862*4dc78e53SAndroid Build Coastguard Worker 	if (err < 0)
863*4dc78e53SAndroid Build Coastguard Worker 		return nl_syserr2nlerr(err);
864*4dc78e53SAndroid Build Coastguard Worker 
865*4dc78e53SAndroid Build Coastguard Worker 	return 0;
866*4dc78e53SAndroid Build Coastguard Worker }
867*4dc78e53SAndroid Build Coastguard Worker 
868*4dc78e53SAndroid Build Coastguard Worker /** @} */
869*4dc78e53SAndroid Build Coastguard Worker 
870*4dc78e53SAndroid Build Coastguard Worker /**
871*4dc78e53SAndroid Build Coastguard Worker  * @name Attributes
872*4dc78e53SAndroid Build Coastguard Worker  * @{
873*4dc78e53SAndroid Build Coastguard Worker  */
874*4dc78e53SAndroid Build Coastguard Worker 
875*4dc78e53SAndroid Build Coastguard Worker /**
876*4dc78e53SAndroid Build Coastguard Worker  * Set address family
877*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object
878*4dc78e53SAndroid Build Coastguard Worker  * @arg family		Address family
879*4dc78e53SAndroid Build Coastguard Worker  *
880*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_get_family()
881*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_set_family(struct nl_addr * addr,int family)882*4dc78e53SAndroid Build Coastguard Worker void nl_addr_set_family(struct nl_addr *addr, int family)
883*4dc78e53SAndroid Build Coastguard Worker {
884*4dc78e53SAndroid Build Coastguard Worker 	addr->a_family = family;
885*4dc78e53SAndroid Build Coastguard Worker }
886*4dc78e53SAndroid Build Coastguard Worker 
887*4dc78e53SAndroid Build Coastguard Worker /**
888*4dc78e53SAndroid Build Coastguard Worker  * Return address family
889*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object
890*4dc78e53SAndroid Build Coastguard Worker  *
891*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_set_family()
892*4dc78e53SAndroid Build Coastguard Worker  *
893*4dc78e53SAndroid Build Coastguard Worker  * @return The numeric address family or `AF_UNSPEC`
894*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_get_family(const struct nl_addr * addr)895*4dc78e53SAndroid Build Coastguard Worker int nl_addr_get_family(const struct nl_addr *addr)
896*4dc78e53SAndroid Build Coastguard Worker {
897*4dc78e53SAndroid Build Coastguard Worker 	return addr->a_family;
898*4dc78e53SAndroid Build Coastguard Worker }
899*4dc78e53SAndroid Build Coastguard Worker 
900*4dc78e53SAndroid Build Coastguard Worker /**
901*4dc78e53SAndroid Build Coastguard Worker  * Set binary address of abstract address object.
902*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
903*4dc78e53SAndroid Build Coastguard Worker  * @arg buf		Buffer containing binary address.
904*4dc78e53SAndroid Build Coastguard Worker  * @arg len		Length of buffer containing binary address.
905*4dc78e53SAndroid Build Coastguard Worker  *
906*4dc78e53SAndroid Build Coastguard Worker  * Modifies the binary address portion of the abstract address. The
907*4dc78e53SAndroid Build Coastguard Worker  * abstract address must be capable of holding the required amount
908*4dc78e53SAndroid Build Coastguard Worker  * or this function will fail.
909*4dc78e53SAndroid Build Coastguard Worker  *
910*4dc78e53SAndroid Build Coastguard Worker  * @note This function will *not* modify the prefix length. It is within
911*4dc78e53SAndroid Build Coastguard Worker  *       the responsibility of the caller to set the prefix length to the
912*4dc78e53SAndroid Build Coastguard Worker  *       desirable length.
913*4dc78e53SAndroid Build Coastguard Worker  *
914*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_alloc()
915*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_get_binary_addr()
916*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_get_len()
917*4dc78e53SAndroid Build Coastguard Worker  *
918*4dc78e53SAndroid Build Coastguard Worker  * @return 0 on success or a negative error code.
919*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_set_binary_addr(struct nl_addr * addr,const void * buf,size_t len)920*4dc78e53SAndroid Build Coastguard Worker int nl_addr_set_binary_addr(struct nl_addr *addr, const void *buf, size_t len)
921*4dc78e53SAndroid Build Coastguard Worker {
922*4dc78e53SAndroid Build Coastguard Worker 	if (len > addr->a_maxsize)
923*4dc78e53SAndroid Build Coastguard Worker 		return -NLE_RANGE;
924*4dc78e53SAndroid Build Coastguard Worker 
925*4dc78e53SAndroid Build Coastguard Worker 	addr->a_len = len;
926*4dc78e53SAndroid Build Coastguard Worker 	memset(addr->a_addr, 0, addr->a_maxsize);
927*4dc78e53SAndroid Build Coastguard Worker 
928*4dc78e53SAndroid Build Coastguard Worker 	if (len)
929*4dc78e53SAndroid Build Coastguard Worker 		memcpy(addr->a_addr, buf, len);
930*4dc78e53SAndroid Build Coastguard Worker 
931*4dc78e53SAndroid Build Coastguard Worker 	return 0;
932*4dc78e53SAndroid Build Coastguard Worker }
933*4dc78e53SAndroid Build Coastguard Worker 
934*4dc78e53SAndroid Build Coastguard Worker /**
935*4dc78e53SAndroid Build Coastguard Worker  * Get binary address of abstract address object.
936*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
937*4dc78e53SAndroid Build Coastguard Worker  *
938*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_set_binary_addr()
939*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_get_len()
940*4dc78e53SAndroid Build Coastguard Worker  *
941*4dc78e53SAndroid Build Coastguard Worker  * @return Pointer to binary address of length nl_addr_get_len()
942*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_get_binary_addr(const struct nl_addr * addr)943*4dc78e53SAndroid Build Coastguard Worker void *nl_addr_get_binary_addr(const struct nl_addr *addr)
944*4dc78e53SAndroid Build Coastguard Worker {
945*4dc78e53SAndroid Build Coastguard Worker 	return (void*)addr->a_addr;
946*4dc78e53SAndroid Build Coastguard Worker }
947*4dc78e53SAndroid Build Coastguard Worker 
948*4dc78e53SAndroid Build Coastguard Worker /**
949*4dc78e53SAndroid Build Coastguard Worker  * Get length of binary address of abstract address object.
950*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
951*4dc78e53SAndroid Build Coastguard Worker  *
952*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_get_binary_addr()
953*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_set_binary_addr()
954*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_get_len(const struct nl_addr * addr)955*4dc78e53SAndroid Build Coastguard Worker unsigned int nl_addr_get_len(const struct nl_addr *addr)
956*4dc78e53SAndroid Build Coastguard Worker {
957*4dc78e53SAndroid Build Coastguard Worker 	return addr->a_len;
958*4dc78e53SAndroid Build Coastguard Worker }
959*4dc78e53SAndroid Build Coastguard Worker 
960*4dc78e53SAndroid Build Coastguard Worker /**
961*4dc78e53SAndroid Build Coastguard Worker  * Set the prefix length of an abstract address
962*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object
963*4dc78e53SAndroid Build Coastguard Worker  * @arg prefixlen	New prefix length
964*4dc78e53SAndroid Build Coastguard Worker  *
965*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_get_prefixlen()
966*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_set_prefixlen(struct nl_addr * addr,int prefixlen)967*4dc78e53SAndroid Build Coastguard Worker void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
968*4dc78e53SAndroid Build Coastguard Worker {
969*4dc78e53SAndroid Build Coastguard Worker 	addr->a_prefixlen = prefixlen;
970*4dc78e53SAndroid Build Coastguard Worker }
971*4dc78e53SAndroid Build Coastguard Worker 
972*4dc78e53SAndroid Build Coastguard Worker /**
973*4dc78e53SAndroid Build Coastguard Worker  * Return prefix length of abstract address object.
974*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object
975*4dc78e53SAndroid Build Coastguard Worker  *
976*4dc78e53SAndroid Build Coastguard Worker  * @see nl_addr_set_prefixlen()
977*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr_get_prefixlen(const struct nl_addr * addr)978*4dc78e53SAndroid Build Coastguard Worker unsigned int nl_addr_get_prefixlen(const struct nl_addr *addr)
979*4dc78e53SAndroid Build Coastguard Worker {
980*4dc78e53SAndroid Build Coastguard Worker 	return addr->a_prefixlen;
981*4dc78e53SAndroid Build Coastguard Worker }
982*4dc78e53SAndroid Build Coastguard Worker 
983*4dc78e53SAndroid Build Coastguard Worker /** @} */
984*4dc78e53SAndroid Build Coastguard Worker 
985*4dc78e53SAndroid Build Coastguard Worker /**
986*4dc78e53SAndroid Build Coastguard Worker  * @name Translations to Strings
987*4dc78e53SAndroid Build Coastguard Worker  * @{
988*4dc78e53SAndroid Build Coastguard Worker  */
989*4dc78e53SAndroid Build Coastguard Worker 
990*4dc78e53SAndroid Build Coastguard Worker /**
991*4dc78e53SAndroid Build Coastguard Worker  * Convert abstract address object to character string.
992*4dc78e53SAndroid Build Coastguard Worker  * @arg addr		Abstract address object.
993*4dc78e53SAndroid Build Coastguard Worker  * @arg buf		Destination buffer.
994*4dc78e53SAndroid Build Coastguard Worker  * @arg size		Size of destination buffer.
995*4dc78e53SAndroid Build Coastguard Worker  *
996*4dc78e53SAndroid Build Coastguard Worker  * Converts an abstract address to a character string and stores
997*4dc78e53SAndroid Build Coastguard Worker  * the result in the specified destination buffer.
998*4dc78e53SAndroid Build Coastguard Worker  *
999*4dc78e53SAndroid Build Coastguard Worker  * @return Address represented in ASCII stored in destination buffer.
1000*4dc78e53SAndroid Build Coastguard Worker  */
nl_addr2str(const struct nl_addr * addr,char * buf,size_t size)1001*4dc78e53SAndroid Build Coastguard Worker char *nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
1002*4dc78e53SAndroid Build Coastguard Worker {
1003*4dc78e53SAndroid Build Coastguard Worker 	unsigned int i;
1004*4dc78e53SAndroid Build Coastguard Worker 	char tmp[16];
1005*4dc78e53SAndroid Build Coastguard Worker 
1006*4dc78e53SAndroid Build Coastguard Worker 	if (!addr || !addr->a_len) {
1007*4dc78e53SAndroid Build Coastguard Worker 		snprintf(buf, size, "none");
1008*4dc78e53SAndroid Build Coastguard Worker 		if (addr)
1009*4dc78e53SAndroid Build Coastguard Worker 			goto prefix;
1010*4dc78e53SAndroid Build Coastguard Worker 		else
1011*4dc78e53SAndroid Build Coastguard Worker 			return buf;
1012*4dc78e53SAndroid Build Coastguard Worker 	}
1013*4dc78e53SAndroid Build Coastguard Worker 
1014*4dc78e53SAndroid Build Coastguard Worker 	switch (addr->a_family) {
1015*4dc78e53SAndroid Build Coastguard Worker 		case AF_INET:
1016*4dc78e53SAndroid Build Coastguard Worker 			inet_ntop(AF_INET, addr->a_addr, buf, size);
1017*4dc78e53SAndroid Build Coastguard Worker 			break;
1018*4dc78e53SAndroid Build Coastguard Worker 
1019*4dc78e53SAndroid Build Coastguard Worker 		case AF_INET6:
1020*4dc78e53SAndroid Build Coastguard Worker 			inet_ntop(AF_INET6, addr->a_addr, buf, size);
1021*4dc78e53SAndroid Build Coastguard Worker 			break;
1022*4dc78e53SAndroid Build Coastguard Worker 
1023*4dc78e53SAndroid Build Coastguard Worker 		case AF_MPLS:
1024*4dc78e53SAndroid Build Coastguard Worker 			mpls_ntop(AF_MPLS, addr->a_addr, buf, size);
1025*4dc78e53SAndroid Build Coastguard Worker 			break;
1026*4dc78e53SAndroid Build Coastguard Worker 
1027*4dc78e53SAndroid Build Coastguard Worker 		case AF_DECnet:
1028*4dc78e53SAndroid Build Coastguard Worker 			dnet_ntop(addr->a_addr, addr->a_len, buf, size);
1029*4dc78e53SAndroid Build Coastguard Worker 			break;
1030*4dc78e53SAndroid Build Coastguard Worker 
1031*4dc78e53SAndroid Build Coastguard Worker 		case AF_LLC:
1032*4dc78e53SAndroid Build Coastguard Worker 		default:
1033*4dc78e53SAndroid Build Coastguard Worker 			snprintf(buf, size, "%02x",
1034*4dc78e53SAndroid Build Coastguard Worker 				 (unsigned char) addr->a_addr[0]);
1035*4dc78e53SAndroid Build Coastguard Worker 			for (i = 1; i < addr->a_len; i++) {
1036*4dc78e53SAndroid Build Coastguard Worker 				snprintf(tmp, sizeof(tmp), ":%02x",
1037*4dc78e53SAndroid Build Coastguard Worker 					 (unsigned char) addr->a_addr[i]);
1038*4dc78e53SAndroid Build Coastguard Worker 				strncat(buf, tmp, size - strlen(buf) - 1);
1039*4dc78e53SAndroid Build Coastguard Worker 			}
1040*4dc78e53SAndroid Build Coastguard Worker 			break;
1041*4dc78e53SAndroid Build Coastguard Worker 	}
1042*4dc78e53SAndroid Build Coastguard Worker 
1043*4dc78e53SAndroid Build Coastguard Worker prefix:
1044*4dc78e53SAndroid Build Coastguard Worker 	if (addr->a_family != AF_MPLS &&
1045*4dc78e53SAndroid Build Coastguard Worker 	    (unsigned)addr->a_prefixlen != (8u * ((size_t)addr->a_len))) {
1046*4dc78e53SAndroid Build Coastguard Worker 		snprintf(tmp, sizeof(tmp), "/%d", addr->a_prefixlen);
1047*4dc78e53SAndroid Build Coastguard Worker 		strncat(buf, tmp, size - strlen(buf) - 1);
1048*4dc78e53SAndroid Build Coastguard Worker 	}
1049*4dc78e53SAndroid Build Coastguard Worker 
1050*4dc78e53SAndroid Build Coastguard Worker 	return buf;
1051*4dc78e53SAndroid Build Coastguard Worker }
1052*4dc78e53SAndroid Build Coastguard Worker 
1053*4dc78e53SAndroid Build Coastguard Worker /** @} */
1054*4dc78e53SAndroid Build Coastguard Worker 
1055*4dc78e53SAndroid Build Coastguard Worker /**
1056*4dc78e53SAndroid Build Coastguard Worker  * @name Address Family Transformations
1057*4dc78e53SAndroid Build Coastguard Worker  * @{
1058*4dc78e53SAndroid Build Coastguard Worker  */
1059*4dc78e53SAndroid Build Coastguard Worker 
1060*4dc78e53SAndroid Build Coastguard Worker static const struct trans_tbl afs[] = {
1061*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_UNSPEC,unspec),
1062*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_UNIX,unix),
1063*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_INET,inet),
1064*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_AX25,ax25),
1065*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_IPX,ipx),
1066*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_APPLETALK,appletalk),
1067*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_NETROM,netrom),
1068*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_BRIDGE,bridge),
1069*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_ATMPVC,atmpvc),
1070*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_X25,x25),
1071*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_INET6,inet6),
1072*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_ROSE,rose),
1073*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_DECnet,decnet),
1074*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_NETBEUI,netbeui),
1075*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_SECURITY,security),
1076*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_KEY,key),
1077*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_NETLINK,netlink),
1078*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_PACKET,packet),
1079*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_ASH,ash),
1080*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_ECONET,econet),
1081*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_ATMSVC,atmsvc),
1082*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_RDS
1083*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_RDS,rds),
1084*4dc78e53SAndroid Build Coastguard Worker #endif
1085*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_SNA,sna),
1086*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_IRDA,irda),
1087*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_PPPOX,pppox),
1088*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_WANPIPE,wanpipe),
1089*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_LLC,llc),
1090*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_CAN
1091*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_CAN,can),
1092*4dc78e53SAndroid Build Coastguard Worker #endif
1093*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_TIPC
1094*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_TIPC,tipc),
1095*4dc78e53SAndroid Build Coastguard Worker #endif
1096*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_BLUETOOTH,bluetooth),
1097*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_IUCV
1098*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_IUCV,iucv),
1099*4dc78e53SAndroid Build Coastguard Worker #endif
1100*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_RXRPC
1101*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_RXRPC,rxrpc),
1102*4dc78e53SAndroid Build Coastguard Worker #endif
1103*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_ISDN
1104*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_ISDN,isdn),
1105*4dc78e53SAndroid Build Coastguard Worker #endif
1106*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_PHONET
1107*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_PHONET,phonet),
1108*4dc78e53SAndroid Build Coastguard Worker #endif
1109*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_IEEE802154
1110*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_IEEE802154,ieee802154),
1111*4dc78e53SAndroid Build Coastguard Worker #endif
1112*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_CAIF
1113*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_CAIF,caif),
1114*4dc78e53SAndroid Build Coastguard Worker #endif
1115*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_ALG
1116*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_ALG,alg),
1117*4dc78e53SAndroid Build Coastguard Worker #endif
1118*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_NFC
1119*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_NFC,nfc),
1120*4dc78e53SAndroid Build Coastguard Worker #endif
1121*4dc78e53SAndroid Build Coastguard Worker #ifdef AF_VSOCK
1122*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_VSOCK,vsock),
1123*4dc78e53SAndroid Build Coastguard Worker #endif
1124*4dc78e53SAndroid Build Coastguard Worker 	__ADD(AF_MPLS,mpls),
1125*4dc78e53SAndroid Build Coastguard Worker };
1126*4dc78e53SAndroid Build Coastguard Worker 
nl_af2str(int family,char * buf,size_t size)1127*4dc78e53SAndroid Build Coastguard Worker char *nl_af2str(int family, char *buf, size_t size)
1128*4dc78e53SAndroid Build Coastguard Worker {
1129*4dc78e53SAndroid Build Coastguard Worker 	return __type2str(family, buf, size, afs, ARRAY_SIZE(afs));
1130*4dc78e53SAndroid Build Coastguard Worker }
1131*4dc78e53SAndroid Build Coastguard Worker 
nl_str2af(const char * name)1132*4dc78e53SAndroid Build Coastguard Worker int nl_str2af(const char *name)
1133*4dc78e53SAndroid Build Coastguard Worker {
1134*4dc78e53SAndroid Build Coastguard Worker 	int fam = __str2type(name, afs, ARRAY_SIZE(afs));
1135*4dc78e53SAndroid Build Coastguard Worker 	return fam >= 0 ? fam : -EINVAL;
1136*4dc78e53SAndroid Build Coastguard Worker }
1137*4dc78e53SAndroid Build Coastguard Worker 
1138*4dc78e53SAndroid Build Coastguard Worker /** @} */
1139*4dc78e53SAndroid Build Coastguard Worker 
1140*4dc78e53SAndroid Build Coastguard Worker /** @} */
1141