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