xref: /netbsd-src/usr.sbin/mopd/common/device.c (revision 001c68bd94f75ce9270b69227c4199fbf34ee396)
1 /*	$NetBSD: device.c,v 1.6 2003/04/20 00:17:22 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1993-95 Mats O Jansson.  All rights reserved.
5  *
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.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Mats O Jansson.
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #ifndef lint
34 __RCSID("$NetBSD: device.c,v 1.6 2003/04/20 00:17:22 christos Exp $");
35 #endif
36 
37 #include "os.h"
38 #include "common.h"
39 #include "device.h"
40 #include "mopdef.h"
41 #include "pf.h"
42 #include "log.h"
43 
44 struct	if_info *iflist;		/* Interface List		*/
45 
46 void	deviceOpen __P((char *, u_short, int));
47 
48 #ifdef	DEV_NEW_CONF
49 /*
50  * Return ethernet adress for interface
51  */
52 
53 void
54 deviceEthAddr(ifname, eaddr)
55 	char *ifname;
56         u_char *eaddr;
57 {
58 	char inbuf[8192];
59 	struct ifconf ifc;
60 	struct ifreq *ifr;
61 	struct sockaddr_dl *sdl;
62 	int fd;
63 	int i, len;
64 
65 	/* We cannot use SIOCGIFADDR on the BPF descriptor.
66 	   We must instead get all the interfaces with SIOCGIFCONF
67 	   and find the right one.  */
68 
69 	/* Use datagram socket to get Ethernet address. */
70 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
71 		mopLogErr("deviceEthAddr: socket");
72 
73 	ifc.ifc_len = sizeof(inbuf);
74 	ifc.ifc_buf = inbuf;
75 	if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 ||
76 	    ifc.ifc_len < sizeof(struct ifreq))
77 		mopLogErr("deviceEthAddr: SIOGIFCONF");
78 	ifr = ifc.ifc_req;
79 	for (i = 0; i < ifc.ifc_len;
80 	     i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
81 		len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
82 		sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
83 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
84 		    sdl->sdl_alen != 6)
85 			continue;
86 		if (!strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))) {
87 			memmove((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6);
88 			return;
89 		}
90 	}
91 
92 	mopLogErrX("deviceEthAddr: Never saw interface `%s'!", ifname);
93 }
94 #endif	/* DEV_NEW_CONF */
95 
96 void
97 deviceOpen(ifname, proto, trans)
98 	char	*ifname;
99 	u_short	 proto;
100 	int	 trans;
101 {
102 	struct if_info *p, tmp;
103 
104 	strlcpy(tmp.if_name, ifname, sizeof(tmp.if_name));
105 	tmp.iopen   = pfInit;
106 
107 	switch (proto) {
108 	case MOP_K_PROTO_RC:
109 		tmp.read = mopReadRC;
110 		tmp.fd   = mopOpenRC(&tmp, trans);
111 		break;
112 	case MOP_K_PROTO_DL:
113 		tmp.read = mopReadDL;
114 		tmp.fd   = mopOpenDL(&tmp, trans);
115 		break;
116 	default:
117 		break;
118 	}
119 
120 	if (tmp.fd != -1) {
121 
122 		p = (struct if_info *)malloc(sizeof(*p));
123 		if (p == 0)
124 			mopLogErr("deviceOpen: malloc");
125 
126 		p->next = iflist;
127 		iflist = p;
128 
129 		strcpy(p->if_name,tmp.if_name);
130 		p->iopen   = tmp.iopen;
131 		p->write   = pfWrite;
132 		p->read    = tmp.read;
133 		memset((char *)p->eaddr, 0, sizeof(p->eaddr));
134 		p->fd      = tmp.fd;
135 
136 #ifdef	DEV_NEW_CONF
137 		deviceEthAddr(p->if_name,&p->eaddr[0]);
138 #else
139 		p->eaddr[0]= tmp.eaddr[0];
140 		p->eaddr[1]= tmp.eaddr[1];
141 		p->eaddr[2]= tmp.eaddr[2];
142 		p->eaddr[3]= tmp.eaddr[3];
143 		p->eaddr[4]= tmp.eaddr[4];
144 		p->eaddr[5]= tmp.eaddr[5];
145 #endif	/* DEV_NEW_CONF */
146 
147 	}
148 }
149 
150 void
151 deviceInitOne(ifname)
152 	char	*ifname;
153 {
154 	char	interface[IFNAME_SIZE];
155 	struct if_info *p;
156 	int	trans;
157 #ifdef _AIX
158 	char	dev[IFNAME_SIZE];
159 	int	unit,j;
160 
161 	unit = 0;
162 	for (j = 0; j < strlen(ifname); j++) {
163 		if (isalpha(ifname[j])) {
164 			dev[j] = ifname[j];
165 		} else {
166 			if (isdigit(ifname[j])) {
167 				unit = unit*10 + ifname[j] - '0';
168 				dev[j] = '\0';
169 			}
170 		}
171 	}
172 
173 	if ((strlen(dev) == 2) &&
174 	    (dev[0] == 'e') &&
175 	    ((dev[1] == 'n') || (dev[1] == 't'))) {
176 		snprintf(interface, sizeof(interface), "ent%d\0", unit);
177 	} else {
178 		snprintf(interface, sizeof(interface), "%s%d\0", dev, unit);
179 	}
180 #else
181 	snprintf(interface, sizeof(interface), "%s", ifname);
182 #endif /* _AIX */
183 
184 	/* Ok, init it just once */
185 
186 	p = iflist;
187 	for (p = iflist; p; p = p->next)  {
188 		if (strcmp(p->if_name,interface) == 0) {
189 			return;
190 		}
191 	}
192 
193 	if (!mopInteractive)
194 		syslog(LOG_INFO, "Initialized %s", interface);
195 
196 	/* Ok, get transport information */
197 
198 	trans = pfTrans(interface);
199 
200 #ifndef NORC
201 	/* Start with MOP Remote Console */
202 
203 	switch (trans) {
204 	case TRANS_ETHER:
205 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
206 		break;
207 	case TRANS_8023:
208 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
209 		break;
210 	case TRANS_ETHER+TRANS_8023:
211 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
212 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
213 		break;
214 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
215 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023);
216 		break;
217 	}
218 #endif
219 
220 #ifndef NODL
221 	/* and next MOP Dump/Load */
222 
223 	switch (trans) {
224 	case TRANS_ETHER:
225 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
226 		break;
227 	case TRANS_8023:
228 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
229 		break;
230 	case TRANS_ETHER+TRANS_8023:
231 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
232 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
233 		break;
234 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
235 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023);
236 		break;
237 	}
238 #endif
239 
240 }
241 
242 /*
243  * Initialize all "candidate" interfaces that are in the system
244  * configuration list.  A "candidate" is up, not loopback and not
245  * point to point.
246  */
247 void
248 deviceInitAll()
249 {
250 #ifdef	DEV_NEW_CONF
251 	char inbuf[8192];
252 	struct ifconf ifc;
253 	struct ifreq *ifr;
254 	struct sockaddr_dl *sdl;
255 	int fd;
256 	int i, len;
257 
258 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
259 		mopLogErr("deviceInitAll: socket");
260 
261 	ifc.ifc_len = sizeof(inbuf);
262 	ifc.ifc_buf = inbuf;
263 	if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 ||
264 	    ifc.ifc_len < sizeof(struct ifreq))
265 		mopLogErr("deviceInitAll: SIOCGIFCONF");
266 	ifr = ifc.ifc_req;
267 	for (i = 0; i < ifc.ifc_len;
268 	     i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) {
269 		len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
270 		sdl = (struct sockaddr_dl *)&ifr->ifr_addr;
271 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
272 		    sdl->sdl_alen != 6)
273 			continue;
274 		if (ioctl(fd, SIOCGIFFLAGS, (caddr_t)ifr) < 0) {
275 			mopLogWarn("deviceInitAll: SIOCGIFFLAGS");
276 			continue;
277 		}
278 		if ((ifr->ifr_flags &
279 		    (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
280 			continue;
281 		deviceInitOne(ifr->ifr_name);
282 	}
283 	(void) close(fd);
284 #else
285 	int fd;
286 	int n;
287 	struct ifreq ibuf[8], *ifrp;
288 	struct ifconf ifc;
289 
290 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
291 		mopLogErr("deviceInitAll: old socket");
292 	ifc.ifc_len = sizeof ibuf;
293 	ifc.ifc_buf = (caddr_t)ibuf;
294 	if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
295 	    ifc.ifc_len < sizeof(struct ifreq))
296 		mopLogErr("deviceInitAll: old SIOCGIFCONF");
297 	ifrp = ibuf;
298 	n = ifc.ifc_len / sizeof(*ifrp);
299 	for (; --n >= 0; ++ifrp) {
300 		if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) {
301 			continue;
302 		}
303 		if (/*(ifrp->ifr_flags & IFF_UP) == 0 ||*/
304 		    ifrp->ifr_flags & IFF_LOOPBACK ||
305 		    ifrp->ifr_flags & IFF_POINTOPOINT)
306 			continue;
307 		deviceInitOne(ifrp->ifr_name);
308 	}
309 
310 	(void) close(fd);
311 #endif /* DEV_NEW_CONF */
312 }
313