1 /* $NetBSD: util.c,v 1.17 2013/10/19 00:35:30 christos Exp $ */
4 * Copyright (c) 2008 David Young. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: util.c,v 1.17 2013/10/19 00:35:30 christos Exp $");
44 #include <sys/param.h>
45 #include <sys/types.h>
46 #include <sys/socket.h>
49 #include <sys/ioctl.h>
51 #include <net/if_dl.h>
52 #include <netinet/in.h> /* XXX */
62 static int oaf
= -1, s
;
64 if (oaf
== naf
|| (oaf
!= -1 && naf
== AF_UNSPEC
))
73 s
= prog_socket(naf
, SOCK_DGRAM
, 0);
82 get_string(const char *val
, const char *sep
, u_int8_t
*buf
, int *lenp
,
91 hexstr
= hexok
&& val
[0] == '0' && tolower((u_char
)val
[1]) == 'x';
97 if (sep
!= NULL
&& strchr(sep
, *val
) != NULL
) {
102 if (!isxdigit((u_char
)val
[0]) ||
103 !isxdigit((u_char
)val
[1])) {
104 warnx("bad hexadecimal digits");
108 if (p
>= buf
+ len
) {
110 warnx("hexadecimal digits too long");
112 warnx("strings too long");
116 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
117 *p
++ = (tohex((u_char
)val
[0]) << 4) |
118 tohex((u_char
)val
[1]);
126 memset(p
, 0, *lenp
- len
);
132 print_string(const u_int8_t
*buf
, int len
)
139 if (len
< 2 || buf
[0] != '0' || tolower(buf
[1]) != 'x') {
140 for (; i
< len
; i
++) {
141 if (!isprint(buf
[i
]))
148 if (hasspc
|| len
== 0)
149 printf("\"%.*s\"", len
, buf
);
151 printf("%.*s", len
, buf
);
154 for (i
= 0; i
< len
; i
++)
155 printf("%02x", buf
[i
]);
159 struct paddr_prefix
*
160 prefixlen_to_mask(int af
, int plen
)
164 struct sockaddr_in sin
;
165 struct sockaddr_in6 sin6
;
167 struct paddr_prefix
*pfx
;
172 memset(&u
, 0, sizeof(u
));
176 addrlen
= sizeof(u
.sin
.sin_addr
);
177 addr
= (uint8_t *)&u
.sin
.sin_addr
;
178 u
.sa
.sa_len
= sizeof(u
.sin
);
181 addrlen
= sizeof(u
.sin6
.sin6_addr
);
182 addr
= (uint8_t *)&u
.sin6
.sin6_addr
;
183 u
.sa
.sa_len
= sizeof(u
.sin6
);
191 if (plen
< 0 || (size_t)plen
> addrlen
* NBBY
) {
197 plen
= addrlen
* NBBY
;
199 memset(addr
, 0xff, (plen
+ NBBY
- 1) / NBBY
);
203 addr
[plen
/ NBBY
] &= ~((uint8_t)0xff >> nbit
);
204 pfx
= malloc(offsetof(struct paddr_prefix
, pfx_addr
) + u
.sa
.sa_len
);
208 memcpy(&pfx
->pfx_addr
, &u
.sa
, u
.sa
.sa_len
);
214 direct_ioctl(prop_dictionary_t env
, unsigned long cmd
, void *data
)
219 if ((s
= getsock(AF_UNSPEC
)) == -1)
220 err(EXIT_FAILURE
, "getsock");
222 if ((ifname
= getifname(env
)) == NULL
)
223 err(EXIT_FAILURE
, "getifname");
225 estrlcpy(data
, ifname
, IFNAMSIZ
);
227 return prog_ioctl(s
, cmd
, data
);
231 indirect_ioctl(prop_dictionary_t env
, unsigned long cmd
, void *data
)
235 memset(&ifr
, 0, sizeof(ifr
));
239 return direct_ioctl(env
, cmd
, &ifr
);
243 print_link_addresses(prop_dictionary_t env
, bool print_active_only
)
245 char hbuf
[NI_MAXHOST
];
248 struct ifaddrs
*ifa
, *ifap
;
249 const struct sockaddr_dl
*sdl
;
250 struct if_laddrreq iflr
;
252 if ((ifname
= getifname(env
)) == NULL
)
253 err(EXIT_FAILURE
, "%s: getifname", __func__
);
255 if ((s
= getsock(AF_LINK
)) == -1)
256 err(EXIT_FAILURE
, "%s: getsock", __func__
);
258 if (getifaddrs(&ifap
) == -1)
259 err(EXIT_FAILURE
, "%s: getifaddrs", __func__
);
261 memset(&iflr
, 0, sizeof(iflr
));
263 strlcpy(iflr
.iflr_name
, ifname
, sizeof(iflr
.iflr_name
));
265 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
266 if (strcmp(ifname
, ifa
->ifa_name
) != 0)
268 if (ifa
->ifa_addr
->sa_family
!= AF_LINK
)
271 sdl
= satocsdl(ifa
->ifa_addr
);
273 memcpy(&iflr
.addr
, ifa
->ifa_addr
, MIN(ifa
->ifa_addr
->sa_len
,
275 iflr
.flags
= IFLR_PREFIX
;
276 iflr
.prefixlen
= sdl
->sdl_alen
* NBBY
;
278 if (prog_ioctl(s
, SIOCGLIFADDR
, &iflr
) == -1)
279 err(EXIT_FAILURE
, "%s: ioctl", __func__
);
281 if (((iflr
.flags
& IFLR_ACTIVE
) != 0) != print_active_only
)
284 if (getnameinfo(ifa
->ifa_addr
, ifa
->ifa_addr
->sa_len
,
285 hbuf
, sizeof(hbuf
), NULL
, 0,
286 Nflag
? 0 : NI_NUMERICHOST
) == 0 &&
289 print_active_only
? "address:" : "link", hbuf
);
296 ifa_get_preference(const char *ifname
, const struct sockaddr
*sa
)
298 struct if_addrprefreq ifap
;
301 if ((s
= getsock(sa
->sa_family
)) == -1) {
302 if (errno
== EPROTONOSUPPORT
)
304 err(EXIT_FAILURE
, "socket");
306 memset(&ifap
, 0, sizeof(ifap
));
307 estrlcpy(ifap
.ifap_name
, ifname
, sizeof(ifap
.ifap_name
));
308 memcpy(&ifap
.ifap_addr
, sa
, MIN(sizeof(ifap
.ifap_addr
), sa
->sa_len
));
309 if (prog_ioctl(s
, SIOCGIFADDRPREF
, &ifap
) == -1) {
310 if (errno
== EADDRNOTAVAIL
|| errno
== EAFNOSUPPORT
)
312 warn("SIOCGIFADDRPREF");
314 return ifap
.ifap_preference
;
318 ifa_print_preference(const char *ifname
, const struct sockaddr
*sa
)
325 preference
= ifa_get_preference(ifname
, sa
);
326 printf(" preference %" PRId16
, preference
);
330 ifa_any_preferences(const char *ifname
, struct ifaddrs
*ifap
, int family
)
334 /* Print address preference numbers if any address has a non-zero
335 * preference assigned.
337 for (ifa
= ifap
; ifa
!= NULL
; ifa
= ifa
->ifa_next
) {
338 if (strcmp(ifname
, ifa
->ifa_name
) != 0)
340 if (ifa
->ifa_addr
->sa_family
!= family
)
342 if (ifa_get_preference(ifa
->ifa_name
, ifa
->ifa_addr
) != 0)