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