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