1/* $NetBSD: dev_net.c,v 1.23 2008/04/28 20:24:06 martin Exp $ */ 2 3/*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Gordon W. Ross. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h>
| 1/* $NetBSD: dev_net.c,v 1.23 2008/04/28 20:24:06 martin Exp $ */ 2 3/*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Gordon W. Ross. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h>
|
84 85static int net_getparams(int sock); 86 87struct devsw netdev = { 88 "net", 89 DEVT_NET, 90 net_init, 91 net_strategy, 92 net_open, 93 net_close, 94 noioctl, 95 net_print, 96 net_cleanup 97}; 98 99static int 100net_init(void) 101{ 102 103 return (0); 104} 105 106/* 107 * Called by devopen after it sets f->f_dev to our devsw entry. 108 * This opens the low-level device and sets f->f_devdata. 109 * This is declared with variable arguments... 110 */ 111static int 112net_open(struct open_file *f, ...) 113{ 114 struct iodesc *d; 115 va_list args; 116 char *devname; /* Device part of file name (or NULL). */ 117 int error = 0; 118 119 va_start(args, f); 120 devname = va_arg(args, char*); 121 va_end(args); 122 123 /* Before opening another interface, close the previous one first. */ 124 if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0) 125 net_cleanup(); 126 127 /* On first open, do netif open, mount, etc. */ 128 if (netdev_opens == 0) { 129 /* Find network interface. */ 130 if (netdev_sock < 0) { 131 netdev_sock = netif_open(devname); 132 if (netdev_sock < 0) { 133 printf("net_open: netif_open() failed\n"); 134 return (ENXIO); 135 } 136 netdev_name = strdup(devname); 137#ifdef NETIF_DEBUG 138 if (debug) 139 printf("net_open: netif_open() succeeded\n"); 140#endif 141 } 142 /* 143 * If network params were not set by netif_open(), try to get 144 * them via bootp, rarp, etc. 145 */ 146 if (rootip.s_addr == 0) { 147 /* Get root IP address, and path, etc. */ 148 error = net_getparams(netdev_sock); 149 if (error) { 150 /* getparams makes its own noise */ 151 free(netdev_name); 152 netif_close(netdev_sock); 153 netdev_sock = -1; 154 return (error); 155 } 156 } 157 /* 158 * Set the variables required by the kernel's nfs_diskless 159 * mechanism. This is the minimum set of variables required to 160 * mount a root filesystem without needing to obtain additional 161 * info from bootp or other sources. 162 */ 163 d = socktodesc(netdev_sock); 164 setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 1); 165 setenv("boot.netif.ip", inet_ntoa(myip), 1); 166 setenv("boot.netif.netmask", intoa(netmask), 1); 167 setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 168 setenv("boot.netif.server", inet_ntoa(rootip), 1); 169 if (netproto == NET_TFTP) { 170 setenv("boot.tftproot.server", inet_ntoa(rootip), 1); 171 setenv("boot.tftproot.path", rootpath, 1); 172 } else if (netproto == NET_NFS) { 173 setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 174 setenv("boot.nfsroot.path", rootpath, 1); 175 } 176 if (intf_mtu != 0) { 177 char mtu[16]; 178 sprintf(mtu, "%u", intf_mtu); 179 setenv("boot.netif.mtu", mtu, 1); 180 } 181 182 } 183 netdev_opens++; 184 f->f_devdata = &netdev_sock; 185 return (error); 186} 187 188static int 189net_close(struct open_file *f) 190{ 191 192#ifdef NETIF_DEBUG 193 if (debug) 194 printf("net_close: opens=%d\n", netdev_opens); 195#endif 196 197 f->f_devdata = NULL; 198 199 return (0); 200} 201 202static void 203net_cleanup(void) 204{ 205 206 if (netdev_sock >= 0) { 207#ifdef NETIF_DEBUG 208 if (debug) 209 printf("net_cleanup: calling netif_close()\n"); 210#endif 211 rootip.s_addr = 0; 212 free(netdev_name); 213 netif_close(netdev_sock); 214 netdev_sock = -1; 215 } 216} 217 218static int 219net_strategy() 220{ 221 222 return (EIO); 223} 224 225#define SUPPORT_BOOTP 226 227/* 228 * Get info for NFS boot: our IP address, our hostname, 229 * server IP address, and our root path on the server. 230 * There are two ways to do this: The old, Sun way, 231 * and the more modern, BOOTP way. (RFC951, RFC1048) 232 * 233 * The default is to use the Sun bootparams RPC 234 * (because that is what the kernel will do). 235 * MD code can make try_bootp initialied data, 236 * which will override this common definition. 237 */ 238#ifdef SUPPORT_BOOTP 239int try_bootp = 1; 240#endif 241 242extern n_long ip_convertaddr(char *p); 243 244static int 245net_getparams(int sock) 246{ 247 char buf[MAXHOSTNAMELEN]; 248 n_long rootaddr, smask; 249 250#ifdef SUPPORT_BOOTP 251 /* 252 * Try to get boot info using BOOTP. If we succeed, then 253 * the server IP address, gateway, and root path will all 254 * be initialized. If any remain uninitialized, we will 255 * use RARP and RPC/bootparam (the Sun way) to get them. 256 */ 257 if (try_bootp) 258 bootp(sock, BOOTP_NONE); 259 if (myip.s_addr != 0) 260 goto exit; 261#ifdef NETIF_DEBUG 262 if (debug) 263 printf("net_open: BOOTP failed, trying RARP/RPC...\n"); 264#endif 265#endif 266 267 /* 268 * Use RARP to get our IP address. This also sets our 269 * netmask to the "natural" default for our address. 270 */ 271 if (rarp_getipaddress(sock)) { 272 printf("net_open: RARP failed\n"); 273 return (EIO); 274 } 275 printf("net_open: client addr: %s\n", inet_ntoa(myip)); 276 277 /* Get our hostname, server IP address, gateway. */ 278 if (bp_whoami(sock)) { 279 printf("net_open: bootparam/whoami RPC failed\n"); 280 return (EIO); 281 } 282#ifdef NETIF_DEBUG 283 if (debug) 284 printf("net_open: client name: %s\n", hostname); 285#endif 286 287 /* 288 * Ignore the gateway from whoami (unreliable). 289 * Use the "gateway" parameter instead. 290 */ 291 smask = 0; 292 gateip.s_addr = 0; 293 if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { 294 /* Got it! Parse the netmask. */ 295 smask = ip_convertaddr(buf); 296 } 297 if (smask) { 298 netmask = smask; 299#ifdef NETIF_DEBUG 300 if (debug) 301 printf("net_open: subnet mask: %s\n", intoa(netmask)); 302#endif 303 } 304#ifdef NETIF_DEBUG 305 if (gateip.s_addr && debug) 306 printf("net_open: net gateway: %s\n", inet_ntoa(gateip)); 307#endif 308 309 /* Get the root server and pathname. */ 310 if (bp_getfile(sock, "root", &rootip, rootpath)) { 311 printf("net_open: bootparam/getfile RPC failed\n"); 312 return (EIO); 313 } 314exit: 315 if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) 316 rootip.s_addr = rootaddr; 317 318#ifdef NETIF_DEBUG 319 if (debug) { 320 printf("net_open: server addr: %s\n", inet_ntoa(rootip)); 321 printf("net_open: server path: %s\n", rootpath); 322 } 323#endif 324 325 return (0); 326} 327
| 84 85static int net_getparams(int sock); 86 87struct devsw netdev = { 88 "net", 89 DEVT_NET, 90 net_init, 91 net_strategy, 92 net_open, 93 net_close, 94 noioctl, 95 net_print, 96 net_cleanup 97}; 98 99static int 100net_init(void) 101{ 102 103 return (0); 104} 105 106/* 107 * Called by devopen after it sets f->f_dev to our devsw entry. 108 * This opens the low-level device and sets f->f_devdata. 109 * This is declared with variable arguments... 110 */ 111static int 112net_open(struct open_file *f, ...) 113{ 114 struct iodesc *d; 115 va_list args; 116 char *devname; /* Device part of file name (or NULL). */ 117 int error = 0; 118 119 va_start(args, f); 120 devname = va_arg(args, char*); 121 va_end(args); 122 123 /* Before opening another interface, close the previous one first. */ 124 if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0) 125 net_cleanup(); 126 127 /* On first open, do netif open, mount, etc. */ 128 if (netdev_opens == 0) { 129 /* Find network interface. */ 130 if (netdev_sock < 0) { 131 netdev_sock = netif_open(devname); 132 if (netdev_sock < 0) { 133 printf("net_open: netif_open() failed\n"); 134 return (ENXIO); 135 } 136 netdev_name = strdup(devname); 137#ifdef NETIF_DEBUG 138 if (debug) 139 printf("net_open: netif_open() succeeded\n"); 140#endif 141 } 142 /* 143 * If network params were not set by netif_open(), try to get 144 * them via bootp, rarp, etc. 145 */ 146 if (rootip.s_addr == 0) { 147 /* Get root IP address, and path, etc. */ 148 error = net_getparams(netdev_sock); 149 if (error) { 150 /* getparams makes its own noise */ 151 free(netdev_name); 152 netif_close(netdev_sock); 153 netdev_sock = -1; 154 return (error); 155 } 156 } 157 /* 158 * Set the variables required by the kernel's nfs_diskless 159 * mechanism. This is the minimum set of variables required to 160 * mount a root filesystem without needing to obtain additional 161 * info from bootp or other sources. 162 */ 163 d = socktodesc(netdev_sock); 164 setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 1); 165 setenv("boot.netif.ip", inet_ntoa(myip), 1); 166 setenv("boot.netif.netmask", intoa(netmask), 1); 167 setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 168 setenv("boot.netif.server", inet_ntoa(rootip), 1); 169 if (netproto == NET_TFTP) { 170 setenv("boot.tftproot.server", inet_ntoa(rootip), 1); 171 setenv("boot.tftproot.path", rootpath, 1); 172 } else if (netproto == NET_NFS) { 173 setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 174 setenv("boot.nfsroot.path", rootpath, 1); 175 } 176 if (intf_mtu != 0) { 177 char mtu[16]; 178 sprintf(mtu, "%u", intf_mtu); 179 setenv("boot.netif.mtu", mtu, 1); 180 } 181 182 } 183 netdev_opens++; 184 f->f_devdata = &netdev_sock; 185 return (error); 186} 187 188static int 189net_close(struct open_file *f) 190{ 191 192#ifdef NETIF_DEBUG 193 if (debug) 194 printf("net_close: opens=%d\n", netdev_opens); 195#endif 196 197 f->f_devdata = NULL; 198 199 return (0); 200} 201 202static void 203net_cleanup(void) 204{ 205 206 if (netdev_sock >= 0) { 207#ifdef NETIF_DEBUG 208 if (debug) 209 printf("net_cleanup: calling netif_close()\n"); 210#endif 211 rootip.s_addr = 0; 212 free(netdev_name); 213 netif_close(netdev_sock); 214 netdev_sock = -1; 215 } 216} 217 218static int 219net_strategy() 220{ 221 222 return (EIO); 223} 224 225#define SUPPORT_BOOTP 226 227/* 228 * Get info for NFS boot: our IP address, our hostname, 229 * server IP address, and our root path on the server. 230 * There are two ways to do this: The old, Sun way, 231 * and the more modern, BOOTP way. (RFC951, RFC1048) 232 * 233 * The default is to use the Sun bootparams RPC 234 * (because that is what the kernel will do). 235 * MD code can make try_bootp initialied data, 236 * which will override this common definition. 237 */ 238#ifdef SUPPORT_BOOTP 239int try_bootp = 1; 240#endif 241 242extern n_long ip_convertaddr(char *p); 243 244static int 245net_getparams(int sock) 246{ 247 char buf[MAXHOSTNAMELEN]; 248 n_long rootaddr, smask; 249 250#ifdef SUPPORT_BOOTP 251 /* 252 * Try to get boot info using BOOTP. If we succeed, then 253 * the server IP address, gateway, and root path will all 254 * be initialized. If any remain uninitialized, we will 255 * use RARP and RPC/bootparam (the Sun way) to get them. 256 */ 257 if (try_bootp) 258 bootp(sock, BOOTP_NONE); 259 if (myip.s_addr != 0) 260 goto exit; 261#ifdef NETIF_DEBUG 262 if (debug) 263 printf("net_open: BOOTP failed, trying RARP/RPC...\n"); 264#endif 265#endif 266 267 /* 268 * Use RARP to get our IP address. This also sets our 269 * netmask to the "natural" default for our address. 270 */ 271 if (rarp_getipaddress(sock)) { 272 printf("net_open: RARP failed\n"); 273 return (EIO); 274 } 275 printf("net_open: client addr: %s\n", inet_ntoa(myip)); 276 277 /* Get our hostname, server IP address, gateway. */ 278 if (bp_whoami(sock)) { 279 printf("net_open: bootparam/whoami RPC failed\n"); 280 return (EIO); 281 } 282#ifdef NETIF_DEBUG 283 if (debug) 284 printf("net_open: client name: %s\n", hostname); 285#endif 286 287 /* 288 * Ignore the gateway from whoami (unreliable). 289 * Use the "gateway" parameter instead. 290 */ 291 smask = 0; 292 gateip.s_addr = 0; 293 if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { 294 /* Got it! Parse the netmask. */ 295 smask = ip_convertaddr(buf); 296 } 297 if (smask) { 298 netmask = smask; 299#ifdef NETIF_DEBUG 300 if (debug) 301 printf("net_open: subnet mask: %s\n", intoa(netmask)); 302#endif 303 } 304#ifdef NETIF_DEBUG 305 if (gateip.s_addr && debug) 306 printf("net_open: net gateway: %s\n", inet_ntoa(gateip)); 307#endif 308 309 /* Get the root server and pathname. */ 310 if (bp_getfile(sock, "root", &rootip, rootpath)) { 311 printf("net_open: bootparam/getfile RPC failed\n"); 312 return (EIO); 313 } 314exit: 315 if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) 316 rootip.s_addr = rootaddr; 317 318#ifdef NETIF_DEBUG 319 if (debug) { 320 printf("net_open: server addr: %s\n", inet_ntoa(rootip)); 321 printf("net_open: server path: %s\n", rootpath); 322 } 323#endif 324 325 return (0); 326} 327
|