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