|
|
1.1 root 1: /* $Id: bsd-if.c,v 1.2 2003/05/18 00:06:06 fredette Exp $ */
2:
3: /* host/bsd/bsd-if.c - BSD interface support: */
4:
5: /*
6: * Copyright (c) 2001, 2003 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <tme/common.h>
37: _TME_RCSID("$Id: bsd-if.c,v 1.2 2003/05/18 00:06:06 fredette Exp $");
38:
39: /* includes: */
40: #include "bsd-impl.h"
41: #include <string.h>
42: #include <errno.h>
43: #include <fcntl.h>
44: #include <netdb.h>
45: #include <sys/param.h>
46: #include <sys/socket.h>
47: #include <sys/stat.h>
48: #include <net/if.h>
49: #include <netinet/in_systm.h>
50: #include <netinet/in.h>
51: #if defined(HAVE_SYS_SOCKIO_H)
52: #include <sys/sockio.h>
53: #elif defined(HAVE_SYS_SOCKETIO_H)
54: #include <sys/socketio.h>
55: #endif /* HAVE_SYS_SOCKETIO_H */
56: #include <sys/ioctl.h>
57: #ifdef HAVE_IOCTLS_H
58: #include <ioctls.h>
59: #endif /* HAVE_IOCTLS_H */
60: #ifdef HAVE_NET_IF_ETHER_H
61: #include <net/if_ether.h>
62: #endif /* HAVE_NET_IF_ETHER_H */
63: #ifdef HAVE_NET_ETHERNET_H
64: #include <net/ethernet.h>
65: #endif /* HAVE_NET_ETHERNET_H */
66: #include <netinet/ip.h>
67: #ifdef HAVE_NET_IF_DL_H
68: #include <net/if_dl.h>
69: #endif /* HAVE_NET_IF_DL_H */
70: #include <arpa/inet.h>
71:
72: /* this macro helps us size a struct ifreq: */
73: #ifdef HAVE_SOCKADDR_SA_LEN
74: #define SIZEOF_IFREQ(ifr) (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
75: #else /* !HAVE_SOCKADDR_SA_LEN */
76: #define SIZEOF_IFREQ(ifr) (sizeof(ifr->ifr_name) + sizeof(struct sockaddr))
77: #endif /* !HAVE_SOCKADDR_SA_LEN */
78:
79: /* this finds a network interface: */
80: int
81: tme_bsd_if_find(const char *ifr_name_user, struct ifreq **_ifreq, tme_uint8_t **_if_addr, unsigned int *_if_addr_size)
82: {
83: int saved_errno;
84: int dummy_fd;
85: char ifreq_buffer[16384]; /* FIXME - magic constant. */
86: struct ifconf ifc;
87: struct ifreq *ifr;
88: struct ifreq *ifr_user;
89: size_t ifr_offset;
90: struct sockaddr_in saved_ip_address;
91: short saved_flags;
92: #ifdef HAVE_AF_LINK
93: struct ifreq *link_ifreqs[20]; /* FIXME - magic constant. */
94: size_t link_ifreqs_count;
95: size_t link_ifreqs_i;
96: struct sockaddr_dl *sadl;
97: #endif /* HAVE_AF_LINK */
98:
99: /* make a dummy socket so we can read the interface list: */
100: if ((dummy_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
101: return (NULL);
102: }
103:
104: /* read the interface list: */
105: ifc.ifc_len = sizeof(ifreq_buffer);
106: ifc.ifc_buf = ifreq_buffer;
107: if (ioctl(dummy_fd, SIOCGIFCONF, &ifc) < 0) {
108: saved_errno = errno;
109: close(dummy_fd);
110: errno = saved_errno;
111: return (-1);
112: }
113:
114: #ifdef HAVE_AF_LINK
115: /* start our list of link address ifreqs: */
116: link_ifreqs_count = 0;
117: #endif /* HAVE_AF_LINK */
118:
119: /* walk the interface list: */
120: ifr_user = NULL;
121: for (ifr_offset = 0;; ifr_offset += SIZEOF_IFREQ(ifr)) {
122:
123: /* stop walking if we have run out of space in the buffer. note
124: that before we can use SIZEOF_IFREQ, we have to make sure that
125: there is a minimum number of bytes in the buffer to use it
126: (namely, that there's a whole struct sockaddr available): */
127: ifr = (struct ifreq *) (ifreq_buffer + ifr_offset);
128: if (((ifr_offset
129: + sizeof(ifr->ifr_name)
130: + sizeof(struct sockaddr))
131: > ifc.ifc_len)
132: || ((ifr_offset
133: + SIZEOF_IFREQ(ifr))
134: > ifc.ifc_len)) {
135: errno = ENOENT;
136: break;
137: }
138:
139: #ifdef HAVE_AF_LINK
140: /* if this is a hardware address, save it: */
141: if (ifr->ifr_addr.sa_family == AF_LINK) {
142: if (link_ifreqs_count < TME_ARRAY_ELS(link_ifreqs)) {
143: link_ifreqs[link_ifreqs_count++] = ifr;
144: }
145: continue;
146: }
147: #endif /* HAVE_AF_LINK */
148:
149: /* ignore this interface if it doesn't do IP: */
150: /* XXX is this actually important? */
151: if (ifr->ifr_addr.sa_family != AF_INET) {
152: continue;
153: }
154:
155: /* get the interface flags, preserving the IP address in the
156: struct ifreq across the call: */
157: saved_ip_address = *((struct sockaddr_in *) & ifr->ifr_addr);
158: if (ioctl(dummy_fd, SIOCGIFFLAGS, ifr) < 0) {
159: ifr = NULL;
160: break;
161: }
162: saved_flags = ifr->ifr_flags;
163: *((struct sockaddr_in *) & ifr->ifr_addr) = saved_ip_address;
164:
165: /* ignore this interface if it isn't up and running: */
166: if ((saved_flags & (IFF_UP | IFF_RUNNING))
167: != (IFF_UP | IFF_RUNNING)) {
168: continue;
169: }
170:
171: /* if we don't have an interface yet, take this one depending on
172: whether the user asked for an interface by name or not. if he
173: did, and this is it, take this one. if he didn't, and this
174: isn't a loopback interface, take this one: */
175: if (ifr_user == NULL
176: && (ifr_name_user != NULL
177: ? !strncmp(ifr->ifr_name, ifr_name_user, sizeof(ifr->ifr_name))
178: : !(ifr->ifr_flags & IFF_LOOPBACK))) {
179: ifr_user = ifr;
180: }
181: }
182:
183: /* close the dummy socket: */
184: saved_errno = errno;
185: close(dummy_fd);
186: errno = saved_errno;
187:
188: /* if we don't have an interface to return: */
189: if (ifr_user == NULL) {
190: return (errno);
191: }
192:
193: /* return this interface: */
194: *_ifreq = (struct ifreq *) tme_memdup(ifr_user, SIZEOF_IFREQ(ifr_user));
195:
196: /* assume that we can't find this interface's hardware address: */
197: if (_if_addr != NULL) {
198: *_if_addr = NULL;
199: }
200: if (_if_addr_size != NULL) {
201: *_if_addr_size = 0;
202: }
203:
204: #ifdef HAVE_AF_LINK
205:
206: /* try to find an AF_LINK ifreq that gives us the interface's
207: hardware address: */
208: ifr = NULL;
209: for (link_ifreqs_i = 0;
210: link_ifreqs_i < link_ifreqs_count;
211: link_ifreqs_i++) {
212: if (!strncmp(link_ifreqs[link_ifreqs_i]->ifr_name,
213: ifr_user->ifr_name,
214: sizeof(ifr_user->ifr_name))) {
215: ifr = link_ifreqs[link_ifreqs_i];
216: break;
217: }
218: }
219:
220: /* if we found one, return the hardware address: */
221: if (ifr != NULL) {
222: sadl = (struct sockaddr_dl *) &ifr->ifr_addr;
223: if (_if_addr_size != NULL) {
224: *_if_addr_size = sadl->sdl_alen;
225: }
226: if (_if_addr != NULL) {
227: *_if_addr = tme_new(tme_uint8_t, sadl->sdl_alen);
228: memcpy(*_if_addr, LLADDR(sadl), sadl->sdl_alen);
229: }
230: }
231:
232: #endif /* HAVE_AF_LINK */
233:
234: /* done: */
235: return (TME_OK);
236: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.