xref: /netbsd-src/usr.sbin/mopd/common/device.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: device.c,v 1.9 2003/11/10 08:51:52 wiz 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.9 2003/11/10 08:51:52 wiz 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 address for interface
51  */
52 
53 void
54 deviceEthAddr(ifname, eaddr)
55 	char *ifname;
56         u_char *eaddr;
57 {
58 	struct sockaddr_dl *sdl;
59 	struct ifaddrs *ifap, *ifa;
60 
61 	if (getifaddrs(&ifap) != 0)
62 		mopLogErr("deviceEthAddr: getifaddrs");
63 
64 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
65 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
66 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
67 		    sdl->sdl_alen != 6)
68 			continue;
69 		if (!strcmp(ifa->ifa_name, ifname)) {
70 			memmove((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6);
71 			freeifaddrs(ifap);
72 			return;
73 		}
74 	}
75 
76 	freeifaddrs(ifap);
77 	mopLogErrX("deviceEthAddr: Never saw interface `%s'!", ifname);
78 }
79 #endif	/* DEV_NEW_CONF */
80 
81 void
82 deviceOpen(ifname, proto, trans)
83 	char	*ifname;
84 	u_short	 proto;
85 	int	 trans;
86 {
87 	struct if_info *p, tmp;
88 
89 	strlcpy(tmp.if_name, ifname, sizeof(tmp.if_name));
90 	tmp.iopen   = pfInit;
91 
92 	switch (proto) {
93 	case MOP_K_PROTO_RC:
94 		tmp.read = mopReadRC;
95 		tmp.fd   = mopOpenRC(&tmp, trans);
96 		break;
97 	case MOP_K_PROTO_DL:
98 		tmp.read = mopReadDL;
99 		tmp.fd   = mopOpenDL(&tmp, trans);
100 		break;
101 	default:
102 		break;
103 	}
104 
105 	if (tmp.fd != -1) {
106 		p = (struct if_info *)malloc(sizeof(*p));
107 		if (p == 0)
108 			mopLogErr("deviceOpen: malloc");
109 
110 		p->next = iflist;
111 		iflist = p;
112 
113 		strlcpy(p->if_name, tmp.if_name, sizeof(p->if_name));
114 		p->iopen   = tmp.iopen;
115 		p->write   = pfWrite;
116 		p->read    = tmp.read;
117 		memset((char *)p->eaddr, 0, sizeof(p->eaddr));
118 		p->fd      = tmp.fd;
119 
120 #ifdef	DEV_NEW_CONF
121 		deviceEthAddr(p->if_name,&p->eaddr[0]);
122 #else
123 		p->eaddr[0]= tmp.eaddr[0];
124 		p->eaddr[1]= tmp.eaddr[1];
125 		p->eaddr[2]= tmp.eaddr[2];
126 		p->eaddr[3]= tmp.eaddr[3];
127 		p->eaddr[4]= tmp.eaddr[4];
128 		p->eaddr[5]= tmp.eaddr[5];
129 #endif	/* DEV_NEW_CONF */
130 
131 	}
132 }
133 
134 void
135 deviceInitOne(ifname)
136 	char	*ifname;
137 {
138 	char	interface[IFNAME_SIZE];
139 	struct if_info *p;
140 	int	trans;
141 #ifdef _AIX
142 	char	dev[IFNAME_SIZE];
143 	int	unit,j;
144 
145 	unit = 0;
146 	for (j = 0; j < strlen(ifname); j++) {
147 		if (isalpha(ifname[j])) {
148 			dev[j] = ifname[j];
149 		} else {
150 			if (isdigit(ifname[j])) {
151 				unit = unit*10 + ifname[j] - '0';
152 				dev[j] = '\0';
153 			}
154 		}
155 	}
156 
157 	if ((strlen(dev) == 2) &&
158 	    (dev[0] == 'e') &&
159 	    ((dev[1] == 'n') || (dev[1] == 't'))) {
160 		snprintf(interface, sizeof(interface), "ent%d\0", unit);
161 	} else {
162 		snprintf(interface, sizeof(interface), "%s%d\0", dev, unit);
163 	}
164 #else
165 	snprintf(interface, sizeof(interface), "%s", ifname);
166 #endif /* _AIX */
167 
168 	/* Ok, init it just once */
169 
170 	p = iflist;
171 	for (p = iflist; p; p = p->next)  {
172 		if (strcmp(p->if_name,interface) == 0) {
173 			return;
174 		}
175 	}
176 
177 	if (!mopInteractive)
178 		syslog(LOG_INFO, "Initialized %s", interface);
179 
180 	/* Ok, get transport information */
181 
182 	trans = pfTrans(interface);
183 
184 #ifndef NORC
185 	/* Start with MOP Remote Console */
186 
187 	switch (trans) {
188 	case TRANS_ETHER:
189 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
190 		break;
191 	case TRANS_8023:
192 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
193 		break;
194 	case TRANS_ETHER+TRANS_8023:
195 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
196 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
197 		break;
198 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
199 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023);
200 		break;
201 	}
202 #endif
203 
204 #ifndef NODL
205 	/* and next MOP Dump/Load */
206 
207 	switch (trans) {
208 	case TRANS_ETHER:
209 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
210 		break;
211 	case TRANS_8023:
212 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
213 		break;
214 	case TRANS_ETHER+TRANS_8023:
215 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
216 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
217 		break;
218 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
219 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023);
220 		break;
221 	}
222 #endif
223 
224 }
225 
226 /*
227  * Initialize all "candidate" interfaces that are in the system
228  * configuration list.  A "candidate" is up, not loopback and not
229  * point to point.
230  */
231 void
232 deviceInitAll()
233 {
234 #ifdef	DEV_NEW_CONF
235 	struct sockaddr_dl *sdl;
236 	struct ifaddrs *ifap, *ifa;
237 
238 	if (getifaddrs(&ifap) != 0)
239 		mopLogErr("deviceInitAll: socket");
240 
241 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
242 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
243 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
244 		    sdl->sdl_alen != 6)
245 			continue;
246 		if ((ifa->ifa_flags &
247 		    (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
248 			continue;
249 		deviceInitOne(ifa->ifa_name);
250 	}
251 
252 	freeifaddrs(ifap);
253 #else
254 	struct ifaddrs *ifap, *ifa;
255 
256 	if (getifaddrs(&ifap) != 0)
257 		mopLogErr("deviceInitAll: old socket");
258 
259 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
260 		if (/*(ifa->ifa_flags & IFF_UP) == 0 ||*/
261 		    ifa->ifa_flags & IFF_LOOPBACK ||
262 		    ifa->ifa_flags & IFF_POINTOPOINT)
263 			continue;
264 		deviceInitOne(ifa->ifa_name);
265 	}
266 
267 	freeifaddrs(ifap);
268 #endif /* DEV_NEW_CONF */
269 }
270