Annotation of embedaddon/libpdel/net/if_iface.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (c) 2001-2002 Packet Design, LLC.
4: * All rights reserved.
5: *
6: * Subject to the following obligations and disclaimer of warranty,
7: * use and redistribution of this software, in source or object code
8: * forms, with or without modifications are expressly permitted by
9: * Packet Design; provided, however, that:
10: *
11: * (i) Any and all reproductions of the source or object code
12: * must include the copyright notice above and the following
13: * disclaimer of warranties; and
14: * (ii) No rights are granted, in any manner or form, to use
15: * Packet Design trademarks, including the mark "PACKET DESIGN"
16: * on advertising, endorsements, or otherwise except as such
17: * appears in the above copyright notice or in the software.
18: *
19: * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
20: * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
21: * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
22: * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
23: * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
24: * OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
25: * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
26: * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
27: * RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
28: * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
29: * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
30: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
31: * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
32: * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
33: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
35: * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
36: * THE POSSIBILITY OF SUCH DAMAGE.
37: *
38: * Author: Archie Cobbs <archie@freebsd.org>
39: */
40:
41: #include <sys/types.h>
42: #include <sys/param.h>
43: #include <sys/socket.h>
44: #include <sys/sysctl.h>
45: #include <sys/sockio.h>
46:
47: #include <net/if.h>
48: #include <net/if_dl.h>
49: #include <net/route.h>
50:
51: #include <netinet/in.h>
52: #include <arpa/inet.h>
53:
54: #include <stdio.h>
55: #include <stdlib.h>
56: #include <stdarg.h>
57: #include <unistd.h>
58: #include <string.h>
59: #include <errno.h>
60: #include <err.h>
61:
62: #include "structs/structs.h"
63: #include "structs/type/array.h"
64:
65: #include "util/typed_mem.h"
66: #include "net/if_util.h"
67:
68: #define ROUNDUP(a) \
69: ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
70: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
71:
72: static struct if_msghdr *if_find(const char *ifname,
73: u_char **bufp, const char *mtype);
74: static int if_info(u_char **bufp, const char *mtype);
75:
76: /*
77: * Get list of IP addresses and netmasks configured on an interface.
78: */
79: int
80: if_get_ip_addrs(const char *ifname, struct in_addr **iplistp,
81: struct in_addr **nmlistp, const char *mtype)
82: {
83: struct if_msghdr *ifm;
84: struct ifa_msghdr *ifam;
85: struct in_addr *iplist = NULL;
86: struct in_addr *nmlist = NULL;
87: int errno_save;
88: int num = 0;
89: u_char *buf;
90:
91: /* Find interface info */
92: if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
93: return (-1);
94:
95: /* Search for first IP address */
96: for (ifam = (struct ifa_msghdr *)(void *)
97: ((u_char *)ifm + ifm->ifm_msglen);
98: ifam->ifam_type == RTM_NEWADDR;
99: ifam = (struct ifa_msghdr *)(void *)
100: ((u_char *)ifam + ifam->ifam_msglen))
101: num++;
102:
103: /* Allocate arrays */
104: if ((iplist = MALLOC(mtype, num * sizeof(*iplist))) == NULL
105: || (nmlist = MALLOC(mtype, num * sizeof(*nmlist))) == NULL) {
106: errno_save = errno;
107: FREE(mtype, iplist); /* ok if NULL */
108: FREE(TYPED_MEM_TEMP, buf);
109: errno = errno_save;
110: return (-1);
111: }
112:
113: /* Search for IP address/netmask combinations */
114: num = 0;
115: for (ifam = (struct ifa_msghdr *)(void *)
116: ((u_char *)ifm + ifm->ifm_msglen);
117: ifam->ifam_type == RTM_NEWADDR;
118: ifam = (struct ifa_msghdr *)(void *)
119: ((u_char *)ifam + ifam->ifam_msglen)) {
120: char *cp = (char *)(ifam + 1);
121: int need = RTA_IFA | RTA_NETMASK;
122: int i;
123:
124: /* Find IP address and netmask, if any */
125: if ((ifam->ifam_addrs & need) != need)
126: continue;
127: for (i = 1; i != 0 && need != 0; i <<= 1) {
128: if ((ifam->ifam_addrs & i) == 0)
129: continue;
130: if (i == RTA_IFA
131: && ((struct sockaddr *)(void *)cp)->sa_family
132: == AF_INET) {
133: iplist[num] = ((struct sockaddr_in *)
134: (void *)cp)->sin_addr;
135: } else if (i == RTA_NETMASK) {
136: nmlist[num] = ((struct sockaddr_in *)
137: (void *)cp)->sin_addr;
138: }
139: need &= ~i;
140: ADVANCE(cp, (struct sockaddr *)cp);
141: }
142: if (need == 0)
143: num++;
144: }
145:
146: /* Done */
147: FREE(TYPED_MEM_TEMP, buf);
148: *iplistp = iplist;
149: *nmlistp = nmlist;
150: return (num);
151: }
152:
153: /*
154: * Get the first IP address on an interface.
155: */
156: int
157: if_get_ip_addr(const char *ifname, struct in_addr *ipp, struct in_addr *nmp)
158: {
159: struct in_addr *iplist;
160: struct in_addr *nmlist;
161: int nip;
162:
163: if ((nip = if_get_ip_addrs(ifname,
164: &iplist, &nmlist, TYPED_MEM_TEMP)) == -1)
165: return (-1);
166: if (nip == 0) {
167: FREE(TYPED_MEM_TEMP, iplist);
168: FREE(TYPED_MEM_TEMP, nmlist);
169: errno = ENOENT;
170: return (-1);
171: }
172: if (ipp != NULL)
173: *ipp = iplist[0];
174: if (nmp != NULL)
175: *nmp = nmlist[0];
176: FREE(TYPED_MEM_TEMP, iplist);
177: FREE(TYPED_MEM_TEMP, nmlist);
178: return (0);
179: }
180:
181: /*
182: * Get the flags associated with an interface.
183: */
184: int
185: if_get_flags(const char *ifname)
186: {
187: struct if_msghdr *ifm;
188: u_char *buf;
189: int rtn;
190:
191: if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
192: return (-1);
193: rtn = ifm->ifm_flags;
194: FREE(TYPED_MEM_TEMP, buf);
195: return (rtn);
196: }
197:
198: /*
199: * Set the flags associated with an interface.
200: */
201: int
202: if_set_flags(const char *ifname, int flags)
203: {
204: struct ifreq ifr;
205: int r;
206: int s;
207:
208: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
209: return (-1);
210: memset(&ifr, 0, sizeof(ifr));
211: strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
212: ifr.ifr_flags = flags;
213: r = ioctl(s, SIOCSIFFLAGS, (char *)&ifr);
214: (void)close(s);
215: return (r);
216: }
217:
218: /*
219: * Get the MTU associated with an interface.
220: */
221: int
222: if_get_mtu(const char *ifname)
223: {
224: struct if_msghdr *ifm;
225: u_char *buf;
226: int rtn;
227:
228: if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
229: return (-1);
230: rtn = ifm->ifm_data.ifi_mtu;
231: FREE(TYPED_MEM_TEMP, buf);
232: return (rtn);
233: }
234:
235: /*
236: * Set the MTU associated with an interface.
237: */
238: int
239: if_set_mtu(const char *ifname, u_int mtu)
240: {
241: struct ifreq ifr;
242: int r;
243: int s;
244:
245: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
246: return (-1);
247: memset(&ifr, 0, sizeof(ifr));
248: strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
249: ifr.ifr_mtu = mtu;
250: r = ioctl(s, SIOCSIFMTU, (char *)&ifr);
251: (void)close(s);
252: return (r);
253: }
254:
255: /*
256: * Get the interface type.
257: */
258: int
259: if_get_type(const char *ifname)
260: {
261: struct if_msghdr *ifm;
262: u_char *buf;
263: int rtn;
264:
265: if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
266: return (-1);
267: rtn = ifm->ifm_data.ifi_type;
268: FREE(TYPED_MEM_TEMP, buf);
269: return (rtn);
270: }
271:
272: /*
273: * Get the link address for an interface.
274: */
275: int
276: if_get_link_addr(const char *ifname,
277: struct sockaddr_dl **sdlp, const char *mtype)
278: {
279: struct if_msghdr *ifm;
280: struct sockaddr_dl *sdl;
281: int errno_save;
282: u_char *buf;
283:
284: if ((ifm = if_find(ifname, &buf, TYPED_MEM_TEMP)) == NULL)
285: return (-1);
286: sdl = (struct sockaddr_dl *)(ifm + 1);
287: if ((*sdlp = MALLOC(mtype, sdl->sdl_len)) == NULL) {
288: errno_save = errno;
289: FREE(TYPED_MEM_TEMP, buf);
290: errno = errno_save;
291: return (-1);
292: }
293: memcpy(*sdlp, sdl, sdl->sdl_len);
294: FREE(TYPED_MEM_TEMP, buf);
295: return (0);
296: }
297:
298: /*
299: * Gets the names of all system interfaces.
300: */
301: int
302: if_get_list(char ***listp, const char *mtype)
303: {
304: char **list = NULL;
305: int errno_save;
306: int num = 0;
307: u_char *buf;
308: u_char *ptr;
309: int len;
310:
311: /* Get raw data from kernel */
312: if ((len = if_info(&buf, TYPED_MEM_TEMP)) == -1)
313: return (-1);
314:
315: /* Scan interfaces */
316: for (ptr = buf;
317: ptr < buf + len;
318: ptr += ((struct if_msghdr *)(void *)ptr)->ifm_msglen) {
319: struct if_msghdr *const ifm = (struct if_msghdr *)(void *)ptr;
320:
321: /* Sanity check version */
322: if (ifm->ifm_version != RTM_VERSION) {
323: errno = EIO;
324: goto fail;
325: }
326:
327: /* Next interface? */
328: if (ifm->ifm_type == RTM_IFINFO) {
329: struct sockaddr_dl *const sdl
330: = (struct sockaddr_dl *)(ifm + 1);
331: char nbuf[IF_NAMESIZE + 1];
332: void *new_list;
333:
334: /* Get name */
335: if (sdl->sdl_nlen > sizeof(nbuf) - 1)
336: continue;
337: memcpy(nbuf, sdl->sdl_data, sdl->sdl_nlen);
338: nbuf[sdl->sdl_nlen] = '\0';
339:
340: /* Add name to list */
341: if ((new_list = REALLOC(mtype, list,
342: (num + 1) * sizeof(*list))) == NULL)
343: goto fail;
344: list = new_list;
345: if ((list[num] = STRDUP(mtype, nbuf)) == NULL)
346: goto fail;
347: num++;
348: }
349: }
350:
351: /* Done */
352: FREE(TYPED_MEM_TEMP, buf);
353: *listp = list;
354: return (num);
355:
356: fail:
357: errno_save = errno;
358: while (num > 0)
359: FREE(mtype, list[--num]);
360: FREE(mtype, list);
361: FREE(TYPED_MEM_TEMP, buf);
362: errno = errno_save;
363: return (-1);
364: }
365:
366: /*
367: * Get the flags or type associated with an interface.
368: * Caller must free *bufp.
369: *
370: * Returns -1 and sets errno if there was a problem.
371: */
372: static struct if_msghdr *
373: if_find(const char *ifname, u_char **bufp, const char *mtype)
374: {
375: u_char *buf;
376: u_char *ptr;
377: size_t len;
378:
379: /* Get raw data from kernel */
380: if ((len = if_info(&buf, mtype)) == -1)
381: return (NULL);
382:
383: /* Scan for desired interface */
384: for (ptr = buf;
385: ptr < buf + len;
386: ptr += ((struct if_msghdr *)(void *)ptr)->ifm_msglen) {
387: struct if_msghdr *const ifm = (struct if_msghdr *)(void *)ptr;
388: struct sockaddr_dl *sdl;
389:
390: /* Sanity check version */
391: if (ifm->ifm_version != RTM_VERSION) {
392: FREE(mtype, buf);
393: errno = EIO;
394: return (NULL);
395: }
396:
397: /* Next interface or previous interface address? */
398: if (ifm->ifm_type != RTM_IFINFO)
399: continue;
400:
401: /* Compare interface name */
402: sdl = (struct sockaddr_dl *)(ifm + 1);
403: if (strlen(ifname) != sdl->sdl_nlen ||
404: strncmp(ifname, sdl->sdl_data, sdl->sdl_nlen) != 0)
405: continue;
406:
407: /* Found it */
408: *bufp = buf;
409: return (ifm);
410: }
411:
412: /* Not found */
413: FREE(mtype, buf);
414: errno = ENOENT;
415: return (NULL);
416: }
417:
418: /*
419: * Get the interface list. Caller must free *bufp.
420: */
421: static int
422: if_info(u_char **bufp, const char *mtype)
423: {
424: int mib[6] = { CTL_NET, PF_ROUTE, 0, AF_INET, NET_RT_IFLIST, 0 };
425: size_t length;
426: u_char *buf;
427:
428: if (sysctl(mib, 6, NULL, &length, NULL, 0) == -1)
429: return (-1);
430: length += 256;
431: if ((buf = MALLOC(mtype, length)) == NULL)
432: return (-1);
433: if (sysctl(mib, 6, buf, &length, NULL, 0) == -1)
434: return (-1);
435: *bufp = buf;
436: return (length);
437: }
438:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>