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
deviceEthAddr(const char * ifname,u_char * eaddr)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
deviceOpen(const char * ifname,u_short proto,int trans)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
deviceInitOne(const char * ifname)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
deviceInitAll(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