xref: /netbsd-src/usr.sbin/mopd/common/device.c (revision 76cf3a021ce49ebf6df0dfedfcb368e0b1b5c444)
1 /*	$NetBSD: device.c,v 1.14 2024/12/03 05:40:39 kalvisd 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.14 2024/12/03 05:40:39 kalvisd 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 	tmp.fd      = -1;
95 
96 	switch (proto) {
97 	case MOP_K_PROTO_RC:
98 		tmp.read = mopReadRC;
99 		tmp.fd   = mopOpenRC(&tmp, trans);
100 		break;
101 	case MOP_K_PROTO_DL:
102 		tmp.read = mopReadDL;
103 		tmp.fd   = mopOpenDL(&tmp, trans);
104 		break;
105 	default:
106 		break;
107 	}
108 
109 	if (tmp.fd != -1) {
110 		p = malloc(sizeof(*p));
111 		if (p == 0)
112 			mopLogErr("deviceOpen: malloc");
113 
114 		p->next = iflist;
115 		iflist = p;
116 
117 		strlcpy(p->if_name, tmp.if_name, sizeof(p->if_name));
118 		p->iopen   = tmp.iopen;
119 		p->write   = pfWrite;
120 		p->read    = tmp.read;
121 		memset((char *)p->eaddr, 0, sizeof(p->eaddr));
122 		p->fd      = tmp.fd;
123 
124 #ifdef	DEV_NEW_CONF
125 		deviceEthAddr(p->if_name,&p->eaddr[0]);
126 #else
127 		p->eaddr[0]= tmp.eaddr[0];
128 		p->eaddr[1]= tmp.eaddr[1];
129 		p->eaddr[2]= tmp.eaddr[2];
130 		p->eaddr[3]= tmp.eaddr[3];
131 		p->eaddr[4]= tmp.eaddr[4];
132 		p->eaddr[5]= tmp.eaddr[5];
133 #endif	/* DEV_NEW_CONF */
134 
135 	}
136 }
137 
138 void
139 deviceInitOne(const char *ifname)
140 {
141 	char	interface[IFNAME_SIZE];
142 	struct if_info *p;
143 	int	trans;
144 #ifdef _AIX
145 	char	dev[IFNAME_SIZE];
146 	int	unit,j;
147 
148 	unit = 0;
149 	for (j = 0; j < strlen(ifname); j++) {
150 		if (isalpha(ifname[j])) {
151 			dev[j] = ifname[j];
152 		} else {
153 			if (isdigit(ifname[j])) {
154 				unit = unit*10 + ifname[j] - '0';
155 				dev[j] = '\0';
156 			}
157 		}
158 	}
159 
160 	if ((strlen(dev) == 2) &&
161 	    (dev[0] == 'e') &&
162 	    ((dev[1] == 'n') || (dev[1] == 't'))) {
163 		snprintf(interface, sizeof(interface), "ent%d\0", unit);
164 	} else {
165 		snprintf(interface, sizeof(interface), "%s%d\0", dev, unit);
166 	}
167 #else
168 	snprintf(interface, sizeof(interface), "%s", ifname);
169 #endif /* _AIX */
170 
171 	/* Ok, init it just once */
172 
173 	p = iflist;
174 	for (p = iflist; p; p = p->next)  {
175 		if (strcmp(p->if_name,interface) == 0) {
176 			return;
177 		}
178 	}
179 
180 	if (!mopInteractive)
181 		syslog(LOG_INFO, "Initialized %s", interface);
182 
183 	/* Ok, get transport information */
184 
185 	trans = pfTrans(interface);
186 
187 #ifndef NORC
188 	/* Start with MOP Remote Console */
189 
190 	switch (trans) {
191 	case TRANS_ETHER:
192 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
193 		break;
194 	case TRANS_8023:
195 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
196 		break;
197 	case TRANS_ETHER+TRANS_8023:
198 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER);
199 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023);
200 		break;
201 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
202 		deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023);
203 		break;
204 	}
205 #endif
206 
207 #ifndef NODL
208 	/* and next MOP Dump/Load */
209 
210 	switch (trans) {
211 	case TRANS_ETHER:
212 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
213 		break;
214 	case TRANS_8023:
215 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
216 		break;
217 	case TRANS_ETHER+TRANS_8023:
218 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER);
219 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023);
220 		break;
221 	case TRANS_ETHER+TRANS_8023+TRANS_AND:
222 		deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023);
223 		break;
224 	}
225 #endif
226 
227 }
228 
229 /*
230  * Initialize all "candidate" interfaces that are in the system
231  * configuration list.  A "candidate" is up, not loopback and not
232  * point to point.
233  */
234 void
235 deviceInitAll(void)
236 {
237 	struct ifaddrs *ifap, *ifa;
238 
239 	if (getifaddrs(&ifap) != 0)
240 		mopLogErr("deviceInitAll: socket");
241 
242 	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
243 #ifdef	AF_LINK
244 		struct sockaddr_dl *sdl;
245 		sdl = (struct sockaddr_dl *)ifa->ifa_addr;
246 		if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER ||
247 		    sdl->sdl_alen != 6)
248 			continue;
249 #endif
250 		if ((ifa->ifa_flags &
251 		    (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP)
252 			continue;
253 		deviceInitOne(ifa->ifa_name);
254 	}
255 
256 	freeifaddrs(ifap);
257 }
258