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