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