xref: /netbsd-src/sys/lib/libsa/netif.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
1 /*	$NetBSD: netif.c,v 1.15 2000/03/30 12:19:48 augustss 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/types.h>
36 #include <sys/cdefs.h>
37 #include <sys/mount.h>
38 #ifdef _STANDALONE
39 #include <lib/libkern/libkern.h>
40 #else
41 #include <string.h>
42 #endif
43 
44 #include <netinet/in.h>
45 #include <netinet/in_systm.h>
46 
47 #include "stand.h"
48 #include "net.h"
49 #include "netif.h"
50 
51 struct iodesc sockets[SOPEN_MAX];
52 #ifdef NETIF_DEBUG
53 int netif_debug = 0;
54 #endif
55 
56 /*
57  * netif_init:
58  *
59  * initialize the generic network interface layer
60  */
61 
62 void
63 netif_init()
64 {
65 	struct netif_driver *drv;
66 	int d, i;
67 
68 #ifdef NETIF_DEBUG
69 	if (netif_debug)
70 		printf("netif_init: called\n");
71 #endif
72 	for (d = 0; d < n_netif_drivers; d++) {
73 		drv = netif_drivers[d];
74 		for (i = 0; i < drv->netif_nifs; i++)
75 			drv->netif_ifs[i].dif_used = 0;
76 	}
77 }
78 
79 int	netif_match __P((struct netif *, void *));
80 
81 int
82 netif_match(nif, machdep_hint)
83 	struct netif *nif;
84 	void *machdep_hint;
85 {
86 	struct netif_driver *drv = nif->nif_driver;
87 
88 #if 0
89 	if (netif_debug)
90 		printf("%s%d: netif_match (%d)\n", drv->netif_bname,
91 		    nif->nif_unit, nif->nif_sel);
92 #endif
93 	return drv->netif_match(nif, machdep_hint);
94 }
95 
96 struct netif *
97 netif_select(machdep_hint)
98 	void *machdep_hint;
99 {
100 	int d, u, unit_done, s;
101 	struct netif_driver *drv;
102 	struct netif cur_if;
103 	static struct netif best_if;
104 	int best_val;
105 	int val;
106 
107 	best_val = 0;
108 	best_if.nif_driver = NULL;
109 
110 #ifdef NETIF_DEBUG
111 	if (netif_debug)
112 		printf("netif_select: %d interfaces\n", n_netif_drivers);
113 #endif
114 
115 	for (d = 0; d < n_netif_drivers; d++) {
116 		cur_if.nif_driver = netif_drivers[d];
117 		drv = cur_if.nif_driver;
118 
119 		for (u = 0; u < drv->netif_nifs; u++) {
120 			cur_if.nif_unit = u;
121 			unit_done = 0;
122 
123 #ifdef NETIF_DEBUG
124 			if (netif_debug)
125 				printf("\t%s%d:", drv->netif_bname,
126 				    cur_if.nif_unit);
127 #endif
128 
129 			for (s = 0; s < drv->netif_ifs[u].dif_nsel; s++) {
130 				cur_if.nif_sel = s;
131 
132 				if (drv->netif_ifs[u].dif_used & (1 << s)) {
133 #ifdef NETIF_DEBUG
134 					if (netif_debug)
135 						printf(" [%d used]", s);
136 #endif
137 					continue;
138 				}
139 
140 				val = netif_match(&cur_if, machdep_hint);
141 #ifdef NETIF_DEBUG
142 				if (netif_debug)
143 					printf(" [%d -> %d]", s, val);
144 #endif
145 				if (val > best_val) {
146 					best_val = val;
147 					best_if = cur_if;
148 				}
149 			}
150 #ifdef NETIF_DEBUG
151 			if (netif_debug)
152 				printf("\n");
153 #endif
154 		}
155 	}
156 
157 	if (best_if.nif_driver == NULL)
158 		return NULL;
159 
160 	best_if.nif_driver->
161 	    netif_ifs[best_if.nif_unit].dif_used |= (1 << best_if.nif_sel);
162 
163 #ifdef NETIF_DEBUG
164 	if (netif_debug)
165 		printf("netif_select: %s%d(%d) wins\n",
166 			best_if.nif_driver->netif_bname,
167 			best_if.nif_unit, best_if.nif_sel);
168 #endif
169 	return &best_if;
170 }
171 
172 int
173 netif_probe(nif, machdep_hint)
174 	struct netif *nif;
175 	void *machdep_hint;
176 {
177 	struct netif_driver *drv = nif->nif_driver;
178 
179 #ifdef NETIF_DEBUG
180 	if (netif_debug)
181 		printf("%s%d: netif_probe\n", drv->netif_bname, nif->nif_unit);
182 #endif
183 	return drv->netif_probe(nif, machdep_hint);
184 }
185 
186 void
187 netif_attach(nif, desc, machdep_hint)
188 	struct netif *nif;
189 	struct iodesc *desc;
190 	void *machdep_hint;
191 {
192 	struct netif_driver *drv = nif->nif_driver;
193 
194 #ifdef NETIF_DEBUG
195 	if (netif_debug)
196 		printf("%s%d: netif_attach\n", drv->netif_bname, nif->nif_unit);
197 #endif
198 	desc->io_netif = nif;
199 #ifdef PARANOID
200 	if (drv->netif_init == NULL)
201 		panic("%s%d: no netif_init support\n", drv->netif_bname,
202 		    nif->nif_unit);
203 #endif
204 	drv->netif_init(desc, machdep_hint);
205 	bzero(drv->netif_ifs[nif->nif_unit].dif_stats,
206 	    sizeof(struct netif_stats));
207 }
208 
209 void
210 netif_detach(nif)
211 	struct netif *nif;
212 {
213 	struct netif_driver *drv = nif->nif_driver;
214 
215 #ifdef NETIF_DEBUG
216 	if (netif_debug)
217 		printf("%s%d: netif_detach\n", drv->netif_bname, nif->nif_unit);
218 #endif
219 #ifdef PARANOID
220 	if (drv->netif_end == NULL)
221 		panic("%s%d: no netif_end support\n", drv->netif_bname,
222 		    nif->nif_unit);
223 #endif
224 	drv->netif_end(nif);
225 }
226 
227 ssize_t
228 netif_get(desc, pkt, len, timo)
229 	struct iodesc *desc;
230 	void *pkt;
231 	size_t len;
232 	time_t timo;
233 {
234 #ifdef NETIF_DEBUG
235 	struct netif *nif = desc->io_netif;
236 #endif
237 	struct netif_driver *drv = desc->io_netif->nif_driver;
238 	ssize_t rv;
239 
240 #ifdef NETIF_DEBUG
241 	if (netif_debug)
242 		printf("%s%d: netif_get\n", drv->netif_bname, nif->nif_unit);
243 #endif
244 #ifdef PARANOID
245 	if (drv->netif_get == NULL)
246 		panic("%s%d: no netif_get support\n", drv->netif_bname,
247 		    nif->nif_unit);
248 #endif
249 	rv = drv->netif_get(desc, pkt, len, timo);
250 #ifdef NETIF_DEBUG
251 	if (netif_debug)
252 		printf("%s%d: netif_get returning %d\n", drv->netif_bname,
253 		    nif->nif_unit, (int)rv);
254 #endif
255 	return rv;
256 }
257 
258 ssize_t
259 netif_put(desc, pkt, len)
260 	struct iodesc *desc;
261 	void *pkt;
262 	size_t len;
263 {
264 #ifdef NETIF_DEBUG
265 	struct netif *nif = desc->io_netif;
266 #endif
267 	struct netif_driver *drv = desc->io_netif->nif_driver;
268 	ssize_t rv;
269 
270 #ifdef NETIF_DEBUG
271 	if (netif_debug)
272 		printf("%s%d: netif_put\n", drv->netif_bname, nif->nif_unit);
273 #endif
274 #ifdef PARANOID
275 	if (drv->netif_put == NULL)
276 		panic("%s%d: no netif_put support\n", drv->netif_bname,
277 		    nif->nif_unit);
278 #endif
279 	rv = drv->netif_put(desc, pkt, len);
280 #ifdef NETIF_DEBUG
281 	if (netif_debug)
282 		printf("%s%d: netif_put returning %d\n", drv->netif_bname,
283 		    nif->nif_unit, (int)rv);
284 #endif
285 	return rv;
286 }
287 
288 struct iodesc *
289 socktodesc(sock)
290 	int sock;
291 {
292 #if !defined(LIBSA_NO_FD_CHECKING)
293 	if (sock >= SOPEN_MAX) {
294 		errno = EBADF;
295 		return (NULL);
296 	}
297 #endif
298 	return (&sockets[sock]);
299 }
300 
301 int
302 netif_open(machdep_hint)
303 	void *machdep_hint;
304 {
305 	int fd;
306 	struct iodesc *s;
307 	struct netif *nif;
308 
309 	/* find a free socket */
310 	for (fd = 0, s = sockets; fd < SOPEN_MAX; fd++, s++)
311 		if (s->io_netif == (struct netif *)0)
312 			goto fnd;
313 	errno = EMFILE;
314 	return (-1);
315 
316 fnd:
317 	bzero(s, sizeof(*s));
318 	netif_init();
319 	nif = netif_select(machdep_hint);
320 	if (!nif)
321 		panic("netboot: no interfaces left untried");
322 	if (netif_probe(nif, machdep_hint)) {
323 		printf("netboot: couldn't probe %s%d\n",
324 		    nif->nif_driver->netif_bname, nif->nif_unit);
325 		errno = EINVAL;
326 		return(-1);
327 	}
328 	netif_attach(nif, s, machdep_hint);
329 
330 	return(fd);
331 }
332 
333 int
334 netif_close(sock)
335 	int sock;
336 {
337 #if !defined(LIBSA_NO_FD_CHECKING)
338 	if (sock >= SOPEN_MAX) {
339 		errno = EBADF;
340 		return(-1);
341 	}
342 #endif
343 	netif_detach(sockets[sock].io_netif);
344 	sockets[sock].io_netif = (struct netif *)0;
345 
346 	return(0);
347 }
348