1 /*        $NetBSD: netif.c,v 1.27 2023/09/14 03:08:31 rin Exp $       */
2 
3 /*
4  * Copyright (c) 1993 Adam Glass
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *        This product includes software developed by Adam Glass.
18  * 4. The name of the Author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/cdefs.h>
36 #include <sys/mount.h>
37 #ifdef _STANDALONE
38 #include <lib/libkern/libkern.h>
39 #else
40 #include <string.h>
41 #endif
42 
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45 
46 #include "stand.h"
47 #include "netif.h"
48 
49 struct iodesc sockets[SOPEN_MAX];
50 #ifdef NETIF_DEBUG
51 int netif_debug = 0;
52 #endif
53 
54 /*
55  * netif_init:
56  *
57  * initialize the generic network interface layer
58  */
59 
60 void
netif_init(void)61 netif_init(void)
62 {
63           struct netif_driver *drv;
64           int d, i;
65 
66 #ifdef NETIF_DEBUG
67           if (netif_debug)
68                     printf("%s: called\n", __func__);
69 #endif
70           for (d = 0; d < n_netif_drivers; d++) {
71                     drv = netif_drivers[d];
72                     for (i = 0; i < drv->netif_nifs; i++)
73                               drv->netif_ifs[i].dif_used = 0;
74           }
75 }
76 
77 int       netif_match(struct netif *, void *);
78 
79 int
netif_match(struct netif * nif,void * machdep_hint)80 netif_match(struct netif *nif, void *machdep_hint)
81 {
82           struct netif_driver *drv = nif->nif_driver;
83 
84 #if 0
85           if (netif_debug)
86                     printf("%s%d: %s (%d)\n", drv->netif_bname,
87                         nif->nif_unit, __func__, nif->nif_sel);
88 #endif
89           return drv->netif_match(nif, machdep_hint);
90 }
91 
92 struct netif *
netif_select(void * machdep_hint)93 netif_select(void *machdep_hint)
94 {
95           int d, u, s;
96           struct netif_driver *drv;
97           struct netif cur_if;
98           static struct netif best_if;
99           int best_val;
100           int val;
101 
102           best_val = 0;
103           best_if.nif_driver = NULL;
104 
105 #ifdef NETIF_DEBUG
106           if (netif_debug)
107                     printf("%s: %d interfaces\n", __func__, n_netif_drivers);
108 #endif
109 
110           for (d = 0; d < n_netif_drivers; d++) {
111                     cur_if.nif_driver = netif_drivers[d];
112                     drv = cur_if.nif_driver;
113 
114                     for (u = 0; u < drv->netif_nifs; u++) {
115                               cur_if.nif_unit = u;
116 
117 #ifdef NETIF_DEBUG
118                               if (netif_debug)
119                                         printf("\t%s%d:", drv->netif_bname,
120                                             cur_if.nif_unit);
121 #endif
122 
123                               for (s = 0; s < drv->netif_ifs[u].dif_nsel; s++) {
124                                         cur_if.nif_sel = s;
125 
126                                         if (drv->netif_ifs[u].dif_used & (1 << s)) {
127 #ifdef NETIF_DEBUG
128                                                   if (netif_debug)
129                                                             printf(" [%d used]", s);
130 #endif
131                                                   continue;
132                                         }
133 
134                                         val = netif_match(&cur_if, machdep_hint);
135 #ifdef NETIF_DEBUG
136                                         if (netif_debug)
137                                                   printf(" [%d -> %d]", s, val);
138 #endif
139                                         if (val > best_val) {
140                                                   best_val = val;
141                                                   best_if = cur_if;
142                                         }
143                               }
144 #ifdef NETIF_DEBUG
145                               if (netif_debug)
146                                         printf("\n");
147 #endif
148                     }
149           }
150 
151           if (best_if.nif_driver == NULL)
152                     return NULL;
153 
154           best_if.nif_driver->
155               netif_ifs[best_if.nif_unit].dif_used |= (1 << best_if.nif_sel);
156 
157 #ifdef NETIF_DEBUG
158           if (netif_debug)
159                     printf("%s: %s%d(%d) wins\n", __func__,
160                               best_if.nif_driver->netif_bname,
161                               best_if.nif_unit, best_if.nif_sel);
162 #endif
163           return &best_if;
164 }
165 
166 int
netif_probe(struct netif * nif,void * machdep_hint)167 netif_probe(struct netif *nif, void *machdep_hint)
168 {
169           struct netif_driver *drv = nif->nif_driver;
170 
171 #ifdef NETIF_DEBUG
172           if (netif_debug)
173                     printf("%s%d: %s\n", drv->netif_bname, nif->nif_unit, __func__);
174 #endif
175           return drv->netif_probe(nif, machdep_hint);
176 }
177 
178 void
netif_attach(struct netif * nif,struct iodesc * desc,void * machdep_hint)179 netif_attach(struct netif *nif, struct iodesc *desc, void *machdep_hint)
180 {
181           struct netif_driver *drv = nif->nif_driver;
182 
183 #ifdef NETIF_DEBUG
184           if (netif_debug)
185                     printf("%s%d: %s\n", drv->netif_bname, nif->nif_unit, __func__);
186 #endif
187           desc->io_netif = nif;
188 #ifdef PARANOID
189           if (drv->netif_init == NULL)
190                     panic("%s%d: no netif_init support", drv->netif_bname,
191                         nif->nif_unit);
192 #endif
193           drv->netif_init(desc, machdep_hint);
194           (void)memset(drv->netif_ifs[nif->nif_unit].dif_stats, 0,
195               sizeof(struct netif_stats));
196 }
197 
198 void
netif_detach(struct netif * nif)199 netif_detach(struct netif *nif)
200 {
201           struct netif_driver *drv = nif->nif_driver;
202 
203 #ifdef NETIF_DEBUG
204           if (netif_debug)
205                     printf("%s%d: %s\n", drv->netif_bname, nif->nif_unit, __func__);
206 #endif
207 #ifdef PARANOID
208           if (drv->netif_end == NULL)
209                     panic("%s%d: no netif_end support", drv->netif_bname,
210                         nif->nif_unit);
211 #endif
212           drv->netif_end(nif);
213 }
214 
215 ssize_t
netif_get(struct iodesc * desc,void * pkt,size_t len,saseconds_t timo)216 netif_get(struct iodesc *desc, void *pkt, size_t len, saseconds_t timo)
217 {
218           struct netif *nif = desc->io_netif;
219           struct netif_driver *drv = nif->nif_driver;
220           ssize_t rv;
221 
222 #ifdef NETIF_DEBUG
223           if (netif_debug)
224                     printf("%s%d: %s\n", drv->netif_bname, nif->nif_unit, __func__);
225 #endif
226 #ifdef PARANOID
227           if (drv->netif_get == NULL)
228                     panic("%s%d: no %s support", drv->netif_bname,
229                         nif->nif_unit, __func__);
230 #endif
231           rv = drv->netif_get(desc, pkt, len, timo);
232 #ifdef NETIF_DEBUG
233           if (netif_debug)
234                     printf("%s%d: %s returning %zd\n", drv->netif_bname,
235                         nif->nif_unit, __func__, rv);
236 #endif
237           return rv;
238 }
239 
240 ssize_t
netif_put(struct iodesc * desc,void * pkt,size_t len)241 netif_put(struct iodesc *desc, void *pkt, size_t len)
242 {
243           struct netif *nif = desc->io_netif;
244           struct netif_driver *drv = nif->nif_driver;
245           ssize_t rv;
246 
247 #ifdef NETIF_DEBUG
248           if (netif_debug)
249                     printf("%s%d: %s\n", drv->netif_bname, nif->nif_unit, __func__);
250 #endif
251 #ifdef PARANOID
252           if (drv->netif_put == NULL)
253                     panic("%s%d: no netif_put support", drv->netif_bname,
254                         nif->nif_unit);
255 #endif
256           rv = drv->netif_put(desc, pkt, len);
257 #ifdef NETIF_DEBUG
258           if (netif_debug)
259                     printf("%s%d: %s returning %zd\n", drv->netif_bname,
260                         nif->nif_unit, __func__, rv);
261 #endif
262           return rv;
263 }
264 
265 struct iodesc *
socktodesc(int sock)266 socktodesc(int sock)
267 {
268 #if !defined(LIBSA_NO_FD_CHECKING)
269           if (sock >= SOPEN_MAX) {
270                     errno = EBADF;
271                     return NULL;
272           }
273 #endif
274           return &sockets[sock];
275 }
276 
277 int
netif_open(void * machdep_hint)278 netif_open(void *machdep_hint)
279 {
280           int fd;
281           struct iodesc *s;
282           struct netif *nif;
283 
284           /* find a free socket */
285           for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++)
286                     if (s->io_netif == (struct netif *)0)
287                               goto fnd;
288           errno = EMFILE;
289           return -1;
290 
291 fnd:
292           (void)memset(s, 0, sizeof(*s));
293           netif_init();
294           nif = netif_select(machdep_hint);
295           if (!nif) {
296                     errno = ENXIO;
297                     return -1;
298           }
299           if (netif_probe(nif, machdep_hint)) {
300                     printf("%s: couldn't probe %s%d\n", __func__,
301                         nif->nif_driver->netif_bname, nif->nif_unit);
302                     errno = EINVAL;
303                     return -1;
304           }
305           netif_attach(nif, s, machdep_hint);
306 
307           return fd;
308 }
309 
310 int
netif_close(int sock)311 netif_close(int sock)
312 {
313 #if !defined(LIBSA_NO_FD_CHECKING)
314           if (sock >= SOPEN_MAX) {
315                     errno = EBADF;
316                     return -1;
317           }
318 #endif
319           netif_detach(sockets[sock].io_netif);
320           sockets[sock].io_netif = (struct netif *)0;
321 
322           return 0;
323 }
324