1 /* $NetBSD: netif.c,v 1.10 1997/09/06 13:57:14 drochner 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 <string.h> 38 39 #include <netinet/in.h> 40 #include <netinet/in_systm.h> 41 42 #include "stand.h" 43 #include "net.h" 44 #include "netif.h" 45 46 typedef TAILQ_HEAD(socket_list, iodesc) socket_list_t; 47 48 /* 49 * Open socket list. The current implementation and assumption is, 50 * we only remove entries from tail and we only add new entries to tail. 51 * This decision is to keep iodesc id management simple - we get list 52 * entries ordered by continiously growing io_id field. 53 * If we do have multiple sockets open and we do close socket not from tail, 54 * this entry will be marked unused. netif_open() will reuse unused entry, or 55 * netif_close() will free all unused tail entries. 56 */ 57 static socket_list_t sockets = TAILQ_HEAD_INITIALIZER(sockets); 58 59 #ifdef NETIF_DEBUG 60 int netif_debug = 0; 61 #endif 62 63 /* 64 * netif_init: 65 * 66 * initialize the generic network interface layer 67 */ 68 69 void 70 netif_init(void) 71 { 72 struct netif_driver *drv; 73 int d, i; 74 75 #ifdef NETIF_DEBUG 76 if (netif_debug) 77 printf("netif_init: called\n"); 78 #endif 79 for (d = 0; netif_drivers[d]; d++) { 80 drv = netif_drivers[d]; 81 for (i = 0; i < drv->netif_nifs; i++) 82 drv->netif_ifs[i].dif_used = 0; 83 } 84 } 85 86 int 87 netif_match(struct netif *nif, void *machdep_hint) 88 { 89 struct netif_driver *drv = nif->nif_driver; 90 91 #ifdef NETIF_DEBUG 92 if (netif_debug) 93 printf("%s%d: netif_match (%d)\n", drv->netif_bname, 94 nif->nif_unit, nif->nif_sel); 95 #endif 96 return drv->netif_match(nif, machdep_hint); 97 } 98 99 struct netif * 100 netif_select(void *machdep_hint) 101 { 102 int d, u, s; 103 struct netif_driver *drv; 104 struct netif cur_if; 105 static struct netif best_if; 106 int best_val; 107 int val; 108 109 best_val = 0; 110 best_if.nif_driver = NULL; 111 112 for (d = 0; netif_drivers[d] != NULL; d++) { 113 cur_if.nif_driver = netif_drivers[d]; 114 drv = cur_if.nif_driver; 115 116 for (u = 0; u < drv->netif_nifs; u++) { 117 cur_if.nif_unit = u; 118 119 #ifdef NETIF_DEBUG 120 if (netif_debug) 121 printf("\t%s%d:", drv->netif_bname, 122 cur_if.nif_unit); 123 #endif 124 125 for (s = 0; s < drv->netif_ifs[u].dif_nsel; s++) { 126 cur_if.nif_sel = s; 127 128 if (drv->netif_ifs[u].dif_used & (1 << s)) { 129 #ifdef NETIF_DEBUG 130 if (netif_debug) 131 printf(" [%d used]", s); 132 #endif 133 continue; 134 } 135 136 val = netif_match(&cur_if, machdep_hint); 137 #ifdef NETIF_DEBUG 138 if (netif_debug) 139 printf(" [%d -> %d]", s, val); 140 #endif 141 if (val > best_val) { 142 best_val = val; 143 best_if = cur_if; 144 } 145 } 146 #ifdef NETIF_DEBUG 147 if (netif_debug) 148 printf("\n"); 149 #endif 150 } 151 } 152 153 if (best_if.nif_driver == NULL) 154 return NULL; 155 156 best_if.nif_driver-> 157 netif_ifs[best_if.nif_unit].dif_used |= (1 << best_if.nif_sel); 158 159 #ifdef NETIF_DEBUG 160 if (netif_debug) 161 printf("netif_select: %s%d(%d) wins\n", 162 best_if.nif_driver->netif_bname, 163 best_if.nif_unit, best_if.nif_sel); 164 #endif 165 return &best_if; 166 } 167 168 int 169 netif_probe(struct netif *nif, void *machdep_hint) 170 { 171 struct netif_driver *drv = nif->nif_driver; 172 173 #ifdef NETIF_DEBUG 174 if (netif_debug) 175 printf("%s%d: netif_probe\n", drv->netif_bname, nif->nif_unit); 176 #endif 177 return drv->netif_probe(nif, machdep_hint); 178 } 179 180 void 181 netif_attach(struct netif *nif, struct iodesc *desc, void *machdep_hint) 182 { 183 struct netif_driver *drv = nif->nif_driver; 184 185 #ifdef NETIF_DEBUG 186 if (netif_debug) 187 printf("%s%d: netif_attach\n", drv->netif_bname, nif->nif_unit); 188 #endif 189 desc->io_netif = nif; 190 #ifdef PARANOID 191 if (drv->netif_init == NULL) 192 panic("%s%d: no netif_init support", drv->netif_bname, 193 nif->nif_unit); 194 #endif 195 drv->netif_init(desc, machdep_hint); 196 bzero(drv->netif_ifs[nif->nif_unit].dif_stats, 197 sizeof(struct netif_stats)); 198 } 199 200 void 201 netif_detach(struct netif *nif) 202 { 203 struct netif_driver *drv = nif->nif_driver; 204 205 #ifdef NETIF_DEBUG 206 if (netif_debug) 207 printf("%s%d: netif_detach\n", drv->netif_bname, nif->nif_unit); 208 #endif 209 #ifdef PARANOID 210 if (drv->netif_end == NULL) 211 panic("%s%d: no netif_end support", drv->netif_bname, 212 nif->nif_unit); 213 #endif 214 drv->netif_end(nif); 215 } 216 217 ssize_t 218 netif_get(struct iodesc *desc, void **pkt, time_t timo) 219 { 220 #ifdef NETIF_DEBUG 221 struct netif *nif = desc->io_netif; 222 #endif 223 struct netif_driver *drv = desc->io_netif->nif_driver; 224 ssize_t rv; 225 226 #ifdef NETIF_DEBUG 227 if (netif_debug) 228 printf("%s%d: netif_get\n", drv->netif_bname, nif->nif_unit); 229 #endif 230 #ifdef PARANOID 231 if (drv->netif_get == NULL) 232 panic("%s%d: no netif_get support", drv->netif_bname, 233 nif->nif_unit); 234 #endif 235 rv = drv->netif_get(desc, pkt, timo); 236 #ifdef NETIF_DEBUG 237 if (netif_debug) 238 printf("%s%d: netif_get returning %d\n", drv->netif_bname, 239 nif->nif_unit, (int)rv); 240 #endif 241 return (rv); 242 } 243 244 ssize_t 245 netif_put(struct iodesc *desc, void *pkt, size_t len) 246 { 247 #ifdef NETIF_DEBUG 248 struct netif *nif = desc->io_netif; 249 #endif 250 struct netif_driver *drv = desc->io_netif->nif_driver; 251 ssize_t rv; 252 253 #ifdef NETIF_DEBUG 254 if (netif_debug) 255 printf("%s%d: netif_put\n", drv->netif_bname, nif->nif_unit); 256 #endif 257 #ifdef PARANOID 258 if (drv->netif_put == NULL) 259 panic("%s%d: no netif_put support", drv->netif_bname, 260 nif->nif_unit); 261 #endif 262 rv = drv->netif_put(desc, pkt, len); 263 #ifdef NETIF_DEBUG 264 if (netif_debug) 265 printf("%s%d: netif_put returning %d\n", drv->netif_bname, 266 nif->nif_unit, (int)rv); 267 #endif 268 return (rv); 269 } 270 271 /* 272 * socktodesc_impl: 273 * 274 * Walk socket list and return pointer to iodesc structure. 275 * if id is < 0, return first unused iodesc. 276 */ 277 static struct iodesc * 278 socktodesc_impl(int socket) 279 { 280 struct iodesc *s; 281 282 TAILQ_FOREACH(s, &sockets, io_link) { 283 /* search by socket id */ 284 if (socket >= 0) { 285 if (s->io_id == socket) 286 break; 287 continue; 288 } 289 /* search for first unused entry */ 290 if (s->io_netif == NULL) 291 break; 292 } 293 return (s); 294 } 295 296 struct iodesc * 297 socktodesc(int sock) 298 { 299 struct iodesc *desc; 300 301 if (sock < 0) 302 desc = NULL; 303 else 304 desc = socktodesc_impl(sock); 305 306 if (desc == NULL) 307 errno = EBADF; 308 309 return (desc); 310 } 311 312 int 313 netif_open(void *machdep_hint) 314 { 315 struct iodesc *s; 316 struct netif *nif; 317 318 /* find a free socket */ 319 s = socktodesc_impl(-1); 320 if (s == NULL) { 321 struct iodesc *last; 322 323 s = calloc(1, sizeof (*s)); 324 if (s == NULL) 325 return (-1); 326 327 last = TAILQ_LAST(&sockets, socket_list); 328 if (last != NULL) 329 s->io_id = last->io_id + 1; 330 TAILQ_INSERT_TAIL(&sockets, s, io_link); 331 } 332 333 netif_init(); 334 nif = netif_select(machdep_hint); 335 if (!nif) 336 panic("netboot: no interfaces left untried"); 337 if (netif_probe(nif, machdep_hint)) { 338 printf("netboot: couldn't probe %s%d\n", 339 nif->nif_driver->netif_bname, nif->nif_unit); 340 errno = EINVAL; 341 return (-1); 342 } 343 netif_attach(nif, s, machdep_hint); 344 345 return (s->io_id); 346 } 347 348 int 349 netif_close(int sock) 350 { 351 struct iodesc *s, *last; 352 int err; 353 354 err = 0; 355 s = socktodesc_impl(sock); 356 if (s == NULL || sock < 0) { 357 err = EBADF; 358 return (-1); 359 } 360 netif_detach(s->io_netif); 361 bzero(&s->destip, sizeof (s->destip)); 362 bzero(&s->myip, sizeof (s->myip)); 363 s->destport = 0; 364 s->myport = 0; 365 s->xid = 0; 366 bzero(s->myea, sizeof (s->myea)); 367 s->io_netif = NULL; 368 369 /* free unused entries from tail. */ 370 TAILQ_FOREACH_REVERSE_SAFE(last, &sockets, socket_list, io_link, s) { 371 if (last->io_netif != NULL) 372 break; 373 TAILQ_REMOVE(&sockets, last, io_link); 374 free(last); 375 } 376 377 if (err) { 378 errno = err; 379 return (-1); 380 } 381 382 return (0); 383 } 384