1 |
|
|
/* $OpenBSD: device.c,v 1.17 2017/01/21 08:33:51 krw 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 |
|
|
struct if_info *iflist; /* Interface List */ |
34 |
|
|
|
35 |
|
|
#ifdef DEV_NEW_CONF |
36 |
|
|
/* |
37 |
|
|
* Return ethernet address for interface |
38 |
|
|
*/ |
39 |
|
|
|
40 |
|
|
void |
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 |
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 |
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 |
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 |
|
|
} |