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