Fix markup.
[netbsd-mini2440.git] / sbin / ifconfig / util.c
blob366cb10bbc6a0d4c1c00d00459fc34b71b7e72c7
1 /* $NetBSD: util.c,v 1.8 2008/07/02 07:44:15 dyoung Exp $ */
3 /*-
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
8 * are met:
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
25 * SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 #ifndef lint
30 __RCSID("$NetBSD: util.c,v 1.8 2008/07/02 07:44:15 dyoung Exp $");
31 #endif /* not lint */
33 #include <ctype.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <stddef.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <util.h>
43 #include <sys/socket.h>
44 #include <sys/ioctl.h>
45 #include <net/if.h>
46 #include <netinet/in.h> /* XXX */
48 #include "env.h"
49 #include "util.h"
51 int
52 getsock(int naf)
54 static int oaf = -1, s;
56 if (oaf == naf || (oaf != -1 && naf == AF_UNSPEC))
57 return s;
59 if (oaf != -1)
60 close(s);
62 if (naf == AF_UNSPEC)
63 naf = AF_INET;
65 s = socket(naf, SOCK_DGRAM, 0);
66 if (s == -1)
67 oaf = -1;
68 else
69 oaf = naf;
70 return s;
73 const char *
74 get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
76 int len;
77 bool hexstr;
78 u_int8_t *p;
80 len = *lenp;
81 p = buf;
82 hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
83 if (hexstr)
84 val += 2;
85 for (;;) {
86 if (*val == '\0')
87 break;
88 if (sep != NULL && strchr(sep, *val) != NULL) {
89 val++;
90 break;
92 if (hexstr) {
93 if (!isxdigit((u_char)val[0]) ||
94 !isxdigit((u_char)val[1])) {
95 warnx("bad hexadecimal digits");
96 return NULL;
99 if (p > buf + len) {
100 if (hexstr)
101 warnx("hexadecimal digits too long");
102 else
103 warnx("strings too long");
104 return NULL;
106 if (hexstr) {
107 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
108 *p++ = (tohex((u_char)val[0]) << 4) |
109 tohex((u_char)val[1]);
110 #undef tohex
111 val += 2;
112 } else
113 *p++ = *val++;
115 len = p - buf;
116 if (len < *lenp)
117 memset(p, 0, *lenp - len);
118 *lenp = len;
119 return val;
122 void
123 print_string(const u_int8_t *buf, int len)
125 int i;
126 bool hasspc;
128 i = 0;
129 hasspc = false;
130 if (len < 2 || buf[0] != '0' || tolower(buf[1]) != 'x') {
131 for (; i < len; i++) {
132 if (!isprint(buf[i]))
133 break;
134 if (isspace(buf[i]))
135 hasspc = true;
138 if (i == len) {
139 if (hasspc || len == 0)
140 printf("\"%.*s\"", len, buf);
141 else
142 printf("%.*s", len, buf);
143 } else {
144 printf("0x");
145 for (i = 0; i < len; i++)
146 printf("%02x", buf[i]);
150 struct paddr_prefix *
151 prefixlen_to_mask(int af, int plen)
153 union {
154 struct sockaddr sa;
155 struct sockaddr_in sin;
156 struct sockaddr_in6 sin6;
157 } u;
158 struct paddr_prefix *pfx;
159 size_t addrlen;
160 uint8_t *addr;
161 int nbit;
163 memset(&u, 0, sizeof(u));
165 switch (af) {
166 case AF_INET:
167 addrlen = sizeof(u.sin.sin_addr);
168 addr = (uint8_t *)&u.sin.sin_addr;
169 u.sa.sa_len = sizeof(u.sin);
170 break;
171 case AF_INET6:
172 addrlen = sizeof(u.sin6.sin6_addr);
173 addr = (uint8_t *)&u.sin6.sin6_addr;
174 u.sa.sa_len = sizeof(u.sin6);
175 break;
176 default:
177 errno = EINVAL;
178 return NULL;
180 u.sa.sa_family = af;
182 if (plen < 0 || (size_t)plen > addrlen * NBBY) {
183 errno = EINVAL;
184 return NULL;
187 if (plen == 0)
188 plen = addrlen * NBBY;
190 memset(addr, 0xff, (plen + NBBY - 1) / NBBY);
192 nbit = plen % NBBY;
193 if (nbit != 0)
194 addr[plen / NBBY] &= ~((uint8_t)0xff >> nbit);
195 pfx = malloc(offsetof(struct paddr_prefix, pfx_addr) + u.sa.sa_len);
196 if (pfx == NULL)
197 return NULL;
198 pfx->pfx_len = plen;
199 memcpy(&pfx->pfx_addr, &u.sa, u.sa.sa_len);
201 return pfx;
205 direct_ioctl(prop_dictionary_t env, unsigned long cmd, void *data)
207 const char *ifname;
208 int s;
210 if ((s = getsock(AF_UNSPEC)) == -1)
211 err(EXIT_FAILURE, "getsock");
213 if ((ifname = getifname(env)) == NULL)
214 err(EXIT_FAILURE, "getifname");
216 estrlcpy(data, ifname, IFNAMSIZ);
218 return ioctl(s, cmd, data);
222 indirect_ioctl(prop_dictionary_t env, unsigned long cmd, void *data)
224 struct ifreq ifr;
226 memset(&ifr, 0, sizeof(ifr));
228 ifr.ifr_data = data;
230 return direct_ioctl(env, cmd, &ifr);
233 #ifdef INET6
234 /* KAME idiosyncrasy */
235 void
236 in6_fillscopeid(struct sockaddr_in6 *sin6)
238 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
239 sin6->sin6_scope_id =
240 ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
241 sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
244 #endif /* INET6 */