xref: /netbsd-src/usr.sbin/mopd/common/device.c (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
1 /*	$NetBSD: device.c,v 1.13 2016/06/08 01:11:49 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  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "port.h"
28 #ifndef lint
29 __RCSID("$NetBSD: device.c,v 1.13 2016/06/08 01:11:49 christos Exp $");
30 #endif
31 
32 #include "os.h"
33 #include "common.h"
34 #include "device.h"
35 #include "mopdef.h"
36 #include "pf.h"
37 #include "log.h"
38 
39 struct	if_info *iflist;		/* Interface List		*/
40 
41 void	deviceOpen(const char *, u_short, int);
42 
43 /*
44  * Return ethernet address for interface
45  */
46 
47 void
48 deviceEthAddr(const char *ifname, u_char *eaddr)
49 {
50 #ifndef AF_LINK
51 	int fd;
52 	struct ifreq ifr;
53 
54 	/* Use datagram socket to get Ethernet address. */
55 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
56 		mopLogErr("deviceEthAddr: socket");
57 
58 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
59 	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1)
60 		mopLogErr("deviceEthAddr: SIOGIFHWADDR");
61 	memcpy(eaddr, ifr.ifr_hwaddr.sa_data, 6);
62 	close(fd);
63 #else
64 	struct sockaddr_dl *sdl;
65 	struct ifaddrs *ifap, *ifa;
66 
67 	if (getifaddrs(&ifap) != 0)
68 		mopLogErr("deviceEthAddr: getifaddrs");
69 
70 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
71 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
72 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
73 		    sdl->sdl_alen != 6)
74 			continue;
75 		if (!strcmp(ifa->ifa_name, ifname)) {
76 			memmove((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6);
77 			freeifaddrs(ifap);
78 			return;
79 		}
80 	}
81 
82 	freeifaddrs(ifap);
83 	mopLogErrX("deviceEthAddr: Never saw interface `%s'!", ifname);
84 #endif
85 }
86 
87 void
88 deviceOpen(const char *ifname, u_short proto, int trans)
89 {
90 	struct if_info *p, tmp;
91 
92 	strlcpy(tmp.if_name, ifname, sizeof(tmp.if_name));
93 	tmp.iopen   = pfInit;
94 
95 	switch (proto) {
96 	case MOP_K_PROTO_RC:
97 		tmp.read = mopReadRC;
98 		tmp.fd   = mopOpenRC(&tmp, trans);
99 		break;
100 	case MOP_K_PROTO_DL:
101 		tmp.read = mopReadDL;
102 		tmp.fd   = mopOpenDL(&tmp, trans);
103 		break;
104 	default:
105 		break;
106 	}
107 
108 	if (tmp.fd != -1) {
109 		p = malloc(sizeof(*p));
110 		if (p == 0)
111 			mopLogErr("deviceOpen: malloc");
112 
113 		p->next = iflist;
114 		iflist = p;
115 
116 		strlcpy(p->if_name, tmp.if_name, sizeof(p->if_name));
117 		p->iopen   = tmp.iopen;
118 		p->write   = pfWrite;
119 		p->read    = tmp.read;
120 		memset((char *)p->eaddr, 0, sizeof(p->eaddr));
121 		p->fd      = tmp.fd;
122 
123 #ifdef	DEV_NEW_CONF
124 		deviceEthAddr(p->if_name,&p->eaddr[0]);
125 #else
126 		p->eaddr[0]= tmp.eaddr[0];
127 		p->eaddr[1]= tmp.eaddr[1];
128 		p->eaddr[2]= tmp.eaddr[2];
129 		p->eaddr[3]= tmp.eaddr[3];
130 		p->eaddr[4]= tmp.eaddr[4];
131 		p->eaddr[5]= tmp.eaddr[5];
132 #endif	/* DEV_NEW_CONF */
133 
134 	}
135 }
136 
137 void
138 deviceInitOne(const char *ifname)
139 {
140 	char	interface[IFNAME_SIZE];
141 	struct if_info *p;
142 	int	trans;
143 #ifdef _AIX
144 	char	dev[IFNAME_SIZE];
145 	int	unit,j;
146 
147 	unit = 0;
148 	for (j = 0; j < strlen(ifname); j++) {
149 		if (isalpha(ifname[j])) {
150 			dev[j] = ifname[j];
151 		} else {
152 			if (isdigit(ifname[j])) {
153 				unit = unit*10 + ifname[j] - '0';
154 				dev[j] = '\0';
155 			}
156 		}
157 	}
158 
159 	if ((strlen(dev) == 2) &&
160 	    (dev[0] == 'e') &&
161 	    ((dev[1] == 'n') || (dev[1] == 't'))) {
162 		snprintf(interface, sizeof(interface), "ent%d\0", unit);
163 	} else {
164 		snprintf(interface, sizeof(interface), "%s%d\0", dev, unit);
165 	}
166 #else
167 	snprintf(interface, sizeof(interface), "%s", ifname);
168 #endif /* _AIX */
169 
170 	/* Ok, init it just once */
171 
172 	p = iflist;
173 	for (p = iflist; p; p = p->next)  {
174 		if (strcmp(p->if_name,interface) == 0) {
175 			return;
176 		}
177 	}
178 
179 	if (!mopInteractive)
180 		syslog(LOG_INFO, "Initialized %s", interface);
181 
182 	/* Ok, get transport information */
183 
184 	trans = pfTrans(interface);
185 
186 #ifndef NORC
187 	/* Start with MOP Remote Console */
188 
189 	switch (trans) {
190 	case TRANS_ETHER:
191 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
192 		break;
193 	case TRANS_8023:
194 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
195 		break;
196 	case TRANS_ETHER+TRANS_8023:
197 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
198 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
199 		break;
200 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
201 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023);
202 		break;
203 	}
204 #endif
205 
206 #ifndef NODL
207 	/* and next MOP Dump/Load */
208 
209 	switch (trans) {
210 	case TRANS_ETHER:
211 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
212 		break;
213 	case TRANS_8023:
214 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
215 		break;
216 	case TRANS_ETHER+TRANS_8023:
217 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
218 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
219 		break;
220 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
221 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023);
222 		break;
223 	}
224 #endif
225 
226 }
227 
228 /*
229  * Initialize all "candidate" interfaces that are in the system
230  * configuration list.  A "candidate" is up, not loopback and not
231  * point to point.
232  */
233 void
234 deviceInitAll(void)
235 {
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 #ifdef	AF_LINK
243 		struct sockaddr_dl *sdl;
244 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
245 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
246 		    sdl->sdl_alen != 6)
247 			continue;
248 #endif
249 		if ((ifa->ifa_flags &
250 		    (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
251 			continue;
252 		deviceInitOne(ifa->ifa_name);
253 	}
254 
255 	freeifaddrs(ifap);
256 }
257