Index: head/sys/amd64/amd64/autoconf.c =================================================================== --- head/sys/amd64/amd64/autoconf.c (revision 25722) +++ head/sys/amd64/amd64/autoconf.c (revision 25723) @@ -1,445 +1,452 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.66 1997/04/26 18:57:34 peter Exp $ + * $Id: autoconf.c,v 1.67 1997/05/04 15:24:19 joerg Exp $ */ /* * Setup the system to run on the current machine. * * Configure() is called at boot time and initializes the vba * device tables and the memory controller monitoring. Available * devices are determined (from possibilities mentioned in ioconf.c), * and the drivers are initialized. */ #include "opt_smp.h" #include "opt_cd9660.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(APIC_IO) #include #endif /* APIC_IO */ #include /* For interrupts */ #include "isa.h" #if NISA > 0 #include #endif #include "eisa.h" #if NEISA > 0 #include #endif #include "pci.h" #if NPCI > 0 #include #endif #include "crd.h" #if NCRD > 0 #include #endif #include "scbus.h" #if NSCBUS > 0 #include #endif static void configure __P((void *)); SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) static void configure_finish __P((void)); static void configure_start __P((void)); static int setdumpdev __P((dev_t dev)); static void setroot __P((void)); #ifdef CD9660 #include #include #include #include #include /* * XXX All this CD-ROM root stuff is fairly messy. Ick. * * We need to try out all our potential CDROM drives, so we need a table. */ static struct { char *name; int major; } try_cdrom[] = { { "cd", 6 }, { "mcd", 7 }, { "scd", 16 }, { "matcd", 17 }, { "wcd", 19 }, { 0, 0} }; static int find_cdrom_root __P((void)); static int find_cdrom_root() { int i, j, error; struct bdevsw *bd; dev_t orootdev; #if CD9660_ROOTDELAY > 0 DELAY(CD9660_ROOTDELAY * 1000000); #endif orootdev = rootdev; for (i = 0 ; i < 2; i++) for (j = 0 ; try_cdrom[j].name ; j++) { if (try_cdrom[j].major >= nblkdev) continue; rootdev = makedev(try_cdrom[j].major, i * 8); bd = bdevsw[major(rootdev)]; if (bd == NULL || bd->d_open == NULL) continue; if (bootverbose) printf("trying %s%d as rootdev (0x%x)\n", try_cdrom[j].name, i, rootdev); error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); if (error == 0) { if (bd->d_close != NULL) (bd->d_close)(rootdev, FREAD, S_IFBLK, curproc); return 0; } } rootdev = orootdev; return EINVAL; } #endif /* CD9660 */ static void configure_start() { #if NSCBUS > 0 scsi_configure_start(); #endif } static void configure_finish() { #if NSCBUS > 0 scsi_configure_finish(); #endif } /* * Determine i/o configuration for a machine. */ static void configure(dummy) void *dummy; { int i; configure_start(); /* Allow all routines to decide for themselves if they want intrs */ #if defined(APIC_IO) configure_local_apic(); #endif /* APIC_IO */ enable_intr(); #if !defined(APIC_IO) INTREN(IRQ_SLAVE); #endif /* !APIC_IO */ #if NEISA > 0 eisa_configure(); #endif #if NPCI > 0 pci_configure(); #endif #if NISA > 0 isa_configure(); #endif #if NCRD > 0 /* After everyone else has a chance at grabbing resources */ pccard_configure(); #endif if (setdumpdev(dumpdev) != 0) dumpdev = NODEV; configure_finish(); cninit_finish(); if (bootverbose) { /* * Print out the BIOS's idea of the disk geometries. */ printf("BIOS Geometries:\n"); for (i = 0; i < N_BIOS_GEOM; i++) { unsigned long bios_geom; int max_cylinder, max_head, max_sector; bios_geom = bootinfo.bi_bios_geom[i]; /* * XXX the bootstrap punts a 1200K floppy geometry * when the get-disk-geometry interrupt fails. Skip * drives that have this geometry. */ if (bios_geom == 0x4f010f) continue; printf(" %x:%08lx ", i, bios_geom); max_cylinder = bios_geom >> 16; max_head = (bios_geom >> 8) & 0xff; max_sector = bios_geom & 0xff; printf( "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", max_cylinder, max_cylinder + 1, max_head, max_head + 1, max_sector, max_sector); } printf(" %d accounted for\n", bootinfo.bi_n_bios_used); printf("Device configuration finished.\n"); } #ifdef CD9660 if ((boothowto & RB_CDROM)) { if (bootverbose) printf("Considering CD-ROM root f/s.\n"); /* NB: find_cdrom_root() sets rootdev if successful. */ if (find_cdrom_root() == 0) mountrootfsname = "cd9660"; else if (bootverbose) printf("No CD-ROM available as root f/s.\n"); } #endif #ifdef MFS_ROOT if (!mountrootfsname) { if (bootverbose) printf("Considering MFS root f/s.\n"); mountrootfsname = "mfs"; /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif +#ifdef BOOTP_NFSROOT + if (!mountrootfsname && !nfs_diskless_valid) { + if (bootverbose) + printf("Considering BOOTP NFS root f/s.\n"); + mountrootfsname = "nfs"; + } +#endif /* BOOTP_NFSROOT */ #ifdef NFS if (!mountrootfsname && nfs_diskless_valid) { if (bootverbose) printf("Considering NFS root f/s.\n"); mountrootfsname = "nfs"; } #endif /* NFS */ #ifdef FFS if (!mountrootfsname) { mountrootfsname = "ufs"; if (bootverbose) printf("Considering FFS root f/s.\n"); /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif #ifdef LFS if (!mountrootfsname) { if (bootverbose) printf("Considering LFS root f/s.\n"); mountrootfsname = "lfs"; /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif if (!mountrootfsname) { panic("Nobody wants to mount my root for me"); } setconf(); cold = 0; if (bootverbose) printf("configure() finished.\n"); } static int setdumpdev(dev) dev_t dev; { int maj, psize; long newdumplo; if (dev == NODEV) { dumpdev = dev; return (0); } maj = major(dev); if (maj >= nblkdev) return (ENXIO); if (bdevsw[maj] == NULL) return (ENXIO); /* XXX is this right? */ if (bdevsw[maj]->d_psize == NULL) return (ENXIO); /* XXX should be ENODEV ? */ psize = bdevsw[maj]->d_psize(dev); if (psize == -1) return (ENXIO); /* XXX should be ENODEV ? */ newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; if (newdumplo < 0) return (ENOSPC); dumpdev = dev; dumplo = newdumplo; return (0); } u_long bootdev = 0; /* not a dev_t - encoding is different */ static char devname[][2] = { {'w','d'}, /* 0 = wd */ {'s','w'}, /* 1 = sw */ #define FDMAJOR 2 {'f','d'}, /* 2 = fd */ {'w','t'}, /* 3 = wt */ {'s','d'}, /* 4 = sd -- new SCSI system */ }; #define PARTITIONMASK 0x7 #define PARTITIONSHIFT 3 #define FDUNITSHIFT 6 #define RAW_PART 2 /* * Attempt to find the device from which we were booted. * If we can do so, and not instructed not to do so, * change rootdev to correspond to the load device. */ static void setroot() { int majdev, mindev, unit, part, adaptor; dev_t orootdev; /*printf("howto %x bootdev %x ", boothowto, bootdev);*/ if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) return; majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; if (majdev > sizeof(devname) / sizeof(devname[0])) return; adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; if (majdev == FDMAJOR) { part = RAW_PART; mindev = unit << FDUNITSHIFT; } else { part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; mindev = (unit << PARTITIONSHIFT) + part; } orootdev = rootdev; rootdev = makedev(majdev, mindev); /* * If the original rootdev is the same as the one * just calculated, don't need to adjust the swap configuration. */ if (rootdev == orootdev) return; printf("changing root device to %c%c%d%c\n", devname[majdev][0], devname[majdev][1], mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), part + 'a'); } static int sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS { int error; dev_t ndumpdev; ndumpdev = dumpdev; error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); if (error == 0 && req->newptr != NULL) error = setdumpdev(ndumpdev); return (error); } SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); Index: head/sys/conf/NOTES =================================================================== --- head/sys/conf/NOTES (revision 25722) +++ head/sys/conf/NOTES (revision 25723) @@ -1,1229 +1,1236 @@ # # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.335 1997/05/10 11:16:22 jhay Exp $ +# $Id: LINT,v 1.336 1997/05/10 17:40:53 fsmp Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from # this file as required. # # # This directive is mandatory; it defines the architecture to be # configured for; in this case, the 386 family based IBM-PC and # compatibles. # machine "i386" # # This is the ``identification'' of the kernel. Usually this should # be the same as the name of your kernel. # ident LINT # # The `maxusers' parameter controls the static sizing of a number of # internal system tables by a complicated formula defined in param.c. # maxusers 10 # # Certain applications can grow to be larger than the 128M limit # that FreeBSD initially imposes. Below are some options to # allow that limit to grow to 256MB, and can be increased further # with changing the parameters. MAXDSIZ is the maximum that the # limit can be set to, and the DFLDSIZ is the default value for # the limit. You might want to set the default lower than the # max, and explicitly set the maximum with a shell command for processes # that regularly exceed the limit like INND. # options "MAXDSIZ=(256*1024*1024)" options "DFLDSIZ=(256*1024*1024)" # When this is set, be extra conservative in various parts of the kernel # and choose functionality over speed (on the widest variety of systems). options FAILSAFE # This allows you to actually store this configuration file into # the kernel binary itself, where it may be later read by saying: # strings /kernel | grep ^___ | sed -e 's/^___//' > MYKERNEL # options INCLUDE_CONFIG_FILE # Include this file in kernel # # This directive defines a number of things: # - The compiled kernel is to be called `kernel' # - The root filesystem might be on partition wd0a # - Crash dumps will be written to wd0b, if possible. Specifying the # dump device here is not recommended. Use dumpon(8). # config kernel root on wd0 dumps on wd0 ##################################################################### # SMP OPTIONS: # # SMP enables building of a Symmetric MultiProcessor Kernel. # APIC_IO enables the use of the IO APIC for Symmetric I/O. # NCPU sets the number of CPUs, defaults to 2. # NBUS sets the number of busses, defaults to 4. # NAPIC sets the number of IO APICs on the motherboard, defaults to 1. # NINTR sets the total number of INTs provided by the motherboard. # # SMP_AUTOSTART automates the startup of the additional CPUs. # SMP_PRIVPAGES maintain 'per-CPU' private data, NOT implemented yet! # # SMP_TIMER_NC is for motherboards that claim 8254 connectivity to the IO APIC, # when in fact it is NOT connected. # # Notes: # # An SMP kernel will ONLY run on an Intel MP spec. qualified motherboard. # # Be sure to disable 'cpu "I386_CPU"' && 'cpu "I486_CPU"' for SMP kernels. # # Check the 'Rogue SMP hardware' section to see if additional options # are required by your hardware. # # Mandatory: options SMP # Symmetric MultiProcessor Kernel options APIC_IO # Symmetric (APIC) I/O # Useful: options SMP_AUTOSTART # start the additional CPUs during boot # Optional, these are the defaults: #options NCPU=2 # number of CPUs #options NBUS=4 # number of busses #options NAPIC=1 # number of IO APICs #options NINTR=24 # number of INTs # Currently unusable: #options SMP_PRIVPAGES # BROKEN: architecture problem # # Rogue SMP hardware: # # Tyan Tomcat II: #options SMP_TIMER_NC # 8254 NOT connected to APIC # SuperMicro P6DNE: #options SMP_TIMER_NC # 8254 NOT connected to APIC # Bridged PCI cards: # # The MP tables of most of the current generation MP motherboards # do NOT properly support bridged PCI cards. To use one of these # cards you should refer to ??? ##################################################################### # CPU OPTIONS # # You must specify at least one CPU (the one you intend to run on); # deleting the specification for CPUs you don't need to use may make # parts of the system run faster. This is especially true removing # I386_CPU. # cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(tm) cpu "I686_CPU" # aka Pentium Pro(tm) # # Options for CPU features. # # CPU_BLUELIGHTNING_FPU_OP_CACHE enables FPU operand cache on IBM # BlueLightning CPU. It works only with Cyrix FPU, and this option # should not be used with Intel FPU. # # CPU_BLUELIGHTNING_3X enables triple-clock mode on IBM Blue Lightning # CPU if CPU supports it. The default is double-clock mode on # BlueLightning CPU box. # # CPU_BTB_EN enables branch target buffer on Cyrix 5x86 (NOTE 1). # # CPU_DISABLE_5X86_LSSER disables load store serialize (i.e. enables # reorder). This option should not be used if you use memory mapped # I/O device(s). # # CPU_FASTER_5X86_FPU enables faster FPU exception handler. # # CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products # for i386 machines. # CPU_IORT defines I/O clock delay time (NOTE 1). Default vaules of # I/O clock delay time on Cyrix 5x86 and 6x86 are 0 and 7,respectively # (no clock delay). # # CPU_LOOP_EN prevents flushing the prefetch buffer if the destination # of a jump is already present in the prefetch buffer on Cyrix 5x86(NOTE # 1). # # CPU_RSTK_EN enables return stack on Cyrix 5x86 (NOTE 1). # # CPU_SUSP_HLT enables suspend on HALT. If this option is set, CPU # enters suspend mode following execution of HALT instruction. # # CYRIX_CACHE_WORKS enables CPU cache on Cyrix 486 CPUs with cache # flush at hold state. # # CYRIX_CACHE_REALLY_WORKS enables (1) CPU cache on Cyrix 486 CPUs # without cache flush at hold state, and (2) write-back CPU cache on # Cyrix 6x86 whose revision < 2.7 (NOTE 2). # # NOTE 1: The options, CPU_BTB_EN, CPU_LOOP_EN, CPU_IORT, # CPU_LOOP_ENand CPU_RSTK_EN should no be used becasue of CPU bugs. # These options may crash your system. # # NOTE 2: If CYRIX_CACHE_REALLY_WORKS is not set, CPU cache is enabled # in write-through mode when revision < 2.7. If revision of Cyrix # 6x86 >= 2.7, CPU cache is always enabled in write-back mode. # options "CPU_BLUELIGHTNING_FPU_OP_CACHE" options "CPU_BLUELIGHTNING_3X" options "CPU_BTB_EN" options "CPU_DISABLE_5X86_LSSER" options "CPU_FASTER_5X86_FPU" options "CPU_I486_ON_386" options "CPU_IORT" options "CPU_LOOP_EN" options "CPU_RSTK_EN" options "CPU_SUSP_HLT" options "CYRIX_CACHE_WORKS" options "CYRIX_CACHE_REALLY_WORKS" # # A math emulator is mandatory if you wish to run on hardware which # does not have a floating-point processor. Pick either the original, # bogus (but freely-distributable) math emulator, or a much more # fully-featured but GPL-licensed emulator taken from Linux. # options MATH_EMULATE #Support for x87 emulation # Don't enable both of these in a real config. options GPL_MATH_EMULATE #Support for x87 emulation via #new math emulator ##################################################################### # COMPATIBILITY OPTIONS # # Implement system calls compatible with 4.3BSD and older versions of # FreeBSD. You probably do NOT want to remove this as much current code # still relies on the 4.3 emulation. # options "COMPAT_43" # # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). # options USER_LDT #allow user-level control of i386 ldt # # These three options provide support for System V Interface # Definition-style interprocess communication, in the form of shared # memory, semaphores, and message queues, respectively. # options SYSVSHM options SYSVSEM options SYSVMSG # # This option includes a MD5 routine in the kernel, this is used for # various authentication and privacy uses. # options "MD5" ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # Don't drop into DDB for a panic. Intended for unattended operation # where you may want to drop to DDB from the console, but still want # the machine to recover from a panic # options DDB_UNATTENDED # # KTRACE enables the system-call tracing facility ktrace(2). # options KTRACE #kernel tracing # # The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # options DIAGNOSTIC # # PERFMON causes the driver for Pentium/Pentium Pro performance counters # to be compiled. See perfmon(4) for more information. # options PERFMON # XXX - this doesn't belong here. # Allow ordinary users to take the console - this is useful for X. options UCONSOLE # XXX - this doesn't belong here either options USERCONFIG #boot -c editor options USERCONFIG_BOOT #imply -c and parse info area options VISUAL_USERCONFIG #visual boot -c editor ##################################################################### # NETWORKING OPTIONS # # Protocol families: # Only the INET (Internet) family is officially supported in FreeBSD. # Source code for the NS (Xerox Network Service) is provided for amusement # value. # options INET #Internet communications protocols options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) options NETATALK #Appletalk communications protocols # These are currently broken but are shipped due to interest. #options NS #Xerox NS protocols # These are currently broken and are no longer shipped due to lack # of interest. #options CCITT #X.25 network layer #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 #options LLC #X.25 link layer for Ethernets #options HDLC #X.25 link layer for serial lines #options EON #ISO CLNP over IP #options NSIP #XNS over IP # # Network interfaces: # The `loop' pseudo-device is MANDATORY when networking is enabled. # The `ether' pseudo-device provides generic code to handle # Ethernets; it is MANDATORY when a Ethernet device driver is # configured. # The 'fddi' pseudo-device provides generic code to support FDDI. # The `sppp' pseudo-device serves a similar role for certain types # of synchronous PPP links (like `cx', `ar'). # The `sl' pseudo-device implements the Serial Line IP (SLIP) service. # The `ppp' pseudo-device implements the Point-to-Point Protocol. # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be # aware of the legal and administrative consequences of enabling this # option. The number of devices determines the maximum number of # simultaneous BPF clients programs runnable. # The `disc' pseudo-device implements a minimal network interface, # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) # pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver(user process ppp) # # Internet family options: # # TCP_COMPAT_42 causes the TCP code to emulate certain bugs present in # 4.2BSD. This option should not be used unless you have a 4.2BSD # machine and TCP connections fail. # # MROUTING enables the kernel multicast packet forwarder, which works # with mrouted(8). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE sends # logged packets to the system logger. IPFIREWALL_VERBOSE_LIMIT # limits the number of times a matching entry can be logged. # # IPDIVERT enables the divert IP sockets, used by ``ipfw divert'' # # TCPDEBUG is undocumented. # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options "IPFIREWALL_VERBOSE_LIMIT=100" #limit verbosity options IPDIVERT #divert sockets options TCPDEBUG ##################################################################### # FILESYSTEM OPTIONS # # Only the root, /usr, and /tmp filesystems need be statically # compiled; everything else will be automatically loaded at mount # time. (Exception: the UFS family---FFS, MFS, and LFS---cannot # currently be demand-loaded.) Some people still prefer to statically # compile other filesystems as well. # # NB: The LFS, PORTAL, and UNION filesystems are known to be buggy, # and WILL panic your system if you attempt to do anything with them. # They are included here as an incentive for some enterprising soul to # sit down and fix them. # # Note: 4.4BSD NQNFS lease checking has relatively high cost for # _local_ I/O as well as remote I/O. Don't use it unless you will # using NQNFS. # # One of these is mandatory: options FFS #Fast filesystem options NFS #Network File System # The rest are optional: options NQNFS #Enable NQNFS lease checking # options NFS_NOSERVER #Disable the NFS-server code. options "CD9660" #ISO 9660 filesystem options FDESC #File descriptor filesystem options KERNFS #Kernel filesystem options LFS #Log filesystem options MFS #Memory File System options MSDOSFS #MS DOS File System options NULLFS #NULL filesystem options PORTAL #Portal filesystem options PROCFS #Process filesystem options UMAPFS #UID map filesystem options UNION #Union filesystem # This DEVFS is experimental but seems to work options DEVFS #devices filesystem # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. options MFS_ROOT=10 # Allow the MFS_ROOT code to load the MFS image from floppy if it is missing. options MFS_AUTOLOAD # Allow this many swap-devices. options NSWAPDEV=20 # Disk quotas are supported when this option is enabled. If you # change the value of this option, you must do a `make clean' in your # kernel compile directory in order to get a working kernel. # options QUOTA #enable disk quotas # Add more checking code to various filesystems #options NULLFS_DIAGNOSTIC #options KERNFS_DIAGNOSTIC #options UMAPFS_DIAGNOSTIC #options UNION_DIAGNOSTIC # In particular multi-session CD-Rs might require a huge amount of # time in order to "settle". If we are about mounting them as the # root f/s, we gotta wait a little. # # The number is supposed to be in seconds. options "CD9660_ROOTDELAY=20" # Add some error checking code to the null_bypass routine # in the NULL filesystem #options SAFETY ##################################################################### # SCSI DEVICES # SCSI DEVICE CONFIGURATION # The SCSI subsystem consists of the `base' SCSI code, a number of # high-level SCSI device `type' drivers, and the low-level host-adapter # device drivers. The host adapters are listed in the ISA and PCI # device configuration sections below. # # Beginning with FreeBSD 2.0.5 you can wire down your SCSI devices so # that a given bus, target, and LUN always come on line as the same # device unit. In earlier versions the unit numbers were assigned # in the order that the devices were probed on the SCSI bus. This # means that if you removed a disk drive, you may have had to rewrite # your /etc/fstab file, and also that you had to be careful when adding # a new disk as it may have been probed earlier and moved your device # configuration around. # This old behavior is maintained as the default behavior. The unit # assignment begins with the first non-wired down unit for a device # type. For example, if you wire a disk as "sd3" then the first # non-wired disk will be assigned sd4. # The syntax for wiring down devices is: # controller scbus0 at ahc0 # Single bus device # controller scbus1 at ahc1 bus 0 # Single bus device # controller scbus3 at ahc2 bus 0 # Twin bus device # controller scbus2 at ahc2 bus 1 # Twin bus device # disk sd0 at scbus0 target 0 unit 0 # disk sd1 at scbus3 target 1 # disk sd2 at scbus2 target 3 # tape st1 at scbus1 target 6 # device cd0 at scbus? # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. # All SCSI devices allocate as many units as are required. # The "unknown" device (uk? in pre-2.0.5) is now part of the base SCSI # configuration and doesn't have to be explicitly configured. controller scbus0 #base SCSI code device ch0 #SCSI media changers device sd0 #SCSI disks device st0 #SCSI tapes device cd0 #SCSI CD-ROMs device od0 #SCSI optical disk # The previous devices (ch, sd, st, cd) are recognized by config. # config doesn't (and shouldn't) know about these newer ones, # so we have to specify that they are on a SCSI bus with the "at scbus?" # clause. device worm0 at scbus? # SCSI worm device pt0 at scbus? # SCSI processor type device sctarg0 at scbus? # SCSI target # SCSI OPTIONS: # SCSIDEBUG: When defined enables debugging macros # NO_SCSI_SENSE: When defined disables sense descriptions (about 4k) # SCSI_REPORT_GEOMETRY: Always report disk geometry at boot up instead # of only when booting verbosely. options SCSIDEBUG #options NO_SCSI_SENSE options SCSI_REPORT_GEOMETRY # Options for the `od' optical disk driver: # # If drive returns sense key as 0x02 with vendor specific additional # sense code (ASC) and additional sense code qualifier (ASCQ), or # illegal ASC and ASCQ. This cause an error (NOT READY) and retrying. # To suppress this, use the following option. # options OD_BOGUS_NOT_READY # # For an automatic spindown, try this. Again, preferably as an # option in your config file. # WARNING! Use at your own risk. Joerg's ancient SONY SMO drive # groks it fine, while Shunsuke's Fujitsu chokes on it and times # out. # options OD_AUTO_TURNOFF ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS # # Of these, only the `log' device is truly mandatory. The `pty' # device usually turns out to be ``effectively mandatory'', as it is # required for `telnetd', `rlogind', `screen', `emacs', and `xterm', # among others. # If you wish to run certain # system utilities which are compressed by default (like /stand/sysinstall) # then `gzip' becomes mandatory too. # pseudo-device pty 16 #Pseudo ttys - can go as high as 256 pseudo-device speaker #Play IBM BASIC-style noises out your speaker pseudo-device log #Kernel syslog interface (/dev/klog) pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. pseudo-device ccd 4 #Concatenated disk driver # These are only for watching for bitrot in old tty code. # broken #pseudo-device tb # These are only for watching for bitrot in old SCSI code. pseudo-device su #scsi user pseudo-device ssc #super scsi ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # EISA support is available for some device, so they can be auto-probed. # Micro Channel is not supported at all. # # Mandatory ISA devices: isa, sc or vt, npx # controller isa0 # # Options for `isa': # # AUTO_EOI_1 enables the `automatic EOI' feature for the master 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # This option breaks suspend/resume on some portables. # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # BOUNCE_BUFFERS provides support for ISA DMA on machines with more # than 16 megabytes of memory. It doesn't hurt on other machines. # Some broken EISA and VLB hardware may need this, too. # # MAXMEM specifies the amount of RAM on the machine; if this is not # specified, FreeBSD will read the amount of memory from the CMOS RAM, # so the amount of memory will be limited to 64MB or 16MB depending on # the BIOS. The amount is in kilobytes, so for a machine with 128MB of # RAM, it would be 131072 (128 * 1024). # # TUNE_1542 enables the automatic ISA bus speed selection for the # Adaptec 1542 boards. Does not work for all boards, use it with caution. # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. # # PAS_JOYSTICK_ENABLE enables the gameport on the ProAudio Spectrum options "AUTO_EOI_1" #options "AUTO_EOI_2" options BOUNCE_BUFFERS options "MAXMEM=(128*1024)" #options "TUNE_1542" #options BROKEN_KEYBOARD_RESET #options PAS_JOYSTICK_ENABLE # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint options PCVT_FREEBSD=210 # pcvt running on FreeBSD >= 2.0.5 options XSERVER # include code for XFree86 options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible) - default. device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr options MAXCONS=16 # number of virtual consoles options SLOW_VGA # do byte-wide i/o's to TS and GDC regs # # `flags' for sc0: # 0x01 Use a 'visual' bell # 0x02 Use a 'blink' cursor # 0x04 Use a 'block' cursor # 0x08 Force detection of keyboard, else we always assume a keyboard # 0x10 Old-style (XT) keyboard support, useful for older ThinkPads # # The Numeric Processing eXtension driver. This should be configured if # your machine has a math co-processor, unless the coprocessor is very # buggy. If it is not configured then you *must* configure math emulation # (see above). If both npx0 and emulation are configured, then only npx0 # is used (provided it works). device npx0 at isa? port "IO_NPX" iosiz 0x0 flags 0x0 irq 13 vector npxintr # # `flags' for npx0: # 0x01 don't use the npx registers to optimize bcopy # 0x02 don't use the npx registers to optimize bzero # 0x04 don't use the npx registers to optimize copyin or copyout. # The npx registers are normally used to optimize copying and zeroing when # all of the following conditions are satisfied: # "I586_CPU" is an option # the cpu is an i586 (perhaps not a Pentium) # the probe for npx0 succeeds # INT 16 exception handling works. # Then copying and zeroing using the npx registers is normally 30-100% faster. # The flags can be used to control cases where it doesn't work or is slower. # Setting them at boot time using userconfig works right (the optimizations # are not used until later in the bootstrap when npx0 is attached). # # # `iosiz' for npx0: # This can be used instead of the MAXMEM option to set the memory size. If # it is nonzero, then it overrides both the MAXMEM option and the memory # size reported by the BIOS. Setting it at boot time using userconfig takes # effect on the next reboot after the change has been recorded in the kernel # binary (the size is used early in the boot before userconfig has a chance # to change it). # # # Optional ISA and EISA devices: # # # SCSI host adapters: `aha', `aic', `bt', `nca' # # aha: Adaptec 154x # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers # nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 # uha: UltraStore 14F and 34F # sea: Seagate ST01/02 8 bit controller (slow!) # wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. # controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr controller aic0 at isa? port 0x340 bio irq 11 vector aicintr controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr controller nca1 at isa? port 0x1f84 controller nca2 at isa? port 0x1f8c controller nca3 at isa? port 0x1e88 controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' # # NB: ``Enhanced IDE'' is NOT supported at this time. # # The flags fields are used to enable the multi-sector I/O and # the 32BIT I/O modes. The flags may be used in either the controller # definition or in the individual disk definitions. The controller # definition is supported for the boot configuration stuff. # # Each drive has a 16 bit flags value defined: # The low 8 bits are the maximum value for the multi-sector I/O, # where 0xff defaults to the maximum that the drive can handle. # The high bit of the 16 bit flags (0x8000) allows probing for # 32 bit transfers. # # The flags field for the drives can be specified in the controller # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: #controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be # allowed to probe for 32 bit transfers, but will allow multi-sector # transfers up to the maximum that the drive supports. # # controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 # # Options for `wdc': # # CMD640 enables serializing access to primary and secondary channel # of the CMD640B IDE Chip. The serializing will only take place # if this option is set *and* the chip is probed by the pci-system. # options "CMD640" #Enable work around for CMD640 h/w bug # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus options ATAPI_STATIC #Don't do it as an LKM # IDE CD-ROM driver - requires wdc controller and ATAPI option device wcd0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: #controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 tape ft0 at fdc0 drive 2 # # Options for `fd': # # FDSEEKWAIT selects a non-default head-settle time (i.e., the time to # wait after a seek is performed). The default value (1/32 s) is # usually sufficient. The units are inverse seconds, so a value of 16 # here means to wait 1/16th of a second; you should choose a power of # two. # XXX: this seems to be missing! options FDSEEKWAIT=16 # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: # port can be specified as ?, this will cause the driver to scan # the BIOS port list; # the irq and vector clauses may be omitted, this # will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports # psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) device lpt0 at isa? port? tty irq 7 vector lptintr device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr device mse0 at isa? port 0x23c tty irq 5 vector mseintr device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # Options for psm: options PSM_CHECKSYNC #checks the header byte for sync. device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr # # `flags' for serial drivers that support consoles (only for sio now): # 0x10 enable console support for this unit. The other console flags # are ignored unless this is set. Enabling console support does # not make the unit the preferred console - boot with -h or set # the 0x20 flag for that. Currently, at most one unit can have # console support; the first one (in config file order) with # this flag set is preferred. Setting this flag for sio0 gives # the old behaviour. # 0x20 force this unit to be the console (unless there is another # higher priority console). This replaces the COMCONSOLE option. # 0x40 reserve this unit for low level console operations. Do not # # Options for serial drivers that support consoles (only for sio now): options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to #DDB, if available. options CONSPEED=115200 #speed for serial console (default 9600) # Options for sio: options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs options DSI_SOFT_MODEM #code for DSI Softmodems # # Network interfaces: `cx', `ed', `el', `ep', `ie', `is', `le', `lnc' # # ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver (requires sppp) # cx: Cronyx/Sigma multiport sync/async (with Cisco or PPP framing) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) # fe: Fujitsu MB86960A/MB86965A Ethernet # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210 # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # sr: RISCom/N2 hdlc sync 1/2 port V.35/X.21 serial driver (requires sppp) # ze: IBM/National Semiconductor PCMCIA ethernet controller. # zp: 3Com PCMCIA Etherlink III (It does not require shared memory for # send/receive operation, but it needs 'iomem' to read/write the # attribute memory) # device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device eg0 at isa? port 0x310 net irq 5 vector egintr device el0 at isa? port 0x300 net irq 9 vector elintr device ep0 at isa? port 0x300 net irq 10 vector epintr device ex0 at isa? port? net irq? vector exintr device fe0 at isa? port 0x300 net irq ? vector feintr device ie0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector ieintr device ie1 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr device sr0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector srintr # Needed so that we can (bogusly) include both the dedicated PCCARD # drivers and the generic support options LINT_PCCARD_HACK device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # ATM related options # # The `en' device provides support for Efficient Networks (ENI) # ENI-155 PCI midway cards, and the Adaptec 155Mbps PCI ATM cards (ANA-59x0). # # atm pseudo-device privides generic atm functions and is required for # atm devices. # NETNATM enables the netnatm protocol family that can be used to # bypass TCP/IP. # # the current driver supports only PVC operations (no atm-arp, no multicast). # for more details, please read the original documents at # http://www.ccrc.wustl.edu/pub/chuck/bsdatm/wucs.html # pseudo-device atm device en0 device en1 options NETNATM #native ATM # # Audio drivers: `snd', `sb', `pas', `gus', `pca' # # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card # # Beware! The addresses specified below are also hard-coded in # i386/isa/sound/sound_config.h. If you change the values here, you # must also change the values in the include file. # # pca: PCM audio through your PC speaker # # If you don't have a lpt0 device at IRQ 7, you can remove the # ``conflicts'' specification in the appropriate device entries below. # # If you have a GUS-MAX card and want to use the CS4231 codec on the # card the drqs for the gus max must be 8 bit (1, 2, or 3). # # If you would like to use the full duplex option on the gus, then define # flags to be the ``read dma channel''. # # options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset # options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset # options EXCLUDE_SBPRO #PAS-16 # options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line. # PAS16: The order of the pas0/sb0/opl0 is important since the # sb emulation is enabled in the pas-16 attach. # # The i386/isa/sound/sound.doc has more information. # Controls all sound devices controller snd0 device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr device sb0 at isa? port 0x220 irq 5 conflicts drq 1 vector sbintr device sbxvi0 at isa? port? irq? drq 5 conflicts device sbmidi0 at isa? port 0x330 irq? conflicts #device awe0 at isa? port 0x620 device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr #device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr device opl0 at isa? port 0x388 conflicts device mpu0 at isa? port 0x330 irq 6 drq 0 device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # More undocumented sound devices with bogus configurations for linting. # broken #device sscape0 at isa? port 0x330 irq 6 drq 0 #device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr # Not controlled by `snd' device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM # matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # bktr: Bt848 capture boards (http://www.freebsd.org/~fsmp/HomeAuto/Bt848.html) # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # gp: National Instruments AT-GPIB and AT-GPIB/TNT board # asc: GI1904-based hand scanners, e.g. the Trust Amiscan Grey # gsc: Genius GS-4500 hand scanner. # joy: joystick # labpc: National Instrument's Lab-PC and Lab-PC+ # rc: RISCom/8 multiport card # tw: TW-523 power line interface for use with X-10 home control products # si: Specialix SI/XIO 4-32 port terminal multiplexor # stl: Stallion EasyIO and EasyConnection 8/32 (cd1400 based) # stli: Stallion EasyConnection 8/64, ONboard, Brumby (intelligent) # # Notes on APM # The flags takes the following meaning for apm0: # 0x0020 Statclock is broken. # 0x0011 Limit APM protocol to 1.1 or 1.0 # 0x0010 Limit APM protocol to 1.0 # # # Notes on the spigot: # The video spigot is at 0xad6. This port address can not be changed. # The irq values may only be 10, 11, or 15 # I/O memory is an 8kb region. Possible values are: # 0a0000, 0a2000, ..., 0fffff, f00000, f02000, ..., ffffff # The start address must be on an even boundary. # Add the following option if you want to allow non-root users to be able # to access the spigot. This option is not secure because it allows users # direct access to the I/O page. # options SPIGOT_UNSECURE # # Notes on the Digiboard driver: # # The following flag values have special meanings: # 0x01 - alternate layout of pins # 0x02 - use the windowed PC/Xe in 64K mode # Notes on the Specialix SI/XIO driver: # **This is NOT a Specialix supported Driver!** # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. # Notes on the Stallion stl and stli drivers: # See src/i386/isa/README.stl for complete instructions. # This is version 0.0.5alpha, unsupported by Stallion. # The stl driver has a secondary IO port hard coded at 0x280. You need # to change src/i386/isa/stallion.c if you reconfigure this on the boards. # The "flags" and "iosiz" settings on the stli driver depend on the board: # EasyConnection 8/64 ISA: flags 23 iosiz 0x1000 # EasyConnection 8/64 EISA: flags 24 iosiz 0x10000 # EasyConnection 8/64 MCA: flags 25 iosiz 0x1000 # ONboard ISA: flags 4 iosiz 0x10000 # ONboard EISA: flags 7 iosiz 0x10000 # ONboard MCA: flags 3 iosiz 0x10000 # Brumby: flags 2 iosiz 0x4000 # Stallion: flags 1 iosiz 0x10000 device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device qcam0 at isa? port "IO_LPT3" tty device apm0 at isa? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port "IO_GAME" device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr device rc0 at isa? port 0x220 tty irq 12 vector rcintr # the port and irq for tw0 are fictitious device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 vector siintr device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr device bqu0 at isa? port 0x150 device stl0 at isa? port 0x2a0 tty irq 10 vector stlintr device stli0 at isa? port 0x2a0 tty iomem 0xcc000 flags 23 iosiz 0x1000 # # EISA devices: # # The EISA bus device is eisa0. It provides auto-detection and # configuration support for all devices on the EISA bus. # # The `ahb' device provides support for the Adaptec 174X adapter. # # The `ahc' device provides support for the Adaptec 274X and 284X # adapters. The 284X, although a VLB card responds to EISA probes. # # fea: DEC DEFEA EISA FDDI adapter # controller eisa0 controller ahb0 controller ahc0 device fea0 # enable tagged command queuing, which is a major performance win on # devices that support it (and controllers with enough SCB's) options AHC_TAGENABLE # enable SCB paging - See the ahc.4 man page options AHC_SCBPAGING_ENABLE # The aic7xxx driver will attempt to use memory mapped I/O for all PCI # controllers that have it configured only if this option is set. Unfortunately, # this doesn't work on some motherboards, which prevents it from being the # default. options AHC_ALLOW_MEMIO # By default, only 10 EISA slots are probed, since the slot numbers # above clash with the configuration address space of the PCI subsystem, # and the EISA probe is not very smart about this. This is sufficient # for most machines, but in particular the HP NetServer LC series comes # with an onboard AIC7770 dual-channel SCSI controller on EISA slot #11, # thus you need to bump this figure to 12 for them. options "EISA_SLOTS=12" # # PCI devices: # # The main PCI bus device is `pci'. It provides auto-detection and # configuration support for all devices on the PCI bus, using either # configuration mode defined in the PCI specification. # # The `ahc' device provides support for the Adaptec 29/3940(U)(W) # and motherboard based AIC7870/AIC7880 adapters. # # The `ncr' device provides support for the NCR 53C810 and 53C825 # self-contained SCSI host adapters. # # The `amd' device provides support for the Tekram DC-390 and 390T # SCSI host adapters, but is expected to work with any AMD 53c974 # PCI SCSI chip and the AMD Ethernet+SCSI Combo chip, after some # local patches were applied to the sources (that had originally # been written by Tekram and limited to work with their SCSI cards). # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `fxp' device provides support for the Intel EtherExpress Pro/100B # PCI Fast Ethernet adapters. # # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The `meteor' device is a PCI video capture board. It can also have the # following options: # options METEOR_ALLOC_PAGES=xxx preallocate kernel pages for data entry # figure (ROWS*COLUMN*BYTES_PER_PIXEL*FRAME+PAGE_SIZE-1)/PAGE_SIZE # options METEOR_DEALLOC_PAGES remove all allocated pages on close(2) # options METEOR_DEALLOC_ABOVE=xxx remove all allocated pages above the # specified amount. If this value is below the allocated amount no action # taken # option METEOR_SYSTEM_DEFAULT={METEOR_PAL|METEOR_NTSC|METEOR_SECAM}, used # for initialization of fps routine when a signal is not present. # # The 'bktr' device is a PCI video capture board. It also has a TV tuner # on board. # controller pci0 controller ahc1 controller ncr0 controller amd0 device de0 device fxp0 device vx0 device fpa0 device meteor0 device bktr0 # # PCCARD/PCMCIA # # crd: slot controller # pcic: slots controller crd0 controller pcic0 at crd? controller pcic1 at crd? # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardware' # above. # For older notebooks that signal a powerfail condition (external # power supply dropped, or battery state low) by issuing an NMI: options POWERFAIL_NMI # make it beep instead of panicing + +# Kernel BOOTP support + +options BOOTP # Use BOOTP to obtain IP address/hostname +options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info +options "BOOTP_NFSV3" # Use NFS v3 to NFS mount root +options BOOTP_COMPAT # Workaround for broken bootp daemons. # # An obsolete option to test kern_opt.c. # options GATEWAY # More undocumented options for linting. options CLK_CALIBRATION_LOOP options "CLK_USE_I8254_CALIBRATION" options "CLK_USE_I586_CALIBRATION" options CLUSTERDEBUG options COMPAT_LINUX options DEBUG options DEVFS_ROOT options "EXT2FS" options "I586_CTR_GUPROF" options "I586_PMC_GUPROF=0x70000" options "IBCS2" options LOCKF_DEBUG options KBD_MAXRETRY=4 options KBD_MAXWAIT=6 options KBD_RESETDELAY=201 options KBDIO_DEBUG=2 options MSGMNB=2049 options MSGMNI=41 options MSGSEG=2049 options MSGSSZ=16 options MSGTQL=41 options NBUF=512 options NMBCLUSTERS=1024 options NPX_DEBUG options PSM_ACCEL=1 options PSM_DEBUG=1 options PSM_EMULATION options "SCSI_2_DEF" options SCSI_DELAY=8 # Be pessimistic about Joe SCSI device options SCSI_NCR_DEBUG options SCSI_NCR_DFLT_TAGS=4 options SCSI_NCR_MAX_SYNC=10000 options SCSI_NCR_MAX_WIDE=1 options SCSI_NCR_MYADDR=7 options SEMMAP=31 options SEMMNI=11 options SEMMNS=61 options SEMMNU=31 options SEMMSL=61 options SEMOPM=101 options SEMUME=11 options SHOW_BUSYBUFS # List buffers that prevent root unmount options SHMALL=1025 options "SHMMAX=(SHMMAXPGS*PAGE_SIZE+1)" options SHMMAXPGS=1025 options SHMMIN=2 options SHMMNI=33 options SHMSEG=9 options SI_DEBUG options SIMPLELOCK_DEBUG options SPX_HACK Index: head/sys/conf/files =================================================================== --- head/sys/conf/files (revision 25722) +++ head/sys/conf/files (revision 25723) @@ -1,411 +1,413 @@ ddb/db_access.c optional ddb ddb/db_aout.c optional ddb ddb/db_break.c optional ddb ddb/db_command.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_lex.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_sym.c optional ddb ddb/db_trap.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb dev/ccd/ccd.c optional ccd device-driver dev/en/midway.c optional en device-driver dev/pdq/pdq.c optional fea device-driver dev/pdq/pdq_ifsubr.c optional fea device-driver dev/pdq/pdq.c optional fpa device-driver dev/pdq/pdq_ifsubr.c optional fpa device-driver dev/vn/vn.c optional vn dev/vx/if_vx.c optional vx device-driver gnu/ext2fs/ext2_alloc.c optional ext2fs gnu/ext2fs/ext2_balloc.c optional ext2fs gnu/ext2fs/ext2_inode.c optional ext2fs gnu/ext2fs/ext2_inode_cnv.c optional ext2fs gnu/ext2fs/ext2_linux_balloc.c optional ext2fs gnu/ext2fs/ext2_linux_ialloc.c optional ext2fs gnu/ext2fs/ext2_lookup.c optional ext2fs gnu/ext2fs/ext2_subr.c optional ext2fs gnu/ext2fs/ext2_vfsops.c optional ext2fs gnu/ext2fs/ext2_vnops.c optional ext2fs isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 kern/imgact_aout.c standard kern/imgact_elf.c standard kern/imgact_gzip.c optional gzip kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_smp.c optional smp kern/init_sysent.c standard kern/init_sysvec.c standard kern/kern_module.c standard kern/kern_linker.c standard kern/link_aout.c standard kern/kern_acct.c standard kern/kern_clock.c standard kern/kern_conf.c standard kern/kern_descrip.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_ktrace.c standard kern/kern_lkm.c standard kern/kern_lock.c standard kern/kern_lockf.c standard kern/kern_malloc.c standard kern/kern_mib.c standard kern/kern_ntptime.c standard kern/kern_opt.c standard kern/kern_physio.c standard kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_synch.c standard kern/kern_sysctl.c standard kern/kern_time.c standard kern/kern_xxx.c standard kern/md5c.c optional md5 kern/subr_diskslice.c standard kern/subr_dkbad.c standard kern/subr_log.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rlist.c standard kern/subr_xxx.c standard kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c standard kern/tty_conf.c standard kern/tty_pty.c optional pty kern/tty_snoop.c optional snp kern/tty_subr.c standard kern/tty_tb.c optional tb kern/tty_tty.c standard kern/uipc_domain.c standard kern/uipc_mbuf.c standard kern/uipc_proto.c standard kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_conf.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard miscfs/deadfs/dead_vnops.c standard miscfs/devfs/devfs_tree.c optional devfs miscfs/devfs/devfs_vfsops.c optional devfs miscfs/devfs/devfs_vnops.c optional devfs miscfs/fdesc/fdesc_vfsops.c optional fdesc miscfs/fdesc/fdesc_vnops.c optional fdesc miscfs/fifofs/fifo_vnops.c standard miscfs/kernfs/kernfs_vfsops.c optional kernfs miscfs/kernfs/kernfs_vnops.c optional kernfs miscfs/nullfs/null_subr.c optional nullfs miscfs/nullfs/null_vfsops.c optional nullfs miscfs/nullfs/null_vnops.c optional nullfs miscfs/portal/portal_vfsops.c optional portal miscfs/portal/portal_vnops.c optional portal miscfs/procfs/procfs_ctl.c optional procfs miscfs/procfs/procfs_fpregs.c standard miscfs/procfs/procfs_map.c optional procfs miscfs/procfs/procfs_mem.c standard miscfs/procfs/procfs_note.c optional procfs miscfs/procfs/procfs_regs.c standard miscfs/procfs/procfs_status.c optional procfs miscfs/procfs/procfs_subr.c optional procfs miscfs/procfs/procfs_type.c optional procfs miscfs/procfs/procfs_vfsops.c optional procfs miscfs/procfs/procfs_vnops.c optional procfs miscfs/specfs/spec_vnops.c standard miscfs/umapfs/umap_subr.c optional umapfs miscfs/umapfs/umap_vfsops.c optional umapfs miscfs/umapfs/umap_vnops.c optional umapfs miscfs/union/union_subr.c optional union miscfs/union/union_vfsops.c optional union miscfs/union/union_vnops.c optional union msdosfs/msdosfs_conv.c optional msdosfs msdosfs/msdosfs_denode.c optional msdosfs msdosfs/msdosfs_fat.c optional msdosfs msdosfs/msdosfs_lookup.c optional msdosfs msdosfs/msdosfs_vfsops.c optional msdosfs msdosfs/msdosfs_vnops.c optional msdosfs net/bpf.c optional bpfilter net/bpf_filter.c optional bpfilter net/bsd_comp.c optional ppp net/if.c standard net/if_atmsubr.c optional atm net/if_disc.c optional disc net/if_ethersubr.c optional ether net/if_fddisubr.c optional fddi net/if_loop.c optional loop net/if_media.c standard net/if_mib.c standard net/if_ppp.c optional ppp net/if_sl.c optional sl net/if_spppsubr.c optional sppp net/if_tun.c optional tun net/ppp_tty.c optional ppp net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional ppp net/slcompress.c optional sl netatalk/aarp.c optional netatalk netatalk/at_control.c optional netatalk netatalk/at_proto.c optional netatalk netatalk/at_rmx.c optional netatalkdebug netatalk/ddp_input.c optional netatalk netatalk/ddp_output.c optional netatalk netatalk/ddp_usrreq.c optional netatalk #netccitt/ccitt_proto.c optional ccitt #netccitt/hd_debug.c optional hdlc #netccitt/hd_input.c optional hdlc #netccitt/hd_output.c optional hdlc #netccitt/hd_subr.c optional hdlc #netccitt/hd_timer.c optional hdlc #netccitt/if_x25subr.c optional ccitt #netccitt/llc_input.c optional llc #netccitt/llc_output.c optional llc #netccitt/llc_subr.c optional llc #netccitt/llc_timer.c optional llc #netccitt/pk_acct.c optional ccitt #netccitt/pk_debug.c optional ccitt #netccitt/pk_input.c optional ccitt #netccitt/pk_llcsubr.c optional hdlc #netccitt/pk_llcsubr.c optional llc #netccitt/pk_output.c optional ccitt #netccitt/pk_subr.c optional ccitt #netccitt/pk_timer.c optional ccitt #netccitt/pk_usrreq.c optional ccitt #netimp/if_imp.c optional imp #netimp/if_imphost.c optional imp #netimp/raw_imp.c optional imp netinet/if_atm.c optional atm netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet netinet/in_rmx.c optional inet netinet/ip_divert.c optional ipdivert netinet/ip_fw.c optional ipfirewall netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_mroute.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/tcp_debug.c optional tcpdebug netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netinet/ip_fil.c optional ipfilter inet netinet/fil.c optional ipfilter inet netinet/ip_nat.c optional ipfilter inet netinet/ip_frag.c optional ipfilter inet netinet/ip_state.c optional ipfilter inet netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_error.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_tun.c optional ipx netipx/ipx_usrreq.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx #netiso/clnp_debug.c optional iso #netiso/clnp_er.c optional iso #netiso/clnp_frag.c optional iso #netiso/clnp_input.c optional iso #netiso/clnp_options.c optional iso #netiso/clnp_output.c optional iso #netiso/clnp_raw.c optional iso #netiso/clnp_subr.c optional iso #netiso/clnp_timer.c optional iso #netiso/cltp_usrreq.c optional iso #netiso/esis.c optional iso #netiso/idrp_usrreq.c optional iso #netiso/if_eon.c optional eon #netiso/iso.c optional iso #netiso/iso_chksum.c optional iso #netiso/iso_pcb.c optional iso #netiso/iso_proto.c optional iso #netiso/iso_snpac.c optional iso #netiso/tp_astring.c optional iso #netiso/tp_astring.c optional tpip #netiso/tp_cons.c optional iso #netiso/tp_driver.c optional iso #netiso/tp_driver.c optional tpip #netiso/tp_emit.c optional iso #netiso/tp_emit.c optional tpip #netiso/tp_inet.c optional iso #netiso/tp_inet.c optional tpip #netiso/tp_input.c optional iso #netiso/tp_input.c optional tpip #netiso/tp_iso.c optional iso #netiso/tp_meas.c optional iso #netiso/tp_meas.c optional tpip #netiso/tp_output.c optional iso #netiso/tp_output.c optional tpip #netiso/tp_pcb.c optional iso #netiso/tp_pcb.c optional tpip #netiso/tp_subr.c optional iso #netiso/tp_subr.c optional tpip #netiso/tp_subr2.c optional iso #netiso/tp_subr2.c optional tpip #netiso/tp_timer.c optional iso #netiso/tp_timer.c optional tpip #netiso/tp_trace.c optional iso #netiso/tp_trace.c optional tpip #netiso/tp_usrreq.c optional iso #netiso/tp_usrreq.c optional tpip #netiso/tuba_subr.c optional iso tuba #netiso/tuba_table.c optional iso tuba #netiso/tuba_usrreq.c optional iso tuba netkey/key.c optional key netnatm/natm.c optional natm netnatm/natm_pcb.c optional natm netnatm/natm_proto.c optional natm #netns/idp_usrreq.c optional ns #netns/ns.c optional ns #netns/ns_error.c optional ns #netns/ns_input.c optional ns #netns/ns_ip.c optional ns #netns/ns_output.c optional ns #netns/ns_pcb.c optional ns #netns/ns_proto.c optional ns #netns/spp_debug.c optional ns #netns/spp_usrreq.c optional ns nfs/nfs_bio.c optional nfs nfs/nfs_node.c optional nfs nfs/nfs_nqlease.c optional nfs nfs/nfs_serv.c optional nfs nfs/nfs_socket.c optional nfs nfs/nfs_srvcache.c optional nfs nfs/nfs_subs.c optional nfs nfs/nfs_syscalls.c optional nfs nfs/nfs_vfsops.c optional nfs nfs/nfs_vnops.c optional nfs +nfs/bootp_subr.c optional bootp +nfs/krpc_subr.c optional bootp pccard/pccard.c optional crd pccard/pcic.c optional pcic device-driver pci/aic7870.c optional ahc device-driver \ dependency "aic7xxx_reg.h $S/pci/aic7870.c" pci/brooktree848.c optional bktr device-driver pci/bt9xx.c optional bt device-driver pci/cy_pci.c optional cy device-driver pci/if_de.c optional de device-driver pci/if_ed_p.c optional ed device-driver pci/if_en_pci.c optional en device-driver pci/if_fxp.c optional fxp device-driver pci/if_lnc_p.c optional lnc device-driver pci/if_fpa.c optional fpa device-driver pci/if_sr_p.c optional sr device-driver pci/if_vx_pci.c optional vx device-driver pci/meteor.c optional meteor device-driver pci/ncr.c optional ncr device-driver pci/pci.c optional pci device-driver pci/pcisupport.c optional pci pci/tek390.c optional amd device-driver pci/wdc_p.c optional wdc device-driver scsi/cd.c optional cd scsi/ch.c optional ch scsi/od.c optional od scsi/pt.c optional pt scsi/scsi_base.c optional scbus scsi/scsi_driver.c optional scbus scsi/scsi_ioctl.c optional scbus scsi/scsi_sense.c optional scbus scsi/scsiconf.c optional scbus scsi/sctarg.c optional sctarg scsi/sd.c optional sd scsi/ssc.c optional ssc scsi/st.c optional st scsi/su.c optional su scsi/uk.c optional scbus scsi/worm.c optional worm ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_alloc.c optional mfs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_balloc.c optional mfs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_inode.c optional mfs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_subr.c optional mfs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_tables.c optional mfs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vfsops.c optional mfs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_vnops.c optional mfs ufs/lfs/lfs_alloc.c optional lfs ufs/lfs/lfs_balloc.c optional lfs ufs/lfs/lfs_bio.c optional lfs ufs/lfs/lfs_cksum.c optional lfs ufs/lfs/lfs_debug.c optional lfs ufs/lfs/lfs_inode.c optional lfs ufs/lfs/lfs_segment.c optional lfs ufs/lfs/lfs_subr.c optional lfs ufs/lfs/lfs_syscalls.c optional lfs ufs/lfs/lfs_vfsops.c optional lfs ufs/lfs/lfs_vnops.c optional lfs ufs/mfs/mfs_vfsops.c optional mfs ufs/mfs/mfs_vnops.c optional mfs ufs/ufs/ufs_bmap.c standard ufs/ufs/ufs_disksubr.c standard ufs/ufs/ufs_ihash.c standard ufs/ufs/ufs_inode.c standard ufs/ufs/ufs_lookup.c standard ufs/ufs/ufs_quota.c standard ufs/ufs/ufs_vfsops.c standard ufs/ufs/ufs_vnops.c standard vm/default_pager.c standard vm/device_pager.c standard vm/swap_pager.c standard vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pager.c standard vm/vm_swap.c standard vm/vm_unix.c standard vm/vnode_pager.c standard Index: head/sys/i386/conf/LINT =================================================================== --- head/sys/i386/conf/LINT (revision 25722) +++ head/sys/i386/conf/LINT (revision 25723) @@ -1,1229 +1,1236 @@ # # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.335 1997/05/10 11:16:22 jhay Exp $ +# $Id: LINT,v 1.336 1997/05/10 17:40:53 fsmp Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from # this file as required. # # # This directive is mandatory; it defines the architecture to be # configured for; in this case, the 386 family based IBM-PC and # compatibles. # machine "i386" # # This is the ``identification'' of the kernel. Usually this should # be the same as the name of your kernel. # ident LINT # # The `maxusers' parameter controls the static sizing of a number of # internal system tables by a complicated formula defined in param.c. # maxusers 10 # # Certain applications can grow to be larger than the 128M limit # that FreeBSD initially imposes. Below are some options to # allow that limit to grow to 256MB, and can be increased further # with changing the parameters. MAXDSIZ is the maximum that the # limit can be set to, and the DFLDSIZ is the default value for # the limit. You might want to set the default lower than the # max, and explicitly set the maximum with a shell command for processes # that regularly exceed the limit like INND. # options "MAXDSIZ=(256*1024*1024)" options "DFLDSIZ=(256*1024*1024)" # When this is set, be extra conservative in various parts of the kernel # and choose functionality over speed (on the widest variety of systems). options FAILSAFE # This allows you to actually store this configuration file into # the kernel binary itself, where it may be later read by saying: # strings /kernel | grep ^___ | sed -e 's/^___//' > MYKERNEL # options INCLUDE_CONFIG_FILE # Include this file in kernel # # This directive defines a number of things: # - The compiled kernel is to be called `kernel' # - The root filesystem might be on partition wd0a # - Crash dumps will be written to wd0b, if possible. Specifying the # dump device here is not recommended. Use dumpon(8). # config kernel root on wd0 dumps on wd0 ##################################################################### # SMP OPTIONS: # # SMP enables building of a Symmetric MultiProcessor Kernel. # APIC_IO enables the use of the IO APIC for Symmetric I/O. # NCPU sets the number of CPUs, defaults to 2. # NBUS sets the number of busses, defaults to 4. # NAPIC sets the number of IO APICs on the motherboard, defaults to 1. # NINTR sets the total number of INTs provided by the motherboard. # # SMP_AUTOSTART automates the startup of the additional CPUs. # SMP_PRIVPAGES maintain 'per-CPU' private data, NOT implemented yet! # # SMP_TIMER_NC is for motherboards that claim 8254 connectivity to the IO APIC, # when in fact it is NOT connected. # # Notes: # # An SMP kernel will ONLY run on an Intel MP spec. qualified motherboard. # # Be sure to disable 'cpu "I386_CPU"' && 'cpu "I486_CPU"' for SMP kernels. # # Check the 'Rogue SMP hardware' section to see if additional options # are required by your hardware. # # Mandatory: options SMP # Symmetric MultiProcessor Kernel options APIC_IO # Symmetric (APIC) I/O # Useful: options SMP_AUTOSTART # start the additional CPUs during boot # Optional, these are the defaults: #options NCPU=2 # number of CPUs #options NBUS=4 # number of busses #options NAPIC=1 # number of IO APICs #options NINTR=24 # number of INTs # Currently unusable: #options SMP_PRIVPAGES # BROKEN: architecture problem # # Rogue SMP hardware: # # Tyan Tomcat II: #options SMP_TIMER_NC # 8254 NOT connected to APIC # SuperMicro P6DNE: #options SMP_TIMER_NC # 8254 NOT connected to APIC # Bridged PCI cards: # # The MP tables of most of the current generation MP motherboards # do NOT properly support bridged PCI cards. To use one of these # cards you should refer to ??? ##################################################################### # CPU OPTIONS # # You must specify at least one CPU (the one you intend to run on); # deleting the specification for CPUs you don't need to use may make # parts of the system run faster. This is especially true removing # I386_CPU. # cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(tm) cpu "I686_CPU" # aka Pentium Pro(tm) # # Options for CPU features. # # CPU_BLUELIGHTNING_FPU_OP_CACHE enables FPU operand cache on IBM # BlueLightning CPU. It works only with Cyrix FPU, and this option # should not be used with Intel FPU. # # CPU_BLUELIGHTNING_3X enables triple-clock mode on IBM Blue Lightning # CPU if CPU supports it. The default is double-clock mode on # BlueLightning CPU box. # # CPU_BTB_EN enables branch target buffer on Cyrix 5x86 (NOTE 1). # # CPU_DISABLE_5X86_LSSER disables load store serialize (i.e. enables # reorder). This option should not be used if you use memory mapped # I/O device(s). # # CPU_FASTER_5X86_FPU enables faster FPU exception handler. # # CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products # for i386 machines. # CPU_IORT defines I/O clock delay time (NOTE 1). Default vaules of # I/O clock delay time on Cyrix 5x86 and 6x86 are 0 and 7,respectively # (no clock delay). # # CPU_LOOP_EN prevents flushing the prefetch buffer if the destination # of a jump is already present in the prefetch buffer on Cyrix 5x86(NOTE # 1). # # CPU_RSTK_EN enables return stack on Cyrix 5x86 (NOTE 1). # # CPU_SUSP_HLT enables suspend on HALT. If this option is set, CPU # enters suspend mode following execution of HALT instruction. # # CYRIX_CACHE_WORKS enables CPU cache on Cyrix 486 CPUs with cache # flush at hold state. # # CYRIX_CACHE_REALLY_WORKS enables (1) CPU cache on Cyrix 486 CPUs # without cache flush at hold state, and (2) write-back CPU cache on # Cyrix 6x86 whose revision < 2.7 (NOTE 2). # # NOTE 1: The options, CPU_BTB_EN, CPU_LOOP_EN, CPU_IORT, # CPU_LOOP_ENand CPU_RSTK_EN should no be used becasue of CPU bugs. # These options may crash your system. # # NOTE 2: If CYRIX_CACHE_REALLY_WORKS is not set, CPU cache is enabled # in write-through mode when revision < 2.7. If revision of Cyrix # 6x86 >= 2.7, CPU cache is always enabled in write-back mode. # options "CPU_BLUELIGHTNING_FPU_OP_CACHE" options "CPU_BLUELIGHTNING_3X" options "CPU_BTB_EN" options "CPU_DISABLE_5X86_LSSER" options "CPU_FASTER_5X86_FPU" options "CPU_I486_ON_386" options "CPU_IORT" options "CPU_LOOP_EN" options "CPU_RSTK_EN" options "CPU_SUSP_HLT" options "CYRIX_CACHE_WORKS" options "CYRIX_CACHE_REALLY_WORKS" # # A math emulator is mandatory if you wish to run on hardware which # does not have a floating-point processor. Pick either the original, # bogus (but freely-distributable) math emulator, or a much more # fully-featured but GPL-licensed emulator taken from Linux. # options MATH_EMULATE #Support for x87 emulation # Don't enable both of these in a real config. options GPL_MATH_EMULATE #Support for x87 emulation via #new math emulator ##################################################################### # COMPATIBILITY OPTIONS # # Implement system calls compatible with 4.3BSD and older versions of # FreeBSD. You probably do NOT want to remove this as much current code # still relies on the 4.3 emulation. # options "COMPAT_43" # # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). # options USER_LDT #allow user-level control of i386 ldt # # These three options provide support for System V Interface # Definition-style interprocess communication, in the form of shared # memory, semaphores, and message queues, respectively. # options SYSVSHM options SYSVSEM options SYSVMSG # # This option includes a MD5 routine in the kernel, this is used for # various authentication and privacy uses. # options "MD5" ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # Don't drop into DDB for a panic. Intended for unattended operation # where you may want to drop to DDB from the console, but still want # the machine to recover from a panic # options DDB_UNATTENDED # # KTRACE enables the system-call tracing facility ktrace(2). # options KTRACE #kernel tracing # # The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # options DIAGNOSTIC # # PERFMON causes the driver for Pentium/Pentium Pro performance counters # to be compiled. See perfmon(4) for more information. # options PERFMON # XXX - this doesn't belong here. # Allow ordinary users to take the console - this is useful for X. options UCONSOLE # XXX - this doesn't belong here either options USERCONFIG #boot -c editor options USERCONFIG_BOOT #imply -c and parse info area options VISUAL_USERCONFIG #visual boot -c editor ##################################################################### # NETWORKING OPTIONS # # Protocol families: # Only the INET (Internet) family is officially supported in FreeBSD. # Source code for the NS (Xerox Network Service) is provided for amusement # value. # options INET #Internet communications protocols options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) options NETATALK #Appletalk communications protocols # These are currently broken but are shipped due to interest. #options NS #Xerox NS protocols # These are currently broken and are no longer shipped due to lack # of interest. #options CCITT #X.25 network layer #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 #options LLC #X.25 link layer for Ethernets #options HDLC #X.25 link layer for serial lines #options EON #ISO CLNP over IP #options NSIP #XNS over IP # # Network interfaces: # The `loop' pseudo-device is MANDATORY when networking is enabled. # The `ether' pseudo-device provides generic code to handle # Ethernets; it is MANDATORY when a Ethernet device driver is # configured. # The 'fddi' pseudo-device provides generic code to support FDDI. # The `sppp' pseudo-device serves a similar role for certain types # of synchronous PPP links (like `cx', `ar'). # The `sl' pseudo-device implements the Serial Line IP (SLIP) service. # The `ppp' pseudo-device implements the Point-to-Point Protocol. # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be # aware of the legal and administrative consequences of enabling this # option. The number of devices determines the maximum number of # simultaneous BPF clients programs runnable. # The `disc' pseudo-device implements a minimal network interface, # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) # pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver(user process ppp) # # Internet family options: # # TCP_COMPAT_42 causes the TCP code to emulate certain bugs present in # 4.2BSD. This option should not be used unless you have a 4.2BSD # machine and TCP connections fail. # # MROUTING enables the kernel multicast packet forwarder, which works # with mrouted(8). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE sends # logged packets to the system logger. IPFIREWALL_VERBOSE_LIMIT # limits the number of times a matching entry can be logged. # # IPDIVERT enables the divert IP sockets, used by ``ipfw divert'' # # TCPDEBUG is undocumented. # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options "IPFIREWALL_VERBOSE_LIMIT=100" #limit verbosity options IPDIVERT #divert sockets options TCPDEBUG ##################################################################### # FILESYSTEM OPTIONS # # Only the root, /usr, and /tmp filesystems need be statically # compiled; everything else will be automatically loaded at mount # time. (Exception: the UFS family---FFS, MFS, and LFS---cannot # currently be demand-loaded.) Some people still prefer to statically # compile other filesystems as well. # # NB: The LFS, PORTAL, and UNION filesystems are known to be buggy, # and WILL panic your system if you attempt to do anything with them. # They are included here as an incentive for some enterprising soul to # sit down and fix them. # # Note: 4.4BSD NQNFS lease checking has relatively high cost for # _local_ I/O as well as remote I/O. Don't use it unless you will # using NQNFS. # # One of these is mandatory: options FFS #Fast filesystem options NFS #Network File System # The rest are optional: options NQNFS #Enable NQNFS lease checking # options NFS_NOSERVER #Disable the NFS-server code. options "CD9660" #ISO 9660 filesystem options FDESC #File descriptor filesystem options KERNFS #Kernel filesystem options LFS #Log filesystem options MFS #Memory File System options MSDOSFS #MS DOS File System options NULLFS #NULL filesystem options PORTAL #Portal filesystem options PROCFS #Process filesystem options UMAPFS #UID map filesystem options UNION #Union filesystem # This DEVFS is experimental but seems to work options DEVFS #devices filesystem # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. options MFS_ROOT=10 # Allow the MFS_ROOT code to load the MFS image from floppy if it is missing. options MFS_AUTOLOAD # Allow this many swap-devices. options NSWAPDEV=20 # Disk quotas are supported when this option is enabled. If you # change the value of this option, you must do a `make clean' in your # kernel compile directory in order to get a working kernel. # options QUOTA #enable disk quotas # Add more checking code to various filesystems #options NULLFS_DIAGNOSTIC #options KERNFS_DIAGNOSTIC #options UMAPFS_DIAGNOSTIC #options UNION_DIAGNOSTIC # In particular multi-session CD-Rs might require a huge amount of # time in order to "settle". If we are about mounting them as the # root f/s, we gotta wait a little. # # The number is supposed to be in seconds. options "CD9660_ROOTDELAY=20" # Add some error checking code to the null_bypass routine # in the NULL filesystem #options SAFETY ##################################################################### # SCSI DEVICES # SCSI DEVICE CONFIGURATION # The SCSI subsystem consists of the `base' SCSI code, a number of # high-level SCSI device `type' drivers, and the low-level host-adapter # device drivers. The host adapters are listed in the ISA and PCI # device configuration sections below. # # Beginning with FreeBSD 2.0.5 you can wire down your SCSI devices so # that a given bus, target, and LUN always come on line as the same # device unit. In earlier versions the unit numbers were assigned # in the order that the devices were probed on the SCSI bus. This # means that if you removed a disk drive, you may have had to rewrite # your /etc/fstab file, and also that you had to be careful when adding # a new disk as it may have been probed earlier and moved your device # configuration around. # This old behavior is maintained as the default behavior. The unit # assignment begins with the first non-wired down unit for a device # type. For example, if you wire a disk as "sd3" then the first # non-wired disk will be assigned sd4. # The syntax for wiring down devices is: # controller scbus0 at ahc0 # Single bus device # controller scbus1 at ahc1 bus 0 # Single bus device # controller scbus3 at ahc2 bus 0 # Twin bus device # controller scbus2 at ahc2 bus 1 # Twin bus device # disk sd0 at scbus0 target 0 unit 0 # disk sd1 at scbus3 target 1 # disk sd2 at scbus2 target 3 # tape st1 at scbus1 target 6 # device cd0 at scbus? # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. # All SCSI devices allocate as many units as are required. # The "unknown" device (uk? in pre-2.0.5) is now part of the base SCSI # configuration and doesn't have to be explicitly configured. controller scbus0 #base SCSI code device ch0 #SCSI media changers device sd0 #SCSI disks device st0 #SCSI tapes device cd0 #SCSI CD-ROMs device od0 #SCSI optical disk # The previous devices (ch, sd, st, cd) are recognized by config. # config doesn't (and shouldn't) know about these newer ones, # so we have to specify that they are on a SCSI bus with the "at scbus?" # clause. device worm0 at scbus? # SCSI worm device pt0 at scbus? # SCSI processor type device sctarg0 at scbus? # SCSI target # SCSI OPTIONS: # SCSIDEBUG: When defined enables debugging macros # NO_SCSI_SENSE: When defined disables sense descriptions (about 4k) # SCSI_REPORT_GEOMETRY: Always report disk geometry at boot up instead # of only when booting verbosely. options SCSIDEBUG #options NO_SCSI_SENSE options SCSI_REPORT_GEOMETRY # Options for the `od' optical disk driver: # # If drive returns sense key as 0x02 with vendor specific additional # sense code (ASC) and additional sense code qualifier (ASCQ), or # illegal ASC and ASCQ. This cause an error (NOT READY) and retrying. # To suppress this, use the following option. # options OD_BOGUS_NOT_READY # # For an automatic spindown, try this. Again, preferably as an # option in your config file. # WARNING! Use at your own risk. Joerg's ancient SONY SMO drive # groks it fine, while Shunsuke's Fujitsu chokes on it and times # out. # options OD_AUTO_TURNOFF ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS # # Of these, only the `log' device is truly mandatory. The `pty' # device usually turns out to be ``effectively mandatory'', as it is # required for `telnetd', `rlogind', `screen', `emacs', and `xterm', # among others. # If you wish to run certain # system utilities which are compressed by default (like /stand/sysinstall) # then `gzip' becomes mandatory too. # pseudo-device pty 16 #Pseudo ttys - can go as high as 256 pseudo-device speaker #Play IBM BASIC-style noises out your speaker pseudo-device log #Kernel syslog interface (/dev/klog) pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. pseudo-device ccd 4 #Concatenated disk driver # These are only for watching for bitrot in old tty code. # broken #pseudo-device tb # These are only for watching for bitrot in old SCSI code. pseudo-device su #scsi user pseudo-device ssc #super scsi ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # EISA support is available for some device, so they can be auto-probed. # Micro Channel is not supported at all. # # Mandatory ISA devices: isa, sc or vt, npx # controller isa0 # # Options for `isa': # # AUTO_EOI_1 enables the `automatic EOI' feature for the master 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # This option breaks suspend/resume on some portables. # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # BOUNCE_BUFFERS provides support for ISA DMA on machines with more # than 16 megabytes of memory. It doesn't hurt on other machines. # Some broken EISA and VLB hardware may need this, too. # # MAXMEM specifies the amount of RAM on the machine; if this is not # specified, FreeBSD will read the amount of memory from the CMOS RAM, # so the amount of memory will be limited to 64MB or 16MB depending on # the BIOS. The amount is in kilobytes, so for a machine with 128MB of # RAM, it would be 131072 (128 * 1024). # # TUNE_1542 enables the automatic ISA bus speed selection for the # Adaptec 1542 boards. Does not work for all boards, use it with caution. # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. # # PAS_JOYSTICK_ENABLE enables the gameport on the ProAudio Spectrum options "AUTO_EOI_1" #options "AUTO_EOI_2" options BOUNCE_BUFFERS options "MAXMEM=(128*1024)" #options "TUNE_1542" #options BROKEN_KEYBOARD_RESET #options PAS_JOYSTICK_ENABLE # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint options PCVT_FREEBSD=210 # pcvt running on FreeBSD >= 2.0.5 options XSERVER # include code for XFree86 options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible) - default. device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr options MAXCONS=16 # number of virtual consoles options SLOW_VGA # do byte-wide i/o's to TS and GDC regs # # `flags' for sc0: # 0x01 Use a 'visual' bell # 0x02 Use a 'blink' cursor # 0x04 Use a 'block' cursor # 0x08 Force detection of keyboard, else we always assume a keyboard # 0x10 Old-style (XT) keyboard support, useful for older ThinkPads # # The Numeric Processing eXtension driver. This should be configured if # your machine has a math co-processor, unless the coprocessor is very # buggy. If it is not configured then you *must* configure math emulation # (see above). If both npx0 and emulation are configured, then only npx0 # is used (provided it works). device npx0 at isa? port "IO_NPX" iosiz 0x0 flags 0x0 irq 13 vector npxintr # # `flags' for npx0: # 0x01 don't use the npx registers to optimize bcopy # 0x02 don't use the npx registers to optimize bzero # 0x04 don't use the npx registers to optimize copyin or copyout. # The npx registers are normally used to optimize copying and zeroing when # all of the following conditions are satisfied: # "I586_CPU" is an option # the cpu is an i586 (perhaps not a Pentium) # the probe for npx0 succeeds # INT 16 exception handling works. # Then copying and zeroing using the npx registers is normally 30-100% faster. # The flags can be used to control cases where it doesn't work or is slower. # Setting them at boot time using userconfig works right (the optimizations # are not used until later in the bootstrap when npx0 is attached). # # # `iosiz' for npx0: # This can be used instead of the MAXMEM option to set the memory size. If # it is nonzero, then it overrides both the MAXMEM option and the memory # size reported by the BIOS. Setting it at boot time using userconfig takes # effect on the next reboot after the change has been recorded in the kernel # binary (the size is used early in the boot before userconfig has a chance # to change it). # # # Optional ISA and EISA devices: # # # SCSI host adapters: `aha', `aic', `bt', `nca' # # aha: Adaptec 154x # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers # nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 # uha: UltraStore 14F and 34F # sea: Seagate ST01/02 8 bit controller (slow!) # wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. # controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr controller aic0 at isa? port 0x340 bio irq 11 vector aicintr controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr controller nca1 at isa? port 0x1f84 controller nca2 at isa? port 0x1f8c controller nca3 at isa? port 0x1e88 controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' # # NB: ``Enhanced IDE'' is NOT supported at this time. # # The flags fields are used to enable the multi-sector I/O and # the 32BIT I/O modes. The flags may be used in either the controller # definition or in the individual disk definitions. The controller # definition is supported for the boot configuration stuff. # # Each drive has a 16 bit flags value defined: # The low 8 bits are the maximum value for the multi-sector I/O, # where 0xff defaults to the maximum that the drive can handle. # The high bit of the 16 bit flags (0x8000) allows probing for # 32 bit transfers. # # The flags field for the drives can be specified in the controller # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: #controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be # allowed to probe for 32 bit transfers, but will allow multi-sector # transfers up to the maximum that the drive supports. # # controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 # # Options for `wdc': # # CMD640 enables serializing access to primary and secondary channel # of the CMD640B IDE Chip. The serializing will only take place # if this option is set *and* the chip is probed by the pci-system. # options "CMD640" #Enable work around for CMD640 h/w bug # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus options ATAPI_STATIC #Don't do it as an LKM # IDE CD-ROM driver - requires wdc controller and ATAPI option device wcd0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: #controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 tape ft0 at fdc0 drive 2 # # Options for `fd': # # FDSEEKWAIT selects a non-default head-settle time (i.e., the time to # wait after a seek is performed). The default value (1/32 s) is # usually sufficient. The units are inverse seconds, so a value of 16 # here means to wait 1/16th of a second; you should choose a power of # two. # XXX: this seems to be missing! options FDSEEKWAIT=16 # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: # port can be specified as ?, this will cause the driver to scan # the BIOS port list; # the irq and vector clauses may be omitted, this # will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports # psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) device lpt0 at isa? port? tty irq 7 vector lptintr device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr device mse0 at isa? port 0x23c tty irq 5 vector mseintr device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # Options for psm: options PSM_CHECKSYNC #checks the header byte for sync. device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr # # `flags' for serial drivers that support consoles (only for sio now): # 0x10 enable console support for this unit. The other console flags # are ignored unless this is set. Enabling console support does # not make the unit the preferred console - boot with -h or set # the 0x20 flag for that. Currently, at most one unit can have # console support; the first one (in config file order) with # this flag set is preferred. Setting this flag for sio0 gives # the old behaviour. # 0x20 force this unit to be the console (unless there is another # higher priority console). This replaces the COMCONSOLE option. # 0x40 reserve this unit for low level console operations. Do not # # Options for serial drivers that support consoles (only for sio now): options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to #DDB, if available. options CONSPEED=115200 #speed for serial console (default 9600) # Options for sio: options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs options DSI_SOFT_MODEM #code for DSI Softmodems # # Network interfaces: `cx', `ed', `el', `ep', `ie', `is', `le', `lnc' # # ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver (requires sppp) # cx: Cronyx/Sigma multiport sync/async (with Cisco or PPP framing) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) # fe: Fujitsu MB86960A/MB86965A Ethernet # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210 # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # sr: RISCom/N2 hdlc sync 1/2 port V.35/X.21 serial driver (requires sppp) # ze: IBM/National Semiconductor PCMCIA ethernet controller. # zp: 3Com PCMCIA Etherlink III (It does not require shared memory for # send/receive operation, but it needs 'iomem' to read/write the # attribute memory) # device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device eg0 at isa? port 0x310 net irq 5 vector egintr device el0 at isa? port 0x300 net irq 9 vector elintr device ep0 at isa? port 0x300 net irq 10 vector epintr device ex0 at isa? port? net irq? vector exintr device fe0 at isa? port 0x300 net irq ? vector feintr device ie0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector ieintr device ie1 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr device sr0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector srintr # Needed so that we can (bogusly) include both the dedicated PCCARD # drivers and the generic support options LINT_PCCARD_HACK device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # ATM related options # # The `en' device provides support for Efficient Networks (ENI) # ENI-155 PCI midway cards, and the Adaptec 155Mbps PCI ATM cards (ANA-59x0). # # atm pseudo-device privides generic atm functions and is required for # atm devices. # NETNATM enables the netnatm protocol family that can be used to # bypass TCP/IP. # # the current driver supports only PVC operations (no atm-arp, no multicast). # for more details, please read the original documents at # http://www.ccrc.wustl.edu/pub/chuck/bsdatm/wucs.html # pseudo-device atm device en0 device en1 options NETNATM #native ATM # # Audio drivers: `snd', `sb', `pas', `gus', `pca' # # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card # # Beware! The addresses specified below are also hard-coded in # i386/isa/sound/sound_config.h. If you change the values here, you # must also change the values in the include file. # # pca: PCM audio through your PC speaker # # If you don't have a lpt0 device at IRQ 7, you can remove the # ``conflicts'' specification in the appropriate device entries below. # # If you have a GUS-MAX card and want to use the CS4231 codec on the # card the drqs for the gus max must be 8 bit (1, 2, or 3). # # If you would like to use the full duplex option on the gus, then define # flags to be the ``read dma channel''. # # options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset # options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset # options EXCLUDE_SBPRO #PAS-16 # options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line. # PAS16: The order of the pas0/sb0/opl0 is important since the # sb emulation is enabled in the pas-16 attach. # # The i386/isa/sound/sound.doc has more information. # Controls all sound devices controller snd0 device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr device sb0 at isa? port 0x220 irq 5 conflicts drq 1 vector sbintr device sbxvi0 at isa? port? irq? drq 5 conflicts device sbmidi0 at isa? port 0x330 irq? conflicts #device awe0 at isa? port 0x620 device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr #device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr device opl0 at isa? port 0x388 conflicts device mpu0 at isa? port 0x330 irq 6 drq 0 device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # More undocumented sound devices with bogus configurations for linting. # broken #device sscape0 at isa? port 0x330 irq 6 drq 0 #device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr # Not controlled by `snd' device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM # matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # bktr: Bt848 capture boards (http://www.freebsd.org/~fsmp/HomeAuto/Bt848.html) # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # gp: National Instruments AT-GPIB and AT-GPIB/TNT board # asc: GI1904-based hand scanners, e.g. the Trust Amiscan Grey # gsc: Genius GS-4500 hand scanner. # joy: joystick # labpc: National Instrument's Lab-PC and Lab-PC+ # rc: RISCom/8 multiport card # tw: TW-523 power line interface for use with X-10 home control products # si: Specialix SI/XIO 4-32 port terminal multiplexor # stl: Stallion EasyIO and EasyConnection 8/32 (cd1400 based) # stli: Stallion EasyConnection 8/64, ONboard, Brumby (intelligent) # # Notes on APM # The flags takes the following meaning for apm0: # 0x0020 Statclock is broken. # 0x0011 Limit APM protocol to 1.1 or 1.0 # 0x0010 Limit APM protocol to 1.0 # # # Notes on the spigot: # The video spigot is at 0xad6. This port address can not be changed. # The irq values may only be 10, 11, or 15 # I/O memory is an 8kb region. Possible values are: # 0a0000, 0a2000, ..., 0fffff, f00000, f02000, ..., ffffff # The start address must be on an even boundary. # Add the following option if you want to allow non-root users to be able # to access the spigot. This option is not secure because it allows users # direct access to the I/O page. # options SPIGOT_UNSECURE # # Notes on the Digiboard driver: # # The following flag values have special meanings: # 0x01 - alternate layout of pins # 0x02 - use the windowed PC/Xe in 64K mode # Notes on the Specialix SI/XIO driver: # **This is NOT a Specialix supported Driver!** # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. # Notes on the Stallion stl and stli drivers: # See src/i386/isa/README.stl for complete instructions. # This is version 0.0.5alpha, unsupported by Stallion. # The stl driver has a secondary IO port hard coded at 0x280. You need # to change src/i386/isa/stallion.c if you reconfigure this on the boards. # The "flags" and "iosiz" settings on the stli driver depend on the board: # EasyConnection 8/64 ISA: flags 23 iosiz 0x1000 # EasyConnection 8/64 EISA: flags 24 iosiz 0x10000 # EasyConnection 8/64 MCA: flags 25 iosiz 0x1000 # ONboard ISA: flags 4 iosiz 0x10000 # ONboard EISA: flags 7 iosiz 0x10000 # ONboard MCA: flags 3 iosiz 0x10000 # Brumby: flags 2 iosiz 0x4000 # Stallion: flags 1 iosiz 0x10000 device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device qcam0 at isa? port "IO_LPT3" tty device apm0 at isa? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port "IO_GAME" device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr device rc0 at isa? port 0x220 tty irq 12 vector rcintr # the port and irq for tw0 are fictitious device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 vector siintr device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr device bqu0 at isa? port 0x150 device stl0 at isa? port 0x2a0 tty irq 10 vector stlintr device stli0 at isa? port 0x2a0 tty iomem 0xcc000 flags 23 iosiz 0x1000 # # EISA devices: # # The EISA bus device is eisa0. It provides auto-detection and # configuration support for all devices on the EISA bus. # # The `ahb' device provides support for the Adaptec 174X adapter. # # The `ahc' device provides support for the Adaptec 274X and 284X # adapters. The 284X, although a VLB card responds to EISA probes. # # fea: DEC DEFEA EISA FDDI adapter # controller eisa0 controller ahb0 controller ahc0 device fea0 # enable tagged command queuing, which is a major performance win on # devices that support it (and controllers with enough SCB's) options AHC_TAGENABLE # enable SCB paging - See the ahc.4 man page options AHC_SCBPAGING_ENABLE # The aic7xxx driver will attempt to use memory mapped I/O for all PCI # controllers that have it configured only if this option is set. Unfortunately, # this doesn't work on some motherboards, which prevents it from being the # default. options AHC_ALLOW_MEMIO # By default, only 10 EISA slots are probed, since the slot numbers # above clash with the configuration address space of the PCI subsystem, # and the EISA probe is not very smart about this. This is sufficient # for most machines, but in particular the HP NetServer LC series comes # with an onboard AIC7770 dual-channel SCSI controller on EISA slot #11, # thus you need to bump this figure to 12 for them. options "EISA_SLOTS=12" # # PCI devices: # # The main PCI bus device is `pci'. It provides auto-detection and # configuration support for all devices on the PCI bus, using either # configuration mode defined in the PCI specification. # # The `ahc' device provides support for the Adaptec 29/3940(U)(W) # and motherboard based AIC7870/AIC7880 adapters. # # The `ncr' device provides support for the NCR 53C810 and 53C825 # self-contained SCSI host adapters. # # The `amd' device provides support for the Tekram DC-390 and 390T # SCSI host adapters, but is expected to work with any AMD 53c974 # PCI SCSI chip and the AMD Ethernet+SCSI Combo chip, after some # local patches were applied to the sources (that had originally # been written by Tekram and limited to work with their SCSI cards). # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `fxp' device provides support for the Intel EtherExpress Pro/100B # PCI Fast Ethernet adapters. # # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The `meteor' device is a PCI video capture board. It can also have the # following options: # options METEOR_ALLOC_PAGES=xxx preallocate kernel pages for data entry # figure (ROWS*COLUMN*BYTES_PER_PIXEL*FRAME+PAGE_SIZE-1)/PAGE_SIZE # options METEOR_DEALLOC_PAGES remove all allocated pages on close(2) # options METEOR_DEALLOC_ABOVE=xxx remove all allocated pages above the # specified amount. If this value is below the allocated amount no action # taken # option METEOR_SYSTEM_DEFAULT={METEOR_PAL|METEOR_NTSC|METEOR_SECAM}, used # for initialization of fps routine when a signal is not present. # # The 'bktr' device is a PCI video capture board. It also has a TV tuner # on board. # controller pci0 controller ahc1 controller ncr0 controller amd0 device de0 device fxp0 device vx0 device fpa0 device meteor0 device bktr0 # # PCCARD/PCMCIA # # crd: slot controller # pcic: slots controller crd0 controller pcic0 at crd? controller pcic1 at crd? # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardware' # above. # For older notebooks that signal a powerfail condition (external # power supply dropped, or battery state low) by issuing an NMI: options POWERFAIL_NMI # make it beep instead of panicing + +# Kernel BOOTP support + +options BOOTP # Use BOOTP to obtain IP address/hostname +options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info +options "BOOTP_NFSV3" # Use NFS v3 to NFS mount root +options BOOTP_COMPAT # Workaround for broken bootp daemons. # # An obsolete option to test kern_opt.c. # options GATEWAY # More undocumented options for linting. options CLK_CALIBRATION_LOOP options "CLK_USE_I8254_CALIBRATION" options "CLK_USE_I586_CALIBRATION" options CLUSTERDEBUG options COMPAT_LINUX options DEBUG options DEVFS_ROOT options "EXT2FS" options "I586_CTR_GUPROF" options "I586_PMC_GUPROF=0x70000" options "IBCS2" options LOCKF_DEBUG options KBD_MAXRETRY=4 options KBD_MAXWAIT=6 options KBD_RESETDELAY=201 options KBDIO_DEBUG=2 options MSGMNB=2049 options MSGMNI=41 options MSGSEG=2049 options MSGSSZ=16 options MSGTQL=41 options NBUF=512 options NMBCLUSTERS=1024 options NPX_DEBUG options PSM_ACCEL=1 options PSM_DEBUG=1 options PSM_EMULATION options "SCSI_2_DEF" options SCSI_DELAY=8 # Be pessimistic about Joe SCSI device options SCSI_NCR_DEBUG options SCSI_NCR_DFLT_TAGS=4 options SCSI_NCR_MAX_SYNC=10000 options SCSI_NCR_MAX_WIDE=1 options SCSI_NCR_MYADDR=7 options SEMMAP=31 options SEMMNI=11 options SEMMNS=61 options SEMMNU=31 options SEMMSL=61 options SEMOPM=101 options SEMUME=11 options SHOW_BUSYBUFS # List buffers that prevent root unmount options SHMALL=1025 options "SHMMAX=(SHMMAXPGS*PAGE_SIZE+1)" options SHMMAXPGS=1025 options SHMMIN=2 options SHMMNI=33 options SHMSEG=9 options SI_DEBUG options SIMPLELOCK_DEBUG options SPX_HACK Index: head/sys/i386/conf/NOTES =================================================================== --- head/sys/i386/conf/NOTES (revision 25722) +++ head/sys/i386/conf/NOTES (revision 25723) @@ -1,1229 +1,1236 @@ # # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.335 1997/05/10 11:16:22 jhay Exp $ +# $Id: LINT,v 1.336 1997/05/10 17:40:53 fsmp Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from # this file as required. # # # This directive is mandatory; it defines the architecture to be # configured for; in this case, the 386 family based IBM-PC and # compatibles. # machine "i386" # # This is the ``identification'' of the kernel. Usually this should # be the same as the name of your kernel. # ident LINT # # The `maxusers' parameter controls the static sizing of a number of # internal system tables by a complicated formula defined in param.c. # maxusers 10 # # Certain applications can grow to be larger than the 128M limit # that FreeBSD initially imposes. Below are some options to # allow that limit to grow to 256MB, and can be increased further # with changing the parameters. MAXDSIZ is the maximum that the # limit can be set to, and the DFLDSIZ is the default value for # the limit. You might want to set the default lower than the # max, and explicitly set the maximum with a shell command for processes # that regularly exceed the limit like INND. # options "MAXDSIZ=(256*1024*1024)" options "DFLDSIZ=(256*1024*1024)" # When this is set, be extra conservative in various parts of the kernel # and choose functionality over speed (on the widest variety of systems). options FAILSAFE # This allows you to actually store this configuration file into # the kernel binary itself, where it may be later read by saying: # strings /kernel | grep ^___ | sed -e 's/^___//' > MYKERNEL # options INCLUDE_CONFIG_FILE # Include this file in kernel # # This directive defines a number of things: # - The compiled kernel is to be called `kernel' # - The root filesystem might be on partition wd0a # - Crash dumps will be written to wd0b, if possible. Specifying the # dump device here is not recommended. Use dumpon(8). # config kernel root on wd0 dumps on wd0 ##################################################################### # SMP OPTIONS: # # SMP enables building of a Symmetric MultiProcessor Kernel. # APIC_IO enables the use of the IO APIC for Symmetric I/O. # NCPU sets the number of CPUs, defaults to 2. # NBUS sets the number of busses, defaults to 4. # NAPIC sets the number of IO APICs on the motherboard, defaults to 1. # NINTR sets the total number of INTs provided by the motherboard. # # SMP_AUTOSTART automates the startup of the additional CPUs. # SMP_PRIVPAGES maintain 'per-CPU' private data, NOT implemented yet! # # SMP_TIMER_NC is for motherboards that claim 8254 connectivity to the IO APIC, # when in fact it is NOT connected. # # Notes: # # An SMP kernel will ONLY run on an Intel MP spec. qualified motherboard. # # Be sure to disable 'cpu "I386_CPU"' && 'cpu "I486_CPU"' for SMP kernels. # # Check the 'Rogue SMP hardware' section to see if additional options # are required by your hardware. # # Mandatory: options SMP # Symmetric MultiProcessor Kernel options APIC_IO # Symmetric (APIC) I/O # Useful: options SMP_AUTOSTART # start the additional CPUs during boot # Optional, these are the defaults: #options NCPU=2 # number of CPUs #options NBUS=4 # number of busses #options NAPIC=1 # number of IO APICs #options NINTR=24 # number of INTs # Currently unusable: #options SMP_PRIVPAGES # BROKEN: architecture problem # # Rogue SMP hardware: # # Tyan Tomcat II: #options SMP_TIMER_NC # 8254 NOT connected to APIC # SuperMicro P6DNE: #options SMP_TIMER_NC # 8254 NOT connected to APIC # Bridged PCI cards: # # The MP tables of most of the current generation MP motherboards # do NOT properly support bridged PCI cards. To use one of these # cards you should refer to ??? ##################################################################### # CPU OPTIONS # # You must specify at least one CPU (the one you intend to run on); # deleting the specification for CPUs you don't need to use may make # parts of the system run faster. This is especially true removing # I386_CPU. # cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(tm) cpu "I686_CPU" # aka Pentium Pro(tm) # # Options for CPU features. # # CPU_BLUELIGHTNING_FPU_OP_CACHE enables FPU operand cache on IBM # BlueLightning CPU. It works only with Cyrix FPU, and this option # should not be used with Intel FPU. # # CPU_BLUELIGHTNING_3X enables triple-clock mode on IBM Blue Lightning # CPU if CPU supports it. The default is double-clock mode on # BlueLightning CPU box. # # CPU_BTB_EN enables branch target buffer on Cyrix 5x86 (NOTE 1). # # CPU_DISABLE_5X86_LSSER disables load store serialize (i.e. enables # reorder). This option should not be used if you use memory mapped # I/O device(s). # # CPU_FASTER_5X86_FPU enables faster FPU exception handler. # # CPU_I486_ON_386 enables CPU cache on i486 based CPU upgrade products # for i386 machines. # CPU_IORT defines I/O clock delay time (NOTE 1). Default vaules of # I/O clock delay time on Cyrix 5x86 and 6x86 are 0 and 7,respectively # (no clock delay). # # CPU_LOOP_EN prevents flushing the prefetch buffer if the destination # of a jump is already present in the prefetch buffer on Cyrix 5x86(NOTE # 1). # # CPU_RSTK_EN enables return stack on Cyrix 5x86 (NOTE 1). # # CPU_SUSP_HLT enables suspend on HALT. If this option is set, CPU # enters suspend mode following execution of HALT instruction. # # CYRIX_CACHE_WORKS enables CPU cache on Cyrix 486 CPUs with cache # flush at hold state. # # CYRIX_CACHE_REALLY_WORKS enables (1) CPU cache on Cyrix 486 CPUs # without cache flush at hold state, and (2) write-back CPU cache on # Cyrix 6x86 whose revision < 2.7 (NOTE 2). # # NOTE 1: The options, CPU_BTB_EN, CPU_LOOP_EN, CPU_IORT, # CPU_LOOP_ENand CPU_RSTK_EN should no be used becasue of CPU bugs. # These options may crash your system. # # NOTE 2: If CYRIX_CACHE_REALLY_WORKS is not set, CPU cache is enabled # in write-through mode when revision < 2.7. If revision of Cyrix # 6x86 >= 2.7, CPU cache is always enabled in write-back mode. # options "CPU_BLUELIGHTNING_FPU_OP_CACHE" options "CPU_BLUELIGHTNING_3X" options "CPU_BTB_EN" options "CPU_DISABLE_5X86_LSSER" options "CPU_FASTER_5X86_FPU" options "CPU_I486_ON_386" options "CPU_IORT" options "CPU_LOOP_EN" options "CPU_RSTK_EN" options "CPU_SUSP_HLT" options "CYRIX_CACHE_WORKS" options "CYRIX_CACHE_REALLY_WORKS" # # A math emulator is mandatory if you wish to run on hardware which # does not have a floating-point processor. Pick either the original, # bogus (but freely-distributable) math emulator, or a much more # fully-featured but GPL-licensed emulator taken from Linux. # options MATH_EMULATE #Support for x87 emulation # Don't enable both of these in a real config. options GPL_MATH_EMULATE #Support for x87 emulation via #new math emulator ##################################################################### # COMPATIBILITY OPTIONS # # Implement system calls compatible with 4.3BSD and older versions of # FreeBSD. You probably do NOT want to remove this as much current code # still relies on the 4.3 emulation. # options "COMPAT_43" # # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). # options USER_LDT #allow user-level control of i386 ldt # # These three options provide support for System V Interface # Definition-style interprocess communication, in the form of shared # memory, semaphores, and message queues, respectively. # options SYSVSHM options SYSVSEM options SYSVMSG # # This option includes a MD5 routine in the kernel, this is used for # various authentication and privacy uses. # options "MD5" ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # Don't drop into DDB for a panic. Intended for unattended operation # where you may want to drop to DDB from the console, but still want # the machine to recover from a panic # options DDB_UNATTENDED # # KTRACE enables the system-call tracing facility ktrace(2). # options KTRACE #kernel tracing # # The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # options DIAGNOSTIC # # PERFMON causes the driver for Pentium/Pentium Pro performance counters # to be compiled. See perfmon(4) for more information. # options PERFMON # XXX - this doesn't belong here. # Allow ordinary users to take the console - this is useful for X. options UCONSOLE # XXX - this doesn't belong here either options USERCONFIG #boot -c editor options USERCONFIG_BOOT #imply -c and parse info area options VISUAL_USERCONFIG #visual boot -c editor ##################################################################### # NETWORKING OPTIONS # # Protocol families: # Only the INET (Internet) family is officially supported in FreeBSD. # Source code for the NS (Xerox Network Service) is provided for amusement # value. # options INET #Internet communications protocols options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) options NETATALK #Appletalk communications protocols # These are currently broken but are shipped due to interest. #options NS #Xerox NS protocols # These are currently broken and are no longer shipped due to lack # of interest. #options CCITT #X.25 network layer #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 #options LLC #X.25 link layer for Ethernets #options HDLC #X.25 link layer for serial lines #options EON #ISO CLNP over IP #options NSIP #XNS over IP # # Network interfaces: # The `loop' pseudo-device is MANDATORY when networking is enabled. # The `ether' pseudo-device provides generic code to handle # Ethernets; it is MANDATORY when a Ethernet device driver is # configured. # The 'fddi' pseudo-device provides generic code to support FDDI. # The `sppp' pseudo-device serves a similar role for certain types # of synchronous PPP links (like `cx', `ar'). # The `sl' pseudo-device implements the Serial Line IP (SLIP) service. # The `ppp' pseudo-device implements the Point-to-Point Protocol. # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be # aware of the legal and administrative consequences of enabling this # option. The number of devices determines the maximum number of # simultaneous BPF clients programs runnable. # The `disc' pseudo-device implements a minimal network interface, # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) # pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver(user process ppp) # # Internet family options: # # TCP_COMPAT_42 causes the TCP code to emulate certain bugs present in # 4.2BSD. This option should not be used unless you have a 4.2BSD # machine and TCP connections fail. # # MROUTING enables the kernel multicast packet forwarder, which works # with mrouted(8). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE sends # logged packets to the system logger. IPFIREWALL_VERBOSE_LIMIT # limits the number of times a matching entry can be logged. # # IPDIVERT enables the divert IP sockets, used by ``ipfw divert'' # # TCPDEBUG is undocumented. # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options "IPFIREWALL_VERBOSE_LIMIT=100" #limit verbosity options IPDIVERT #divert sockets options TCPDEBUG ##################################################################### # FILESYSTEM OPTIONS # # Only the root, /usr, and /tmp filesystems need be statically # compiled; everything else will be automatically loaded at mount # time. (Exception: the UFS family---FFS, MFS, and LFS---cannot # currently be demand-loaded.) Some people still prefer to statically # compile other filesystems as well. # # NB: The LFS, PORTAL, and UNION filesystems are known to be buggy, # and WILL panic your system if you attempt to do anything with them. # They are included here as an incentive for some enterprising soul to # sit down and fix them. # # Note: 4.4BSD NQNFS lease checking has relatively high cost for # _local_ I/O as well as remote I/O. Don't use it unless you will # using NQNFS. # # One of these is mandatory: options FFS #Fast filesystem options NFS #Network File System # The rest are optional: options NQNFS #Enable NQNFS lease checking # options NFS_NOSERVER #Disable the NFS-server code. options "CD9660" #ISO 9660 filesystem options FDESC #File descriptor filesystem options KERNFS #Kernel filesystem options LFS #Log filesystem options MFS #Memory File System options MSDOSFS #MS DOS File System options NULLFS #NULL filesystem options PORTAL #Portal filesystem options PROCFS #Process filesystem options UMAPFS #UID map filesystem options UNION #Union filesystem # This DEVFS is experimental but seems to work options DEVFS #devices filesystem # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. options MFS_ROOT=10 # Allow the MFS_ROOT code to load the MFS image from floppy if it is missing. options MFS_AUTOLOAD # Allow this many swap-devices. options NSWAPDEV=20 # Disk quotas are supported when this option is enabled. If you # change the value of this option, you must do a `make clean' in your # kernel compile directory in order to get a working kernel. # options QUOTA #enable disk quotas # Add more checking code to various filesystems #options NULLFS_DIAGNOSTIC #options KERNFS_DIAGNOSTIC #options UMAPFS_DIAGNOSTIC #options UNION_DIAGNOSTIC # In particular multi-session CD-Rs might require a huge amount of # time in order to "settle". If we are about mounting them as the # root f/s, we gotta wait a little. # # The number is supposed to be in seconds. options "CD9660_ROOTDELAY=20" # Add some error checking code to the null_bypass routine # in the NULL filesystem #options SAFETY ##################################################################### # SCSI DEVICES # SCSI DEVICE CONFIGURATION # The SCSI subsystem consists of the `base' SCSI code, a number of # high-level SCSI device `type' drivers, and the low-level host-adapter # device drivers. The host adapters are listed in the ISA and PCI # device configuration sections below. # # Beginning with FreeBSD 2.0.5 you can wire down your SCSI devices so # that a given bus, target, and LUN always come on line as the same # device unit. In earlier versions the unit numbers were assigned # in the order that the devices were probed on the SCSI bus. This # means that if you removed a disk drive, you may have had to rewrite # your /etc/fstab file, and also that you had to be careful when adding # a new disk as it may have been probed earlier and moved your device # configuration around. # This old behavior is maintained as the default behavior. The unit # assignment begins with the first non-wired down unit for a device # type. For example, if you wire a disk as "sd3" then the first # non-wired disk will be assigned sd4. # The syntax for wiring down devices is: # controller scbus0 at ahc0 # Single bus device # controller scbus1 at ahc1 bus 0 # Single bus device # controller scbus3 at ahc2 bus 0 # Twin bus device # controller scbus2 at ahc2 bus 1 # Twin bus device # disk sd0 at scbus0 target 0 unit 0 # disk sd1 at scbus3 target 1 # disk sd2 at scbus2 target 3 # tape st1 at scbus1 target 6 # device cd0 at scbus? # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. # All SCSI devices allocate as many units as are required. # The "unknown" device (uk? in pre-2.0.5) is now part of the base SCSI # configuration and doesn't have to be explicitly configured. controller scbus0 #base SCSI code device ch0 #SCSI media changers device sd0 #SCSI disks device st0 #SCSI tapes device cd0 #SCSI CD-ROMs device od0 #SCSI optical disk # The previous devices (ch, sd, st, cd) are recognized by config. # config doesn't (and shouldn't) know about these newer ones, # so we have to specify that they are on a SCSI bus with the "at scbus?" # clause. device worm0 at scbus? # SCSI worm device pt0 at scbus? # SCSI processor type device sctarg0 at scbus? # SCSI target # SCSI OPTIONS: # SCSIDEBUG: When defined enables debugging macros # NO_SCSI_SENSE: When defined disables sense descriptions (about 4k) # SCSI_REPORT_GEOMETRY: Always report disk geometry at boot up instead # of only when booting verbosely. options SCSIDEBUG #options NO_SCSI_SENSE options SCSI_REPORT_GEOMETRY # Options for the `od' optical disk driver: # # If drive returns sense key as 0x02 with vendor specific additional # sense code (ASC) and additional sense code qualifier (ASCQ), or # illegal ASC and ASCQ. This cause an error (NOT READY) and retrying. # To suppress this, use the following option. # options OD_BOGUS_NOT_READY # # For an automatic spindown, try this. Again, preferably as an # option in your config file. # WARNING! Use at your own risk. Joerg's ancient SONY SMO drive # groks it fine, while Shunsuke's Fujitsu chokes on it and times # out. # options OD_AUTO_TURNOFF ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS # # Of these, only the `log' device is truly mandatory. The `pty' # device usually turns out to be ``effectively mandatory'', as it is # required for `telnetd', `rlogind', `screen', `emacs', and `xterm', # among others. # If you wish to run certain # system utilities which are compressed by default (like /stand/sysinstall) # then `gzip' becomes mandatory too. # pseudo-device pty 16 #Pseudo ttys - can go as high as 256 pseudo-device speaker #Play IBM BASIC-style noises out your speaker pseudo-device log #Kernel syslog interface (/dev/klog) pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. pseudo-device ccd 4 #Concatenated disk driver # These are only for watching for bitrot in old tty code. # broken #pseudo-device tb # These are only for watching for bitrot in old SCSI code. pseudo-device su #scsi user pseudo-device ssc #super scsi ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # EISA support is available for some device, so they can be auto-probed. # Micro Channel is not supported at all. # # Mandatory ISA devices: isa, sc or vt, npx # controller isa0 # # Options for `isa': # # AUTO_EOI_1 enables the `automatic EOI' feature for the master 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # This option breaks suspend/resume on some portables. # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # BOUNCE_BUFFERS provides support for ISA DMA on machines with more # than 16 megabytes of memory. It doesn't hurt on other machines. # Some broken EISA and VLB hardware may need this, too. # # MAXMEM specifies the amount of RAM on the machine; if this is not # specified, FreeBSD will read the amount of memory from the CMOS RAM, # so the amount of memory will be limited to 64MB or 16MB depending on # the BIOS. The amount is in kilobytes, so for a machine with 128MB of # RAM, it would be 131072 (128 * 1024). # # TUNE_1542 enables the automatic ISA bus speed selection for the # Adaptec 1542 boards. Does not work for all boards, use it with caution. # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. # # PAS_JOYSTICK_ENABLE enables the gameport on the ProAudio Spectrum options "AUTO_EOI_1" #options "AUTO_EOI_2" options BOUNCE_BUFFERS options "MAXMEM=(128*1024)" #options "TUNE_1542" #options BROKEN_KEYBOARD_RESET #options PAS_JOYSTICK_ENABLE # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint options PCVT_FREEBSD=210 # pcvt running on FreeBSD >= 2.0.5 options XSERVER # include code for XFree86 options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible) - default. device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr options MAXCONS=16 # number of virtual consoles options SLOW_VGA # do byte-wide i/o's to TS and GDC regs # # `flags' for sc0: # 0x01 Use a 'visual' bell # 0x02 Use a 'blink' cursor # 0x04 Use a 'block' cursor # 0x08 Force detection of keyboard, else we always assume a keyboard # 0x10 Old-style (XT) keyboard support, useful for older ThinkPads # # The Numeric Processing eXtension driver. This should be configured if # your machine has a math co-processor, unless the coprocessor is very # buggy. If it is not configured then you *must* configure math emulation # (see above). If both npx0 and emulation are configured, then only npx0 # is used (provided it works). device npx0 at isa? port "IO_NPX" iosiz 0x0 flags 0x0 irq 13 vector npxintr # # `flags' for npx0: # 0x01 don't use the npx registers to optimize bcopy # 0x02 don't use the npx registers to optimize bzero # 0x04 don't use the npx registers to optimize copyin or copyout. # The npx registers are normally used to optimize copying and zeroing when # all of the following conditions are satisfied: # "I586_CPU" is an option # the cpu is an i586 (perhaps not a Pentium) # the probe for npx0 succeeds # INT 16 exception handling works. # Then copying and zeroing using the npx registers is normally 30-100% faster. # The flags can be used to control cases where it doesn't work or is slower. # Setting them at boot time using userconfig works right (the optimizations # are not used until later in the bootstrap when npx0 is attached). # # # `iosiz' for npx0: # This can be used instead of the MAXMEM option to set the memory size. If # it is nonzero, then it overrides both the MAXMEM option and the memory # size reported by the BIOS. Setting it at boot time using userconfig takes # effect on the next reboot after the change has been recorded in the kernel # binary (the size is used early in the boot before userconfig has a chance # to change it). # # # Optional ISA and EISA devices: # # # SCSI host adapters: `aha', `aic', `bt', `nca' # # aha: Adaptec 154x # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers # nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 # uha: UltraStore 14F and 34F # sea: Seagate ST01/02 8 bit controller (slow!) # wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. # controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr controller aic0 at isa? port 0x340 bio irq 11 vector aicintr controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr controller nca1 at isa? port 0x1f84 controller nca2 at isa? port 0x1f8c controller nca3 at isa? port 0x1e88 controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' # # NB: ``Enhanced IDE'' is NOT supported at this time. # # The flags fields are used to enable the multi-sector I/O and # the 32BIT I/O modes. The flags may be used in either the controller # definition or in the individual disk definitions. The controller # definition is supported for the boot configuration stuff. # # Each drive has a 16 bit flags value defined: # The low 8 bits are the maximum value for the multi-sector I/O, # where 0xff defaults to the maximum that the drive can handle. # The high bit of the 16 bit flags (0x8000) allows probing for # 32 bit transfers. # # The flags field for the drives can be specified in the controller # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: #controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be # allowed to probe for 32 bit transfers, but will allow multi-sector # transfers up to the maximum that the drive supports. # # controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 # # Options for `wdc': # # CMD640 enables serializing access to primary and secondary channel # of the CMD640B IDE Chip. The serializing will only take place # if this option is set *and* the chip is probed by the pci-system. # options "CMD640" #Enable work around for CMD640 h/w bug # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus options ATAPI_STATIC #Don't do it as an LKM # IDE CD-ROM driver - requires wdc controller and ATAPI option device wcd0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: #controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 tape ft0 at fdc0 drive 2 # # Options for `fd': # # FDSEEKWAIT selects a non-default head-settle time (i.e., the time to # wait after a seek is performed). The default value (1/32 s) is # usually sufficient. The units are inverse seconds, so a value of 16 # here means to wait 1/16th of a second; you should choose a power of # two. # XXX: this seems to be missing! options FDSEEKWAIT=16 # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: # port can be specified as ?, this will cause the driver to scan # the BIOS port list; # the irq and vector clauses may be omitted, this # will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports # psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) device lpt0 at isa? port? tty irq 7 vector lptintr device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr device mse0 at isa? port 0x23c tty irq 5 vector mseintr device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # Options for psm: options PSM_CHECKSYNC #checks the header byte for sync. device sio0 at isa? port "IO_COM1" tty flags 0x10 irq 4 vector siointr # # `flags' for serial drivers that support consoles (only for sio now): # 0x10 enable console support for this unit. The other console flags # are ignored unless this is set. Enabling console support does # not make the unit the preferred console - boot with -h or set # the 0x20 flag for that. Currently, at most one unit can have # console support; the first one (in config file order) with # this flag set is preferred. Setting this flag for sio0 gives # the old behaviour. # 0x20 force this unit to be the console (unless there is another # higher priority console). This replaces the COMCONSOLE option. # 0x40 reserve this unit for low level console operations. Do not # # Options for serial drivers that support consoles (only for sio now): options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to #DDB, if available. options CONSPEED=115200 #speed for serial console (default 9600) # Options for sio: options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs options DSI_SOFT_MODEM #code for DSI Softmodems # # Network interfaces: `cx', `ed', `el', `ep', `ie', `is', `le', `lnc' # # ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver (requires sppp) # cx: Cronyx/Sigma multiport sync/async (with Cisco or PPP framing) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) # fe: Fujitsu MB86960A/MB86965A Ethernet # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210 # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # sr: RISCom/N2 hdlc sync 1/2 port V.35/X.21 serial driver (requires sppp) # ze: IBM/National Semiconductor PCMCIA ethernet controller. # zp: 3Com PCMCIA Etherlink III (It does not require shared memory for # send/receive operation, but it needs 'iomem' to read/write the # attribute memory) # device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device eg0 at isa? port 0x310 net irq 5 vector egintr device el0 at isa? port 0x300 net irq 9 vector elintr device ep0 at isa? port 0x300 net irq 10 vector epintr device ex0 at isa? port? net irq? vector exintr device fe0 at isa? port 0x300 net irq ? vector feintr device ie0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector ieintr device ie1 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr device sr0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector srintr # Needed so that we can (bogusly) include both the dedicated PCCARD # drivers and the generic support options LINT_PCCARD_HACK device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # ATM related options # # The `en' device provides support for Efficient Networks (ENI) # ENI-155 PCI midway cards, and the Adaptec 155Mbps PCI ATM cards (ANA-59x0). # # atm pseudo-device privides generic atm functions and is required for # atm devices. # NETNATM enables the netnatm protocol family that can be used to # bypass TCP/IP. # # the current driver supports only PVC operations (no atm-arp, no multicast). # for more details, please read the original documents at # http://www.ccrc.wustl.edu/pub/chuck/bsdatm/wucs.html # pseudo-device atm device en0 device en1 options NETNATM #native ATM # # Audio drivers: `snd', `sb', `pas', `gus', `pca' # # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card # # Beware! The addresses specified below are also hard-coded in # i386/isa/sound/sound_config.h. If you change the values here, you # must also change the values in the include file. # # pca: PCM audio through your PC speaker # # If you don't have a lpt0 device at IRQ 7, you can remove the # ``conflicts'' specification in the appropriate device entries below. # # If you have a GUS-MAX card and want to use the CS4231 codec on the # card the drqs for the gus max must be 8 bit (1, 2, or 3). # # If you would like to use the full duplex option on the gus, then define # flags to be the ``read dma channel''. # # options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset # options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset # options EXCLUDE_SBPRO #PAS-16 # options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line. # PAS16: The order of the pas0/sb0/opl0 is important since the # sb emulation is enabled in the pas-16 attach. # # The i386/isa/sound/sound.doc has more information. # Controls all sound devices controller snd0 device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr device sb0 at isa? port 0x220 irq 5 conflicts drq 1 vector sbintr device sbxvi0 at isa? port? irq? drq 5 conflicts device sbmidi0 at isa? port 0x330 irq? conflicts #device awe0 at isa? port 0x620 device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr #device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr device opl0 at isa? port 0x388 conflicts device mpu0 at isa? port 0x330 irq 6 drq 0 device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # More undocumented sound devices with bogus configurations for linting. # broken #device sscape0 at isa? port 0x330 irq 6 drq 0 #device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr # Not controlled by `snd' device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM # matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # bktr: Bt848 capture boards (http://www.freebsd.org/~fsmp/HomeAuto/Bt848.html) # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # gp: National Instruments AT-GPIB and AT-GPIB/TNT board # asc: GI1904-based hand scanners, e.g. the Trust Amiscan Grey # gsc: Genius GS-4500 hand scanner. # joy: joystick # labpc: National Instrument's Lab-PC and Lab-PC+ # rc: RISCom/8 multiport card # tw: TW-523 power line interface for use with X-10 home control products # si: Specialix SI/XIO 4-32 port terminal multiplexor # stl: Stallion EasyIO and EasyConnection 8/32 (cd1400 based) # stli: Stallion EasyConnection 8/64, ONboard, Brumby (intelligent) # # Notes on APM # The flags takes the following meaning for apm0: # 0x0020 Statclock is broken. # 0x0011 Limit APM protocol to 1.1 or 1.0 # 0x0010 Limit APM protocol to 1.0 # # # Notes on the spigot: # The video spigot is at 0xad6. This port address can not be changed. # The irq values may only be 10, 11, or 15 # I/O memory is an 8kb region. Possible values are: # 0a0000, 0a2000, ..., 0fffff, f00000, f02000, ..., ffffff # The start address must be on an even boundary. # Add the following option if you want to allow non-root users to be able # to access the spigot. This option is not secure because it allows users # direct access to the I/O page. # options SPIGOT_UNSECURE # # Notes on the Digiboard driver: # # The following flag values have special meanings: # 0x01 - alternate layout of pins # 0x02 - use the windowed PC/Xe in 64K mode # Notes on the Specialix SI/XIO driver: # **This is NOT a Specialix supported Driver!** # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. # Notes on the Stallion stl and stli drivers: # See src/i386/isa/README.stl for complete instructions. # This is version 0.0.5alpha, unsupported by Stallion. # The stl driver has a secondary IO port hard coded at 0x280. You need # to change src/i386/isa/stallion.c if you reconfigure this on the boards. # The "flags" and "iosiz" settings on the stli driver depend on the board: # EasyConnection 8/64 ISA: flags 23 iosiz 0x1000 # EasyConnection 8/64 EISA: flags 24 iosiz 0x10000 # EasyConnection 8/64 MCA: flags 25 iosiz 0x1000 # ONboard ISA: flags 4 iosiz 0x10000 # ONboard EISA: flags 7 iosiz 0x10000 # ONboard MCA: flags 3 iosiz 0x10000 # Brumby: flags 2 iosiz 0x4000 # Stallion: flags 1 iosiz 0x10000 device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device qcam0 at isa? port "IO_LPT3" tty device apm0 at isa? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port "IO_GAME" device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr device rc0 at isa? port 0x220 tty irq 12 vector rcintr # the port and irq for tw0 are fictitious device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 vector siintr device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr device bqu0 at isa? port 0x150 device stl0 at isa? port 0x2a0 tty irq 10 vector stlintr device stli0 at isa? port 0x2a0 tty iomem 0xcc000 flags 23 iosiz 0x1000 # # EISA devices: # # The EISA bus device is eisa0. It provides auto-detection and # configuration support for all devices on the EISA bus. # # The `ahb' device provides support for the Adaptec 174X adapter. # # The `ahc' device provides support for the Adaptec 274X and 284X # adapters. The 284X, although a VLB card responds to EISA probes. # # fea: DEC DEFEA EISA FDDI adapter # controller eisa0 controller ahb0 controller ahc0 device fea0 # enable tagged command queuing, which is a major performance win on # devices that support it (and controllers with enough SCB's) options AHC_TAGENABLE # enable SCB paging - See the ahc.4 man page options AHC_SCBPAGING_ENABLE # The aic7xxx driver will attempt to use memory mapped I/O for all PCI # controllers that have it configured only if this option is set. Unfortunately, # this doesn't work on some motherboards, which prevents it from being the # default. options AHC_ALLOW_MEMIO # By default, only 10 EISA slots are probed, since the slot numbers # above clash with the configuration address space of the PCI subsystem, # and the EISA probe is not very smart about this. This is sufficient # for most machines, but in particular the HP NetServer LC series comes # with an onboard AIC7770 dual-channel SCSI controller on EISA slot #11, # thus you need to bump this figure to 12 for them. options "EISA_SLOTS=12" # # PCI devices: # # The main PCI bus device is `pci'. It provides auto-detection and # configuration support for all devices on the PCI bus, using either # configuration mode defined in the PCI specification. # # The `ahc' device provides support for the Adaptec 29/3940(U)(W) # and motherboard based AIC7870/AIC7880 adapters. # # The `ncr' device provides support for the NCR 53C810 and 53C825 # self-contained SCSI host adapters. # # The `amd' device provides support for the Tekram DC-390 and 390T # SCSI host adapters, but is expected to work with any AMD 53c974 # PCI SCSI chip and the AMD Ethernet+SCSI Combo chip, after some # local patches were applied to the sources (that had originally # been written by Tekram and limited to work with their SCSI cards). # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `fxp' device provides support for the Intel EtherExpress Pro/100B # PCI Fast Ethernet adapters. # # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The `meteor' device is a PCI video capture board. It can also have the # following options: # options METEOR_ALLOC_PAGES=xxx preallocate kernel pages for data entry # figure (ROWS*COLUMN*BYTES_PER_PIXEL*FRAME+PAGE_SIZE-1)/PAGE_SIZE # options METEOR_DEALLOC_PAGES remove all allocated pages on close(2) # options METEOR_DEALLOC_ABOVE=xxx remove all allocated pages above the # specified amount. If this value is below the allocated amount no action # taken # option METEOR_SYSTEM_DEFAULT={METEOR_PAL|METEOR_NTSC|METEOR_SECAM}, used # for initialization of fps routine when a signal is not present. # # The 'bktr' device is a PCI video capture board. It also has a TV tuner # on board. # controller pci0 controller ahc1 controller ncr0 controller amd0 device de0 device fxp0 device vx0 device fpa0 device meteor0 device bktr0 # # PCCARD/PCMCIA # # crd: slot controller # pcic: slots controller crd0 controller pcic0 at crd? controller pcic1 at crd? # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardware' # above. # For older notebooks that signal a powerfail condition (external # power supply dropped, or battery state low) by issuing an NMI: options POWERFAIL_NMI # make it beep instead of panicing + +# Kernel BOOTP support + +options BOOTP # Use BOOTP to obtain IP address/hostname +options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info +options "BOOTP_NFSV3" # Use NFS v3 to NFS mount root +options BOOTP_COMPAT # Workaround for broken bootp daemons. # # An obsolete option to test kern_opt.c. # options GATEWAY # More undocumented options for linting. options CLK_CALIBRATION_LOOP options "CLK_USE_I8254_CALIBRATION" options "CLK_USE_I586_CALIBRATION" options CLUSTERDEBUG options COMPAT_LINUX options DEBUG options DEVFS_ROOT options "EXT2FS" options "I586_CTR_GUPROF" options "I586_PMC_GUPROF=0x70000" options "IBCS2" options LOCKF_DEBUG options KBD_MAXRETRY=4 options KBD_MAXWAIT=6 options KBD_RESETDELAY=201 options KBDIO_DEBUG=2 options MSGMNB=2049 options MSGMNI=41 options MSGSEG=2049 options MSGSSZ=16 options MSGTQL=41 options NBUF=512 options NMBCLUSTERS=1024 options NPX_DEBUG options PSM_ACCEL=1 options PSM_DEBUG=1 options PSM_EMULATION options "SCSI_2_DEF" options SCSI_DELAY=8 # Be pessimistic about Joe SCSI device options SCSI_NCR_DEBUG options SCSI_NCR_DFLT_TAGS=4 options SCSI_NCR_MAX_SYNC=10000 options SCSI_NCR_MAX_WIDE=1 options SCSI_NCR_MYADDR=7 options SEMMAP=31 options SEMMNI=11 options SEMMNS=61 options SEMMNU=31 options SEMMSL=61 options SEMOPM=101 options SEMUME=11 options SHOW_BUSYBUFS # List buffers that prevent root unmount options SHMALL=1025 options "SHMMAX=(SHMMAXPGS*PAGE_SIZE+1)" options SHMMAXPGS=1025 options SHMMIN=2 options SHMMNI=33 options SHMSEG=9 options SI_DEBUG options SIMPLELOCK_DEBUG options SPX_HACK Index: head/sys/i386/i386/autoconf.c =================================================================== --- head/sys/i386/i386/autoconf.c (revision 25722) +++ head/sys/i386/i386/autoconf.c (revision 25723) @@ -1,445 +1,452 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.66 1997/04/26 18:57:34 peter Exp $ + * $Id: autoconf.c,v 1.67 1997/05/04 15:24:19 joerg Exp $ */ /* * Setup the system to run on the current machine. * * Configure() is called at boot time and initializes the vba * device tables and the memory controller monitoring. Available * devices are determined (from possibilities mentioned in ioconf.c), * and the drivers are initialized. */ #include "opt_smp.h" #include "opt_cd9660.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(APIC_IO) #include #endif /* APIC_IO */ #include /* For interrupts */ #include "isa.h" #if NISA > 0 #include #endif #include "eisa.h" #if NEISA > 0 #include #endif #include "pci.h" #if NPCI > 0 #include #endif #include "crd.h" #if NCRD > 0 #include #endif #include "scbus.h" #if NSCBUS > 0 #include #endif static void configure __P((void *)); SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) static void configure_finish __P((void)); static void configure_start __P((void)); static int setdumpdev __P((dev_t dev)); static void setroot __P((void)); #ifdef CD9660 #include #include #include #include #include /* * XXX All this CD-ROM root stuff is fairly messy. Ick. * * We need to try out all our potential CDROM drives, so we need a table. */ static struct { char *name; int major; } try_cdrom[] = { { "cd", 6 }, { "mcd", 7 }, { "scd", 16 }, { "matcd", 17 }, { "wcd", 19 }, { 0, 0} }; static int find_cdrom_root __P((void)); static int find_cdrom_root() { int i, j, error; struct bdevsw *bd; dev_t orootdev; #if CD9660_ROOTDELAY > 0 DELAY(CD9660_ROOTDELAY * 1000000); #endif orootdev = rootdev; for (i = 0 ; i < 2; i++) for (j = 0 ; try_cdrom[j].name ; j++) { if (try_cdrom[j].major >= nblkdev) continue; rootdev = makedev(try_cdrom[j].major, i * 8); bd = bdevsw[major(rootdev)]; if (bd == NULL || bd->d_open == NULL) continue; if (bootverbose) printf("trying %s%d as rootdev (0x%x)\n", try_cdrom[j].name, i, rootdev); error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); if (error == 0) { if (bd->d_close != NULL) (bd->d_close)(rootdev, FREAD, S_IFBLK, curproc); return 0; } } rootdev = orootdev; return EINVAL; } #endif /* CD9660 */ static void configure_start() { #if NSCBUS > 0 scsi_configure_start(); #endif } static void configure_finish() { #if NSCBUS > 0 scsi_configure_finish(); #endif } /* * Determine i/o configuration for a machine. */ static void configure(dummy) void *dummy; { int i; configure_start(); /* Allow all routines to decide for themselves if they want intrs */ #if defined(APIC_IO) configure_local_apic(); #endif /* APIC_IO */ enable_intr(); #if !defined(APIC_IO) INTREN(IRQ_SLAVE); #endif /* !APIC_IO */ #if NEISA > 0 eisa_configure(); #endif #if NPCI > 0 pci_configure(); #endif #if NISA > 0 isa_configure(); #endif #if NCRD > 0 /* After everyone else has a chance at grabbing resources */ pccard_configure(); #endif if (setdumpdev(dumpdev) != 0) dumpdev = NODEV; configure_finish(); cninit_finish(); if (bootverbose) { /* * Print out the BIOS's idea of the disk geometries. */ printf("BIOS Geometries:\n"); for (i = 0; i < N_BIOS_GEOM; i++) { unsigned long bios_geom; int max_cylinder, max_head, max_sector; bios_geom = bootinfo.bi_bios_geom[i]; /* * XXX the bootstrap punts a 1200K floppy geometry * when the get-disk-geometry interrupt fails. Skip * drives that have this geometry. */ if (bios_geom == 0x4f010f) continue; printf(" %x:%08lx ", i, bios_geom); max_cylinder = bios_geom >> 16; max_head = (bios_geom >> 8) & 0xff; max_sector = bios_geom & 0xff; printf( "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", max_cylinder, max_cylinder + 1, max_head, max_head + 1, max_sector, max_sector); } printf(" %d accounted for\n", bootinfo.bi_n_bios_used); printf("Device configuration finished.\n"); } #ifdef CD9660 if ((boothowto & RB_CDROM)) { if (bootverbose) printf("Considering CD-ROM root f/s.\n"); /* NB: find_cdrom_root() sets rootdev if successful. */ if (find_cdrom_root() == 0) mountrootfsname = "cd9660"; else if (bootverbose) printf("No CD-ROM available as root f/s.\n"); } #endif #ifdef MFS_ROOT if (!mountrootfsname) { if (bootverbose) printf("Considering MFS root f/s.\n"); mountrootfsname = "mfs"; /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif +#ifdef BOOTP_NFSROOT + if (!mountrootfsname && !nfs_diskless_valid) { + if (bootverbose) + printf("Considering BOOTP NFS root f/s.\n"); + mountrootfsname = "nfs"; + } +#endif /* BOOTP_NFSROOT */ #ifdef NFS if (!mountrootfsname && nfs_diskless_valid) { if (bootverbose) printf("Considering NFS root f/s.\n"); mountrootfsname = "nfs"; } #endif /* NFS */ #ifdef FFS if (!mountrootfsname) { mountrootfsname = "ufs"; if (bootverbose) printf("Considering FFS root f/s.\n"); /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif #ifdef LFS if (!mountrootfsname) { if (bootverbose) printf("Considering LFS root f/s.\n"); mountrootfsname = "lfs"; /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif if (!mountrootfsname) { panic("Nobody wants to mount my root for me"); } setconf(); cold = 0; if (bootverbose) printf("configure() finished.\n"); } static int setdumpdev(dev) dev_t dev; { int maj, psize; long newdumplo; if (dev == NODEV) { dumpdev = dev; return (0); } maj = major(dev); if (maj >= nblkdev) return (ENXIO); if (bdevsw[maj] == NULL) return (ENXIO); /* XXX is this right? */ if (bdevsw[maj]->d_psize == NULL) return (ENXIO); /* XXX should be ENODEV ? */ psize = bdevsw[maj]->d_psize(dev); if (psize == -1) return (ENXIO); /* XXX should be ENODEV ? */ newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; if (newdumplo < 0) return (ENOSPC); dumpdev = dev; dumplo = newdumplo; return (0); } u_long bootdev = 0; /* not a dev_t - encoding is different */ static char devname[][2] = { {'w','d'}, /* 0 = wd */ {'s','w'}, /* 1 = sw */ #define FDMAJOR 2 {'f','d'}, /* 2 = fd */ {'w','t'}, /* 3 = wt */ {'s','d'}, /* 4 = sd -- new SCSI system */ }; #define PARTITIONMASK 0x7 #define PARTITIONSHIFT 3 #define FDUNITSHIFT 6 #define RAW_PART 2 /* * Attempt to find the device from which we were booted. * If we can do so, and not instructed not to do so, * change rootdev to correspond to the load device. */ static void setroot() { int majdev, mindev, unit, part, adaptor; dev_t orootdev; /*printf("howto %x bootdev %x ", boothowto, bootdev);*/ if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) return; majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; if (majdev > sizeof(devname) / sizeof(devname[0])) return; adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; if (majdev == FDMAJOR) { part = RAW_PART; mindev = unit << FDUNITSHIFT; } else { part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; mindev = (unit << PARTITIONSHIFT) + part; } orootdev = rootdev; rootdev = makedev(majdev, mindev); /* * If the original rootdev is the same as the one * just calculated, don't need to adjust the swap configuration. */ if (rootdev == orootdev) return; printf("changing root device to %c%c%d%c\n", devname[majdev][0], devname[majdev][1], mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), part + 'a'); } static int sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS { int error; dev_t ndumpdev; ndumpdev = dumpdev; error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); if (error == 0 && req->newptr != NULL) error = setdumpdev(ndumpdev); return (error); } SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); Index: head/sys/kern/init_main.c =================================================================== --- head/sys/kern/init_main.c (revision 25722) +++ head/sys/kern/init_main.c (revision 25723) @@ -1,629 +1,636 @@ /* * Copyright (c) 1995 Terrence R. Lambert * All rights reserved. * * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)init_main.c 8.9 (Berkeley) 1/21/94 - * $Id: init_main.c,v 1.60 1997/04/07 07:15:59 peter Exp $ + * $Id: init_main.c,v 1.61 1997/04/26 11:46:11 peter Exp $ */ #include "opt_rlimit.h" #include "opt_smp.h" #include "opt_devfs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(SMP) #include #endif /* SMP */ #include #include #include #include #include #include #include #include extern struct linker_set sysinit_set; /* XXX */ extern void __main __P((void)); extern void main __P((void *framep)); extern void secondary_main __P((void)); /* Components of the first process -- never freed. */ static struct session session0; static struct pgrp pgrp0; struct proc proc0; static struct pcred cred0; static struct filedesc0 filedesc0; static struct plimit limit0; static struct vmspace vmspace0; #ifndef SMP /* per-cpu on smp */ struct proc *curproc = &proc0; #endif struct proc *initproc; int cmask = CMASK; extern struct user *proc0paddr; struct vnode *rootvp; int boothowto; struct timeval boottime; SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, CTLFLAG_RW, &boottime, timeval, ""); /* * for SMP, the runtime variable has to be per-cpu, so we use the * extern declaration in sys/kernel.h */ #ifndef SMP struct timeval runtime; #endif /* * Promiscuous argument pass for start_init() * * This is a kludge because we use a return from main() rather than a call * to a new routine in locore.s to kick the kernel alive from locore.s. */ static void *init_framep; #if __GNUC__ >= 2 void __main() {} #endif /* * This ensures that there is at least one entry so that the sysinit_set * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never * executed. */ SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL) /* * System startup; initialize the world, create process 0, mount root * filesystem, and fork to create init and pagedaemon. Most of the * hard work is done in the lower-level initialization routines including * startup(), which does memory initialization and autoconfiguration. * * This allows simple addition of new kernel subsystems that require * boot time initialization. It also allows substitution of subsystem * (for instance, a scheduler, kernel profiler, or VM system) by object * module. Finally, it allows for optional "kernel threads", like an LFS * cleaner. */ void main(framep) void *framep; { register struct sysinit **sipp; /* system initialization*/ register struct sysinit **xipp; /* interior loop of sort*/ register struct sysinit *save; /* bubble*/ int rval[2]; /* SI_TYPE_KTHREAD support*/ /* * Copy the locore.s frame pointer for proc0, this is forked into * all other processes. */ init_framep = framep; /* * Perform a bubble sort of the system initialization objects by * their subsystem (primary key) and order (secondary key). * * Since some things care about execution order, this is the * operation which ensures continued function. */ for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) { for( xipp = sipp + 1; *xipp; xipp++) { if( (*sipp)->subsystem < (*xipp)->subsystem || ( (*sipp)->subsystem == (*xipp)->subsystem && (*sipp)->order < (*xipp)->order)) continue; /* skip*/ save = *sipp; *sipp = *xipp; *xipp = save; } } /* * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. * * The last item on the list is expected to be the scheduler, * which will not return. */ for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) { if( (*sipp)->subsystem == SI_SUB_DUMMY) continue; /* skip dummy task(s)*/ switch( (*sipp)->type) { case SI_TYPE_DEFAULT: /* no special processing*/ (*((*sipp)->func))( (*sipp)->udata); break; case SI_TYPE_KTHREAD: /* kernel thread*/ if (fork(&proc0, NULL, rval)) panic("fork kernel process"); cpu_set_fork_handler(pfind(rval[0]), (*sipp)->func, (*sipp)->udata); break; default: panic( "init_main: unrecognized init type"); } } panic("Shouldn't get here!"); /* NOTREACHED*/ } /* * Start a kernel process. This is called after a fork() call in * main() in the file kern/init_main.c. * * This function is used to start "internal" daemons. */ /* ARGSUSED*/ void kproc_start(udata) void *udata; { struct kproc_desc *kp = udata; struct proc *p = curproc; #ifdef DIAGNOSTIC printf("Start pid=%d <%s>\n",p->p_pid, kp->arg0); #endif /* save a global descriptor, if desired*/ if( kp->global_procpp != NULL) *kp->global_procpp = p; /* this is a non-swapped system process*/ p->p_flag |= P_INMEM | P_SYSTEM; /* set up arg0 for 'ps', et al*/ strcpy( p->p_comm, kp->arg0); /* call the processes' main()...*/ (*kp->func)(); /* NOTREACHED */ panic("kproc_start: %s", kp->arg0); } /* *************************************************************************** **** **** The following SYSINIT's belong elsewhere, but have not yet **** been moved. **** *************************************************************************** */ #ifdef OMIT /* * Handled by vfs_mountroot (bad idea) at this time... should be * done the same as 4.4Lite2. */ SYSINIT(swapinit, SI_SUB_SWAP, SI_ORDER_FIRST, swapinit, NULL) #endif /* OMIT*/ static void print_caddr_t __P((void *data)); static void print_caddr_t(data) void *data; { printf("%s", (char *)data); } SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) /* *************************************************************************** **** **** The two following SYSINT's are proc0 specific glue code. I am not **** convinced that they can not be safely combined, but their order of **** operation has been maintained as the same as the original init_main.c **** for right now. **** **** These probably belong in init_proc.c or kern_proc.c, since they **** deal with proc0 (the fork template process). **** *************************************************************************** */ /* ARGSUSED*/ static void proc0_init __P((void *dummy)); static void proc0_init(dummy) void *dummy; { register struct proc *p; register struct filedesc0 *fdp; register unsigned i; /* * Initialize the current process pointer (curproc) before * any possible traps/probes to simplify trap processing. */ p = &proc0; curproc = p; /* XXX redundant*/ /* * Initialize process and pgrp structures. */ procinit(); /* * Initialize sleep queue hash table */ sleepinit(); /* * Create process 0 (the swapper). */ LIST_INSERT_HEAD(&allproc, p, p_list); p->p_pgrp = &pgrp0; LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); LIST_INIT(&pgrp0.pg_members); LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); pgrp0.pg_session = &session0; session0.s_count = 1; session0.s_leader = p; p->p_sysent = &aout_sysvec; p->p_flag = P_INMEM | P_SYSTEM; p->p_stat = SRUN; p->p_nice = NZERO; p->p_rtprio.type = RTP_PRIO_NORMAL; p->p_rtprio.prio = 0; bcopy("swapper", p->p_comm, sizeof ("swapper")); /* Create credentials. */ cred0.p_refcnt = 1; p->p_cred = &cred0; p->p_ucred = crget(); p->p_ucred->cr_ngroups = 1; /* group 0 */ /* Create the file descriptor table. */ fdp = &filedesc0; p->p_fd = &fdp->fd_fd; fdp->fd_fd.fd_refcnt = 1; fdp->fd_fd.fd_cmask = cmask; fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; fdp->fd_fd.fd_nfiles = NDFILE; /* Create the limits structures. */ p->p_limit = &limit0; for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) limit0.pl_rlimit[i].rlim_cur = limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles; limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc; i = ptoa(cnt.v_free_count); limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; limit0.p_refcnt = 1; /* Allocate a prototype map so we have something to fork. */ p->p_vmspace = &vmspace0; vmspace0.vm_refcnt = 1; pmap_pinit(&vmspace0.vm_pmap); vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS), trunc_page(VM_MAXUSER_ADDRESS), TRUE); vmspace0.vm_map.pmap = &vmspace0.vm_pmap; p->p_addr = proc0paddr; /* XXX */ #define INCOMPAT_LITES2 #ifdef INCOMPAT_LITES2 /* * proc0 needs to have a coherent frame base in it's stack. */ cpu_set_init_frame(p, init_framep); /* XXX! */ #endif /* INCOMPAT_LITES2*/ /* * We continue to place resource usage info and signal * actions in the user struct so they're pageable. */ p->p_stats = &p->p_addr->u_stats; p->p_sigacts = &p->p_addr->u_sigacts; /* * Charge root for one process. */ (void)chgproccnt(0, 1); } SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) /* ARGSUSED*/ static void proc0_post __P((void *dummy)); static void proc0_post(dummy) void *dummy; { struct timeval tv; /* * Now can look at time, having had a chance to verify the time * from the file system. Reset p->p_rtime as it may have been * munched in mi_switch() after the time got set. */ gettime(&boottime); proc0.p_stats->p_start = runtime = mono_time = boottime; proc0.p_rtime.tv_sec = proc0.p_rtime.tv_usec = 0; /* * Give the ``random'' number generator a thump. */ microtime(&tv); srandom(tv.tv_sec ^ tv.tv_usec); /* Initialize signal state for process 0. */ siginit(&proc0); } SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) /* *************************************************************************** **** **** The following SYSINIT's and glue code should be moved to the **** respective files on a per subsystem basis. **** *************************************************************************** */ /* ARGSUSED*/ static void sched_setup __P((void *dummy)); static void sched_setup(dummy) void *dummy; { /* Kick off timeout driven events by calling first time. */ roundrobin(NULL); schedcpu(NULL); } SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL) /* ARGSUSED*/ static void xxx_vfs_mountroot __P((void *fsnamep)); +#ifdef BOOTP +extern void bootpc_init __P((void)); +#endif static void xxx_vfs_mountroot(fsnamep) void *fsnamep; { + /* XXX Add a separate SYSINIT entry */ +#ifdef BOOTP + bootpc_init(); +#endif /* Mount the root file system. */ if (vfs_mountrootfs(*((char **) fsnamep))) panic("cannot mount root"); } SYSINIT(mountroot, SI_SUB_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot, &mountrootfsname) /* ARGSUSED*/ static void xxx_vfs_root_fdtab __P((void *dummy)); static void xxx_vfs_root_fdtab(dummy) void *dummy; { register struct filedesc0 *fdp = &filedesc0; /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ if (VFS_ROOT(mountlist.cqh_first, &rootvnode)) panic("cannot find root vnode"); fdp->fd_fd.fd_cdir = rootvnode; VREF(fdp->fd_fd.fd_cdir); VOP_UNLOCK(rootvnode, 0, &proc0); fdp->fd_fd.fd_rdir = NULL; } SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL) /* *************************************************************************** **** **** The following code probably belongs in another file, like **** kern/init_init.c. It is here for two reasons only: **** **** 1) This code returns to startup the system; this is **** abnormal for a kernel thread. **** 2) This code promiscuously uses init_frame **** *************************************************************************** */ static void kthread_init __P((void *dummy)); SYSINIT_KT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kthread_init, NULL) extern void prepare_usermode __P((void)); static void start_init __P((struct proc *p)); /* ARGSUSED*/ static void kthread_init(dummy) void *dummy; { /* Create process 1 (init(8)). */ start_init(curproc); prepare_usermode(); /* * This returns to the fork trampoline, then to user mode. */ return; } /* * List of paths to try when searching for "init". */ static char *initpaths[] = { "/sbin/init", "/sbin/oinit", "/sbin/init.bak", "/stand/sysinstall", NULL, }; /* * Start the initial user process; try exec'ing each pathname in "initpaths". * The program is invoked with one argument containing the boot flags. */ static void start_init(p) struct proc *p; { vm_offset_t addr; struct execve_args args; int options, i, retval[2], error; char **pathp, *path, *ucp, **uap, *arg0, *arg1; initproc = p; /* * Need just enough stack to hold the faked-up "execve()" arguments. */ addr = trunc_page(VM_MAXUSER_ADDRESS - PAGE_SIZE); if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) panic("init: couldn't allocate argument space"); p->p_vmspace->vm_maxsaddr = (caddr_t)addr; p->p_vmspace->vm_ssize = 1; for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { /* * Move out the boot flag argument. */ options = 0; ucp = (char *)USRSTACK; (void)subyte(--ucp, 0); /* trailing zero */ if (boothowto & RB_SINGLE) { (void)subyte(--ucp, 's'); options = 1; } #ifdef notyet if (boothowto & RB_FASTBOOT) { (void)subyte(--ucp, 'f'); options = 1; } #endif #ifdef BOOTCDROM (void)subyte(--ucp, 'C'); options = 1; #endif #if defined(DEVFS) && defined(DEVFS_ROOT) (void)subyte(--ucp, 'd'); options = 1; #endif if (options == 0) (void)subyte(--ucp, '-'); (void)subyte(--ucp, '-'); /* leading hyphen */ arg1 = ucp; /* * Move out the file name (also arg 0). */ for (i = strlen(path) + 1; i >= 0; i--) (void)subyte(--ucp, path[i]); arg0 = ucp; /* * Move out the arg pointers. */ uap = (char **)((int)ucp & ~(NBPW-1)); (void)suword((caddr_t)--uap, 0); /* terminator */ (void)suword((caddr_t)--uap, (int)arg1); (void)suword((caddr_t)--uap, (int)arg0); /* * Point at the arguments. */ args.fname = arg0; args.argv = uap; args.envv = NULL; /* * Now try to exec the program. If can't for any reason * other than it doesn't exist, complain. * * Otherwise return to main() which returns to btext * which completes the system startup. */ if ((error = execve(p, &args, &retval[0])) == 0) return; if (error != ENOENT) printf("exec %s: error %d\n", path, error); } printf("init: not found\n"); panic("no init"); } Index: head/sys/netinet/ip_input.c =================================================================== --- head/sys/netinet/ip_input.c (revision 25722) +++ head/sys/netinet/ip_input.c (revision 25723) @@ -1,1435 +1,1439 @@ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * $Id: ip_input.c,v 1.1.1.2 1997/04/03 10:39:25 darrenr Exp $ + * $Id: ip_input.c,v 1.61 1997/04/03 10:47:10 darrenr Exp $ * $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $ */ #define _IP_VHL #include "opt_ipfw.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef IPFIREWALL #include #endif int rsvp_on = 0; static int ip_rsvp_on; struct socket *ip_rsvpd; static int ipforwarding = 0; SYSCTL_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW, &ipforwarding, 0, ""); static int ipsendredirects = 1; /* XXX */ SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW, &ipsendredirects, 0, ""); int ip_defttl = IPDEFTTL; SYSCTL_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_RW, &ip_defttl, 0, ""); static int ip_dosourceroute = 0; SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW, &ip_dosourceroute, 0, ""); #ifdef DIAGNOSTIC static int ipprintfs = 0; #endif extern struct domain inetdomain; extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; static int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddrhead in_ifaddrhead; /* first inet address */ struct ifqueue ipintrq; SYSCTL_INT(_net_inet_ip, IPCTL_INTRQMAXLEN, intr_queue_maxlen, CTLFLAG_RD, &ipintrq.ifq_maxlen, 0, ""); SYSCTL_INT(_net_inet_ip, IPCTL_INTRQDROPS, intr_queue_drops, CTLFLAG_RD, &ipintrq.ifq_drops, 0, ""); struct ipstat ipstat; static struct ipq ipq; #ifdef IPCTL_DEFMTU SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW, &ip_mtu, 0, ""); #endif #if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1 #undef COMPAT_IPFW #define COMPAT_IPFW 1 #else #undef COMPAT_IPFW #endif #ifdef COMPAT_IPFW /* Firewall hooks */ ip_fw_chk_t *ip_fw_chk_ptr; ip_fw_ctl_t *ip_fw_ctl_ptr; /* IP Network Address Translation (NAT) hooks */ ip_nat_t *ip_nat_ptr; ip_nat_ctl_t *ip_nat_ctl_ptr; #endif #if defined(IPFILTER_LKM) || defined(IPFILTER) int fr_check __P((struct ip *, int, struct ifnet *, int, struct mbuf **)); int (*fr_checkp) __P((struct ip *, int, struct ifnet *, int, struct mbuf **)) = NULL; #endif /* * We need to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here * using IP source routing. This allows connection establishment and * maintenance when the remote end is on a network that is not known * to us. */ static int ip_nhops = 0; static struct ip_srcrt { struct in_addr dst; /* final destination */ char nop; /* one NOP to align */ char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */ struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; } ip_srcrt; #ifdef IPDIVERT /* * Shared variable between ip_input() and ip_reass() to communicate * about which packets, once assembled from fragments, get diverted, * and to which port. */ static u_short frag_divert_port; #endif static void save_rte __P((u_char *, struct in_addr)); static void ip_deq __P((struct ipasfrag *)); static int ip_dooptions __P((struct mbuf *)); static void ip_enq __P((struct ipasfrag *, struct ipasfrag *)); static void ip_forward __P((struct mbuf *, int)); static void ip_freef __P((struct ipq *)); static struct ip * ip_reass __P((struct ipasfrag *, struct ipq *)); static struct in_ifaddr * ip_rtaddr __P((struct in_addr)); static void ipintr __P((void)); /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ void ip_init() { register struct protosw *pr; register int i; TAILQ_INIT(&in_ifaddrhead); pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == 0) panic("ip_init"); for (i = 0; i < IPPROTO_MAX; i++) ip_protox[i] = pr - inetsw; for (pr = inetdomain.dom_protosw; pr < inetdomain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) ip_protox[pr->pr_protocol] = pr - inetsw; ipq.next = ipq.prev = &ipq; ip_id = time.tv_sec & 0xffff; ipintrq.ifq_maxlen = ipqmaxlen; #ifdef IPFIREWALL ip_fw_init(); #endif #ifdef IPNAT ip_nat_init(); #endif } static struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; static struct route ipforward_rt; /* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ void ip_input(struct mbuf *m) { struct ip *ip; struct ipq *fp; struct in_ifaddr *ia; int hlen; u_short sum; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ip_input no HDR"); #endif /* * If no IP addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. * XXX This is broken! We should be able to receive broadcasts * and multicasts even without any local addresses configured. */ if (TAILQ_EMPTY(&in_ifaddrhead)) goto bad; ipstat.ips_total++; if (m->m_pkthdr.len < sizeof(struct ip)) goto tooshort; #ifdef DIAGNOSTIC if (m->m_len < sizeof(struct ip)) panic("ipintr mbuf too short"); #endif if (m->m_len < sizeof (struct ip) && (m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; return; } ip = mtod(m, struct ip *); if (IP_VHL_V(ip->ip_vhl) != IPVERSION) { ipstat.ips_badvers++; goto bad; } hlen = IP_VHL_HL(ip->ip_vhl) << 2; if (hlen < sizeof(struct ip)) { /* minimum header length */ ipstat.ips_badhlen++; goto bad; } if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == 0) { ipstat.ips_badhlen++; return; } ip = mtod(m, struct ip *); } if (hlen == sizeof(struct ip)) { sum = in_cksum_hdr(ip); } else { sum = in_cksum(m, hlen); } if (sum) { ipstat.ips_badsum++; goto bad; } /* * Convert fields to host representation. */ NTOHS(ip->ip_len); if (ip->ip_len < hlen) { ipstat.ips_badlen++; goto bad; } NTOHS(ip->ip_id); NTOHS(ip->ip_off); /* * Check that the amount of data in the buffers * is as at least much as the IP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if (m->m_pkthdr.len < ip->ip_len) { tooshort: ipstat.ips_tooshort++; goto bad; } if (m->m_pkthdr.len > ip->ip_len) { if (m->m_len == m->m_pkthdr.len) { m->m_len = ip->ip_len; m->m_pkthdr.len = ip->ip_len; } else m_adj(m, ip->ip_len - m->m_pkthdr.len); } /* * IpHack's section. * Right now when no processing on packet has done * and it is still fresh out of network we do our black * deals with it. * - Firewall: deny/allow/divert * - Xlate: translate packet's addr/port (NAT). * - Wrap: fake packet's addr/port * - Encapsulate: put it in another IP and send out. */ #if defined(IPFILTER) || defined(IPFILTER_LKM) /* * Check if we want to allow this packet to be processed. * Consider it to be bad if not. */ if (fr_check) { struct mbuf *m1 = m; if ((*fr_checkp)(ip, hlen, m->m_pkthdr.rcvif, 0, &m1) || !m1) return; ip = mtod(m = m1, struct ip *); } #endif #ifdef COMPAT_IPFW if (ip_fw_chk_ptr) { int action; #ifdef IPDIVERT action = (*ip_fw_chk_ptr)(&ip, hlen, m->m_pkthdr.rcvif, ip_divert_ignore, &m); ip_divert_ignore = 0; #else action = (*ip_fw_chk_ptr)(&ip, hlen, m->m_pkthdr.rcvif, 0, &m); #endif if (action == -1) return; if (action != 0) { #ifdef IPDIVERT frag_divert_port = action; goto ours; #else goto bad; /* ipfw said divert but we can't */ #endif } } if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, m->m_pkthdr.rcvif, IP_NAT_IN)) return; #endif /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message * to be sent and the original packet to be freed). */ ip_nhops = 0; /* for source routed packets */ if (hlen > sizeof (struct ip) && ip_dooptions(m)) return; /* greedy RSVP, snatches any PATH packet of the RSVP protocol and no * matter if it is destined to another node, or whether it is * a multicast one, RSVP wants it! and prevents it from being forwarded * anywhere else. Also checks if the rsvp daemon is running before * grabbing the packet. */ if (rsvp_on && ip->ip_p==IPPROTO_RSVP) goto ours; /* * Check our list of addresses, to see if the packet is for us. */ for (ia = in_ifaddrhead.tqh_first; ia; ia = ia->ia_link.tqe_next) { #define satosin(sa) ((struct sockaddr_in *)(sa)) if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; +#ifdef BOOTP_COMPAT + if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY) + goto ours; +#endif if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) { if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr) goto ours; } } if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { struct in_multi *inm; if (ip_mrouter) { /* * If we are acting as a multicast router, all * incoming multicast packets are passed to the * kernel-level multicast forwarding function. * The packet is returned (relatively) intact; if * ip_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. * * (The IP ident field is put in the same byte order * as expected when ip_mforward() is called from * ip_output().) */ ip->ip_id = htons(ip->ip_id); if (ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) { ipstat.ips_cantforward++; m_freem(m); return; } ip->ip_id = ntohs(ip->ip_id); /* * The process-level routing demon needs to receive * all multicast IGMP packets, whether or not this * host belongs to their destination groups. */ if (ip->ip_p == IPPROTO_IGMP) goto ours; ipstat.ips_forward++; } /* * See if we belong to the destination multicast group on the * arrival interface. */ IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); if (inm == NULL) { ipstat.ips_notmember++; m_freem(m); return; } goto ours; } if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST) goto ours; if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; /* * Not for us; forward if possible and desirable. */ if (ipforwarding == 0) { ipstat.ips_cantforward++; m_freem(m); } else ip_forward(m, 0); return; ours: /* * If offset or IP_MF are set, must reassemble. * Otherwise, nothing need be done. * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ if (ip->ip_off & (IP_MF | IP_OFFMASK)) { if (m->m_flags & M_EXT) { /* XXX */ if ((m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; #ifdef IPDIVERT frag_divert_port = 0; #endif return; } ip = mtod(m, struct ip *); } /* * Look for queue of fragments * of this datagram. */ for (fp = ipq.next; fp != &ipq; fp = fp->next) if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_p == fp->ipq_p) goto found; fp = 0; found: /* * Adjust ip_len to not reflect header, * set ip_mff if more fragments are expected, * convert offset of this to bytes. */ ip->ip_len -= hlen; ((struct ipasfrag *)ip)->ipf_mff &= ~1; if (ip->ip_off & IP_MF) ((struct ipasfrag *)ip)->ipf_mff |= 1; ip->ip_off <<= 3; /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { ipstat.ips_fragments++; ip = ip_reass((struct ipasfrag *)ip, fp); if (ip == 0) return; ipstat.ips_reassembled++; m = dtom(ip); } else if (fp) ip_freef(fp); } else ip->ip_len -= hlen; #ifdef IPDIVERT /* * Divert packets here to the divert protocol if required */ if (frag_divert_port) { ip_divert_port = frag_divert_port; frag_divert_port = 0; (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, hlen); return; } #endif /* * Switch out to protocol's input routine. */ ipstat.ips_delivered++; (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); return; bad: m_freem(m); } /* * IP software interrupt routine - to go away sometime soon */ static void ipintr(void) { int s; struct mbuf *m; while(1) { s = splimp(); IF_DEQUEUE(&ipintrq, m); splx(s); if (m == 0) return; ip_input(m); } } NETISR_SET(NETISR_IP, ipintr); /* * Take incoming datagram fragment and try to * reassemble it into whole datagram. If a chain for * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ static struct ip * ip_reass(ip, fp) register struct ipasfrag *ip; register struct ipq *fp; { register struct mbuf *m = dtom(ip); register struct ipasfrag *q; struct mbuf *t; int hlen = ip->ip_hl << 2; int i, next; /* * Presence of header sizes in mbufs * would confuse code below. */ m->m_data += hlen; m->m_len -= hlen; /* * If first fragment to arrive, create a reassembly queue. */ if (fp == 0) { if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) goto dropfrag; fp = mtod(t, struct ipq *); insque(fp, &ipq); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp; fp->ipq_src = ((struct ip *)ip)->ip_src; fp->ipq_dst = ((struct ip *)ip)->ip_dst; #ifdef IPDIVERT fp->ipq_divert = 0; #endif q = (struct ipasfrag *)fp; goto insert; } /* * Find a segment which begins after this one does. */ for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) if (q->ip_off > ip->ip_off) break; /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ if (q->ipf_prev != (struct ipasfrag *)fp) { i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off; if (i > 0) { if (i >= ip->ip_len) goto dropfrag; m_adj(dtom(ip), i); ip->ip_off += i; ip->ip_len -= i; } } /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { struct mbuf *m0; i = (ip->ip_off + ip->ip_len) - q->ip_off; if (i < q->ip_len) { q->ip_len -= i; q->ip_off += i; m_adj(dtom(q), i); break; } m0 = dtom(q); q = q->ipf_next; ip_deq(q->ipf_prev); m_freem(m0); } insert: #ifdef IPDIVERT /* * Any fragment diverting causes the whole packet to divert */ if (frag_divert_port != 0) fp->ipq_divert = frag_divert_port; frag_divert_port = 0; #endif /* * Stick new segment in its place; * check for complete reassembly. */ ip_enq(ip, q->ipf_prev); next = 0; for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { if (q->ip_off != next) return (0); next += q->ip_len; } if (q->ipf_prev->ipf_mff & 1) return (0); /* * Reassembly is complete. Make sure the packet is a sane size. */ if (next + (IP_VHL_HL(((struct ip *)fp->ipq_next)->ip_vhl) << 2) > IP_MAXPACKET) { ipstat.ips_toolong++; ip_freef(fp); return (0); } /* * Concatenate fragments. */ q = fp->ipq_next; m = dtom(q); t = m->m_next; m->m_next = 0; m_cat(m, t); q = q->ipf_next; while (q != (struct ipasfrag *)fp) { t = dtom(q); q = q->ipf_next; m_cat(m, t); } #ifdef IPDIVERT /* * Record divert port for packet, if any */ frag_divert_port = fp->ipq_divert; #endif /* * Create header for new ip packet by * modifying header of first packet; * dequeue and discard fragment reassembly header. * Make header visible. */ ip = fp->ipq_next; ip->ip_len = next; ip->ipf_mff &= ~1; ((struct ip *)ip)->ip_src = fp->ipq_src; ((struct ip *)ip)->ip_dst = fp->ipq_dst; remque(fp); (void) m_free(dtom(fp)); m = dtom(ip); m->m_len += (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2); /* some debugging cruft by sklower, below, will go away soon */ if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */ register int plen = 0; for (t = m; m; m = m->m_next) plen += m->m_len; t->m_pkthdr.len = plen; } return ((struct ip *)ip); dropfrag: ipstat.ips_fragdropped++; m_freem(m); return (0); } /* * Free a fragment reassembly header and all * associated datagrams. */ static void ip_freef(fp) struct ipq *fp; { register struct ipasfrag *q, *p; for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) { p = q->ipf_next; ip_deq(q); m_freem(dtom(q)); } remque(fp); (void) m_free(dtom(fp)); } /* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ static void ip_enq(p, prev) register struct ipasfrag *p, *prev; { p->ipf_prev = prev; p->ipf_next = prev->ipf_next; prev->ipf_next->ipf_prev = p; prev->ipf_next = p; } /* * To ip_enq as remque is to insque. */ static void ip_deq(p) register struct ipasfrag *p; { p->ipf_prev->ipf_next = p->ipf_next; p->ipf_next->ipf_prev = p->ipf_prev; } /* * IP timer processing; * if a timer expires on a reassembly * queue, discard it. */ void ip_slowtimo() { register struct ipq *fp; int s = splnet(); fp = ipq.next; if (fp == 0) { splx(s); return; } while (fp != &ipq) { --fp->ipq_ttl; fp = fp->next; if (fp->prev->ipq_ttl == 0) { ipstat.ips_fragtimeout++; ip_freef(fp->prev); } } splx(s); } /* * Drain off all datagram fragments. */ void ip_drain() { while (ipq.next != &ipq) { ipstat.ips_fragdropped++; ip_freef(ipq.next); } in_rtqdrain(); } /* * Do option processing on a datagram, * possibly discarding it if bad options are encountered, * or forwarding it if source-routed. * Returns 1 if packet has been forwarded/freed, * 0 if the packet should be processed further. */ static int ip_dooptions(m) struct mbuf *m; { register struct ip *ip = mtod(m, struct ip *); register u_char *cp; register struct ip_timestamp *ipt; register struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; struct in_addr *sin, dst; n_time ntime; dst = ip->ip_dst; cp = (u_char *)(ip + 1); cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else { optlen = cp[IPOPT_OLEN]; if (optlen <= 0 || optlen > cnt) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } } switch (opt) { default: break; /* * Source routing with record. * Find interface with current destination address. * If none on this machine then drop if strictly routed, * or do nothing if loosely routed. * Record interface address and bring up next address * component. If strictly routed make sure next * address is on directly accessible net. */ case IPOPT_LSRR: case IPOPT_SSRR: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } ipaddr.sin_addr = ip->ip_dst; ia = (struct in_ifaddr *) ifa_ifwithaddr((struct sockaddr *)&ipaddr); if (ia == 0) { if (opt == IPOPT_SSRR) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } /* * Loose routing, and not at next destination * yet; nothing to do except forward. */ break; } off--; /* 0 origin */ if (off > optlen - sizeof(struct in_addr)) { /* * End of source route. Should be for us. */ save_rte(cp, ip->ip_src); break; } if (!ip_dosourceroute) { char buf[4*sizeof "123"]; strcpy(buf, inet_ntoa(ip->ip_dst)); log(LOG_WARNING, "attempted source route from %s to %s\n", inet_ntoa(ip->ip_src), buf); type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } /* * locate outgoing interface */ (void)memcpy(&ipaddr.sin_addr, cp + off, sizeof(ipaddr.sin_addr)); if (opt == IPOPT_SSRR) { #define INA struct in_ifaddr * #define SA struct sockaddr * if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) ia = (INA)ifa_ifwithnet((SA)&ipaddr); } else ia = ip_rtaddr(ipaddr.sin_addr); if (ia == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } ip->ip_dst = ipaddr.sin_addr; (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); /* * Let ip_intr's mcast routing check handle mcast pkts */ forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); break; case IPOPT_RR: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } /* * If no space remains, ignore. */ off--; /* 0 origin */ if (off > optlen - sizeof(struct in_addr)) break; (void)memcpy(&ipaddr.sin_addr, &ip->ip_dst, sizeof(ipaddr.sin_addr)); /* * locate outgoing interface; if we're the destination, * use the incoming interface (should be same). */ if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; } (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; case IPOPT_TS: code = cp - (u_char *)ip; ipt = (struct ip_timestamp *)cp; if (ipt->ipt_len < 5) goto bad; if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) { if (++ipt->ipt_oflw == 0) goto bad; break; } sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); switch (ipt->ipt_flg) { case IPOPT_TS_TSONLY: break; case IPOPT_TS_TSANDADDR: if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; ipaddr.sin_addr = dst; ia = (INA)ifaof_ifpforaddr((SA)&ipaddr, m->m_pkthdr.rcvif); if (ia == 0) continue; (void)memcpy(sin, &IA_SIN(ia)->sin_addr, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); break; case IPOPT_TS_PRESPEC: if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; (void)memcpy(&ipaddr.sin_addr, sin, sizeof(struct in_addr)); if (ifa_ifwithaddr((SA)&ipaddr) == 0) continue; ipt->ipt_ptr += sizeof(struct in_addr); break; default: goto bad; } ntime = iptime(); (void)memcpy(cp + ipt->ipt_ptr - 1, &ntime, sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); } } if (forward) { ip_forward(m, 1); return (1); } return (0); bad: ip->ip_len -= IP_VHL_HL(ip->ip_vhl) << 2; /* XXX icmp_error adds in hdr length */ icmp_error(m, type, code, 0, 0); ipstat.ips_badoptions++; return (1); } /* * Given address of next destination (final or next hop), * return internet address info of interface to be used to get there. */ static struct in_ifaddr * ip_rtaddr(dst) struct in_addr dst; { register struct sockaddr_in *sin; sin = (struct sockaddr_in *) &ipforward_rt.ro_dst; if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) { if (ipforward_rt.ro_rt) { RTFREE(ipforward_rt.ro_rt); ipforward_rt.ro_rt = 0; } sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = dst; rtalloc_ign(&ipforward_rt, RTF_PRCLONING); } if (ipforward_rt.ro_rt == 0) return ((struct in_ifaddr *)0); return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa); } /* * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */ void save_rte(option, dst) u_char *option; struct in_addr dst; { unsigned olen; olen = option[IPOPT_OLEN]; #ifdef DIAGNOSTIC if (ipprintfs) printf("save_rte: olen %d\n", olen); #endif if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) return; bcopy(option, ip_srcrt.srcopt, olen); ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); ip_srcrt.dst = dst; } /* * Retrieve incoming source route for use in replies, * in the same form used by setsockopt. * The first hop is placed before the options, will be removed later. */ struct mbuf * ip_srcroute() { register struct in_addr *p, *q; register struct mbuf *m; if (ip_nhops == 0) return ((struct mbuf *)0); m = m_get(M_DONTWAIT, MT_SOOPTS); if (m == 0) return ((struct mbuf *)0); #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) + OPTSIZ; #ifdef DIAGNOSTIC if (ipprintfs) printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len); #endif /* * First save first hop for return route */ p = &ip_srcrt.route[ip_nhops - 1]; *(mtod(m, struct in_addr *)) = *p--; #ifdef DIAGNOSTIC if (ipprintfs) printf(" hops %lx", ntohl(mtod(m, struct in_addr *)->s_addr)); #endif /* * Copy option fields and padding (nop) to mbuf. */ ip_srcrt.nop = IPOPT_NOP; ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; (void)memcpy(mtod(m, caddr_t) + sizeof(struct in_addr), &ip_srcrt.nop, OPTSIZ); q = (struct in_addr *)(mtod(m, caddr_t) + sizeof(struct in_addr) + OPTSIZ); #undef OPTSIZ /* * Record return path as an IP source route, * reversing the path (pointers are now aligned). */ while (p >= ip_srcrt.route) { #ifdef DIAGNOSTIC if (ipprintfs) printf(" %lx", ntohl(q->s_addr)); #endif *q++ = *p--; } /* * Last hop goes to final destination. */ *q = ip_srcrt.dst; #ifdef DIAGNOSTIC if (ipprintfs) printf(" %lx\n", ntohl(q->s_addr)); #endif return (m); } /* * Strip out IP options, at higher * level protocol in the kernel. * Second argument is buffer to which options * will be moved, and return value is their length. * XXX should be deleted; last arg currently ignored. */ void ip_stripoptions(m, mopt) register struct mbuf *m; struct mbuf *mopt; { register int i; struct ip *ip = mtod(m, struct ip *); register caddr_t opts; int olen; olen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip); opts = (caddr_t)(ip + 1); i = m->m_len - (sizeof (struct ip) + olen); bcopy(opts + olen, opts, (unsigned)i); m->m_len -= olen; if (m->m_flags & M_PKTHDR) m->m_pkthdr.len -= olen; ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2); } u_char inetctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, EHOSTUNREACH, 0, 0, 0, 0, 0, 0, ENOPROTOOPT }; /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful * icmp message because icmp doesn't have a large enough repertoire * of codes and types. * * If not forwarding, just drop the packet. This could be confusing * if ipforwarding was zero but some routing protocol was advancing * us as a gateway to somewhere. However, we must let the routing * protocol deal with that. * * The srcrt parameter indicates whether the packet is being forwarded * via a source route. */ static void ip_forward(m, srcrt) struct mbuf *m; int srcrt; { register struct ip *ip = mtod(m, struct ip *); register struct sockaddr_in *sin; register struct rtentry *rt; int error, type = 0, code = 0; struct mbuf *mcopy; n_long dest; struct ifnet *destifp; dest = 0; #ifdef DIAGNOSTIC if (ipprintfs) printf("forward: src %lx dst %lx ttl %x\n", ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl); #endif if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) { ipstat.ips_cantforward++; m_freem(m); return; } HTONS(ip->ip_id); if (ip->ip_ttl <= IPTTLDEC) { icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); return; } ip->ip_ttl -= IPTTLDEC; sin = (struct sockaddr_in *)&ipforward_rt.ro_dst; if ((rt = ipforward_rt.ro_rt) == 0 || ip->ip_dst.s_addr != sin->sin_addr.s_addr) { if (ipforward_rt.ro_rt) { RTFREE(ipforward_rt.ro_rt); ipforward_rt.ro_rt = 0; } sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; rtalloc_ign(&ipforward_rt, RTF_PRCLONING); if (ipforward_rt.ro_rt == 0) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); return; } rt = ipforward_rt.ro_rt; } /* * Save at most 64 bytes of the packet in case * we need to generate an ICMP message to the src. */ mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64)); /* * If forwarding packet using same interface that it came in on, * perhaps should send a redirect to sender to shortcut a hop. * Only send redirect if source is sending directly to us, * and if packet was not source routed (or has any options). * Also, don't send redirect if forwarding using a default route * or a route modified by a redirect. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) if (rt->rt_ifp == m->m_pkthdr.rcvif && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(rt_key(rt))->sin_addr.s_addr != 0 && ipsendredirects && !srcrt) { #define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) u_long src = ntohl(ip->ip_src.s_addr); if (RTA(rt) && (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) { if (rt->rt_flags & RTF_GATEWAY) dest = satosin(rt->rt_gateway)->sin_addr.s_addr; else dest = ip->ip_dst.s_addr; /* Router requirements says to only send host redirects */ type = ICMP_REDIRECT; code = ICMP_REDIRECT_HOST; #ifdef DIAGNOSTIC if (ipprintfs) printf("redirect (%d) to %lx\n", code, (u_long)dest); #endif } } error = ip_output(m, (struct mbuf *)0, &ipforward_rt, IP_FORWARDING, 0); if (error) ipstat.ips_cantforward++; else { ipstat.ips_forward++; if (type) ipstat.ips_redirectsent++; else { if (mcopy) m_freem(mcopy); return; } } if (mcopy == NULL) return; destifp = NULL; switch (error) { case 0: /* forwarded, but need redirect */ /* type, code set above */ break; case ENETUNREACH: /* shouldn't happen, checked above */ case EHOSTUNREACH: case ENETDOWN: case EHOSTDOWN: default: type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; break; case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; if (ipforward_rt.ro_rt) destifp = ipforward_rt.ro_rt->rt_ifp; ipstat.ips_cantfrag++; break; case ENOBUFS: type = ICMP_SOURCEQUENCH; code = 0; break; } icmp_error(mcopy, type, code, dest, destifp); } void ip_savecontrol(inp, mp, ip, m) register struct inpcb *inp; register struct mbuf **mp; register struct ip *ip; register struct mbuf *m; { if (inp->inp_socket->so_options & SO_TIMESTAMP) { struct timeval tv; microtime(&tv); *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVDSTADDR) { *mp = sbcreatecontrol((caddr_t) &ip->ip_dst, sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } #ifdef notyet /* XXX * Moving these out of udp_input() made them even more broken * than they already were. */ /* options were tossed already */ if (inp->inp_flags & INP_RECVOPTS) { *mp = sbcreatecontrol((caddr_t) opts_deleted_above, sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } /* ip_srcroute doesn't do what we want here, need to fix */ if (inp->inp_flags & INP_RECVRETOPTS) { *mp = sbcreatecontrol((caddr_t) ip_srcroute(), sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } #endif if (inp->inp_flags & INP_RECVIF) { struct sockaddr_dl sdl; sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]); sdl.sdl_family = AF_LINK; sdl.sdl_index = m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0; sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0; *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len, IP_RECVIF, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } } int ip_rsvp_init(struct socket *so) { if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) return EOPNOTSUPP; if (ip_rsvpd != NULL) return EADDRINUSE; ip_rsvpd = so; /* * This may seem silly, but we need to be sure we don't over-increment * the RSVP counter, in case something slips up. */ if (!ip_rsvp_on) { ip_rsvp_on = 1; rsvp_on++; } return 0; } int ip_rsvp_done(void) { ip_rsvpd = NULL; /* * This may seem silly, but we need to be sure we don't over-decrement * the RSVP counter, in case something slips up. */ if (ip_rsvp_on) { ip_rsvp_on = 0; rsvp_on--; } return 0; } Index: head/sys/nfs/bootp_subr.c =================================================================== --- head/sys/nfs/bootp_subr.c (nonexistent) +++ head/sys/nfs/bootp_subr.c (revision 25723) @@ -0,0 +1,1319 @@ +/* $Id:$ */ + +/* + * Copyright (c) 1995 Gordon Ross, Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * based on: + * nfs/krpc_subr.c + * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */ + +/* + * What is the longest we will wait before re-sending a request? + * Note this is also the frequency of "RPC timeout" messages. + * The re-send loop count sup linearly to this maximum, so the + * first complaint will happen after (1+2+3+4+5)=15 seconds. + */ +#define MAX_RESEND_DELAY 5 /* seconds */ + +/* Definitions from RFC951 */ +struct bootp_packet { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + struct in_addr ciaddr; + struct in_addr yiaddr; + struct in_addr siaddr; + struct in_addr giaddr; + unsigned char chaddr[16]; + char sname[64]; + char file[128]; + unsigned char vend[256]; +}; + +#define IPPORT_BOOTPC 68 +#define IPPORT_BOOTPS 67 + +extern int nfs_diskless_valid; +extern struct nfsv3_diskless nfsv3_diskless; + +/* mountd RPC */ +static int md_mount __P((struct sockaddr_in *mdsin, char *path, + u_char *fhp, int *fhsizep, struct nfs_args *args,struct proc *procp)); +static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path, + u_char *fhp, int *fhsizep, + struct nfs_args *args, + struct proc *procp)); + +#ifdef BOOTP_DEBUG +void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma); +void bootpboot_p_ma(struct sockaddr *ma); +void bootpboot_p_rtentry(struct rtentry *rt); +void bootpboot_p_tree(struct radix_node *rn); +void bootpboot_p_rtlist(void); +void bootpboot_p_iflist(void); +#endif + +int bootpc_call(struct bootp_packet *call, + struct bootp_packet *reply, + struct proc *procp); + +int bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, + struct proc *procp); + +int +bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, + struct sockaddr_in *myaddr, + struct sockaddr_in *netmask, + struct sockaddr_in *gw, + struct proc *procp); + +void bootpc_init(void); + +#ifdef BOOTP_DEBUG +void bootpboot_p_sa(sa,ma) + struct sockaddr *sa; + struct sockaddr *ma; +{ + if (!sa) { + printf("(sockaddr *) "); + return; + } + switch (sa->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + printf("inet %x",ntohl(sin->sin_addr.s_addr)); + if (ma) { + struct sockaddr_in *sin = (struct sockaddr_in *) ma; + printf(" mask %x",ntohl(sin->sin_addr.s_addr)); + } + } + break; + case AF_LINK: + { + struct sockaddr_dl *sli = (struct sockaddr_dl *) sa; + int i; + printf("link %.*s ",sli->sdl_nlen,sli->sdl_data); + for (i=0;isdl_alen;i++) { + if (i>0) + printf(":"); + printf("%x",(unsigned char) sli->sdl_data[i+sli->sdl_nlen]); + } + } + break; + default: + printf("af%d",sa->sa_family); + } +} + +void bootpboot_p_ma(ma) + struct sockaddr *ma; +{ + if (!ma) { + printf(""); + return; + } + printf("%x",*(int*)ma); +} + +void bootpboot_p_rtentry(rt) + struct rtentry *rt; +{ + bootpboot_p_sa(rt_key(rt),rt_mask(rt)); + printf(" "); + bootpboot_p_ma(rt->rt_genmask); + printf(" "); + bootpboot_p_sa(rt->rt_gateway,NULL); + printf(" "); + printf("flags %x",(unsigned short) rt->rt_flags); + printf(" %d",rt->rt_rmx.rmx_expire); + printf(" %s%d\n",rt->rt_ifp->if_name,rt->rt_ifp->if_unit); +} +void bootpboot_p_tree(rn) + struct radix_node *rn; +{ + while (rn) { + if (rn->rn_b < 0) { + if (rn->rn_flags & RNF_ROOT) { + } else { + bootpboot_p_rtentry((struct rtentry *) rn); + } + rn = rn->rn_dupedkey; + } else { + bootpboot_p_tree(rn->rn_l); + bootpboot_p_tree(rn->rn_r); + return; + } + + } +} + +void bootpboot_p_rtlist(void) +{ + printf("Routing table:\n"); + bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); +} + +void bootpboot_p_iflist(void) +{ + struct ifnet *ifp; + struct ifaddr *ifa; + printf("Interface list:\n"); + for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) + { + for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; + ifa=TAILQ_NEXT(ifa,ifa_link)) + if (ifa->ifa_addr->sa_family == AF_INET ) { + printf("%s%d flags %x, addr %x, bcast %x, net %x\n", + ifp->if_name,ifp->if_unit, + (unsigned short) ifp->if_flags, + ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr), + ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr), + ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr) + ); + } + } +} +#endif + +int +bootpc_call(call,reply,procp) + struct bootp_packet *call; + struct bootp_packet *reply; /* output */ + struct proc *procp; +{ + struct socket *so; + struct sockaddr_in *sin,sa; + struct mbuf *m, *nam; + struct uio auio; + struct iovec aio; + int error, rcvflg, timo, secs, len; + u_int tport; + + /* Free at end if not null. */ + nam = NULL; + + /* + * Create socket and set its recieve timeout. + */ + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp))) + goto out; + + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } else { + struct timeval *tv; + tv = mtod(m, struct timeval *); + m->m_len = sizeof(*tv); + tv->tv_sec = 1; + tv->tv_usec = 0; + if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m, procp))) + goto out; + } + + /* + * Enable broadcast. + */ + { + int *on; + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + on = mtod(m, int *); + m->m_len = sizeof(*on); + *on = 1; + if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m, procp))) + goto out; + } + + /* + * Bind the local endpoint to a bootp client port. + */ + m = m_getclr(M_WAIT, MT_SONAME); + sin = mtod(m, struct sockaddr_in *); + sin->sin_len = m->m_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + sin->sin_port = htons(IPPORT_BOOTPC); + error = sobind(so, m, procp); + m_freem(m); + if (error) { + printf("bind failed\n"); + goto out; + } + + /* + * Setup socket address for the server. + */ + nam = m_get(M_WAIT, MT_SONAME); + if (nam == NULL) { + error = ENOBUFS; + goto out; + } + sin = mtod(nam, struct sockaddr_in *); + sin-> sin_len = sizeof(*sin); + sin-> sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_BROADCAST; + sin->sin_port = htons(IPPORT_BOOTPS); + + nam->m_len = sizeof(*sin); + + /* + * Send it, repeatedly, until a reply is received, + * but delay each re-send by an increasing amount. + * If the delay hits the maximum, start complaining. + */ + timo = 0; + for (;;) { + /* Send BOOTP request (or re-send). */ + + aio.iov_base = (caddr_t) call; + aio.iov_len = sizeof(*call); + + auio.uio_iov = &aio; + auio.uio_iovcnt = 1; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_offset = 0; + auio.uio_resid = sizeof(*call); + auio.uio_procp = procp; + + error = sosend(so, nam, &auio, NULL, NULL, 0); + if (error) { + printf("bootpc_call: sosend: %d\n", error); + goto out; + } + + /* Determine new timeout. */ + if (timo < MAX_RESEND_DELAY) + timo++; + else + printf("BOOTP timeout for server 0x%x\n", + ntohl(sin->sin_addr.s_addr)); + + /* + * Wait for up to timo seconds for a reply. + * The socket receive timeout was set to 1 second. + */ + secs = timo; + while (secs > 0) { + aio.iov_base = (caddr_t) reply; + aio.iov_len = sizeof(*reply); + + auio.uio_iov = &aio; + auio.uio_iovcnt = 1; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_READ; + auio.uio_offset = 0; + auio.uio_resid = sizeof(*reply); + auio.uio_procp = procp; + + rcvflg = 0; + error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg); + if (error == EWOULDBLOCK) { + secs--; + call->secs=htons(ntohs(call->secs)+1); + continue; + } + if (error) + goto out; + len = sizeof(*reply) - auio.uio_resid; + + /* Does the reply contain at least a header? */ + if (len < MIN_REPLY_HDR) + continue; + + /* Is it the right reply? */ + if (reply->op != 2) + continue; + + if (reply->xid != call->xid) + continue; + + if (reply->hlen != call->hlen) + continue; + + if (bcmp(reply->chaddr,call->chaddr,call->hlen)) + continue; + + goto gotreply; /* break two levels */ + + } /* while secs */ + } /* forever send/receive */ + + error = ETIMEDOUT; + goto out; + + gotreply: + out: + if (nam) m_freem(nam); + soclose(so); + return error; +} + +int +bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, + struct proc *procp) +{ + struct sockaddr_in *sin; + int error; + struct sockaddr_in dst; + struct sockaddr_in gw; + struct sockaddr_in mask; + + /* + * Bring up the interface. + * + * Get the old interface flags and or IFF_UP into them; if + * IFF_UP set blindly, interface selection can be clobbered. + */ + error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); + ireq->ifr_flags |= IFF_UP; + error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); + + /* + * Do enough of ifconfig(8) so that the chosen interface + * can talk to the servers. (just set the address) + */ + + /* addr is 0.0.0.0 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if addr, error=%d", error); + + /* netmask is 0.0.0.0 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if net addr, error=%d", error); + + /* Broadcast is 255.255.255.255 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_BROADCAST; + error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error); + + /* Add default route to 0.0.0.0 so we can send data */ + + bzero((caddr_t) &dst, sizeof(dst)); + dst.sin_len=sizeof(dst); + dst.sin_family=AF_INET; + dst.sin_addr.s_addr = htonl(0); + + bzero((caddr_t) &gw, sizeof(gw)); + gw.sin_len=sizeof(gw); + gw.sin_family=AF_INET; + gw.sin_addr.s_addr = htonl(0x0); + + bzero((caddr_t) &mask, sizeof(mask)); + mask.sin_len=sizeof(mask); + mask.sin_family=AF_INET; + mask.sin_addr.s_addr = htonl(0); + + error = rtrequest(RTM_ADD, + (struct sockaddr *) &dst, + (struct sockaddr *) &gw, + (struct sockaddr *) &mask, + RTF_UP | RTF_STATIC + , NULL); + if (error) + printf("bootpc_fakeup_interface: add default route, error=%d\n", error); + return error; +} + +int +bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, + struct sockaddr_in *myaddr, + struct sockaddr_in *netmask, + struct sockaddr_in *gw, + struct proc *procp) +{ + int error; + struct sockaddr_in oldgw; + struct sockaddr_in olddst; + struct sockaddr_in oldmask; + struct sockaddr_in *sin; + + /* Remove old default route to 0.0.0.0 */ + + bzero((caddr_t) &olddst, sizeof(olddst)); + olddst.sin_len=sizeof(olddst); + olddst.sin_family=AF_INET; + olddst.sin_addr.s_addr = INADDR_ANY; + + bzero((caddr_t) &oldgw, sizeof(oldgw)); + oldgw.sin_len=sizeof(oldgw); + oldgw.sin_family=AF_INET; + oldgw.sin_addr.s_addr = INADDR_ANY; + + bzero((caddr_t) &oldmask, sizeof(oldmask)); + oldmask.sin_len=sizeof(oldmask); + oldmask.sin_family=AF_INET; + oldmask.sin_addr.s_addr = INADDR_ANY; + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) &olddst, + (struct sockaddr *) &oldgw, + (struct sockaddr *) &oldmask, + (RTF_UP | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del default route, error=%d\n", error); + return error; + } + +#if 0 + olddst.sin_addr.s_addr = INADDR_BROADCAST; + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) &olddst, + (struct sockaddr *) &oldgw, + (struct sockaddr *) NULL, + (RTF_UP | RTF_HOST | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del broadcast route, error=%d\n", error); + } +#endif + + /* + * Do enough of ifconfig(8) so that the chosen interface + * can talk to the servers. (just set the address) + */ + bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask)); + error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); + if (error) + panic("nfs_boot: set if netmask, error=%d", error); + + /* Broadcast is with host part of IP address all 1's */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr; + error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_call: set if broadcast addr, error=%d", error); + + bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr)); + error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); + if (error) + panic("nfs_boot: set if addr, error=%d", error); + + /* Add new default route */ + + error = rtrequest(RTM_ADD, + (struct sockaddr *) &olddst, + (struct sockaddr *) gw, + (struct sockaddr *) &oldmask, + (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: add net route, error=%d\n", error); + return error; + } + +#if 0 + /* Remove default gateway arp entry. This is a kludge, but + somehow the arp entry is added without an arp request + being sent, causing outgoing packets to be dropped onto the floor */ + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) gw, + (struct sockaddr *) NULL, + (struct sockaddr *) NULL, + (RTF_UP | RTF_HOST | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del default gateway linklevel route, error=%d\n", error); + } +#endif + + return 0; +} + +void bootp_expand_path(char *str,size_t len,char *hostname, + struct in_addr addr); +void bootp_expand_path(char *str,size_t len,char *hostname, + struct in_addr addr) +{ + char tmpbuf[128]; + char tmpaddr[20]; + + char *p,*q,*savep; + q = tmpbuf; + + savep = NULL; + sprintf(tmpaddr,"%d.%d.%d.%d", + ((unsigned char *) &addr)[0], + ((unsigned char *) &addr)[1], + ((unsigned char *) &addr)[2], + ((unsigned char *) &addr)[3]); + + for (p=str;*p;) { + switch(*p) { + case '%': + if (!savep) { + switch(*++p) { + case 'H': + savep = ++p; + p= hostname; + break; + case 'I': + savep = ++p; + p = tmpaddr; + break; + default: + goto arnej; + } + break; + } + default: + arnej: + if (q+1>=tmpbuf+sizeof(tmpbuf)) + panic("bootp_expand_path: Cannot expand %s\n",str); + else + *q++ = *p++; + if (!*p && savep) { + p = savep; + savep = NULL; + } + } + } + *q++ = 0; + if (q-tmpbuf>len) { + panic("bootp_expand_path: Too long expansion: %s\n",tmpbuf); + } + strcpy(str,tmpbuf); +} + +void +bootpc_init(void) +{ + struct bootp_packet call; + struct bootp_packet reply; + static u_int32_t xid = ~0xFF; + + struct ifreq ireq; + struct ifnet *ifp; + struct socket *so; + int error; + int code,len; + int i,j; + char rootpath[65]; + char swappath[65]; + + struct sockaddr_in myaddr; + struct sockaddr_in netmask; + struct sockaddr_in gw; + struct sockaddr_in server; + int gotgw=0; + int gotnetmask=0; + int gotserver=0; + int gotrootpath=0; + int gotswappath=0; + +#define EALEN 6 + unsigned char ea[EALEN]; + struct ifaddr *ifa; + struct sockaddr_dl *sdl = NULL; + char *delim; + + struct nfsv3_diskless *nd = &nfsv3_diskless; + struct proc *procp = curproc; + + /* + * If already filled in, don't touch it here + */ + if (nfs_diskless_valid) + return; + + /* + * Bump time if 0. + */ + if (!time.tv_sec) + time.tv_sec++; + + /* + * Find a network interface. + */ + for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) + if ((ifp->if_flags & + (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) + break; + if (ifp == NULL) + panic("bootpc_init: no suitable interface"); + bzero(&ireq,sizeof(ireq)); + sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit); + strcpy(nd->myif.ifra_name,ireq.ifr_name); + printf("bootpc_init: using network interface '%s'\n", + ireq.ifr_name); + + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) + panic("nfs_boot: socreate, error=%d", error); + + bootpc_fakeup_interface(&ireq,so,procp); + + printf("Bootpc testing starting\n"); + + /* Get HW address */ + + for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; + ifa=TAILQ_NEXT(ifa,ifa_link)) + if (ifa->ifa_addr->sa_family == AF_LINK && + (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) && + sdl->sdl_type == IFT_ETHER) + break; + + if (!sdl) + panic("bootpc: Unable to find HW address"); + if (sdl->sdl_alen != EALEN ) + panic("bootpc: HW address len is %d, expected value is %d", + sdl->sdl_alen,EALEN); +#if 1 + printf("bootpc hw address is "); + delim=""; + for (j=0;jsdl_alen;j++) { + printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]); + delim=":"; + } + printf("\n"); +#endif + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + + bzero((caddr_t) &call, sizeof(call)); + + /* bootpc part */ + call.op = 1; /* BOOTREQUEST */ + call.htype= 1; /* 10mb ethernet */ + call.hlen=sdl->sdl_alen; /* Hardware address length */ + call.hops=0; + xid++; + call.xid = txdr_unsigned(xid); + bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen); + + call.vend[0]=99; + call.vend[1]=130; + call.vend[2]=83; + call.vend[3]=99; + call.vend[4]=255; + + call.secs = 0; + call.flags = htons(0x8000); /* We need an broadcast answer */ + + error = bootpc_call(&call,&reply,procp); + + if (error) { +#ifdef BOOTP_NFSROOT + panic("BOOTP call failed"); +#endif + return; + } + + bzero(&myaddr,sizeof(myaddr)); + bzero(&netmask,sizeof(netmask)); + bzero(&gw,sizeof(gw)); + bzero(&server,sizeof(server)); + + myaddr.sin_len = sizeof(myaddr); + myaddr.sin_family = AF_INET; + + netmask.sin_len = sizeof(netmask); + netmask.sin_family = AF_INET; + + gw.sin_len = sizeof(gw); + gw.sin_family= AF_INET; + + server.sin_len = sizeof(gw); + server.sin_family= AF_INET; + + printf("My new ip address is %x\n",htonl(reply.yiaddr.s_addr)); + + myaddr.sin_addr = reply.yiaddr; + + printf("Server ip address is %x\n",htonl(reply.siaddr.s_addr)); + printf("Gateway ip address is %x\n",htonl(reply.giaddr.s_addr)); + + gw.sin_addr = reply.giaddr; + + if (reply.sname[0]) + printf("Server name is %s\n",reply.sname); + if (reply.file[0]) + printf("boot file is %s\n",reply.file); + if (reply.vend[0]==99 && reply.vend[1]==130 && + reply.vend[2]==83 && reply.vend[3]==99) { + j=4; + while (j=sizeof(reply.vend)) { + printf("Truncated field"); + break; + } + switch (code) { + case 1: + if (len!=4) + panic("bootpc: subnet mask len is %d",len); + bcopy(&reply.vend[j],&netmask.sin_addr,4); + gotnetmask=1; + printf("Subnet mask is %d.%d.%d.%d\n", + reply.vend[j], + reply.vend[j+1], + reply.vend[j+2], + reply.vend[j+3]); + break; + case 2: + /* Time offset */ + break; + case 3: + /* Routers */ + if (len % 4) + panic("bootpc: Router Len is %d",len); + if (len > 0) { + bcopy(&reply.vend[j],&gw.sin_addr,4); + gotgw=1; + } + for (i=0;i=sizeof(rootpath)) + panic("bootpc: rootpath >=%d bytes",sizeof(rootpath)); + strncpy(rootpath,&reply.vend[j],len); + rootpath[len]=0; + gotrootpath=1; + printf("Rootpath is %s\n",rootpath); + break; + case 12: + if (len>=MAXHOSTNAMELEN) + panic("bootpc: hostname >=%d bytes",MAXHOSTNAMELEN); + strncpy(nd->my_hostnam,&reply.vend[j],len); + nd->my_hostnam[len]=0; + strncpy(hostname,&reply.vend[j],len); + hostname[len]=0; + printf("Hostname is %s\n",hostname); + break; + case 128: + if (len>=sizeof(swappath)) + panic("bootpc: swappath >=%d bytes",sizeof(swappath)); + strncpy(swappath,&reply.vend[j],len); + swappath[len]=0; + gotswappath=1; + printf("Swappath is %s\n",swappath); + break; + case 129: + { + int swaplen; + if (len!=4) + panic("bootpc: Expected 4 bytes for swaplen, not %d bytes",len); + bcopy(&reply.vend[j],&swaplen,4); + nd->swap_nblks = ntohl(swaplen); + printf("bootpc: Swap size is %d KB\n",nd->swap_nblks); + } + break; + default: + printf("Ignoring field type %d\n",code); + } + j+=len; + } + } + + if (gotrootpath) { + bootp_expand_path(rootpath,sizeof(rootpath), + hostname, + myaddr.sin_addr); + printf("Rootpath is expanded to %s\n",rootpath); + if (gotswappath) { + bootp_expand_path(swappath,sizeof(swappath), + hostname, + myaddr.sin_addr); + printf("Swappath is expanded to %s\n",swappath); + } + else + nd->swap_nblks = 0; + } else { +#ifdef BOOTP_NFSROOT + panic("bootpc: No root path offered"); +#endif + } + + if (!gotserver) { + server.sin_addr = reply.siaddr ; + } + + if (!gotnetmask) { + if (IN_CLASSA(myaddr.sin_addr.s_addr)) + netmask.sin_addr.s_addr = IN_CLASSA_NET; + else if (IN_CLASSB(myaddr.sin_addr.s_addr)) + netmask.sin_addr.s_addr = IN_CLASSB_NET; + else + netmask.sin_addr.s_addr = IN_CLASSC_NET; + } + if (!gotgw) { + /* Use proxyarp */ + gw.sin_addr.s_addr = myaddr.sin_addr.s_addr; + } + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + error = bootpc_adjust_interface(&ireq,so, + &myaddr,&netmask,&gw,procp); + + soclose(so); + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + + nd->root_args.version = NFS_ARGSVERSION; + nd->root_args.rsize = 8192; + nd->root_args.wsize = 8192; + nd->root_args.sotype = SOCK_DGRAM; + nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | + NFSMNT_RESVPORT | NFSMNT_NOCONN); + + nd->swap_args.version = NFS_ARGSVERSION; + nd->swap_args.rsize = 8192; + nd->swap_args.wsize = 8192; + nd->swap_args.sotype = SOCK_DGRAM; + nd->swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | + NFSMNT_RESVPORT | NFSMNT_NOCONN); + + if (gotrootpath) { + if (server.sin_addr.s_addr != reply.siaddr.s_addr ) { + sprintf(nd->root_hostnam,"%d.%d.%d.%d", + ((unsigned char *) &server.sin_addr)[0], + ((unsigned char *) &server.sin_addr)[1], + ((unsigned char *) &server.sin_addr)[2], + ((unsigned char *) &server.sin_addr)[3]); + } else + strcpy(nd->root_hostnam,reply.sname); + bcopy(&server, &nd->root_saddr,sizeof(server)); + + error = md_mount(&nd->root_saddr, rootpath, nd->root_fh, &nd->root_fhsize, + &nd->root_args,procp); + if (error) + panic("nfs_boot: mountd root, error=%d", error); + + if (gotswappath) { + + char *p = swappath; + + while (*p) + p++; + while (p>=swappath && *p != '/') + p--; + + strcpy(nd->swap_hostnam, nd->root_hostnam); + + bcopy(&server, &nd->swap_saddr,sizeof(server)); + + if (p>swappath) + *p = '\0'; + error = md_mount(&nd->swap_saddr, + (p>swappath) ? swappath:"/", + nd->swap_fh, &nd->swap_fhsize,&nd->swap_args,procp); + if (error) + panic("nfs_boot: mountd swap, error=%d", error); + if (p>swappath) + *p = '/'; + + if (p>=swappath) + error = md_lookup_swap(&nd->swap_saddr,p+1,nd->swap_fh, + &nd->swap_fhsize, &nd->swap_args,procp); + if (error) + panic("nfs_boot: lookup swap, error=%d", error); + } + nfs_diskless_valid = 3; + } + + + bcopy(&myaddr,&nd->myif.ifra_addr,sizeof(myaddr)); + bcopy(&myaddr,&nd->myif.ifra_broadaddr,sizeof(myaddr)); + ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = + myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr; + bcopy(&netmask,&nd->myif.ifra_mask,sizeof(netmask)); + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + return; +} + +/* + * RPC: mountd/mount + * Given a server pathname, get an NFS file handle. + * Also, sets sin->sin_port to the NFS service port. + */ +static int +md_mount(mdsin, path, fhp, fhsizep, args, procp) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + int *fhsizep; + struct nfs_args *args; + struct proc *procp; +{ + struct mbuf *m; + int error; + int authunixok; + int authcount; + int authver; + +#ifdef BOOTP_NFSV3 + /* First try NFS v3 */ + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, + &mdsin->sin_port, procp); + if (!error) { + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, + RPCMNT_MOUNT, &m, NULL, curproc); + } + if (!error) { + args->flags |= NFSMNT_NFSV3; + } else { +#endif + /* Fallback to NFS v2 */ + + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, + &mdsin->sin_port, procp); + if (error) return error; + + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, + RPCMNT_MOUNT, &m, NULL, curproc); + if (error) + return error; /* message already freed */ + +#ifdef BOOTP_NFSV3 + } +#endif + + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + error = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (error) + goto bad; + m_adj(m,sizeof(u_int32_t)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + *fhsizep = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (*fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) + goto bad; + m_adj(m,sizeof(u_int32_t)); + } else + *fhsizep = NFSX_V2FH; + + if (m->m_len < (((*fhsizep)+3)&~3)) { + m = m_pullup(m,(((*fhsizep)+3)&~3)); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, *fhsizep); + m_adj(m,(((*fhsizep)+3)&~3)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + authcount = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + authunixok = 0; + m_adj(m,sizeof(u_int32_t)); + if (authcount<0 || authcount>100) + goto bad; + while (authcount>0) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + authver = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (authver == RPCAUTH_UNIX) + authunixok = 1; + authcount--; + m_adj(m,sizeof(u_int32_t)); + } + if (!authunixok) + goto bad; + } + + /* Set port number for NFS use. */ + error = krpc_portmap(mdsin, NFS_PROG, + (args->flags & NFSMNT_NFSV3)?NFS_VER3:NFS_VER2, + &mdsin->sin_port, procp); + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} + +static int md_lookup_swap(mdsin, path, fhp, fhsizep, args, procp) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + int *fhsizep; + struct nfs_args *args; + struct proc *procp; +{ + struct mbuf *m; + int error; + int size = -1; + int attribs_present; + int status; + + m = m_get(M_WAIT,MT_DATA); + if (!m) + return ENOBUFS; + + if (args->flags & NFSMNT_NFSV3) { + *mtod(m,u_int32_t *) = txdr_unsigned(*fhsizep); + bcopy(fhp,mtod(m,u_char *)+sizeof(u_int32_t),*fhsizep); + m->m_len = *fhsizep + sizeof(u_int32_t); + } else { + bcopy(fhp,mtod(m,u_char *),NFSX_V2FH); + m->m_len = NFSX_V2FH; + } + + m->m_next = xdr_string_encode(path, strlen(path)); + if (!m->m_next) { + error = ENOBUFS; + goto out; + } + + /* Do RPC to nfsd. */ + if (args->flags & NFSMNT_NFSV3) + error = krpc_call(mdsin, NFS_PROG, NFS_VER3, + NFSPROC_LOOKUP, &m, NULL, procp); + else + error = krpc_call(mdsin, NFS_PROG, NFS_VER2, + NFSV2PROC_LOOKUP, &m, NULL, procp); + if (error) + return error; /* message already freed */ + + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + status = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + m_adj(m,sizeof(u_int32_t)); + if (status) { + error = ENOENT; + goto out; + } + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + *fhsizep = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (*fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) + goto bad; + m_adj(m,sizeof(u_int32_t)); + } else + *fhsizep = NFSX_V2FH; + + if (m->m_len < (((*fhsizep)+3)&~3)) { + m = m_pullup(m,(((*fhsizep)+3)&~3)); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, *fhsizep); + m_adj(m,(((*fhsizep)+3)&~3)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + attribs_present = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + m_adj(m,sizeof(u_int32_t)); + if (attribs_present) { + if (m->m_len < sizeof(u_int32_t)*21) { + m = m_pullup(m, sizeof(u_int32_t)*21); + if (m == NULL) + goto bad; + } + size = fxdr_unsigned(u_int32_t, mtod(m,u_int32_t *)[6]); + } + } else { + if (m->m_len < sizeof(u_int32_t)*17) { + m = m_pullup(m, sizeof(u_int32_t)*17); + if (m == NULL) + goto bad; + } + size = fxdr_unsigned(u_int32_t, mtod(m,u_int32_t *)[5]); + } + + if (!nfsv3_diskless.swap_nblks && size!= -1) { + nfsv3_diskless.swap_nblks = size/1024; + printf("md_lookup_swap: Swap size is %d KB\n", + nfsv3_diskless.swap_nblks); + } + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} Property changes on: head/sys/nfs/bootp_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/nfs/krpc.h =================================================================== --- head/sys/nfs/krpc.h (nonexistent) +++ head/sys/nfs/krpc.h (revision 25723) @@ -0,0 +1,30 @@ +/* $NetBSD: krpc.h,v 1.4 1995/12/19 23:07:11 cgd Exp $ */ +/* $Id:$ */ + +#include + +int krpc_call __P((struct sockaddr_in *sin, + u_int prog, u_int vers, u_int func, + struct mbuf **data, struct mbuf **from, struct proc *procp)); + +int krpc_portmap __P((struct sockaddr_in *sin, + u_int prog, u_int vers, u_int16_t *portp,struct proc *procp)); + +struct mbuf *xdr_string_encode __P((char *str, int len)); +struct mbuf *xdr_string_decode __P((struct mbuf *m, char *str, int *len_p)); +struct mbuf *xdr_inaddr_encode __P((struct in_addr *ia)); +struct mbuf *xdr_inaddr_decode __P((struct mbuf *m, struct in_addr *ia)); + + +/* + * RPC definitions for the portmapper + */ +#define PMAPPORT 111 +#define PMAPPROG 100000 +#define PMAPVERS 2 +#define PMAPPROC_NULL 0 +#define PMAPPROC_SET 1 +#define PMAPPROC_UNSET 2 +#define PMAPPROC_GETPORT 3 +#define PMAPPROC_DUMP 4 +#define PMAPPROC_CALLIT 5 Property changes on: head/sys/nfs/krpc.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/nfs/krpc_subr.c =================================================================== --- head/sys/nfs/krpc_subr.c (nonexistent) +++ head/sys/nfs/krpc_subr.c (revision 25723) @@ -0,0 +1,592 @@ +/* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */ +/* $Id:$ */ + +/* + * Copyright (c) 1995 Gordon Ross, Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * partially based on: + * libnetboot/rpc.c + * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* + * Kernel support for Sun RPC + * + * Used currently for bootstrapping in nfs diskless configurations. + */ + +/* + * Generic RPC headers + */ + +struct auth_info { + u_int32_t authtype; /* auth type */ + u_int32_t authlen; /* auth length */ +}; + +struct auth_unix { + int32_t ua_time; + int32_t ua_hostname; /* null */ + int32_t ua_uid; + int32_t ua_gid; + int32_t ua_gidlist; /* null */ +}; + +struct rpc_call { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (0) */ + u_int32_t rp_rpcvers; /* rpc version (2) */ + u_int32_t rp_prog; /* program */ + u_int32_t rp_vers; /* version */ + u_int32_t rp_proc; /* procedure */ + struct auth_info rpc_auth; + struct auth_unix rpc_unix; + struct auth_info rpc_verf; +}; + +struct rpc_reply { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (1) */ + int32_t rp_astatus; /* accept status (0: accepted) */ + union { + u_int32_t rpu_errno; + struct { + struct auth_info rok_auth; + u_int32_t rok_status; + } rpu_rok; + } rp_u; +}; +#define rp_errno rp_u.rpu_errno +#define rp_auth rp_u.rpu_rok.rok_auth +#define rp_status rp_u.rpu_rok.rok_status + +#define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */ + +/* + * What is the longest we will wait before re-sending a request? + * Note this is also the frequency of "RPC timeout" messages. + * The re-send loop count sup linearly to this maximum, so the + * first complaint will happen after (1+2+3+4+5)=15 seconds. + */ +#define MAX_RESEND_DELAY 5 /* seconds */ + +/* + * Call portmap to lookup a port number for a particular rpc program + * Returns non-zero error on failure. + */ +int +krpc_portmap(sin, prog, vers, portp, procp) + struct sockaddr_in *sin; /* server address */ + u_int prog, vers; /* host order */ + u_int16_t *portp; /* network order */ + struct proc *procp; +{ + struct sdata { + u_int32_t prog; /* call program */ + u_int32_t vers; /* call version */ + u_int32_t proto; /* call protocol */ + u_int32_t port; /* call port (unused) */ + } *sdata; + struct rdata { + u_int16_t pad; + u_int16_t port; + } *rdata; + struct mbuf *m; + int error; + + /* The portmapper port is fixed. */ + if (prog == PMAPPROG) { + *portp = htons(PMAPPORT); + return 0; + } + + m = m_get(M_WAIT, MT_DATA); + if (m == NULL) + return ENOBUFS; + sdata = mtod(m, struct sdata *); + m->m_len = sizeof(*sdata); + + /* Do the RPC to get it. */ + sdata->prog = txdr_unsigned(prog); + sdata->vers = txdr_unsigned(vers); + sdata->proto = txdr_unsigned(IPPROTO_UDP); + sdata->port = 0; + + sin->sin_port = htons(PMAPPORT); + error = krpc_call(sin, PMAPPROG, PMAPVERS, + PMAPPROC_GETPORT, &m, NULL, procp); + if (error) + return error; + + if (m->m_len < sizeof(*rdata)) { + m = m_pullup(m, sizeof(*rdata)); + if (m == NULL) + return ENOBUFS; + } + rdata = mtod(m, struct rdata *); + *portp = rdata->port; + + m_freem(m); + return 0; +} + +/* + * Do a remote procedure call (RPC) and wait for its reply. + * If from_p is non-null, then we are doing broadcast, and + * the address from whence the response came is saved there. + */ +int +krpc_call(sa, prog, vers, func, data, from_p, procp) + struct sockaddr_in *sa; + u_int prog, vers, func; + struct mbuf **data; /* input/output */ + struct mbuf **from_p; /* output */ + struct proc *procp; +{ + struct socket *so; + struct sockaddr_in *sin; + struct mbuf *m, *nam, *mhead, *from; + struct rpc_call *call; + struct rpc_reply *reply; + struct uio auio; + int error, rcvflg, timo, secs, len; + static u_int32_t xid = ~0xFF; + u_int16_t tport; + + /* + * Validate address family. + * Sorry, this is INET specific... + */ + if (sa->sin_family != AF_INET) + return (EAFNOSUPPORT); + + /* Free at end if not null. */ + nam = mhead = NULL; + from = NULL; + + /* + * Create socket and set its recieve timeout. + */ + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, procp))) + goto out; + + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } else { + struct timeval *tv; + tv = mtod(m, struct timeval *); + m->m_len = sizeof(*tv); + tv->tv_sec = 1; + tv->tv_usec = 0; + if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m, procp))) + goto out; + } + + /* + * Enable broadcast if necessary. + */ + if (from_p) { + int32_t *on; + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + on = mtod(m, int32_t *); + m->m_len = sizeof(*on); + *on = 1; + if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m, procp))) + goto out; + } + + /* + * Bind the local endpoint to a reserved port, + * because some NFS servers refuse requests from + * non-reserved (non-privileged) ports. + */ + m = m_getclr(M_WAIT, MT_SONAME); + sin = mtod(m, struct sockaddr_in *); + sin->sin_len = m->m_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + tport = IPPORT_RESERVED; + do { + tport--; + sin->sin_port = htons(tport); + error = sobind(so, m, procp); + } while (error == EADDRINUSE && + tport > IPPORT_RESERVED / 2); + m_freem(m); + if (error) { + printf("bind failed\n"); + goto out; + } + + /* + * Setup socket address for the server. + */ + nam = m_get(M_WAIT, MT_SONAME); + if (nam == NULL) { + error = ENOBUFS; + goto out; + } + sin = mtod(nam, struct sockaddr_in *); + bcopy((caddr_t)sa, (caddr_t)sin, + (nam->m_len = sa->sin_len)); + + /* + * Prepend RPC message header. + */ + mhead = m_gethdr(M_WAIT, MT_DATA); + mhead->m_next = *data; + call = mtod(mhead, struct rpc_call *); + mhead->m_len = sizeof(*call); + bzero((caddr_t)call, sizeof(*call)); + /* rpc_call part */ + xid++; + call->rp_xid = txdr_unsigned(xid); + /* call->rp_direction = 0; */ + call->rp_rpcvers = txdr_unsigned(2); + call->rp_prog = txdr_unsigned(prog); + call->rp_vers = txdr_unsigned(vers); + call->rp_proc = txdr_unsigned(func); + /* rpc_auth part (auth_unix as root) */ + call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX); + call->rpc_auth.authlen = txdr_unsigned(sizeof(struct auth_unix)); + /* rpc_verf part (auth_null) */ + call->rpc_verf.authtype = 0; + call->rpc_verf.authlen = 0; + + /* + * Setup packet header + */ + len = 0; + m = mhead; + while (m) { + len += m->m_len; + m = m->m_next; + } + mhead->m_pkthdr.len = len; + mhead->m_pkthdr.rcvif = NULL; + + /* + * Send it, repeatedly, until a reply is received, + * but delay each re-send by an increasing amount. + * If the delay hits the maximum, start complaining. + */ + timo = 0; + for (;;) { + /* Send RPC request (or re-send). */ + m = m_copym(mhead, 0, M_COPYALL, M_WAIT); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + error = sosend(so, nam, NULL, m, NULL, 0); + if (error) { + printf("krpc_call: sosend: %d\n", error); + goto out; + } + m = NULL; + + /* Determine new timeout. */ + if (timo < MAX_RESEND_DELAY) + timo++; + else + printf("RPC timeout for server 0x%x\n", + ntohl(sin->sin_addr.s_addr)); + + /* + * Wait for up to timo seconds for a reply. + * The socket receive timeout was set to 1 second. + */ + secs = timo; + while (secs > 0) { + if (from) { + m_freem(from); + from = NULL; + } + if (m) { + m_freem(m); + m = NULL; + } + bzero(&auio,sizeof(auio)); + auio.uio_resid = len = 1<<16; + rcvflg = 0; + error = soreceive(so, &from, &auio, &m, NULL, &rcvflg); + if (error == EWOULDBLOCK) { + secs--; + continue; + } + if (error) + goto out; + len -= auio.uio_resid; + + /* Does the reply contain at least a header? */ + if (len < MIN_REPLY_HDR) + continue; + if (m->m_len < MIN_REPLY_HDR) + continue; + reply = mtod(m, struct rpc_reply *); + + /* Is it the right reply? */ + if (reply->rp_direction != txdr_unsigned(RPC_REPLY)) + continue; + + if (reply->rp_xid != txdr_unsigned(xid)) + continue; + + /* Was RPC accepted? (authorization OK) */ + if (reply->rp_astatus != 0) { + error = fxdr_unsigned(u_int32_t, reply->rp_errno); + printf("rpc denied, error=%d\n", error); + continue; + } + + /* Did the call succeed? */ + if (reply->rp_status != 0) { + error = fxdr_unsigned(u_int32_t, reply->rp_status); + if (error == RPC_PROGMISMATCH) { + error = EBADRPC; + goto out; + } + printf("rpc denied, status=%d\n", error); + continue; + } + + goto gotreply; /* break two levels */ + + } /* while secs */ + } /* forever send/receive */ + + error = ETIMEDOUT; + goto out; + + gotreply: + + /* + * Get RPC reply header into first mbuf, + * get its length, then strip it off. + */ + len = sizeof(*reply); + if (m->m_len < len) { + m = m_pullup(m, len); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + } + reply = mtod(m, struct rpc_reply *); + if (reply->rp_auth.authtype != 0) { + len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen); + len = (len + 3) & ~3; /* XXX? */ + } + m_adj(m, len); + + /* result */ + *data = m; + if (from_p) { + *from_p = from; + from = NULL; + } + + out: + if (nam) m_freem(nam); + if (mhead) m_freem(mhead); + if (from) m_freem(from); + soclose(so); + return error; +} + +/* + * eXternal Data Representation routines. + * (but with non-standard args...) + */ + +/* + * String representation for RPC. + */ +struct xdr_string { + u_int32_t len; /* length without null or padding */ + char data[4]; /* data (longer, of course) */ + /* data is padded to a long-word boundary */ +}; + +struct mbuf * +xdr_string_encode(str, len) + char *str; + int len; +{ + struct mbuf *m; + struct xdr_string *xs; + int dlen; /* padded string length */ + int mlen; /* message length */ + + dlen = (len + 3) & ~3; + mlen = dlen + 4; + + if (mlen > MCLBYTES) /* If too big, we just can't do it. */ + return (NULL); + + m = m_get(M_WAIT, MT_DATA); + if (mlen > MLEN) { + MCLGET(m, M_WAIT); + if ((m->m_flags & M_EXT) == 0) { + (void) m_free(m); /* There can be only one. */ + return (NULL); + } + } + xs = mtod(m, struct xdr_string *); + m->m_len = mlen; + xs->len = txdr_unsigned(len); + bcopy(str, xs->data, len); + return (m); +} + +struct mbuf * +xdr_string_decode(m, str, len_p) + struct mbuf *m; + char *str; + int *len_p; /* bufsize - 1 */ +{ + struct xdr_string *xs; + int mlen; /* message length */ + int slen; /* string length */ + + if (m->m_len < 4) { + m = m_pullup(m, 4); + if (m == NULL) + return (NULL); + } + xs = mtod(m, struct xdr_string *); + slen = fxdr_unsigned(u_int32_t, xs->len); + mlen = 4 + ((slen + 3) & ~3); + + if (slen > *len_p) + slen = *len_p; + m_copydata(m, 4, slen, str); + m_adj(m, mlen); + + str[slen] = '\0'; + *len_p = slen; + + return (m); +} + + +/* + * Inet address in RPC messages + * (Note, really four ints, NOT chars. Blech.) + */ +struct xdr_inaddr { + u_int32_t atype; + u_int32_t addr[4]; +}; + +struct mbuf * +xdr_inaddr_encode(ia) + struct in_addr *ia; /* already in network order */ +{ + struct mbuf *m; + struct xdr_inaddr *xi; + u_int8_t *cp; + u_int32_t *ip; + + m = m_get(M_WAIT, MT_DATA); + xi = mtod(m, struct xdr_inaddr *); + m->m_len = sizeof(*xi); + xi->atype = txdr_unsigned(1); + ip = xi->addr; + cp = (u_int8_t *)&ia->s_addr; + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + + return (m); +} + +struct mbuf * +xdr_inaddr_decode(m, ia) + struct mbuf *m; + struct in_addr *ia; /* already in network order */ +{ + struct xdr_inaddr *xi; + u_int8_t *cp; + u_int32_t *ip; + + if (m->m_len < sizeof(*xi)) { + m = m_pullup(m, sizeof(*xi)); + if (m == NULL) + return (NULL); + } + xi = mtod(m, struct xdr_inaddr *); + if (xi->atype != txdr_unsigned(1)) { + ia->s_addr = INADDR_ANY; + goto out; + } + ip = xi->addr; + cp = (u_int8_t *)&ia->s_addr; + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + +out: + m_adj(m, sizeof(*xi)); + return (m); +} Property changes on: head/sys/nfs/krpc_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/nfs/nfs_vfsops.c =================================================================== --- head/sys/nfs/nfs_vfsops.c (revision 25722) +++ head/sys/nfs/nfs_vfsops.c (revision 25723) @@ -1,1028 +1,1055 @@ /* * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 - * $Id: nfs_vfsops.c,v 1.39 1997/05/03 13:42:50 phk Exp $ + * $Id: nfs_vfsops.c,v 1.40 1997/05/04 15:04:49 phk Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int nfs_mountroot __P((struct mount *mp)); extern int nfs_ticks; struct nfsstats nfsstats; SYSCTL_NODE(_vfs, MOUNT_NFS, nfs, CTLFLAG_RW, 0, "NFS filesystem"); SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD, &nfsstats, nfsstats, ""); #ifdef NFS_DEBUG int nfs_debug; SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); #endif static int nfs_iosize __P((struct nfsmount *nmp)); static int mountnfs __P((struct nfs_args *,struct mount *, struct mbuf *,char *,char *,struct vnode **)); static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p)); static int nfs_start __P(( struct mount *mp, int flags, struct proc *p)); static int nfs_unmount __P(( struct mount *mp, int mntflags, struct proc *p)); static int nfs_root __P(( struct mount *mp, struct vnode **vpp)); static int nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p)); static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp, struct proc *p)); static int nfs_sync __P(( struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)); static int nfs_vptofh __P(( struct vnode *vp, struct fid *fhp)); static int nfs_fhtovp __P((struct mount *mp, struct fid *fhp, struct mbuf *nam, struct vnode **vpp, int *exflagsp, struct ucred **credanonp)); static int nfs_vget __P((struct mount *, ino_t, struct vnode **)); /* * nfs vfs operations. */ static struct vfsops nfs_vfsops = { nfs_mount, nfs_start, nfs_unmount, nfs_root, nfs_quotactl, nfs_statfs, nfs_sync, nfs_vget, nfs_fhtovp, nfs_vptofh, nfs_init }; VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK); /* * This structure must be filled in by a primary bootstrap or bootstrap * server for a diskless/dataless machine. It is initialized below just * to ensure that it is allocated to initialized data (.data not .bss). */ struct nfs_diskless nfs_diskless = { 0 }; +struct nfsv3_diskless nfsv3_diskless = { 0 }; int nfs_diskless_valid = 0; SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, &nfs_diskless_valid, 0, ""); SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, - nfs_diskless.root_hostnam, 0, ""); + nfsv3_diskless.root_hostnam, 0, ""); SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, - &nfs_diskless.root_saddr, sizeof nfs_diskless.root_saddr, + &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr, "%Ssockaddr_in", ""); SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD, - nfs_diskless.swap_hostnam, 0, ""); + nfsv3_diskless.swap_hostnam, 0, ""); SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD, - &nfs_diskless.swap_saddr, sizeof nfs_diskless.swap_saddr, + &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, "%Ssockaddr_in",""); void nfsargs_ntoh __P((struct nfs_args *)); static int nfs_mountdiskless __P((char *, char *, int, struct sockaddr_in *, struct nfs_args *, struct proc *, struct vnode **, struct mount **)); +void nfs_convert_diskless __P((void)); static int nfs_iosize(nmp) struct nfsmount* nmp; { int iosize; /* * Calculate the size used for io buffers. Use the larger * of the two sizes to minimise nfs requests but make sure * that it is at least one VM page to avoid wasting buffer * space. */ iosize = max(nmp->nm_rsize, nmp->nm_wsize); if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; return iosize; } +void nfs_convert_diskless() +{ + bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, + sizeof(struct ifaliasreq)); + bcopy(&nfs_diskless.swap_args,&nfsv3_diskless.swap_args, + sizeof(struct nfs_args)); + nfsv3_diskless.swap_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH); + bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, + MNAMELEN); + nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks; + bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred, + sizeof(struct ucred)); + bcopy(&nfs_diskless.root_args,&nfsv3_diskless.root_args, + sizeof(struct nfs_args)); + nfsv3_diskless.root_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH); + bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, + MNAMELEN); + nfsv3_diskless.root_time = nfs_diskless.root_time; + bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam, + MAXHOSTNAMELEN); + nfs_diskless_valid = 3; +} + /* * nfs statfs call */ int nfs_statfs(mp, sbp, p) struct mount *mp; register struct statfs *sbp; struct proc *p; { register struct vnode *vp; register struct nfs_statfs *sfp; register caddr_t cp; register u_long *tl; register long t1, t2; caddr_t bpos, dpos, cp2; struct nfsmount *nmp = VFSTONFS(mp); int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct ucred *cred; struct nfsnode *np; u_quad_t tquad; #ifndef nolint sfp = (struct nfs_statfs *)0; #endif error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return (error); vp = NFSTOV(np); cred = crget(); cred->cr_ngroups = 1; if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, cred, p); nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); nfsm_fhtom(vp, v3); nfsm_request(vp, NFSPROC_FSSTAT, p, cred); if (v3) nfsm_postop_attr(vp, retattr); if (!error) nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); #ifdef __NetBSD__ #ifdef COMPAT_09 sbp->f_type = 2; #else sbp->f_type = 0; #endif #else sbp->f_type = MOUNT_NFS; #endif sbp->f_flags = nmp->nm_flag; sbp->f_iosize = nfs_iosize(nmp); if (v3) { sbp->f_bsize = NFS_FABLKSIZE; fxdr_hyper(&sfp->sf_tbytes, &tquad); sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); fxdr_hyper(&sfp->sf_fbytes, &tquad); sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); fxdr_hyper(&sfp->sf_abytes, &tquad); sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); } else { sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; } if (sbp != &mp->mnt_stat) { bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); } nfsm_reqdone; vput(vp); crfree(cred); return (error); } /* * nfs version 3 fsinfo rpc call */ int nfs_fsinfo(nmp, vp, cred, p) register struct nfsmount *nmp; register struct vnode *vp; struct ucred *cred; struct proc *p; { register struct nfsv3_fsinfo *fsp; register caddr_t cp; register long t1, t2; register u_long *tl, pref, max; caddr_t bpos, dpos, cp2; int error = 0, retattr; struct mbuf *mreq, *mrep, *md, *mb, *mb2; nfsstats.rpccnt[NFSPROC_FSINFO]++; nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); nfsm_fhtom(vp, 1); nfsm_request(vp, NFSPROC_FSINFO, p, cred); nfsm_postop_attr(vp, retattr); if (!error) { nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); pref = fxdr_unsigned(u_long, fsp->fs_wtpref); if (pref < nmp->nm_wsize) nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_long, fsp->fs_wtmax); if (max < nmp->nm_wsize) { nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize == 0) nmp->nm_wsize = max; } pref = fxdr_unsigned(u_long, fsp->fs_rtpref); if (pref < nmp->nm_rsize) nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_long, fsp->fs_rtmax); if (max < nmp->nm_rsize) { nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize == 0) nmp->nm_rsize = max; } pref = fxdr_unsigned(u_long, fsp->fs_dtpref); if (pref < nmp->nm_readdirsize) nmp->nm_readdirsize = pref; if (max < nmp->nm_readdirsize) { nmp->nm_readdirsize = max; } nmp->nm_flag |= NFSMNT_GOTFSINFO; } nfsm_reqdone; return (error); } /* * Mount a remote root fs via. nfs. This depends on the info in the * nfs_diskless structure that has been filled in properly by some primary * bootstrap. * It goes something like this: * - do enough of "ifconfig" by calling ifioctl() so that the system * can talk to the server * - If nfs_diskless.mygateway is filled in, use that address as * a default gateway. * - hand craft the swap nfs vnode hanging off a fake mount point * if swdevt[0].sw_dev == NODEV * - build the rootfs mount point and call mountnfs() to do the rest. */ int nfs_mountroot(mp) struct mount *mp; { struct mount *swap_mp; - struct nfs_diskless *nd = &nfs_diskless; + struct nfsv3_diskless *nd = &nfsv3_diskless; struct socket *so; struct vnode *vp; struct proc *p = curproc; /* XXX */ int error, i; u_long l; char buf[128]; /* * XXX time must be non-zero when we init the interface or else * the arp code will wedge... */ if (time.tv_sec == 0) time.tv_sec = 1; + if (nfs_diskless_valid==1) + nfs_convert_diskless(); + /* * XXX splnet, so networks will receive... */ splnet(); #ifdef notyet /* Set up swap credentials. */ proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid); proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid); if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) > NGROUPS) proc0.p_ucred->cr_ngroups = NGROUPS; for (i = 0; i < proc0.p_ucred->cr_ngroups; i++) proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]); #endif /* * Do enough of ifconfig(8) so that the critical net interface can * talk to the server. */ error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, p); if (error) panic("nfs_mountroot: socreate(%04x): %d", nd->myif.ifra_addr.sa_family, error); /* * We might not have been told the right interface, so we pass * over the first ten interfaces of the same kind, until we get * one of them configured. */ for (i = strlen(nd->myif.ifra_name) - 1; nd->myif.ifra_name[i] >= '0' && nd->myif.ifra_name[i] <= '9'; nd->myif.ifra_name[i] ++) { error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p); if(!error) break; } if (error) panic("nfs_mountroot: SIOCAIFADDR: %d", error); soclose(so); /* * If the gateway field is filled in, set it as the default route. */ if (nd->mygateway.sin_len != 0) { struct sockaddr_in mask, sin; bzero((caddr_t)&mask, sizeof(mask)); sin = mask; sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); error = rtrequest(RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&nd->mygateway, (struct sockaddr *)&mask, RTF_UP | RTF_GATEWAY, (struct rtentry **)0); if (error) panic("nfs_mountroot: RTM_ADD: %d", error); } /* * Create the rootfs mount point. */ nd->root_args.fh = nd->root_fh; - /* - * If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize. - */ - nd->root_args.fhsize = NFSX_V2FH; + nd->root_args.fhsize = nd->root_fhsize; l = ntohl(nd->root_saddr.sin_addr.s_addr); sprintf(buf,"%ld.%ld.%ld.%ld:%s", (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam); printf("NFS ROOT: %s\n",buf); if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY, &nd->root_saddr, &nd->root_args, p, &vp, &mp)) { if (swap_mp) { mp->mnt_vfc->vfc_refcount--; free(swap_mp, M_MOUNT); } return (error); } swap_mp = NULL; if (nd->swap_nblks) { /* Convert to DEV_BSIZE instead of Kilobyte */ nd->swap_nblks *= 2; /* * Create a fake mount point just for the swap vnode so that the * swap file can be on a different server from the rootfs. */ nd->swap_args.fh = nd->swap_fh; - /* - * If using nfsv3_diskless, replace NFSX_V2FH with - * nd->swap_fhsize. - */ - nd->swap_args.fhsize = NFSX_V2FH; + nd->swap_args.fhsize = nd->swap_fhsize; l = ntohl(nd->swap_saddr.sin_addr.s_addr); sprintf(buf,"%ld.%ld.%ld.%ld:%s", (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam); printf("NFS SWAP: %s\n",buf); if (error = nfs_mountdiskless(buf, "/swap", 0, &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp)) return (error); vfs_unbusy(swap_mp, p); VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = nd->swap_nblks * DEV_BSIZE ; /* * Since the swap file is not the root dir of a file system, * hack it to a regular file. */ vp->v_type = VREG; vp->v_flag = 0; VREF(vp); swaponvp(p, vp, NODEV, nd->swap_nblks); } mp->mnt_flag |= MNT_ROOTFS; mp->mnt_vnodecovered = NULLVP; rootvp = vp; vfs_unbusy(mp, p); /* * This is not really an nfs issue, but it is much easier to * set hostname here and then let the "/etc/rc.xxx" files * mount the right /var based upon its preset value. */ bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN); hostname[MAXHOSTNAMELEN - 1] = '\0'; for (i = 0; i < MAXHOSTNAMELEN; i++) if (hostname[i] == '\0') break; inittodr(ntohl(nd->root_time)); return (0); } /* * Internal version of mount system call for diskless setup. */ static int nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp) char *path; char *which; int mountflag; struct sockaddr_in *sin; struct nfs_args *args; struct proc *p; struct vnode **vpp; struct mount **mpp; { struct mount *mp; struct mbuf *m; int error; mp = *mpp; if (!mp && ( error = vfs_rootmountalloc("nfs", path, &mp))) { printf("nfs_mountroot: NFS not configured"); return (error); } mp->mnt_flag = mountflag; MGET(m, MT_SONAME, M_WAITOK); bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len); m->m_len = sin->sin_len; if (error = mountnfs(args, mp, m, which, path, vpp)) { printf("nfs_mountroot: mount %s on %s: %d", path, which, error); mp->mnt_vfc->vfc_refcount--; vfs_unbusy(mp, p); free(mp, M_MOUNT); return (error); } (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); *mpp = mp; return (0); } #ifndef NO_COMPAT_PRELITE2 /* * Old arguments to mount NFS */ struct onfs_args { struct sockaddr *addr; /* file server address */ int addrlen; /* length of address */ int sotype; /* Socket type */ int proto; /* and Protocol */ u_char *fh; /* File handle to be mounted */ int fhsize; /* Size, in bytes, of fh */ int flags; /* flags */ int wsize; /* write size in bytes */ int rsize; /* read size in bytes */ int readdirsize; /* readdir size in bytes */ int timeo; /* initial timeout in .1 secs */ int retrans; /* times to retry send */ int maxgrouplist; /* Max. size of group list */ int readahead; /* # of blocks to readahead */ int leaseterm; /* Term (sec) of lease */ int deadthresh; /* Retrans threshold */ char *hostname; /* server's name */ }; #endif /* !NO_COMPAT_PRELITE2 */ /* * VFS Operations. * * mount system call * It seems a bit dumb to copyinstr() the host and path here and then * bcopy() them in mountnfs(), but I wanted to detect errors before * doing the sockargs() call because sockargs() allocates an mbuf and * an error after that means that I have to release the mbuf. */ /* ARGSUSED */ static int nfs_mount(mp, path, data, ndp, p) struct mount *mp; char *path; caddr_t data; struct nameidata *ndp; struct proc *p; { int error; struct nfs_args args; struct mbuf *nam; struct vnode *vp; char pth[MNAMELEN], hst[MNAMELEN]; u_int len; u_char nfh[NFSX_V3FHMAX]; if (path == NULL) { nfs_mountroot(mp); return (0); } error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); if (error) return (error); if (args.version != NFS_ARGSVERSION) { #ifndef NO_COMPAT_PRELITE2 /* * If the argument version is unknown, then assume the * caller is a pre-lite2 4.4BSD client and convert its * arguments. */ struct onfs_args oargs; error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args)); if (error) return (error); args.version = NFS_ARGSVERSION; args.addr = oargs.addr; args.addrlen = oargs.addrlen; args.sotype = oargs.sotype; args.proto = oargs.proto; args.fh = oargs.fh; args.fhsize = oargs.fhsize; args.flags = oargs.flags; args.wsize = oargs.wsize; args.rsize = oargs.rsize; args.readdirsize = oargs.readdirsize; args.timeo = oargs.timeo; args.retrans = oargs.retrans; args.maxgrouplist = oargs.maxgrouplist; args.readahead = oargs.readahead; args.leaseterm = oargs.leaseterm; args.deadthresh = oargs.deadthresh; args.hostname = oargs.hostname; #else /* NO_COMPAT_PRELITE2 */ return (EPROGMISMATCH); #endif /* !NO_COMPAT_PRELITE2 */ } error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); if (error) return (error); error = copyinstr(path, pth, MNAMELEN-1, &len); if (error) return (error); bzero(&pth[len], MNAMELEN - len); error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); if (error) return (error); bzero(&hst[len], MNAMELEN - len); /* sockargs() call must be after above copyin() calls */ error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME); if (error) return (error); args.fh = nfh; error = mountnfs(&args, mp, nam, pth, hst, &vp); return (error); } /* * Common code for mount and mountroot */ static int mountnfs(argp, mp, nam, pth, hst, vpp) register struct nfs_args *argp; register struct mount *mp; struct mbuf *nam; char *pth, *hst; struct vnode **vpp; { register struct nfsmount *nmp; struct nfsnode *np; int error, maxio; struct vattr attrs; if (mp->mnt_flag & MNT_UPDATE) { nmp = VFSTONFS(mp); /* update paths, file handles, etc, here XXX */ m_freem(nam); return (0); } else { MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount), M_NFSMNT, M_WAITOK); bzero((caddr_t)nmp, sizeof (struct nfsmount)); TAILQ_INIT(&nmp->nm_uidlruhead); TAILQ_INIT(&nmp->nm_bufq); mp->mnt_data = (qaddr_t)nmp; } vfs_getnewfsid(mp); nmp->nm_mountp = mp; nmp->nm_flag = argp->flags; if (nmp->nm_flag & NFSMNT_NQNFS) /* * We have to set mnt_maxsymlink to a non-zero value so * that COMPAT_43 routines will know that we are setting * the d_type field in directories (and can zero it for * unsuspecting binaries). */ mp->mnt_maxsymlinklen = 1; nmp->nm_timeo = NFS_TIMEO; nmp->nm_retry = NFS_RETRANS; nmp->nm_wsize = NFS_WSIZE; nmp->nm_rsize = NFS_RSIZE; nmp->nm_readdirsize = NFS_READDIRSIZE; nmp->nm_numgrps = NFS_MAXGRPS; nmp->nm_readahead = NFS_DEFRAHEAD; nmp->nm_leaseterm = NQ_DEFLEASE; nmp->nm_deadthresh = NQ_DEADTHRESH; CIRCLEQ_INIT(&nmp->nm_timerhead); nmp->nm_inprog = NULLVP; nmp->nm_fhsize = argp->fhsize; bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); nmp->nm_nam = nam; if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; if (nmp->nm_timeo < NFS_MINTIMEO) nmp->nm_timeo = NFS_MINTIMEO; else if (nmp->nm_timeo > NFS_MAXTIMEO) nmp->nm_timeo = NFS_MAXTIMEO; } if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { nmp->nm_retry = argp->retrans; if (nmp->nm_retry > NFS_MAXREXMIT) nmp->nm_retry = NFS_MAXREXMIT; } if (argp->flags & NFSMNT_NFSV3) { if (argp->sotype == SOCK_DGRAM) maxio = NFS_MAXDGRAMDATA; else maxio = NFS_MAXDATA; } else maxio = NFS_V2MAXDATA; if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { nmp->nm_wsize = argp->wsize; /* Round down to multiple of blocksize */ nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize <= 0) nmp->nm_wsize = NFS_FABLKSIZE; } if (nmp->nm_wsize > maxio) nmp->nm_wsize = maxio; if (nmp->nm_wsize > MAXBSIZE) nmp->nm_wsize = MAXBSIZE; if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { nmp->nm_rsize = argp->rsize; /* Round down to multiple of blocksize */ nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize <= 0) nmp->nm_rsize = NFS_FABLKSIZE; } if (nmp->nm_rsize > maxio) nmp->nm_rsize = maxio; if (nmp->nm_rsize > MAXBSIZE) nmp->nm_rsize = MAXBSIZE; if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { nmp->nm_readdirsize = argp->readdirsize; } if (nmp->nm_readdirsize > maxio) nmp->nm_readdirsize = maxio; if (nmp->nm_readdirsize > nmp->nm_rsize) nmp->nm_readdirsize = nmp->nm_rsize; if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && argp->maxgrouplist <= NFS_MAXGRPS) nmp->nm_numgrps = argp->maxgrouplist; if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && argp->readahead <= NFS_MAXRAHEAD) nmp->nm_readahead = argp->readahead; if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && argp->leaseterm <= NQ_MAXLEASE) nmp->nm_leaseterm = argp->leaseterm; if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && argp->deadthresh <= NQ_NEVERDEAD) nmp->nm_deadthresh = argp->deadthresh; /* Set up the sockets and per-host congestion */ nmp->nm_sotype = argp->sotype; nmp->nm_soproto = argp->proto; /* * For Connection based sockets (TCP,...) defer the connect until * the first request, in case the server is not responding. */ if (nmp->nm_sotype == SOCK_DGRAM && (error = nfs_connect(nmp, (struct nfsreq *)0))) goto bad; /* * This is silly, but it has to be set so that vinifod() works. * We do not want to do an nfs_statfs() here since we can get * stuck on a dead server and we are holding a lock on the mount * point. */ mp->mnt_stat.f_iosize = nfs_iosize(nmp); /* * A reference count is needed on the nfsnode representing the * remote root. If this object is not persistent, then backward * traversals of the mount point (i.e. "..") will not work if * the nfsnode gets flushed out of the cache. Ufs does not have * this problem, because one can identify root inodes by their * number == ROOTINO (2). */ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) goto bad; *vpp = NFSTOV(np); /* * Get file attributes for the mountpoint. This has the side * effect of filling in (*vpp)->v_type with the correct value. */ VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc); /* * Lose the lock but keep the ref. */ VOP_UNLOCK(*vpp, 0, curproc); return (0); bad: nfs_disconnect(nmp); free((caddr_t)nmp, M_NFSMNT); m_freem(nam); return (error); } /* * unmount system call */ static int nfs_unmount(mp, mntflags, p) struct mount *mp; int mntflags; struct proc *p; { register struct nfsmount *nmp; struct nfsnode *np; struct vnode *vp; int error, flags = 0; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; nmp = VFSTONFS(mp); /* * Goes something like this.. * - Check for activity on the root vnode (other than ourselves). * - Call vflush() to clear out vnodes for this file system, * except for the root vnode. * - Decrement reference on the vnode representing remote root. * - Close the socket * - Free up the data structures */ /* * We need to decrement the ref. count on the nfsnode representing * the remote root. See comment in mountnfs(). The VFS unmount() * has done vput on this vnode, otherwise we would get deadlock! */ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return(error); vp = NFSTOV(np); if (vp->v_usecount > 2) { vput(vp); return (EBUSY); } /* * Must handshake with nqnfs_clientd() if it is active. */ nmp->nm_flag |= NFSMNT_DISMINPROG; while (nmp->nm_inprog != NULLVP) (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); error = vflush(mp, vp, flags); if (error) { vput(vp); nmp->nm_flag &= ~NFSMNT_DISMINPROG; return (error); } /* * We are now committed to the unmount. * For NQNFS, let the server daemon free the nfsmount structure. */ if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) nmp->nm_flag |= NFSMNT_DISMNT; /* * There are two reference counts and one lock to get rid of here. */ vput(vp); vrele(vp); vgone(vp); nfs_disconnect(nmp); m_freem(nmp->nm_nam); if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0) free((caddr_t)nmp, M_NFSMNT); return (0); } /* * Return root of a filesystem */ static int nfs_root(mp, vpp) struct mount *mp; struct vnode **vpp; { register struct vnode *vp; struct nfsmount *nmp; struct nfsnode *np; int error; nmp = VFSTONFS(mp); error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return (error); vp = NFSTOV(np); if (vp->v_type == VNON) vp->v_type = VDIR; vp->v_flag = VROOT; *vpp = vp; return (0); } extern int syncprt; /* * Flush out the buffer cache */ /* ARGSUSED */ static int nfs_sync(mp, waitfor, cred, p) struct mount *mp; int waitfor; struct ucred *cred; struct proc *p; { register struct vnode *vp; int error, allerror = 0; /* * Force stale buffer cache information to be flushed. */ loop: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = vp->v_mntvnodes.le_next) { /* * If the vnode that we are about to sync is no longer * associated with this mount point, start over. */ if (vp->v_mount != mp) goto loop; if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL) continue; if (vget(vp, LK_EXCLUSIVE, p)) goto loop; error = VOP_FSYNC(vp, cred, waitfor, p); if (error) allerror = error; vput(vp); } return (allerror); } /* * NFS flat namespace lookup. * Currently unsupported. */ /* ARGSUSED */ static int nfs_vget(mp, ino, vpp) struct mount *mp; ino_t ino; struct vnode **vpp; { return (EOPNOTSUPP); } /* * At this point, this should never happen */ /* ARGSUSED */ static int nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) register struct mount *mp; struct fid *fhp; struct mbuf *nam; struct vnode **vpp; int *exflagsp; struct ucred **credanonp; { return (EINVAL); } /* * Vnode pointer to File handle, should never happen either */ /* ARGSUSED */ static int nfs_vptofh(vp, fhp) struct vnode *vp; struct fid *fhp; { return (EINVAL); } /* * Vfs start routine, a no-op. */ /* ARGSUSED */ static int nfs_start(mp, flags, p) struct mount *mp; int flags; struct proc *p; { return (0); } /* * Do operations associated with quotas, not supported */ /* ARGSUSED */ static int nfs_quotactl(mp, cmd, uid, arg, p) struct mount *mp; int cmd; uid_t uid; caddr_t arg; struct proc *p; { return (EOPNOTSUPP); } Index: head/sys/nfs/rpcv2.h =================================================================== --- head/sys/nfs/rpcv2.h (revision 25722) +++ head/sys/nfs/rpcv2.h (revision 25723) @@ -1,142 +1,143 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)rpcv2.h 8.2 (Berkeley) 3/30/95 - * $Id$ + * $Id: rpcv2.h,v 1.7 1997/02/22 09:42:53 peter Exp $ */ #ifndef _NFS_RPCV2_H_ #define _NFS_RPCV2_H_ /* * Definitions for Sun RPC Version 2, from * "RPC: Remote Procedure Call Protocol Specification" RFC1057 */ /* Version # */ #define RPC_VER2 2 /* Authentication */ #define RPCAUTH_NULL 0 #define RPCAUTH_UNIX 1 #define RPCAUTH_SHORT 2 #define RPCAUTH_KERB4 4 #define RPCAUTH_NQNFS 300000 #define RPCAUTH_MAXSIZ 400 #define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */ #define RPCAUTH_UNIXGIDS 16 /* * Constants associated with authentication flavours. */ #define RPCAKN_FULLNAME 0 #define RPCAKN_NICKNAME 1 /* Rpc Constants */ #define RPC_CALL 0 #define RPC_REPLY 1 #define RPC_MSGACCEPTED 0 #define RPC_MSGDENIED 1 #define RPC_PROGUNAVAIL 1 #define RPC_PROGMISMATCH 2 #define RPC_PROCUNAVAIL 3 #define RPC_GARBAGE 4 /* I like this one */ #define RPC_MISMATCH 0 #define RPC_AUTHERR 1 /* Authentication failures */ #define AUTH_BADCRED 1 #define AUTH_REJECTCRED 2 #define AUTH_BADVERF 3 #define AUTH_REJECTVERF 4 #define AUTH_TOOWEAK 5 /* Give em wheaties */ /* Sizes of rpc header parts */ #define RPC_SIZ 24 #define RPC_REPLYSIZ 28 /* RPC Prog definitions */ #define RPCPROG_MNT 100005 #define RPCMNT_VER1 1 +#define RPCMNT_VER3 3 #define RPCMNT_MOUNT 1 #define RPCMNT_DUMP 2 #define RPCMNT_UMOUNT 3 #define RPCMNT_UMNTALL 4 #define RPCMNT_EXPORT 5 #define RPCMNT_NAMELEN 255 #define RPCMNT_PATHLEN 1024 #define RPCPROG_NFS 100003 /* * Structures used for RPCAUTH_KERB4. */ struct nfsrpc_fullverf { u_long t1; u_long t2; u_long w2; }; struct nfsrpc_fullblock { u_long t1; u_long t2; u_long w1; u_long w2; }; struct nfsrpc_nickverf { u_long kind; struct nfsrpc_fullverf verf; }; /* * and their sizes in bytes.. If sizeof (struct nfsrpc_xx) != these * constants, well then things will break in mount_nfs and nfsd. */ #define RPCX_FULLVERF 12 #define RPCX_FULLBLOCK 16 #define RPCX_NICKVERF 16 #ifdef NFSKERB XXX #else typedef u_char NFSKERBKEY_T[2]; typedef u_char NFSKERBKEYSCHED_T[2]; #endif #define NFS_KERBSRV "rcmd" /* Kerberos Service for NFS */ #define NFS_KERBTTL (30 * 60) /* Credential ttl (sec) */ #define NFS_KERBCLOCKSKEW (5 * 60) /* Clock skew (sec) */ #define NFS_KERBW1(t) (*((u_long *)(&((t).dat[((t).length + 3) & ~0x3])))) #endif Index: head/sys/nfsclient/bootp_subr.c =================================================================== --- head/sys/nfsclient/bootp_subr.c (nonexistent) +++ head/sys/nfsclient/bootp_subr.c (revision 25723) @@ -0,0 +1,1319 @@ +/* $Id:$ */ + +/* + * Copyright (c) 1995 Gordon Ross, Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * based on: + * nfs/krpc_subr.c + * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */ + +/* + * What is the longest we will wait before re-sending a request? + * Note this is also the frequency of "RPC timeout" messages. + * The re-send loop count sup linearly to this maximum, so the + * first complaint will happen after (1+2+3+4+5)=15 seconds. + */ +#define MAX_RESEND_DELAY 5 /* seconds */ + +/* Definitions from RFC951 */ +struct bootp_packet { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + struct in_addr ciaddr; + struct in_addr yiaddr; + struct in_addr siaddr; + struct in_addr giaddr; + unsigned char chaddr[16]; + char sname[64]; + char file[128]; + unsigned char vend[256]; +}; + +#define IPPORT_BOOTPC 68 +#define IPPORT_BOOTPS 67 + +extern int nfs_diskless_valid; +extern struct nfsv3_diskless nfsv3_diskless; + +/* mountd RPC */ +static int md_mount __P((struct sockaddr_in *mdsin, char *path, + u_char *fhp, int *fhsizep, struct nfs_args *args,struct proc *procp)); +static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path, + u_char *fhp, int *fhsizep, + struct nfs_args *args, + struct proc *procp)); + +#ifdef BOOTP_DEBUG +void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma); +void bootpboot_p_ma(struct sockaddr *ma); +void bootpboot_p_rtentry(struct rtentry *rt); +void bootpboot_p_tree(struct radix_node *rn); +void bootpboot_p_rtlist(void); +void bootpboot_p_iflist(void); +#endif + +int bootpc_call(struct bootp_packet *call, + struct bootp_packet *reply, + struct proc *procp); + +int bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, + struct proc *procp); + +int +bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, + struct sockaddr_in *myaddr, + struct sockaddr_in *netmask, + struct sockaddr_in *gw, + struct proc *procp); + +void bootpc_init(void); + +#ifdef BOOTP_DEBUG +void bootpboot_p_sa(sa,ma) + struct sockaddr *sa; + struct sockaddr *ma; +{ + if (!sa) { + printf("(sockaddr *) "); + return; + } + switch (sa->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + printf("inet %x",ntohl(sin->sin_addr.s_addr)); + if (ma) { + struct sockaddr_in *sin = (struct sockaddr_in *) ma; + printf(" mask %x",ntohl(sin->sin_addr.s_addr)); + } + } + break; + case AF_LINK: + { + struct sockaddr_dl *sli = (struct sockaddr_dl *) sa; + int i; + printf("link %.*s ",sli->sdl_nlen,sli->sdl_data); + for (i=0;isdl_alen;i++) { + if (i>0) + printf(":"); + printf("%x",(unsigned char) sli->sdl_data[i+sli->sdl_nlen]); + } + } + break; + default: + printf("af%d",sa->sa_family); + } +} + +void bootpboot_p_ma(ma) + struct sockaddr *ma; +{ + if (!ma) { + printf(""); + return; + } + printf("%x",*(int*)ma); +} + +void bootpboot_p_rtentry(rt) + struct rtentry *rt; +{ + bootpboot_p_sa(rt_key(rt),rt_mask(rt)); + printf(" "); + bootpboot_p_ma(rt->rt_genmask); + printf(" "); + bootpboot_p_sa(rt->rt_gateway,NULL); + printf(" "); + printf("flags %x",(unsigned short) rt->rt_flags); + printf(" %d",rt->rt_rmx.rmx_expire); + printf(" %s%d\n",rt->rt_ifp->if_name,rt->rt_ifp->if_unit); +} +void bootpboot_p_tree(rn) + struct radix_node *rn; +{ + while (rn) { + if (rn->rn_b < 0) { + if (rn->rn_flags & RNF_ROOT) { + } else { + bootpboot_p_rtentry((struct rtentry *) rn); + } + rn = rn->rn_dupedkey; + } else { + bootpboot_p_tree(rn->rn_l); + bootpboot_p_tree(rn->rn_r); + return; + } + + } +} + +void bootpboot_p_rtlist(void) +{ + printf("Routing table:\n"); + bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); +} + +void bootpboot_p_iflist(void) +{ + struct ifnet *ifp; + struct ifaddr *ifa; + printf("Interface list:\n"); + for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) + { + for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; + ifa=TAILQ_NEXT(ifa,ifa_link)) + if (ifa->ifa_addr->sa_family == AF_INET ) { + printf("%s%d flags %x, addr %x, bcast %x, net %x\n", + ifp->if_name,ifp->if_unit, + (unsigned short) ifp->if_flags, + ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr), + ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr), + ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr) + ); + } + } +} +#endif + +int +bootpc_call(call,reply,procp) + struct bootp_packet *call; + struct bootp_packet *reply; /* output */ + struct proc *procp; +{ + struct socket *so; + struct sockaddr_in *sin,sa; + struct mbuf *m, *nam; + struct uio auio; + struct iovec aio; + int error, rcvflg, timo, secs, len; + u_int tport; + + /* Free at end if not null. */ + nam = NULL; + + /* + * Create socket and set its recieve timeout. + */ + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp))) + goto out; + + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } else { + struct timeval *tv; + tv = mtod(m, struct timeval *); + m->m_len = sizeof(*tv); + tv->tv_sec = 1; + tv->tv_usec = 0; + if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m, procp))) + goto out; + } + + /* + * Enable broadcast. + */ + { + int *on; + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + on = mtod(m, int *); + m->m_len = sizeof(*on); + *on = 1; + if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m, procp))) + goto out; + } + + /* + * Bind the local endpoint to a bootp client port. + */ + m = m_getclr(M_WAIT, MT_SONAME); + sin = mtod(m, struct sockaddr_in *); + sin->sin_len = m->m_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + sin->sin_port = htons(IPPORT_BOOTPC); + error = sobind(so, m, procp); + m_freem(m); + if (error) { + printf("bind failed\n"); + goto out; + } + + /* + * Setup socket address for the server. + */ + nam = m_get(M_WAIT, MT_SONAME); + if (nam == NULL) { + error = ENOBUFS; + goto out; + } + sin = mtod(nam, struct sockaddr_in *); + sin-> sin_len = sizeof(*sin); + sin-> sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_BROADCAST; + sin->sin_port = htons(IPPORT_BOOTPS); + + nam->m_len = sizeof(*sin); + + /* + * Send it, repeatedly, until a reply is received, + * but delay each re-send by an increasing amount. + * If the delay hits the maximum, start complaining. + */ + timo = 0; + for (;;) { + /* Send BOOTP request (or re-send). */ + + aio.iov_base = (caddr_t) call; + aio.iov_len = sizeof(*call); + + auio.uio_iov = &aio; + auio.uio_iovcnt = 1; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_offset = 0; + auio.uio_resid = sizeof(*call); + auio.uio_procp = procp; + + error = sosend(so, nam, &auio, NULL, NULL, 0); + if (error) { + printf("bootpc_call: sosend: %d\n", error); + goto out; + } + + /* Determine new timeout. */ + if (timo < MAX_RESEND_DELAY) + timo++; + else + printf("BOOTP timeout for server 0x%x\n", + ntohl(sin->sin_addr.s_addr)); + + /* + * Wait for up to timo seconds for a reply. + * The socket receive timeout was set to 1 second. + */ + secs = timo; + while (secs > 0) { + aio.iov_base = (caddr_t) reply; + aio.iov_len = sizeof(*reply); + + auio.uio_iov = &aio; + auio.uio_iovcnt = 1; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_READ; + auio.uio_offset = 0; + auio.uio_resid = sizeof(*reply); + auio.uio_procp = procp; + + rcvflg = 0; + error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg); + if (error == EWOULDBLOCK) { + secs--; + call->secs=htons(ntohs(call->secs)+1); + continue; + } + if (error) + goto out; + len = sizeof(*reply) - auio.uio_resid; + + /* Does the reply contain at least a header? */ + if (len < MIN_REPLY_HDR) + continue; + + /* Is it the right reply? */ + if (reply->op != 2) + continue; + + if (reply->xid != call->xid) + continue; + + if (reply->hlen != call->hlen) + continue; + + if (bcmp(reply->chaddr,call->chaddr,call->hlen)) + continue; + + goto gotreply; /* break two levels */ + + } /* while secs */ + } /* forever send/receive */ + + error = ETIMEDOUT; + goto out; + + gotreply: + out: + if (nam) m_freem(nam); + soclose(so); + return error; +} + +int +bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, + struct proc *procp) +{ + struct sockaddr_in *sin; + int error; + struct sockaddr_in dst; + struct sockaddr_in gw; + struct sockaddr_in mask; + + /* + * Bring up the interface. + * + * Get the old interface flags and or IFF_UP into them; if + * IFF_UP set blindly, interface selection can be clobbered. + */ + error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); + ireq->ifr_flags |= IFF_UP; + error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); + + /* + * Do enough of ifconfig(8) so that the chosen interface + * can talk to the servers. (just set the address) + */ + + /* addr is 0.0.0.0 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if addr, error=%d", error); + + /* netmask is 0.0.0.0 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if net addr, error=%d", error); + + /* Broadcast is 255.255.255.255 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_BROADCAST; + error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error); + + /* Add default route to 0.0.0.0 so we can send data */ + + bzero((caddr_t) &dst, sizeof(dst)); + dst.sin_len=sizeof(dst); + dst.sin_family=AF_INET; + dst.sin_addr.s_addr = htonl(0); + + bzero((caddr_t) &gw, sizeof(gw)); + gw.sin_len=sizeof(gw); + gw.sin_family=AF_INET; + gw.sin_addr.s_addr = htonl(0x0); + + bzero((caddr_t) &mask, sizeof(mask)); + mask.sin_len=sizeof(mask); + mask.sin_family=AF_INET; + mask.sin_addr.s_addr = htonl(0); + + error = rtrequest(RTM_ADD, + (struct sockaddr *) &dst, + (struct sockaddr *) &gw, + (struct sockaddr *) &mask, + RTF_UP | RTF_STATIC + , NULL); + if (error) + printf("bootpc_fakeup_interface: add default route, error=%d\n", error); + return error; +} + +int +bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, + struct sockaddr_in *myaddr, + struct sockaddr_in *netmask, + struct sockaddr_in *gw, + struct proc *procp) +{ + int error; + struct sockaddr_in oldgw; + struct sockaddr_in olddst; + struct sockaddr_in oldmask; + struct sockaddr_in *sin; + + /* Remove old default route to 0.0.0.0 */ + + bzero((caddr_t) &olddst, sizeof(olddst)); + olddst.sin_len=sizeof(olddst); + olddst.sin_family=AF_INET; + olddst.sin_addr.s_addr = INADDR_ANY; + + bzero((caddr_t) &oldgw, sizeof(oldgw)); + oldgw.sin_len=sizeof(oldgw); + oldgw.sin_family=AF_INET; + oldgw.sin_addr.s_addr = INADDR_ANY; + + bzero((caddr_t) &oldmask, sizeof(oldmask)); + oldmask.sin_len=sizeof(oldmask); + oldmask.sin_family=AF_INET; + oldmask.sin_addr.s_addr = INADDR_ANY; + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) &olddst, + (struct sockaddr *) &oldgw, + (struct sockaddr *) &oldmask, + (RTF_UP | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del default route, error=%d\n", error); + return error; + } + +#if 0 + olddst.sin_addr.s_addr = INADDR_BROADCAST; + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) &olddst, + (struct sockaddr *) &oldgw, + (struct sockaddr *) NULL, + (RTF_UP | RTF_HOST | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del broadcast route, error=%d\n", error); + } +#endif + + /* + * Do enough of ifconfig(8) so that the chosen interface + * can talk to the servers. (just set the address) + */ + bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask)); + error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); + if (error) + panic("nfs_boot: set if netmask, error=%d", error); + + /* Broadcast is with host part of IP address all 1's */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr; + error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_call: set if broadcast addr, error=%d", error); + + bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr)); + error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); + if (error) + panic("nfs_boot: set if addr, error=%d", error); + + /* Add new default route */ + + error = rtrequest(RTM_ADD, + (struct sockaddr *) &olddst, + (struct sockaddr *) gw, + (struct sockaddr *) &oldmask, + (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: add net route, error=%d\n", error); + return error; + } + +#if 0 + /* Remove default gateway arp entry. This is a kludge, but + somehow the arp entry is added without an arp request + being sent, causing outgoing packets to be dropped onto the floor */ + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) gw, + (struct sockaddr *) NULL, + (struct sockaddr *) NULL, + (RTF_UP | RTF_HOST | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del default gateway linklevel route, error=%d\n", error); + } +#endif + + return 0; +} + +void bootp_expand_path(char *str,size_t len,char *hostname, + struct in_addr addr); +void bootp_expand_path(char *str,size_t len,char *hostname, + struct in_addr addr) +{ + char tmpbuf[128]; + char tmpaddr[20]; + + char *p,*q,*savep; + q = tmpbuf; + + savep = NULL; + sprintf(tmpaddr,"%d.%d.%d.%d", + ((unsigned char *) &addr)[0], + ((unsigned char *) &addr)[1], + ((unsigned char *) &addr)[2], + ((unsigned char *) &addr)[3]); + + for (p=str;*p;) { + switch(*p) { + case '%': + if (!savep) { + switch(*++p) { + case 'H': + savep = ++p; + p= hostname; + break; + case 'I': + savep = ++p; + p = tmpaddr; + break; + default: + goto arnej; + } + break; + } + default: + arnej: + if (q+1>=tmpbuf+sizeof(tmpbuf)) + panic("bootp_expand_path: Cannot expand %s\n",str); + else + *q++ = *p++; + if (!*p && savep) { + p = savep; + savep = NULL; + } + } + } + *q++ = 0; + if (q-tmpbuf>len) { + panic("bootp_expand_path: Too long expansion: %s\n",tmpbuf); + } + strcpy(str,tmpbuf); +} + +void +bootpc_init(void) +{ + struct bootp_packet call; + struct bootp_packet reply; + static u_int32_t xid = ~0xFF; + + struct ifreq ireq; + struct ifnet *ifp; + struct socket *so; + int error; + int code,len; + int i,j; + char rootpath[65]; + char swappath[65]; + + struct sockaddr_in myaddr; + struct sockaddr_in netmask; + struct sockaddr_in gw; + struct sockaddr_in server; + int gotgw=0; + int gotnetmask=0; + int gotserver=0; + int gotrootpath=0; + int gotswappath=0; + +#define EALEN 6 + unsigned char ea[EALEN]; + struct ifaddr *ifa; + struct sockaddr_dl *sdl = NULL; + char *delim; + + struct nfsv3_diskless *nd = &nfsv3_diskless; + struct proc *procp = curproc; + + /* + * If already filled in, don't touch it here + */ + if (nfs_diskless_valid) + return; + + /* + * Bump time if 0. + */ + if (!time.tv_sec) + time.tv_sec++; + + /* + * Find a network interface. + */ + for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) + if ((ifp->if_flags & + (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) + break; + if (ifp == NULL) + panic("bootpc_init: no suitable interface"); + bzero(&ireq,sizeof(ireq)); + sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit); + strcpy(nd->myif.ifra_name,ireq.ifr_name); + printf("bootpc_init: using network interface '%s'\n", + ireq.ifr_name); + + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) + panic("nfs_boot: socreate, error=%d", error); + + bootpc_fakeup_interface(&ireq,so,procp); + + printf("Bootpc testing starting\n"); + + /* Get HW address */ + + for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; + ifa=TAILQ_NEXT(ifa,ifa_link)) + if (ifa->ifa_addr->sa_family == AF_LINK && + (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) && + sdl->sdl_type == IFT_ETHER) + break; + + if (!sdl) + panic("bootpc: Unable to find HW address"); + if (sdl->sdl_alen != EALEN ) + panic("bootpc: HW address len is %d, expected value is %d", + sdl->sdl_alen,EALEN); +#if 1 + printf("bootpc hw address is "); + delim=""; + for (j=0;jsdl_alen;j++) { + printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]); + delim=":"; + } + printf("\n"); +#endif + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + + bzero((caddr_t) &call, sizeof(call)); + + /* bootpc part */ + call.op = 1; /* BOOTREQUEST */ + call.htype= 1; /* 10mb ethernet */ + call.hlen=sdl->sdl_alen; /* Hardware address length */ + call.hops=0; + xid++; + call.xid = txdr_unsigned(xid); + bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen); + + call.vend[0]=99; + call.vend[1]=130; + call.vend[2]=83; + call.vend[3]=99; + call.vend[4]=255; + + call.secs = 0; + call.flags = htons(0x8000); /* We need an broadcast answer */ + + error = bootpc_call(&call,&reply,procp); + + if (error) { +#ifdef BOOTP_NFSROOT + panic("BOOTP call failed"); +#endif + return; + } + + bzero(&myaddr,sizeof(myaddr)); + bzero(&netmask,sizeof(netmask)); + bzero(&gw,sizeof(gw)); + bzero(&server,sizeof(server)); + + myaddr.sin_len = sizeof(myaddr); + myaddr.sin_family = AF_INET; + + netmask.sin_len = sizeof(netmask); + netmask.sin_family = AF_INET; + + gw.sin_len = sizeof(gw); + gw.sin_family= AF_INET; + + server.sin_len = sizeof(gw); + server.sin_family= AF_INET; + + printf("My new ip address is %x\n",htonl(reply.yiaddr.s_addr)); + + myaddr.sin_addr = reply.yiaddr; + + printf("Server ip address is %x\n",htonl(reply.siaddr.s_addr)); + printf("Gateway ip address is %x\n",htonl(reply.giaddr.s_addr)); + + gw.sin_addr = reply.giaddr; + + if (reply.sname[0]) + printf("Server name is %s\n",reply.sname); + if (reply.file[0]) + printf("boot file is %s\n",reply.file); + if (reply.vend[0]==99 && reply.vend[1]==130 && + reply.vend[2]==83 && reply.vend[3]==99) { + j=4; + while (j=sizeof(reply.vend)) { + printf("Truncated field"); + break; + } + switch (code) { + case 1: + if (len!=4) + panic("bootpc: subnet mask len is %d",len); + bcopy(&reply.vend[j],&netmask.sin_addr,4); + gotnetmask=1; + printf("Subnet mask is %d.%d.%d.%d\n", + reply.vend[j], + reply.vend[j+1], + reply.vend[j+2], + reply.vend[j+3]); + break; + case 2: + /* Time offset */ + break; + case 3: + /* Routers */ + if (len % 4) + panic("bootpc: Router Len is %d",len); + if (len > 0) { + bcopy(&reply.vend[j],&gw.sin_addr,4); + gotgw=1; + } + for (i=0;i=sizeof(rootpath)) + panic("bootpc: rootpath >=%d bytes",sizeof(rootpath)); + strncpy(rootpath,&reply.vend[j],len); + rootpath[len]=0; + gotrootpath=1; + printf("Rootpath is %s\n",rootpath); + break; + case 12: + if (len>=MAXHOSTNAMELEN) + panic("bootpc: hostname >=%d bytes",MAXHOSTNAMELEN); + strncpy(nd->my_hostnam,&reply.vend[j],len); + nd->my_hostnam[len]=0; + strncpy(hostname,&reply.vend[j],len); + hostname[len]=0; + printf("Hostname is %s\n",hostname); + break; + case 128: + if (len>=sizeof(swappath)) + panic("bootpc: swappath >=%d bytes",sizeof(swappath)); + strncpy(swappath,&reply.vend[j],len); + swappath[len]=0; + gotswappath=1; + printf("Swappath is %s\n",swappath); + break; + case 129: + { + int swaplen; + if (len!=4) + panic("bootpc: Expected 4 bytes for swaplen, not %d bytes",len); + bcopy(&reply.vend[j],&swaplen,4); + nd->swap_nblks = ntohl(swaplen); + printf("bootpc: Swap size is %d KB\n",nd->swap_nblks); + } + break; + default: + printf("Ignoring field type %d\n",code); + } + j+=len; + } + } + + if (gotrootpath) { + bootp_expand_path(rootpath,sizeof(rootpath), + hostname, + myaddr.sin_addr); + printf("Rootpath is expanded to %s\n",rootpath); + if (gotswappath) { + bootp_expand_path(swappath,sizeof(swappath), + hostname, + myaddr.sin_addr); + printf("Swappath is expanded to %s\n",swappath); + } + else + nd->swap_nblks = 0; + } else { +#ifdef BOOTP_NFSROOT + panic("bootpc: No root path offered"); +#endif + } + + if (!gotserver) { + server.sin_addr = reply.siaddr ; + } + + if (!gotnetmask) { + if (IN_CLASSA(myaddr.sin_addr.s_addr)) + netmask.sin_addr.s_addr = IN_CLASSA_NET; + else if (IN_CLASSB(myaddr.sin_addr.s_addr)) + netmask.sin_addr.s_addr = IN_CLASSB_NET; + else + netmask.sin_addr.s_addr = IN_CLASSC_NET; + } + if (!gotgw) { + /* Use proxyarp */ + gw.sin_addr.s_addr = myaddr.sin_addr.s_addr; + } + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + error = bootpc_adjust_interface(&ireq,so, + &myaddr,&netmask,&gw,procp); + + soclose(so); + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + + nd->root_args.version = NFS_ARGSVERSION; + nd->root_args.rsize = 8192; + nd->root_args.wsize = 8192; + nd->root_args.sotype = SOCK_DGRAM; + nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | + NFSMNT_RESVPORT | NFSMNT_NOCONN); + + nd->swap_args.version = NFS_ARGSVERSION; + nd->swap_args.rsize = 8192; + nd->swap_args.wsize = 8192; + nd->swap_args.sotype = SOCK_DGRAM; + nd->swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | + NFSMNT_RESVPORT | NFSMNT_NOCONN); + + if (gotrootpath) { + if (server.sin_addr.s_addr != reply.siaddr.s_addr ) { + sprintf(nd->root_hostnam,"%d.%d.%d.%d", + ((unsigned char *) &server.sin_addr)[0], + ((unsigned char *) &server.sin_addr)[1], + ((unsigned char *) &server.sin_addr)[2], + ((unsigned char *) &server.sin_addr)[3]); + } else + strcpy(nd->root_hostnam,reply.sname); + bcopy(&server, &nd->root_saddr,sizeof(server)); + + error = md_mount(&nd->root_saddr, rootpath, nd->root_fh, &nd->root_fhsize, + &nd->root_args,procp); + if (error) + panic("nfs_boot: mountd root, error=%d", error); + + if (gotswappath) { + + char *p = swappath; + + while (*p) + p++; + while (p>=swappath && *p != '/') + p--; + + strcpy(nd->swap_hostnam, nd->root_hostnam); + + bcopy(&server, &nd->swap_saddr,sizeof(server)); + + if (p>swappath) + *p = '\0'; + error = md_mount(&nd->swap_saddr, + (p>swappath) ? swappath:"/", + nd->swap_fh, &nd->swap_fhsize,&nd->swap_args,procp); + if (error) + panic("nfs_boot: mountd swap, error=%d", error); + if (p>swappath) + *p = '/'; + + if (p>=swappath) + error = md_lookup_swap(&nd->swap_saddr,p+1,nd->swap_fh, + &nd->swap_fhsize, &nd->swap_args,procp); + if (error) + panic("nfs_boot: lookup swap, error=%d", error); + } + nfs_diskless_valid = 3; + } + + + bcopy(&myaddr,&nd->myif.ifra_addr,sizeof(myaddr)); + bcopy(&myaddr,&nd->myif.ifra_broadaddr,sizeof(myaddr)); + ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = + myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr; + bcopy(&netmask,&nd->myif.ifra_mask,sizeof(netmask)); + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + return; +} + +/* + * RPC: mountd/mount + * Given a server pathname, get an NFS file handle. + * Also, sets sin->sin_port to the NFS service port. + */ +static int +md_mount(mdsin, path, fhp, fhsizep, args, procp) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + int *fhsizep; + struct nfs_args *args; + struct proc *procp; +{ + struct mbuf *m; + int error; + int authunixok; + int authcount; + int authver; + +#ifdef BOOTP_NFSV3 + /* First try NFS v3 */ + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, + &mdsin->sin_port, procp); + if (!error) { + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, + RPCMNT_MOUNT, &m, NULL, curproc); + } + if (!error) { + args->flags |= NFSMNT_NFSV3; + } else { +#endif + /* Fallback to NFS v2 */ + + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, + &mdsin->sin_port, procp); + if (error) return error; + + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, + RPCMNT_MOUNT, &m, NULL, curproc); + if (error) + return error; /* message already freed */ + +#ifdef BOOTP_NFSV3 + } +#endif + + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + error = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (error) + goto bad; + m_adj(m,sizeof(u_int32_t)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + *fhsizep = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (*fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) + goto bad; + m_adj(m,sizeof(u_int32_t)); + } else + *fhsizep = NFSX_V2FH; + + if (m->m_len < (((*fhsizep)+3)&~3)) { + m = m_pullup(m,(((*fhsizep)+3)&~3)); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, *fhsizep); + m_adj(m,(((*fhsizep)+3)&~3)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + authcount = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + authunixok = 0; + m_adj(m,sizeof(u_int32_t)); + if (authcount<0 || authcount>100) + goto bad; + while (authcount>0) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + authver = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (authver == RPCAUTH_UNIX) + authunixok = 1; + authcount--; + m_adj(m,sizeof(u_int32_t)); + } + if (!authunixok) + goto bad; + } + + /* Set port number for NFS use. */ + error = krpc_portmap(mdsin, NFS_PROG, + (args->flags & NFSMNT_NFSV3)?NFS_VER3:NFS_VER2, + &mdsin->sin_port, procp); + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} + +static int md_lookup_swap(mdsin, path, fhp, fhsizep, args, procp) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + int *fhsizep; + struct nfs_args *args; + struct proc *procp; +{ + struct mbuf *m; + int error; + int size = -1; + int attribs_present; + int status; + + m = m_get(M_WAIT,MT_DATA); + if (!m) + return ENOBUFS; + + if (args->flags & NFSMNT_NFSV3) { + *mtod(m,u_int32_t *) = txdr_unsigned(*fhsizep); + bcopy(fhp,mtod(m,u_char *)+sizeof(u_int32_t),*fhsizep); + m->m_len = *fhsizep + sizeof(u_int32_t); + } else { + bcopy(fhp,mtod(m,u_char *),NFSX_V2FH); + m->m_len = NFSX_V2FH; + } + + m->m_next = xdr_string_encode(path, strlen(path)); + if (!m->m_next) { + error = ENOBUFS; + goto out; + } + + /* Do RPC to nfsd. */ + if (args->flags & NFSMNT_NFSV3) + error = krpc_call(mdsin, NFS_PROG, NFS_VER3, + NFSPROC_LOOKUP, &m, NULL, procp); + else + error = krpc_call(mdsin, NFS_PROG, NFS_VER2, + NFSV2PROC_LOOKUP, &m, NULL, procp); + if (error) + return error; /* message already freed */ + + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + status = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + m_adj(m,sizeof(u_int32_t)); + if (status) { + error = ENOENT; + goto out; + } + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + *fhsizep = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (*fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) + goto bad; + m_adj(m,sizeof(u_int32_t)); + } else + *fhsizep = NFSX_V2FH; + + if (m->m_len < (((*fhsizep)+3)&~3)) { + m = m_pullup(m,(((*fhsizep)+3)&~3)); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, *fhsizep); + m_adj(m,(((*fhsizep)+3)&~3)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + attribs_present = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + m_adj(m,sizeof(u_int32_t)); + if (attribs_present) { + if (m->m_len < sizeof(u_int32_t)*21) { + m = m_pullup(m, sizeof(u_int32_t)*21); + if (m == NULL) + goto bad; + } + size = fxdr_unsigned(u_int32_t, mtod(m,u_int32_t *)[6]); + } + } else { + if (m->m_len < sizeof(u_int32_t)*17) { + m = m_pullup(m, sizeof(u_int32_t)*17); + if (m == NULL) + goto bad; + } + size = fxdr_unsigned(u_int32_t, mtod(m,u_int32_t *)[5]); + } + + if (!nfsv3_diskless.swap_nblks && size!= -1) { + nfsv3_diskless.swap_nblks = size/1024; + printf("md_lookup_swap: Swap size is %d KB\n", + nfsv3_diskless.swap_nblks); + } + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} Property changes on: head/sys/nfsclient/bootp_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/nfsclient/krpc.h =================================================================== --- head/sys/nfsclient/krpc.h (nonexistent) +++ head/sys/nfsclient/krpc.h (revision 25723) @@ -0,0 +1,30 @@ +/* $NetBSD: krpc.h,v 1.4 1995/12/19 23:07:11 cgd Exp $ */ +/* $Id:$ */ + +#include + +int krpc_call __P((struct sockaddr_in *sin, + u_int prog, u_int vers, u_int func, + struct mbuf **data, struct mbuf **from, struct proc *procp)); + +int krpc_portmap __P((struct sockaddr_in *sin, + u_int prog, u_int vers, u_int16_t *portp,struct proc *procp)); + +struct mbuf *xdr_string_encode __P((char *str, int len)); +struct mbuf *xdr_string_decode __P((struct mbuf *m, char *str, int *len_p)); +struct mbuf *xdr_inaddr_encode __P((struct in_addr *ia)); +struct mbuf *xdr_inaddr_decode __P((struct mbuf *m, struct in_addr *ia)); + + +/* + * RPC definitions for the portmapper + */ +#define PMAPPORT 111 +#define PMAPPROG 100000 +#define PMAPVERS 2 +#define PMAPPROC_NULL 0 +#define PMAPPROC_SET 1 +#define PMAPPROC_UNSET 2 +#define PMAPPROC_GETPORT 3 +#define PMAPPROC_DUMP 4 +#define PMAPPROC_CALLIT 5 Property changes on: head/sys/nfsclient/krpc.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/nfsclient/krpc_subr.c =================================================================== --- head/sys/nfsclient/krpc_subr.c (nonexistent) +++ head/sys/nfsclient/krpc_subr.c (revision 25723) @@ -0,0 +1,592 @@ +/* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */ +/* $Id:$ */ + +/* + * Copyright (c) 1995 Gordon Ross, Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * partially based on: + * libnetboot/rpc.c + * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* + * Kernel support for Sun RPC + * + * Used currently for bootstrapping in nfs diskless configurations. + */ + +/* + * Generic RPC headers + */ + +struct auth_info { + u_int32_t authtype; /* auth type */ + u_int32_t authlen; /* auth length */ +}; + +struct auth_unix { + int32_t ua_time; + int32_t ua_hostname; /* null */ + int32_t ua_uid; + int32_t ua_gid; + int32_t ua_gidlist; /* null */ +}; + +struct rpc_call { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (0) */ + u_int32_t rp_rpcvers; /* rpc version (2) */ + u_int32_t rp_prog; /* program */ + u_int32_t rp_vers; /* version */ + u_int32_t rp_proc; /* procedure */ + struct auth_info rpc_auth; + struct auth_unix rpc_unix; + struct auth_info rpc_verf; +}; + +struct rpc_reply { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (1) */ + int32_t rp_astatus; /* accept status (0: accepted) */ + union { + u_int32_t rpu_errno; + struct { + struct auth_info rok_auth; + u_int32_t rok_status; + } rpu_rok; + } rp_u; +}; +#define rp_errno rp_u.rpu_errno +#define rp_auth rp_u.rpu_rok.rok_auth +#define rp_status rp_u.rpu_rok.rok_status + +#define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */ + +/* + * What is the longest we will wait before re-sending a request? + * Note this is also the frequency of "RPC timeout" messages. + * The re-send loop count sup linearly to this maximum, so the + * first complaint will happen after (1+2+3+4+5)=15 seconds. + */ +#define MAX_RESEND_DELAY 5 /* seconds */ + +/* + * Call portmap to lookup a port number for a particular rpc program + * Returns non-zero error on failure. + */ +int +krpc_portmap(sin, prog, vers, portp, procp) + struct sockaddr_in *sin; /* server address */ + u_int prog, vers; /* host order */ + u_int16_t *portp; /* network order */ + struct proc *procp; +{ + struct sdata { + u_int32_t prog; /* call program */ + u_int32_t vers; /* call version */ + u_int32_t proto; /* call protocol */ + u_int32_t port; /* call port (unused) */ + } *sdata; + struct rdata { + u_int16_t pad; + u_int16_t port; + } *rdata; + struct mbuf *m; + int error; + + /* The portmapper port is fixed. */ + if (prog == PMAPPROG) { + *portp = htons(PMAPPORT); + return 0; + } + + m = m_get(M_WAIT, MT_DATA); + if (m == NULL) + return ENOBUFS; + sdata = mtod(m, struct sdata *); + m->m_len = sizeof(*sdata); + + /* Do the RPC to get it. */ + sdata->prog = txdr_unsigned(prog); + sdata->vers = txdr_unsigned(vers); + sdata->proto = txdr_unsigned(IPPROTO_UDP); + sdata->port = 0; + + sin->sin_port = htons(PMAPPORT); + error = krpc_call(sin, PMAPPROG, PMAPVERS, + PMAPPROC_GETPORT, &m, NULL, procp); + if (error) + return error; + + if (m->m_len < sizeof(*rdata)) { + m = m_pullup(m, sizeof(*rdata)); + if (m == NULL) + return ENOBUFS; + } + rdata = mtod(m, struct rdata *); + *portp = rdata->port; + + m_freem(m); + return 0; +} + +/* + * Do a remote procedure call (RPC) and wait for its reply. + * If from_p is non-null, then we are doing broadcast, and + * the address from whence the response came is saved there. + */ +int +krpc_call(sa, prog, vers, func, data, from_p, procp) + struct sockaddr_in *sa; + u_int prog, vers, func; + struct mbuf **data; /* input/output */ + struct mbuf **from_p; /* output */ + struct proc *procp; +{ + struct socket *so; + struct sockaddr_in *sin; + struct mbuf *m, *nam, *mhead, *from; + struct rpc_call *call; + struct rpc_reply *reply; + struct uio auio; + int error, rcvflg, timo, secs, len; + static u_int32_t xid = ~0xFF; + u_int16_t tport; + + /* + * Validate address family. + * Sorry, this is INET specific... + */ + if (sa->sin_family != AF_INET) + return (EAFNOSUPPORT); + + /* Free at end if not null. */ + nam = mhead = NULL; + from = NULL; + + /* + * Create socket and set its recieve timeout. + */ + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, procp))) + goto out; + + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } else { + struct timeval *tv; + tv = mtod(m, struct timeval *); + m->m_len = sizeof(*tv); + tv->tv_sec = 1; + tv->tv_usec = 0; + if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m, procp))) + goto out; + } + + /* + * Enable broadcast if necessary. + */ + if (from_p) { + int32_t *on; + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + on = mtod(m, int32_t *); + m->m_len = sizeof(*on); + *on = 1; + if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m, procp))) + goto out; + } + + /* + * Bind the local endpoint to a reserved port, + * because some NFS servers refuse requests from + * non-reserved (non-privileged) ports. + */ + m = m_getclr(M_WAIT, MT_SONAME); + sin = mtod(m, struct sockaddr_in *); + sin->sin_len = m->m_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + tport = IPPORT_RESERVED; + do { + tport--; + sin->sin_port = htons(tport); + error = sobind(so, m, procp); + } while (error == EADDRINUSE && + tport > IPPORT_RESERVED / 2); + m_freem(m); + if (error) { + printf("bind failed\n"); + goto out; + } + + /* + * Setup socket address for the server. + */ + nam = m_get(M_WAIT, MT_SONAME); + if (nam == NULL) { + error = ENOBUFS; + goto out; + } + sin = mtod(nam, struct sockaddr_in *); + bcopy((caddr_t)sa, (caddr_t)sin, + (nam->m_len = sa->sin_len)); + + /* + * Prepend RPC message header. + */ + mhead = m_gethdr(M_WAIT, MT_DATA); + mhead->m_next = *data; + call = mtod(mhead, struct rpc_call *); + mhead->m_len = sizeof(*call); + bzero((caddr_t)call, sizeof(*call)); + /* rpc_call part */ + xid++; + call->rp_xid = txdr_unsigned(xid); + /* call->rp_direction = 0; */ + call->rp_rpcvers = txdr_unsigned(2); + call->rp_prog = txdr_unsigned(prog); + call->rp_vers = txdr_unsigned(vers); + call->rp_proc = txdr_unsigned(func); + /* rpc_auth part (auth_unix as root) */ + call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX); + call->rpc_auth.authlen = txdr_unsigned(sizeof(struct auth_unix)); + /* rpc_verf part (auth_null) */ + call->rpc_verf.authtype = 0; + call->rpc_verf.authlen = 0; + + /* + * Setup packet header + */ + len = 0; + m = mhead; + while (m) { + len += m->m_len; + m = m->m_next; + } + mhead->m_pkthdr.len = len; + mhead->m_pkthdr.rcvif = NULL; + + /* + * Send it, repeatedly, until a reply is received, + * but delay each re-send by an increasing amount. + * If the delay hits the maximum, start complaining. + */ + timo = 0; + for (;;) { + /* Send RPC request (or re-send). */ + m = m_copym(mhead, 0, M_COPYALL, M_WAIT); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + error = sosend(so, nam, NULL, m, NULL, 0); + if (error) { + printf("krpc_call: sosend: %d\n", error); + goto out; + } + m = NULL; + + /* Determine new timeout. */ + if (timo < MAX_RESEND_DELAY) + timo++; + else + printf("RPC timeout for server 0x%x\n", + ntohl(sin->sin_addr.s_addr)); + + /* + * Wait for up to timo seconds for a reply. + * The socket receive timeout was set to 1 second. + */ + secs = timo; + while (secs > 0) { + if (from) { + m_freem(from); + from = NULL; + } + if (m) { + m_freem(m); + m = NULL; + } + bzero(&auio,sizeof(auio)); + auio.uio_resid = len = 1<<16; + rcvflg = 0; + error = soreceive(so, &from, &auio, &m, NULL, &rcvflg); + if (error == EWOULDBLOCK) { + secs--; + continue; + } + if (error) + goto out; + len -= auio.uio_resid; + + /* Does the reply contain at least a header? */ + if (len < MIN_REPLY_HDR) + continue; + if (m->m_len < MIN_REPLY_HDR) + continue; + reply = mtod(m, struct rpc_reply *); + + /* Is it the right reply? */ + if (reply->rp_direction != txdr_unsigned(RPC_REPLY)) + continue; + + if (reply->rp_xid != txdr_unsigned(xid)) + continue; + + /* Was RPC accepted? (authorization OK) */ + if (reply->rp_astatus != 0) { + error = fxdr_unsigned(u_int32_t, reply->rp_errno); + printf("rpc denied, error=%d\n", error); + continue; + } + + /* Did the call succeed? */ + if (reply->rp_status != 0) { + error = fxdr_unsigned(u_int32_t, reply->rp_status); + if (error == RPC_PROGMISMATCH) { + error = EBADRPC; + goto out; + } + printf("rpc denied, status=%d\n", error); + continue; + } + + goto gotreply; /* break two levels */ + + } /* while secs */ + } /* forever send/receive */ + + error = ETIMEDOUT; + goto out; + + gotreply: + + /* + * Get RPC reply header into first mbuf, + * get its length, then strip it off. + */ + len = sizeof(*reply); + if (m->m_len < len) { + m = m_pullup(m, len); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + } + reply = mtod(m, struct rpc_reply *); + if (reply->rp_auth.authtype != 0) { + len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen); + len = (len + 3) & ~3; /* XXX? */ + } + m_adj(m, len); + + /* result */ + *data = m; + if (from_p) { + *from_p = from; + from = NULL; + } + + out: + if (nam) m_freem(nam); + if (mhead) m_freem(mhead); + if (from) m_freem(from); + soclose(so); + return error; +} + +/* + * eXternal Data Representation routines. + * (but with non-standard args...) + */ + +/* + * String representation for RPC. + */ +struct xdr_string { + u_int32_t len; /* length without null or padding */ + char data[4]; /* data (longer, of course) */ + /* data is padded to a long-word boundary */ +}; + +struct mbuf * +xdr_string_encode(str, len) + char *str; + int len; +{ + struct mbuf *m; + struct xdr_string *xs; + int dlen; /* padded string length */ + int mlen; /* message length */ + + dlen = (len + 3) & ~3; + mlen = dlen + 4; + + if (mlen > MCLBYTES) /* If too big, we just can't do it. */ + return (NULL); + + m = m_get(M_WAIT, MT_DATA); + if (mlen > MLEN) { + MCLGET(m, M_WAIT); + if ((m->m_flags & M_EXT) == 0) { + (void) m_free(m); /* There can be only one. */ + return (NULL); + } + } + xs = mtod(m, struct xdr_string *); + m->m_len = mlen; + xs->len = txdr_unsigned(len); + bcopy(str, xs->data, len); + return (m); +} + +struct mbuf * +xdr_string_decode(m, str, len_p) + struct mbuf *m; + char *str; + int *len_p; /* bufsize - 1 */ +{ + struct xdr_string *xs; + int mlen; /* message length */ + int slen; /* string length */ + + if (m->m_len < 4) { + m = m_pullup(m, 4); + if (m == NULL) + return (NULL); + } + xs = mtod(m, struct xdr_string *); + slen = fxdr_unsigned(u_int32_t, xs->len); + mlen = 4 + ((slen + 3) & ~3); + + if (slen > *len_p) + slen = *len_p; + m_copydata(m, 4, slen, str); + m_adj(m, mlen); + + str[slen] = '\0'; + *len_p = slen; + + return (m); +} + + +/* + * Inet address in RPC messages + * (Note, really four ints, NOT chars. Blech.) + */ +struct xdr_inaddr { + u_int32_t atype; + u_int32_t addr[4]; +}; + +struct mbuf * +xdr_inaddr_encode(ia) + struct in_addr *ia; /* already in network order */ +{ + struct mbuf *m; + struct xdr_inaddr *xi; + u_int8_t *cp; + u_int32_t *ip; + + m = m_get(M_WAIT, MT_DATA); + xi = mtod(m, struct xdr_inaddr *); + m->m_len = sizeof(*xi); + xi->atype = txdr_unsigned(1); + ip = xi->addr; + cp = (u_int8_t *)&ia->s_addr; + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + + return (m); +} + +struct mbuf * +xdr_inaddr_decode(m, ia) + struct mbuf *m; + struct in_addr *ia; /* already in network order */ +{ + struct xdr_inaddr *xi; + u_int8_t *cp; + u_int32_t *ip; + + if (m->m_len < sizeof(*xi)) { + m = m_pullup(m, sizeof(*xi)); + if (m == NULL) + return (NULL); + } + xi = mtod(m, struct xdr_inaddr *); + if (xi->atype != txdr_unsigned(1)) { + ia->s_addr = INADDR_ANY; + goto out; + } + ip = xi->addr; + cp = (u_int8_t *)&ia->s_addr; + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + +out: + m_adj(m, sizeof(*xi)); + return (m); +} Property changes on: head/sys/nfsclient/krpc_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/sys/nfsclient/nfs_vfsops.c =================================================================== --- head/sys/nfsclient/nfs_vfsops.c (revision 25722) +++ head/sys/nfsclient/nfs_vfsops.c (revision 25723) @@ -1,1028 +1,1055 @@ /* * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 - * $Id: nfs_vfsops.c,v 1.39 1997/05/03 13:42:50 phk Exp $ + * $Id: nfs_vfsops.c,v 1.40 1997/05/04 15:04:49 phk Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int nfs_mountroot __P((struct mount *mp)); extern int nfs_ticks; struct nfsstats nfsstats; SYSCTL_NODE(_vfs, MOUNT_NFS, nfs, CTLFLAG_RW, 0, "NFS filesystem"); SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD, &nfsstats, nfsstats, ""); #ifdef NFS_DEBUG int nfs_debug; SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); #endif static int nfs_iosize __P((struct nfsmount *nmp)); static int mountnfs __P((struct nfs_args *,struct mount *, struct mbuf *,char *,char *,struct vnode **)); static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p)); static int nfs_start __P(( struct mount *mp, int flags, struct proc *p)); static int nfs_unmount __P(( struct mount *mp, int mntflags, struct proc *p)); static int nfs_root __P(( struct mount *mp, struct vnode **vpp)); static int nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p)); static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp, struct proc *p)); static int nfs_sync __P(( struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)); static int nfs_vptofh __P(( struct vnode *vp, struct fid *fhp)); static int nfs_fhtovp __P((struct mount *mp, struct fid *fhp, struct mbuf *nam, struct vnode **vpp, int *exflagsp, struct ucred **credanonp)); static int nfs_vget __P((struct mount *, ino_t, struct vnode **)); /* * nfs vfs operations. */ static struct vfsops nfs_vfsops = { nfs_mount, nfs_start, nfs_unmount, nfs_root, nfs_quotactl, nfs_statfs, nfs_sync, nfs_vget, nfs_fhtovp, nfs_vptofh, nfs_init }; VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK); /* * This structure must be filled in by a primary bootstrap or bootstrap * server for a diskless/dataless machine. It is initialized below just * to ensure that it is allocated to initialized data (.data not .bss). */ struct nfs_diskless nfs_diskless = { 0 }; +struct nfsv3_diskless nfsv3_diskless = { 0 }; int nfs_diskless_valid = 0; SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, &nfs_diskless_valid, 0, ""); SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, - nfs_diskless.root_hostnam, 0, ""); + nfsv3_diskless.root_hostnam, 0, ""); SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, - &nfs_diskless.root_saddr, sizeof nfs_diskless.root_saddr, + &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr, "%Ssockaddr_in", ""); SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD, - nfs_diskless.swap_hostnam, 0, ""); + nfsv3_diskless.swap_hostnam, 0, ""); SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD, - &nfs_diskless.swap_saddr, sizeof nfs_diskless.swap_saddr, + &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, "%Ssockaddr_in",""); void nfsargs_ntoh __P((struct nfs_args *)); static int nfs_mountdiskless __P((char *, char *, int, struct sockaddr_in *, struct nfs_args *, struct proc *, struct vnode **, struct mount **)); +void nfs_convert_diskless __P((void)); static int nfs_iosize(nmp) struct nfsmount* nmp; { int iosize; /* * Calculate the size used for io buffers. Use the larger * of the two sizes to minimise nfs requests but make sure * that it is at least one VM page to avoid wasting buffer * space. */ iosize = max(nmp->nm_rsize, nmp->nm_wsize); if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; return iosize; } +void nfs_convert_diskless() +{ + bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, + sizeof(struct ifaliasreq)); + bcopy(&nfs_diskless.swap_args,&nfsv3_diskless.swap_args, + sizeof(struct nfs_args)); + nfsv3_diskless.swap_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH); + bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, + MNAMELEN); + nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks; + bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred, + sizeof(struct ucred)); + bcopy(&nfs_diskless.root_args,&nfsv3_diskless.root_args, + sizeof(struct nfs_args)); + nfsv3_diskless.root_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH); + bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, + MNAMELEN); + nfsv3_diskless.root_time = nfs_diskless.root_time; + bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam, + MAXHOSTNAMELEN); + nfs_diskless_valid = 3; +} + /* * nfs statfs call */ int nfs_statfs(mp, sbp, p) struct mount *mp; register struct statfs *sbp; struct proc *p; { register struct vnode *vp; register struct nfs_statfs *sfp; register caddr_t cp; register u_long *tl; register long t1, t2; caddr_t bpos, dpos, cp2; struct nfsmount *nmp = VFSTONFS(mp); int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct ucred *cred; struct nfsnode *np; u_quad_t tquad; #ifndef nolint sfp = (struct nfs_statfs *)0; #endif error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return (error); vp = NFSTOV(np); cred = crget(); cred->cr_ngroups = 1; if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, cred, p); nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); nfsm_fhtom(vp, v3); nfsm_request(vp, NFSPROC_FSSTAT, p, cred); if (v3) nfsm_postop_attr(vp, retattr); if (!error) nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); #ifdef __NetBSD__ #ifdef COMPAT_09 sbp->f_type = 2; #else sbp->f_type = 0; #endif #else sbp->f_type = MOUNT_NFS; #endif sbp->f_flags = nmp->nm_flag; sbp->f_iosize = nfs_iosize(nmp); if (v3) { sbp->f_bsize = NFS_FABLKSIZE; fxdr_hyper(&sfp->sf_tbytes, &tquad); sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); fxdr_hyper(&sfp->sf_fbytes, &tquad); sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); fxdr_hyper(&sfp->sf_abytes, &tquad); sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); } else { sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; } if (sbp != &mp->mnt_stat) { bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); } nfsm_reqdone; vput(vp); crfree(cred); return (error); } /* * nfs version 3 fsinfo rpc call */ int nfs_fsinfo(nmp, vp, cred, p) register struct nfsmount *nmp; register struct vnode *vp; struct ucred *cred; struct proc *p; { register struct nfsv3_fsinfo *fsp; register caddr_t cp; register long t1, t2; register u_long *tl, pref, max; caddr_t bpos, dpos, cp2; int error = 0, retattr; struct mbuf *mreq, *mrep, *md, *mb, *mb2; nfsstats.rpccnt[NFSPROC_FSINFO]++; nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); nfsm_fhtom(vp, 1); nfsm_request(vp, NFSPROC_FSINFO, p, cred); nfsm_postop_attr(vp, retattr); if (!error) { nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); pref = fxdr_unsigned(u_long, fsp->fs_wtpref); if (pref < nmp->nm_wsize) nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_long, fsp->fs_wtmax); if (max < nmp->nm_wsize) { nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize == 0) nmp->nm_wsize = max; } pref = fxdr_unsigned(u_long, fsp->fs_rtpref); if (pref < nmp->nm_rsize) nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_long, fsp->fs_rtmax); if (max < nmp->nm_rsize) { nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize == 0) nmp->nm_rsize = max; } pref = fxdr_unsigned(u_long, fsp->fs_dtpref); if (pref < nmp->nm_readdirsize) nmp->nm_readdirsize = pref; if (max < nmp->nm_readdirsize) { nmp->nm_readdirsize = max; } nmp->nm_flag |= NFSMNT_GOTFSINFO; } nfsm_reqdone; return (error); } /* * Mount a remote root fs via. nfs. This depends on the info in the * nfs_diskless structure that has been filled in properly by some primary * bootstrap. * It goes something like this: * - do enough of "ifconfig" by calling ifioctl() so that the system * can talk to the server * - If nfs_diskless.mygateway is filled in, use that address as * a default gateway. * - hand craft the swap nfs vnode hanging off a fake mount point * if swdevt[0].sw_dev == NODEV * - build the rootfs mount point and call mountnfs() to do the rest. */ int nfs_mountroot(mp) struct mount *mp; { struct mount *swap_mp; - struct nfs_diskless *nd = &nfs_diskless; + struct nfsv3_diskless *nd = &nfsv3_diskless; struct socket *so; struct vnode *vp; struct proc *p = curproc; /* XXX */ int error, i; u_long l; char buf[128]; /* * XXX time must be non-zero when we init the interface or else * the arp code will wedge... */ if (time.tv_sec == 0) time.tv_sec = 1; + if (nfs_diskless_valid==1) + nfs_convert_diskless(); + /* * XXX splnet, so networks will receive... */ splnet(); #ifdef notyet /* Set up swap credentials. */ proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid); proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid); if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) > NGROUPS) proc0.p_ucred->cr_ngroups = NGROUPS; for (i = 0; i < proc0.p_ucred->cr_ngroups; i++) proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]); #endif /* * Do enough of ifconfig(8) so that the critical net interface can * talk to the server. */ error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, p); if (error) panic("nfs_mountroot: socreate(%04x): %d", nd->myif.ifra_addr.sa_family, error); /* * We might not have been told the right interface, so we pass * over the first ten interfaces of the same kind, until we get * one of them configured. */ for (i = strlen(nd->myif.ifra_name) - 1; nd->myif.ifra_name[i] >= '0' && nd->myif.ifra_name[i] <= '9'; nd->myif.ifra_name[i] ++) { error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p); if(!error) break; } if (error) panic("nfs_mountroot: SIOCAIFADDR: %d", error); soclose(so); /* * If the gateway field is filled in, set it as the default route. */ if (nd->mygateway.sin_len != 0) { struct sockaddr_in mask, sin; bzero((caddr_t)&mask, sizeof(mask)); sin = mask; sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); error = rtrequest(RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&nd->mygateway, (struct sockaddr *)&mask, RTF_UP | RTF_GATEWAY, (struct rtentry **)0); if (error) panic("nfs_mountroot: RTM_ADD: %d", error); } /* * Create the rootfs mount point. */ nd->root_args.fh = nd->root_fh; - /* - * If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize. - */ - nd->root_args.fhsize = NFSX_V2FH; + nd->root_args.fhsize = nd->root_fhsize; l = ntohl(nd->root_saddr.sin_addr.s_addr); sprintf(buf,"%ld.%ld.%ld.%ld:%s", (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam); printf("NFS ROOT: %s\n",buf); if (error = nfs_mountdiskless(buf, "/", MNT_RDONLY, &nd->root_saddr, &nd->root_args, p, &vp, &mp)) { if (swap_mp) { mp->mnt_vfc->vfc_refcount--; free(swap_mp, M_MOUNT); } return (error); } swap_mp = NULL; if (nd->swap_nblks) { /* Convert to DEV_BSIZE instead of Kilobyte */ nd->swap_nblks *= 2; /* * Create a fake mount point just for the swap vnode so that the * swap file can be on a different server from the rootfs. */ nd->swap_args.fh = nd->swap_fh; - /* - * If using nfsv3_diskless, replace NFSX_V2FH with - * nd->swap_fhsize. - */ - nd->swap_args.fhsize = NFSX_V2FH; + nd->swap_args.fhsize = nd->swap_fhsize; l = ntohl(nd->swap_saddr.sin_addr.s_addr); sprintf(buf,"%ld.%ld.%ld.%ld:%s", (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam); printf("NFS SWAP: %s\n",buf); if (error = nfs_mountdiskless(buf, "/swap", 0, &nd->swap_saddr, &nd->swap_args, p, &vp, &swap_mp)) return (error); vfs_unbusy(swap_mp, p); VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = nd->swap_nblks * DEV_BSIZE ; /* * Since the swap file is not the root dir of a file system, * hack it to a regular file. */ vp->v_type = VREG; vp->v_flag = 0; VREF(vp); swaponvp(p, vp, NODEV, nd->swap_nblks); } mp->mnt_flag |= MNT_ROOTFS; mp->mnt_vnodecovered = NULLVP; rootvp = vp; vfs_unbusy(mp, p); /* * This is not really an nfs issue, but it is much easier to * set hostname here and then let the "/etc/rc.xxx" files * mount the right /var based upon its preset value. */ bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN); hostname[MAXHOSTNAMELEN - 1] = '\0'; for (i = 0; i < MAXHOSTNAMELEN; i++) if (hostname[i] == '\0') break; inittodr(ntohl(nd->root_time)); return (0); } /* * Internal version of mount system call for diskless setup. */ static int nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp) char *path; char *which; int mountflag; struct sockaddr_in *sin; struct nfs_args *args; struct proc *p; struct vnode **vpp; struct mount **mpp; { struct mount *mp; struct mbuf *m; int error; mp = *mpp; if (!mp && ( error = vfs_rootmountalloc("nfs", path, &mp))) { printf("nfs_mountroot: NFS not configured"); return (error); } mp->mnt_flag = mountflag; MGET(m, MT_SONAME, M_WAITOK); bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len); m->m_len = sin->sin_len; if (error = mountnfs(args, mp, m, which, path, vpp)) { printf("nfs_mountroot: mount %s on %s: %d", path, which, error); mp->mnt_vfc->vfc_refcount--; vfs_unbusy(mp, p); free(mp, M_MOUNT); return (error); } (void) copystr(which, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); *mpp = mp; return (0); } #ifndef NO_COMPAT_PRELITE2 /* * Old arguments to mount NFS */ struct onfs_args { struct sockaddr *addr; /* file server address */ int addrlen; /* length of address */ int sotype; /* Socket type */ int proto; /* and Protocol */ u_char *fh; /* File handle to be mounted */ int fhsize; /* Size, in bytes, of fh */ int flags; /* flags */ int wsize; /* write size in bytes */ int rsize; /* read size in bytes */ int readdirsize; /* readdir size in bytes */ int timeo; /* initial timeout in .1 secs */ int retrans; /* times to retry send */ int maxgrouplist; /* Max. size of group list */ int readahead; /* # of blocks to readahead */ int leaseterm; /* Term (sec) of lease */ int deadthresh; /* Retrans threshold */ char *hostname; /* server's name */ }; #endif /* !NO_COMPAT_PRELITE2 */ /* * VFS Operations. * * mount system call * It seems a bit dumb to copyinstr() the host and path here and then * bcopy() them in mountnfs(), but I wanted to detect errors before * doing the sockargs() call because sockargs() allocates an mbuf and * an error after that means that I have to release the mbuf. */ /* ARGSUSED */ static int nfs_mount(mp, path, data, ndp, p) struct mount *mp; char *path; caddr_t data; struct nameidata *ndp; struct proc *p; { int error; struct nfs_args args; struct mbuf *nam; struct vnode *vp; char pth[MNAMELEN], hst[MNAMELEN]; u_int len; u_char nfh[NFSX_V3FHMAX]; if (path == NULL) { nfs_mountroot(mp); return (0); } error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); if (error) return (error); if (args.version != NFS_ARGSVERSION) { #ifndef NO_COMPAT_PRELITE2 /* * If the argument version is unknown, then assume the * caller is a pre-lite2 4.4BSD client and convert its * arguments. */ struct onfs_args oargs; error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args)); if (error) return (error); args.version = NFS_ARGSVERSION; args.addr = oargs.addr; args.addrlen = oargs.addrlen; args.sotype = oargs.sotype; args.proto = oargs.proto; args.fh = oargs.fh; args.fhsize = oargs.fhsize; args.flags = oargs.flags; args.wsize = oargs.wsize; args.rsize = oargs.rsize; args.readdirsize = oargs.readdirsize; args.timeo = oargs.timeo; args.retrans = oargs.retrans; args.maxgrouplist = oargs.maxgrouplist; args.readahead = oargs.readahead; args.leaseterm = oargs.leaseterm; args.deadthresh = oargs.deadthresh; args.hostname = oargs.hostname; #else /* NO_COMPAT_PRELITE2 */ return (EPROGMISMATCH); #endif /* !NO_COMPAT_PRELITE2 */ } error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); if (error) return (error); error = copyinstr(path, pth, MNAMELEN-1, &len); if (error) return (error); bzero(&pth[len], MNAMELEN - len); error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); if (error) return (error); bzero(&hst[len], MNAMELEN - len); /* sockargs() call must be after above copyin() calls */ error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME); if (error) return (error); args.fh = nfh; error = mountnfs(&args, mp, nam, pth, hst, &vp); return (error); } /* * Common code for mount and mountroot */ static int mountnfs(argp, mp, nam, pth, hst, vpp) register struct nfs_args *argp; register struct mount *mp; struct mbuf *nam; char *pth, *hst; struct vnode **vpp; { register struct nfsmount *nmp; struct nfsnode *np; int error, maxio; struct vattr attrs; if (mp->mnt_flag & MNT_UPDATE) { nmp = VFSTONFS(mp); /* update paths, file handles, etc, here XXX */ m_freem(nam); return (0); } else { MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount), M_NFSMNT, M_WAITOK); bzero((caddr_t)nmp, sizeof (struct nfsmount)); TAILQ_INIT(&nmp->nm_uidlruhead); TAILQ_INIT(&nmp->nm_bufq); mp->mnt_data = (qaddr_t)nmp; } vfs_getnewfsid(mp); nmp->nm_mountp = mp; nmp->nm_flag = argp->flags; if (nmp->nm_flag & NFSMNT_NQNFS) /* * We have to set mnt_maxsymlink to a non-zero value so * that COMPAT_43 routines will know that we are setting * the d_type field in directories (and can zero it for * unsuspecting binaries). */ mp->mnt_maxsymlinklen = 1; nmp->nm_timeo = NFS_TIMEO; nmp->nm_retry = NFS_RETRANS; nmp->nm_wsize = NFS_WSIZE; nmp->nm_rsize = NFS_RSIZE; nmp->nm_readdirsize = NFS_READDIRSIZE; nmp->nm_numgrps = NFS_MAXGRPS; nmp->nm_readahead = NFS_DEFRAHEAD; nmp->nm_leaseterm = NQ_DEFLEASE; nmp->nm_deadthresh = NQ_DEADTHRESH; CIRCLEQ_INIT(&nmp->nm_timerhead); nmp->nm_inprog = NULLVP; nmp->nm_fhsize = argp->fhsize; bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); nmp->nm_nam = nam; if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; if (nmp->nm_timeo < NFS_MINTIMEO) nmp->nm_timeo = NFS_MINTIMEO; else if (nmp->nm_timeo > NFS_MAXTIMEO) nmp->nm_timeo = NFS_MAXTIMEO; } if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { nmp->nm_retry = argp->retrans; if (nmp->nm_retry > NFS_MAXREXMIT) nmp->nm_retry = NFS_MAXREXMIT; } if (argp->flags & NFSMNT_NFSV3) { if (argp->sotype == SOCK_DGRAM) maxio = NFS_MAXDGRAMDATA; else maxio = NFS_MAXDATA; } else maxio = NFS_V2MAXDATA; if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { nmp->nm_wsize = argp->wsize; /* Round down to multiple of blocksize */ nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize <= 0) nmp->nm_wsize = NFS_FABLKSIZE; } if (nmp->nm_wsize > maxio) nmp->nm_wsize = maxio; if (nmp->nm_wsize > MAXBSIZE) nmp->nm_wsize = MAXBSIZE; if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { nmp->nm_rsize = argp->rsize; /* Round down to multiple of blocksize */ nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize <= 0) nmp->nm_rsize = NFS_FABLKSIZE; } if (nmp->nm_rsize > maxio) nmp->nm_rsize = maxio; if (nmp->nm_rsize > MAXBSIZE) nmp->nm_rsize = MAXBSIZE; if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { nmp->nm_readdirsize = argp->readdirsize; } if (nmp->nm_readdirsize > maxio) nmp->nm_readdirsize = maxio; if (nmp->nm_readdirsize > nmp->nm_rsize) nmp->nm_readdirsize = nmp->nm_rsize; if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && argp->maxgrouplist <= NFS_MAXGRPS) nmp->nm_numgrps = argp->maxgrouplist; if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && argp->readahead <= NFS_MAXRAHEAD) nmp->nm_readahead = argp->readahead; if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && argp->leaseterm <= NQ_MAXLEASE) nmp->nm_leaseterm = argp->leaseterm; if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && argp->deadthresh <= NQ_NEVERDEAD) nmp->nm_deadthresh = argp->deadthresh; /* Set up the sockets and per-host congestion */ nmp->nm_sotype = argp->sotype; nmp->nm_soproto = argp->proto; /* * For Connection based sockets (TCP,...) defer the connect until * the first request, in case the server is not responding. */ if (nmp->nm_sotype == SOCK_DGRAM && (error = nfs_connect(nmp, (struct nfsreq *)0))) goto bad; /* * This is silly, but it has to be set so that vinifod() works. * We do not want to do an nfs_statfs() here since we can get * stuck on a dead server and we are holding a lock on the mount * point. */ mp->mnt_stat.f_iosize = nfs_iosize(nmp); /* * A reference count is needed on the nfsnode representing the * remote root. If this object is not persistent, then backward * traversals of the mount point (i.e. "..") will not work if * the nfsnode gets flushed out of the cache. Ufs does not have * this problem, because one can identify root inodes by their * number == ROOTINO (2). */ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) goto bad; *vpp = NFSTOV(np); /* * Get file attributes for the mountpoint. This has the side * effect of filling in (*vpp)->v_type with the correct value. */ VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc); /* * Lose the lock but keep the ref. */ VOP_UNLOCK(*vpp, 0, curproc); return (0); bad: nfs_disconnect(nmp); free((caddr_t)nmp, M_NFSMNT); m_freem(nam); return (error); } /* * unmount system call */ static int nfs_unmount(mp, mntflags, p) struct mount *mp; int mntflags; struct proc *p; { register struct nfsmount *nmp; struct nfsnode *np; struct vnode *vp; int error, flags = 0; if (mntflags & MNT_FORCE) flags |= FORCECLOSE; nmp = VFSTONFS(mp); /* * Goes something like this.. * - Check for activity on the root vnode (other than ourselves). * - Call vflush() to clear out vnodes for this file system, * except for the root vnode. * - Decrement reference on the vnode representing remote root. * - Close the socket * - Free up the data structures */ /* * We need to decrement the ref. count on the nfsnode representing * the remote root. See comment in mountnfs(). The VFS unmount() * has done vput on this vnode, otherwise we would get deadlock! */ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return(error); vp = NFSTOV(np); if (vp->v_usecount > 2) { vput(vp); return (EBUSY); } /* * Must handshake with nqnfs_clientd() if it is active. */ nmp->nm_flag |= NFSMNT_DISMINPROG; while (nmp->nm_inprog != NULLVP) (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); error = vflush(mp, vp, flags); if (error) { vput(vp); nmp->nm_flag &= ~NFSMNT_DISMINPROG; return (error); } /* * We are now committed to the unmount. * For NQNFS, let the server daemon free the nfsmount structure. */ if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) nmp->nm_flag |= NFSMNT_DISMNT; /* * There are two reference counts and one lock to get rid of here. */ vput(vp); vrele(vp); vgone(vp); nfs_disconnect(nmp); m_freem(nmp->nm_nam); if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0) free((caddr_t)nmp, M_NFSMNT); return (0); } /* * Return root of a filesystem */ static int nfs_root(mp, vpp) struct mount *mp; struct vnode **vpp; { register struct vnode *vp; struct nfsmount *nmp; struct nfsnode *np; int error; nmp = VFSTONFS(mp); error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return (error); vp = NFSTOV(np); if (vp->v_type == VNON) vp->v_type = VDIR; vp->v_flag = VROOT; *vpp = vp; return (0); } extern int syncprt; /* * Flush out the buffer cache */ /* ARGSUSED */ static int nfs_sync(mp, waitfor, cred, p) struct mount *mp; int waitfor; struct ucred *cred; struct proc *p; { register struct vnode *vp; int error, allerror = 0; /* * Force stale buffer cache information to be flushed. */ loop: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = vp->v_mntvnodes.le_next) { /* * If the vnode that we are about to sync is no longer * associated with this mount point, start over. */ if (vp->v_mount != mp) goto loop; if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL) continue; if (vget(vp, LK_EXCLUSIVE, p)) goto loop; error = VOP_FSYNC(vp, cred, waitfor, p); if (error) allerror = error; vput(vp); } return (allerror); } /* * NFS flat namespace lookup. * Currently unsupported. */ /* ARGSUSED */ static int nfs_vget(mp, ino, vpp) struct mount *mp; ino_t ino; struct vnode **vpp; { return (EOPNOTSUPP); } /* * At this point, this should never happen */ /* ARGSUSED */ static int nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) register struct mount *mp; struct fid *fhp; struct mbuf *nam; struct vnode **vpp; int *exflagsp; struct ucred **credanonp; { return (EINVAL); } /* * Vnode pointer to File handle, should never happen either */ /* ARGSUSED */ static int nfs_vptofh(vp, fhp) struct vnode *vp; struct fid *fhp; { return (EINVAL); } /* * Vfs start routine, a no-op. */ /* ARGSUSED */ static int nfs_start(mp, flags, p) struct mount *mp; int flags; struct proc *p; { return (0); } /* * Do operations associated with quotas, not supported */ /* ARGSUSED */ static int nfs_quotactl(mp, cmd, uid, arg, p) struct mount *mp; int cmd; uid_t uid; caddr_t arg; struct proc *p; { return (EOPNOTSUPP); } Index: stable/2.2/sys/conf/files =================================================================== --- stable/2.2/sys/conf/files (revision 25722) +++ stable/2.2/sys/conf/files (revision 25723) @@ -1,393 +1,395 @@ ddb/db_access.c optional ddb ddb/db_aout.c optional ddb ddb/db_break.c optional ddb ddb/db_command.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_lex.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_sym.c optional ddb ddb/db_trap.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb dev/ccd/ccd.c optional ccd device-driver dev/pdq/pdq.c optional fea device-driver dev/pdq/pdq_ifsubr.c optional fea device-driver dev/pdq/pdq.c optional fpa device-driver dev/pdq/pdq_ifsubr.c optional fpa device-driver dev/vn/vn.c optional vn dev/vx/if_vx.c optional vx device-driver gnu/ext2fs/ext2_alloc.c optional ext2fs gnu/ext2fs/ext2_balloc.c optional ext2fs gnu/ext2fs/ext2_inode.c optional ext2fs gnu/ext2fs/ext2_inode_cnv.c optional ext2fs gnu/ext2fs/ext2_linux_balloc.c optional ext2fs gnu/ext2fs/ext2_linux_ialloc.c optional ext2fs gnu/ext2fs/ext2_lookup.c optional ext2fs gnu/ext2fs/ext2_subr.c optional ext2fs gnu/ext2fs/ext2_vfsops.c optional ext2fs gnu/ext2fs/ext2_vnops.c optional ext2fs isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 kern/imgact_aout.c standard kern/imgact_elf.c standard kern/imgact_gzip.c optional gzip kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard kern/init_sysvec.c standard kern/kern_acct.c standard kern/kern_clock.c standard kern/kern_conf.c standard kern/kern_descrip.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_ktrace.c standard kern/kern_lkm.c standard kern/kern_lockf.c standard kern/kern_malloc.c standard kern/kern_mib.c standard kern/kern_ntptime.c standard kern/kern_opt.c standard kern/kern_physio.c standard kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_synch.c standard kern/kern_sysctl.c standard kern/kern_time.c standard kern/kern_xxx.c standard kern/md5c.c optional md5 kern/subr_diskslice.c standard kern/subr_dkbad.c standard kern/subr_log.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rlist.c standard kern/subr_xxx.c standard kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c standard kern/tty_conf.c standard kern/tty_pty.c optional pty kern/tty_snoop.c optional snp kern/tty_subr.c standard kern/tty_tb.c optional tb kern/tty_tty.c standard kern/uipc_domain.c standard kern/uipc_mbuf.c standard kern/uipc_proto.c standard kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_conf.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard miscfs/deadfs/dead_vnops.c standard miscfs/devfs/devfs_tree.c optional devfs miscfs/devfs/devfs_vfsops.c optional devfs miscfs/devfs/devfs_vnops.c optional devfs miscfs/fdesc/fdesc_vfsops.c optional fdesc miscfs/fdesc/fdesc_vnops.c optional fdesc miscfs/fifofs/fifo_vnops.c standard miscfs/kernfs/kernfs_vfsops.c optional kernfs miscfs/kernfs/kernfs_vnops.c optional kernfs miscfs/nullfs/null_subr.c optional nullfs miscfs/nullfs/null_vfsops.c optional nullfs miscfs/nullfs/null_vnops.c optional nullfs miscfs/portal/portal_vfsops.c optional portal miscfs/portal/portal_vnops.c optional portal miscfs/procfs/procfs_ctl.c optional procfs miscfs/procfs/procfs_fpregs.c standard miscfs/procfs/procfs_map.c optional procfs miscfs/procfs/procfs_mem.c standard miscfs/procfs/procfs_note.c optional procfs miscfs/procfs/procfs_regs.c standard miscfs/procfs/procfs_status.c optional procfs miscfs/procfs/procfs_subr.c optional procfs miscfs/procfs/procfs_type.c optional procfs miscfs/procfs/procfs_vfsops.c optional procfs miscfs/procfs/procfs_vnops.c optional procfs miscfs/specfs/spec_vnops.c standard miscfs/umapfs/umap_subr.c optional umapfs miscfs/umapfs/umap_vfsops.c optional umapfs miscfs/umapfs/umap_vnops.c optional umapfs miscfs/union/union_subr.c optional union miscfs/union/union_vfsops.c optional union miscfs/union/union_vnops.c optional union msdosfs/msdosfs_conv.c optional msdosfs msdosfs/msdosfs_denode.c optional msdosfs msdosfs/msdosfs_fat.c optional msdosfs msdosfs/msdosfs_lookup.c optional msdosfs msdosfs/msdosfs_vfsops.c optional msdosfs msdosfs/msdosfs_vnops.c optional msdosfs net/bpf.c optional bpfilter net/bpf_filter.c optional bpfilter net/bsd_comp.c optional ppp net/if.c standard net/if_disc.c optional disc net/if_ethersubr.c optional ether net/if_fddisubr.c optional fddi net/if_loop.c optional loop net/if_mib.c standard net/if_ppp.c optional ppp net/if_sl.c optional sl net/if_spppsubr.c optional sppp net/if_tun.c optional tun net/ppp_tty.c optional ppp net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional ppp net/slcompress.c optional sl netatalk/aarp.c optional netatalk netatalk/at_control.c optional netatalk netatalk/at_proto.c optional netatalk netatalk/at_rmx.c optional netatalkdebug netatalk/ddp_input.c optional netatalk netatalk/ddp_output.c optional netatalk netatalk/ddp_usrreq.c optional netatalk #netccitt/ccitt_proto.c optional ccitt #netccitt/hd_debug.c optional hdlc #netccitt/hd_input.c optional hdlc #netccitt/hd_output.c optional hdlc #netccitt/hd_subr.c optional hdlc #netccitt/hd_timer.c optional hdlc #netccitt/if_x25subr.c optional ccitt #netccitt/llc_input.c optional llc #netccitt/llc_output.c optional llc #netccitt/llc_subr.c optional llc #netccitt/llc_timer.c optional llc #netccitt/pk_acct.c optional ccitt #netccitt/pk_debug.c optional ccitt #netccitt/pk_input.c optional ccitt #netccitt/pk_llcsubr.c optional hdlc #netccitt/pk_llcsubr.c optional llc #netccitt/pk_output.c optional ccitt #netccitt/pk_subr.c optional ccitt #netccitt/pk_timer.c optional ccitt #netccitt/pk_usrreq.c optional ccitt #netimp/if_imp.c optional imp #netimp/if_imphost.c optional imp #netimp/raw_imp.c optional imp netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet netinet/in_rmx.c optional inet netinet/ip_divert.c optional ipdivert netinet/ip_fw.c optional ipfirewall netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_mroute.c optional inet netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/tcp_debug.c optional tcpdebug netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_error.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_tun.c optional ipx netipx/ipx_usrreq.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx #netiso/clnp_debug.c optional iso #netiso/clnp_er.c optional iso #netiso/clnp_frag.c optional iso #netiso/clnp_input.c optional iso #netiso/clnp_options.c optional iso #netiso/clnp_output.c optional iso #netiso/clnp_raw.c optional iso #netiso/clnp_subr.c optional iso #netiso/clnp_timer.c optional iso #netiso/cltp_usrreq.c optional iso #netiso/esis.c optional iso #netiso/idrp_usrreq.c optional iso #netiso/if_eon.c optional eon #netiso/iso.c optional iso #netiso/iso_chksum.c optional iso #netiso/iso_pcb.c optional iso #netiso/iso_proto.c optional iso #netiso/iso_snpac.c optional iso #netiso/tp_astring.c optional iso #netiso/tp_astring.c optional tpip #netiso/tp_cons.c optional iso #netiso/tp_driver.c optional iso #netiso/tp_driver.c optional tpip #netiso/tp_emit.c optional iso #netiso/tp_emit.c optional tpip #netiso/tp_inet.c optional iso #netiso/tp_inet.c optional tpip #netiso/tp_input.c optional iso #netiso/tp_input.c optional tpip #netiso/tp_iso.c optional iso #netiso/tp_meas.c optional iso #netiso/tp_meas.c optional tpip #netiso/tp_output.c optional iso #netiso/tp_output.c optional tpip #netiso/tp_pcb.c optional iso #netiso/tp_pcb.c optional tpip #netiso/tp_subr.c optional iso #netiso/tp_subr.c optional tpip #netiso/tp_subr2.c optional iso #netiso/tp_subr2.c optional tpip #netiso/tp_timer.c optional iso #netiso/tp_timer.c optional tpip #netiso/tp_trace.c optional iso #netiso/tp_trace.c optional tpip #netiso/tp_usrreq.c optional iso #netiso/tp_usrreq.c optional tpip #netiso/tuba_subr.c optional iso tuba #netiso/tuba_table.c optional iso tuba #netiso/tuba_usrreq.c optional iso tuba netkey/key.c optional key #netns/idp_usrreq.c optional ns #netns/ns.c optional ns #netns/ns_error.c optional ns #netns/ns_input.c optional ns #netns/ns_ip.c optional ns #netns/ns_output.c optional ns #netns/ns_pcb.c optional ns #netns/ns_proto.c optional ns #netns/spp_debug.c optional ns #netns/spp_usrreq.c optional ns nfs/nfs_bio.c optional nfs nfs/nfs_node.c optional nfs nfs/nfs_nqlease.c optional nfs nfs/nfs_serv.c optional nfs nfs/nfs_socket.c optional nfs nfs/nfs_srvcache.c optional nfs nfs/nfs_subs.c optional nfs nfs/nfs_syscalls.c optional nfs nfs/nfs_vfsops.c optional nfs nfs/nfs_vnops.c optional nfs +nfs/bootp_subr.c optional bootp +nfs/krpc_subr.c optional bootp pccard/pccard.c optional crd pccard/pcic.c optional pcic device-driver pci/aic7870.c optional ahc device-driver \ dependency "aic7xxx_reg.h $S/pci/aic7870.c" pci/bt9xx.c optional bt device-driver pci/cy_pci.c optional cy device-driver pci/if_de.c optional de device-driver pci/if_ed_p.c optional ed device-driver pci/if_fxp.c optional fxp device-driver pci/if_lnc_p.c optional lnc device-driver pci/if_fpa.c optional fpa device-driver pci/if_sr_p.c optional sr device-driver pci/if_vx_pci.c optional vx device-driver pci/meteor.c optional meteor device-driver pci/ncr.c optional ncr device-driver pci/pci.c optional pci device-driver pci/pcisupport.c optional pci pci/tek390.c optional amd device-driver pci/wdc_p.c optional wdc device-driver scsi/cd.c optional cd scsi/ch.c optional ch scsi/od.c optional od scsi/pt.c optional pt scsi/scsi_base.c optional scbus scsi/scsi_driver.c optional scbus scsi/scsi_ioctl.c optional scbus scsi/scsi_sense.c optional scbus scsi/scsiconf.c optional scbus scsi/sctarg.c optional sctarg scsi/sd.c optional sd scsi/ssc.c optional ssc scsi/st.c optional st scsi/su.c optional su scsi/uk.c optional scbus scsi/worm.c optional worm ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_alloc.c optional mfs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_balloc.c optional mfs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_inode.c optional mfs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_subr.c optional mfs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_tables.c optional mfs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vfsops.c optional mfs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_vnops.c optional mfs ufs/lfs/lfs_alloc.c optional lfs ufs/lfs/lfs_balloc.c optional lfs ufs/lfs/lfs_bio.c optional lfs ufs/lfs/lfs_cksum.c optional lfs ufs/lfs/lfs_debug.c optional lfs ufs/lfs/lfs_inode.c optional lfs ufs/lfs/lfs_segment.c optional lfs ufs/lfs/lfs_subr.c optional lfs ufs/lfs/lfs_syscalls.c optional lfs ufs/lfs/lfs_vfsops.c optional lfs ufs/lfs/lfs_vnops.c optional lfs ufs/mfs/mfs_vfsops.c optional mfs ufs/mfs/mfs_vnops.c optional mfs ufs/ufs/ufs_bmap.c standard ufs/ufs/ufs_disksubr.c standard ufs/ufs/ufs_ihash.c standard ufs/ufs/ufs_inode.c standard ufs/ufs/ufs_lookup.c standard ufs/ufs/ufs_quota.c standard ufs/ufs/ufs_vfsops.c standard ufs/ufs/ufs_vnops.c standard vm/default_pager.c standard vm/device_pager.c standard vm/kern_lock.c standard vm/swap_pager.c standard vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pager.c standard vm/vm_swap.c standard vm/vm_unix.c standard vm/vnode_pager.c standard Index: stable/2.2/sys/i386/conf/LINT =================================================================== --- stable/2.2/sys/i386/conf/LINT (revision 25722) +++ stable/2.2/sys/i386/conf/LINT (revision 25723) @@ -1,1073 +1,1080 @@ # # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.286.2.19 1997/03/19 03:01:49 obrien Exp $ +# $Id: LINT,v 1.286.2.20 1997/04/14 00:48:32 gibbs Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from # this file as required. # # # This directive is mandatory; it defines the architecture to be # configured for; in this case, the 386 family. You must also specify # at least one CPU (the one you intend to run on); deleting the # specification for CPUs you don't need to use may make parts of the # system run faster. This is especially true removing I386_CPU. # machine "i386" cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(tm) cpu "I686_CPU" # aka Pentium Pro(tm) # # This is the ``identification'' of the kernel. Usually this should # be the same as the name of your kernel. # ident LINT # # The `maxusers' parameter controls the static sizing of a number of # internal system tables by a complicated formula defined in param.c. # maxusers 10 # # Under some circumstances it is convenient to increase the defaults # for the maximum number of processes per user and the maximum number # of open files files per user. E.g., (1) in a large news server, user # `news' may need more than 100 concurrent processes. (2) a user may # need lots of windows under X. In both cases, it may be inconvenient # to start all the processes from a parent whose soft rlimit on the # number of processes is large enough. The following options work by # changing the soft rlimits for init. # options CHILD_MAX=128 options OPEN_MAX=128 # # Certain applications can grow to be larger than the 128M limit # that FreeBSD initially imposes. Below are some options to # allow that limit to grow to 256MB, and can be increased further # with changing the parameters. MAXDSIZ is the maximum that the # limit can be set to, and the DFLDSIZ is the default value for # the limit. You might want to set the default lower than the # max, and explicitly set the maximum with a shell command for processes # that regularly exceed the limit like INND. # options "MAXDSIZ=(256*1024*1024)" options "DFLDSIZ=(256*1024*1024)" # # A math emulator is mandatory if you wish to run on hardware which # does not have a floating-point processor. Pick either the original, # bogus (but freely-distributable) math emulator, or a much more # fully-featured but GPL-licensed emulator taken from Linux. # options MATH_EMULATE #Support for x87 emulation # Don't enable both of these in a real config. options GPL_MATH_EMULATE #Support for x87 emulation via #new math emulator # When this is set, be extra conservative in various parts of the kernel # and choose functionality over speed (on the widest variety of systems). # # (Note that one of the effects of removing this option is to enable # tagged commands in the `ncr' driver. See the comments to # AHC_TAGENABLE for a note of warning.) options FAILSAFE # This allows you to actually store this configuration file into # the kernel binary itself, where it may be later read by saying: # strings /kernel | grep ^___ | sed -e 's/^___//' > MYKERNEL # options INCLUDE_CONFIG_FILE # Include this file in kernel # # This directive defines a number of things: # - The compiled kernel is to be called `kernel' # - The root filesystem might be on partition wd0a # - Crash dumps will be written to wd0b, if possible. Specifying the # dump device here is not recommended. Use dumpon(8). # config kernel root on wd0 dumps on wd0 ##################################################################### # COMPATIBILITY OPTIONS # # Implement system calls compatible with 4.3BSD and older versions of # FreeBSD. You probably do NOT want to remove this as much current code # still relies on the 4.3 emulation. # options "COMPAT_43" # # Allow user-mode programs to manipulate their local descriptor tables. # This option is required for the WINE Windows(tm) emulator, and is # not used by anything else (that we know of). # options USER_LDT #allow user-level control of i386 ldt # # These three options provide support for System V Interface # Definition-style interprocess communication, in the form of shared # memory, semaphores, and message queues, respectively. # options SYSVSHM options SYSVSEM options SYSVMSG # # This option includes a MD5 routine in the kernel, this is used for # various authentication and privacy uses. # options "MD5" ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # Don't drop into DDB for a panic. Intended for unattended operation # where you may want to drop to DDB from the console, but still want # the machine to recover from a panic # options DDB_UNATTENDED # # KTRACE enables the system-call tracing facility ktrace(2). # options KTRACE #kernel tracing # # The DIAGNOSTIC option is used in a number of source files to enable # extra sanity checking of internal structures. This support is not # enabled by default because of the extra time it would take to check # for these conditions, which can only occur as a result of # programming errors. # options DIAGNOSTIC # # PERFMON causes the driver for Pentium/Pentium Pro performance counters # to be compiled. See perfmon(4) for more information. # options PERFMON # XXX - this doesn't belong here. # Allow ordinary users to take the console - this is useful for X. options UCONSOLE # XXX - this doesn't belong here either options USERCONFIG #boot -c editor options USERCONFIG_BOOT #imply -c and parse info area options VISUAL_USERCONFIG #visual boot -c editor ##################################################################### # NETWORKING OPTIONS # # Protocol families: # Only the INET (Internet) family is officially supported in FreeBSD. # Source code for the NS (Xerox Network Service) is provided for amusement # value. # options INET #Internet communications protocols options IPX #IPX/SPX communications protocols options IPXIP #IPX in IP encapsulation (not available) options IPTUNNEL #IP in IPX encapsulation (not available) options IPXPRINTFS=0 #IPX/SPX Console Debugging Information options IPX_ERRPRINTFS=0 #IPX/SPX Console Debugging Information options NETATALK #Appletalk communications protocols # These are currently broken but are shipped due to interest. #options NS #Xerox NS protocols # These are currently broken and are no longer shipped due to lack # of interest. #options CCITT #X.25 network layer #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 #options LLC #X.25 link layer for Ethernets #options HDLC #X.25 link layer for serial lines #options EON #ISO CLNP over IP #options NSIP #XNS over IP # # Network interfaces: # The `loop' pseudo-device is MANDATORY when networking is enabled. # The `ether' pseudo-device provides generic code to handle # Ethernets; it is MANDATORY when a Ethernet device driver is # configured. # The 'fddi' pseudo-device provides generic code to support FDDI. # The `sppp' pseudo-device serves a similar role for certain types # of synchronous PPP links (like `cx', `ar'). # The `sl' pseudo-device implements the Serial Line IP (SLIP) service. # The `ppp' pseudo-device implements the Point-to-Point Protocol. # The `bpfilter' pseudo-device enables the Berkeley Packet Filter. Be # aware of the legal and administrative consequences of enabling this # option. The number of devices determines the maximum number of # simultaneous BPF clients programs runnable. # The `disc' pseudo-device implements a minimal network interface, # which throws away all packets sent and never receives any. It is # included for testing purposes. # The `tun' pseudo-device implements the User Process PPP (iijppp) # pseudo-device ether #Generic Ethernet pseudo-device fddi #Generic FDDI pseudo-device sppp #Generic Synchronous PPP pseudo-device loop #Network loopback device pseudo-device sl 2 #Serial Line IP pseudo-device ppp 2 #Point-to-point protocol pseudo-device bpfilter 4 #Berkeley packet filter pseudo-device disc #Discard device pseudo-device tun 1 #Tunnel driver(user process ppp) # # Internet family options: # # TCP_COMPAT_42 causes the TCP code to emulate certain bugs present in # 4.2BSD. This option should not be used unless you have a 4.2BSD # machine and TCP connections fail. # # MROUTING enables the kernel multicast packet forwarder, which works # with mrouted(8). # # IPFIREWALL enables support for IP firewall construction, in # conjunction with the `ipfw' program. IPFIREWALL_VERBOSE sends # logged packets to the system logger. IPFIREWALL_VERBOSE_LIMIT # limits the number of times a matching entry can be logged. # # IPDIVERT enables the divert IP sockets, used by ``ipfw divert'' # # TCPDEBUG is undocumented. # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options "IPFIREWALL_VERBOSE_LIMIT=100" #limit verbosity options IPDIVERT #divert sockets options TCPDEBUG ##################################################################### # FILESYSTEM OPTIONS # # Only the root, /usr, and /tmp filesystems need be statically # compiled; everything else will be automatically loaded at mount # time. (Exception: the UFS family---FFS, MFS, and LFS---cannot # currently be demand-loaded.) Some people still prefer to statically # compile other filesystems as well. # # NB: The LFS, PORTAL, and UNION filesystems are known to be buggy, # and WILL panic your system if you attempt to do anything with them. # They are included here as an incentive for some enterprising soul to # sit down and fix them. # # Note: 4.4BSD NQNFS lease checking has relatively high cost for # _local_ I/O as well as remote I/O. Don't use it unless you will # using NQNFS. # # One of these is mandatory: options FFS #Fast filesystem options NFS #Network File System # The rest are optional: options NQNFS #Enable NQNFS lease checking # options NFS_NOSERVER #Disable the NFS-server code. options "CD9660" #ISO 9660 filesystem options FDESC #File descriptor filesystem options KERNFS #Kernel filesystem options LFS #Log filesystem options MFS #Memory File System options MSDOSFS #MS DOS File System options NULLFS #NULL filesystem options PORTAL #Portal filesystem options PROCFS #Process filesystem options UMAPFS #UID map filesystem options UNION #Union filesystem # This DEVFS is experimental but seems to work options DEVFS #devices filesystem # Make space in the kernel for a MFS root filesystem. Define to the number # of kilobytes to reserve for the filesystem. options MFS_ROOT=10 # Allow the MFS_ROOT code to load the MFS image from floppy if it is missing. options MFS_AUTOLOAD # Allow this many swap-devices. options NSWAPDEV=20 # Disk quotas are supported when this option is enabled. If you # change the value of this option, you must do a `make clean' in your # kernel compile directory in order to get a working kernel. # options QUOTA #enable disk quotas # Add more checking code to various filesystems #options NULLFS_DIAGNOSTIC #options KERNFS_DIAGNOSTIC #options UMAPFS_DIAGNOSTIC #options UNION_DIAGNOSTIC # Add some error checking code to the null_bypass routine # in the NULL filesystem #options SAFETY ##################################################################### # SCSI DEVICES # SCSI DEVICE CONFIGURATION # The SCSI subsystem consists of the `base' SCSI code, a number of # high-level SCSI device `type' drivers, and the low-level host-adapter # device drivers. The host adapters are listed in the ISA and PCI # device configuration sections below. # # Beginning with FreeBSD 2.0.5 you can wire down your SCSI devices so # that a given bus, target, and LUN always come on line as the same # device unit. In earlier versions the unit numbers were assigned # in the order that the devices were probed on the SCSI bus. This # means that if you removed a disk drive, you may have had to rewrite # your /etc/fstab file, and also that you had to be careful when adding # a new disk as it may have been probed earlier and moved your device # configuration around. # This old behavior is maintained as the default behavior. The unit # assignment begins with the first non-wired down unit for a device # type. For example, if you wire a disk as "sd3" then the first # non-wired disk will be assigned sd4. # The syntax for wiring down devices is: # controller scbus0 at ahc0 # Single bus device # controller scbus1 at ahc1 bus 0 # Single bus device # controller scbus3 at ahc2 bus 0 # Twin bus device # controller scbus2 at ahc2 bus 1 # Twin bus device # disk sd0 at scbus0 target 0 unit 0 # disk sd1 at scbus3 target 1 # disk sd2 at scbus2 target 3 # tape st1 at scbus1 target 6 # device cd0 at scbus? # "units" (SCSI logical unit number) that are not specified are # treated as if specified as LUN 0. # All SCSI devices allocate as many units as are required. # The "unknown" device (uk? in pre-2.0.5) is now part of the base SCSI # configuration and doesn't have to be explicitly configured. controller scbus0 #base SCSI code device ch0 #SCSI media changers device sd0 #SCSI disks device st0 #SCSI tapes device cd0 #SCSI CD-ROMs device od0 #SCSI optical disk # The previous devices (ch, sd, st, cd) are recognized by config. # config doesn't (and shouldn't) know about these newer ones, # so we have to specify that they are on a SCSI bus with the "at scbus?" # clause. device worm0 at scbus? # SCSI worm device pt0 at scbus? # SCSI processor type device sctarg0 at scbus? # SCSI target # SCSI OPTIONS: # SCSIDEBUG: When defined enables debugging macros # NO_SCSI_SENSE: When defined disables sense descriptions (about 4k) # SCSI_REPORT_GEOMETRY: Always report disk geometry at boot up instead # of only when booting verbosely. options SCSIDEBUG #options NO_SCSI_SENSE options SCSI_REPORT_GEOMETRY # Options for the `od' optical disk driver: # # If drive returns sense key as 0x02 with vendor specific additional # sense code (ASC) and additional sense code qualifier (ASCQ), or # illegal ASC and ASCQ. This cause an error (NOT READY) and retrying. # To suppress this, use the following option. # options OD_BOGUS_NOT_READY # # For an automatic spindown, try this. Again, preferrably as an # option in your config file. # WARNING! Use at your own risk. Joerg's ancient SONY SMO drive # groks it fine, while Shunsuke's Fujitsu chokes on it and times # out. # options OD_AUTO_TURNOFF ##################################################################### # MISCELLANEOUS DEVICES AND OPTIONS # # Of these, only the `log' device is truly mandatory. The `pty' # device usually turns out to be ``effectively mandatory'', as it is # required for `telnetd', `rlogind', `screen', `emacs', and `xterm', # among others. # If you wish to run certain # system utilities which are compressed by default (like /stand/sysinstall) # then `gzip' becomes mandatory too. # pseudo-device pty 16 #Pseudo ttys - can go as high as 256 pseudo-device speaker #Play IBM BASIC-style noises out your speaker pseudo-device log #Kernel syslog interface (/dev/klog) pseudo-device gzip #Exec gzipped a.out's pseudo-device vn #Vnode driver (turns a file into a device) pseudo-device snp 3 #Snoop device - to look at pty/vty/etc.. pseudo-device ccd 4 #Concatenated disk driver # These are only for watching for bitrot in old tty code. # broken #pseudo-device tb # These are only for watching for bitrot in old SCSI code. pseudo-device su #scsi user pseudo-device ssc #super scsi ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # EISA support is available for some device, so they can be auto-probed. # Micro Channel is not supported at all. # # Mandatory ISA devices: isa, sc or vt, npx # controller isa0 # # Options for `isa': # # AUTO_EOI_1 enables the `automatic EOI' feature for the master 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # This option breaks suspend/resume on some portables. # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 0.7-1.25 usec for each interrupt. # Automatic EOI is documented not to work for for the slave with the # original i8259A, but it works for some clones and some integrated # versions. # # BOUNCE_BUFFERS provides support for ISA DMA on machines with more # than 16 megabytes of memory. It doesn't hurt on other machines. # Some broken EISA and VLB hardware may need this, too. # # MAXMEM specifies the amount of RAM on the machine; if this is not # specified, FreeBSD will read the amount of memory from the CMOS RAM, # so the amount of memory will be limited to 64MB or 16MB depending on # the BIOS. The amount is in kilobytes, so for a machine with 128MB of # RAM, it would be 131072 (128 * 1024). # # TUNE_1542 enables the automatic ISA bus speed selection for the # Adaptec 1542 boards. Does not work for all boards, use it with caution. # # BROKEN_KEYBOARD_RESET disables the use of the keyboard controller to # reset the CPU for reboot. This is needed on some systems with broken # keyboard controllers. # # PAS_JOYSTICK_ENABLE enables the gameport on the ProAudio Spectrum options "AUTO_EOI_1" #options "AUTO_EOI_2" options BOUNCE_BUFFERS options "MAXMEM=(128*1024)" #options "TUNE_1542" #options BROKEN_KEYBOARD_RESET #options PAS_JOYSTICK_ENABLE # Enable this and PCVT_FREEBSD for pcvt vt220 compatible console driver device vt0 at isa? port "IO_KBD" tty irq 1 vector pcrint options PCVT_FREEBSD=210 # pcvt running on FreeBSD >= 2.0.5 options XSERVER # include code for XFree86 options FAT_CURSOR # start with block cursor # This PCVT option is for keyboards such as those used on IBM ThinkPad laptops options PCVT_SCANSET=2 # IBM keyboards are non-std # The syscons console driver (sco color console compatible) - default. device sc0 at isa? port "IO_KBD" tty irq 1 vector scintr options MAXCONS=16 # number of virtual consoles options SLOW_VGA # do byte-wide i/o's to TS and GDC regs # # `flags' for sc0: # 0x01 Use a 'visual' bell # 0x02 Use a 'blink' cursor # 0x04 Use a 'block' cursor # 0x08 Force detection of keyboard, else we always assume a keyboard # 0x10 Old-style (XT) keyboard support, useful for older ThinkPads # # This device is mandatory. # # The Numeric Processing eXtension is used to either enable the # coprocessor or enable math emulation. If your machine doesn't contain # a math co-processor, you must *also* add the option "MATH_EMULATE". # THIS IS NOT AN OPTIONAL ENTRY, DO NOT REMOVE IT device npx0 at isa? port "IO_NPX" iosiz 0x0 flags 0x0 irq 13 vector npxintr # # `flags' for npx0: # 0x01 don't use the npx registers to optimize bcopy # 0x02 don't use the npx registers to optimize bzero # 0x04 don't use the npx registers to optimize copyin or copyout. # The npx registers are normally used to optimize copying and zeroing when # all of the following conditions are satisfied: # "I586_CPU" is an option # the cpu is an i586 (perhaps not a Pentium) # the probe for npx0 succeeds # INT 16 exception handling works. # Then copying and zeroing using the npx registers is normally 30-100% faster. # The flags can be used to control cases where it doesn't work or is slower. # Setting them at boot time using userconfig works right (the optimizations # are not used until later in the bootstrap when npx0 is attached). # # # `iosiz' for npx0: # This can be used instead of the MAXMEM option to set the memory size. If # it is nonzero, then it overrides both the MAXMEM option and the memory # size reported by the BIOS. Setting it at boot time using userconfig takes # effect on the next reboot after the change has been recorded in the kernel # binary (the size is used early in the boot before userconfig has a chance # to change it). # # # Optional ISA and EISA devices: # # # SCSI host adapters: `aha', `aic', `bt', `nca' # # aha: Adaptec 154x # ahc: Adaptec 274x/284x/294x # aic: Adaptec 152x and sound cards using the Adaptec AIC-6360 (slow!) # bt: Most Buslogic controllers # nca: ProAudioSpectrum cards using the NCR 5380 or Trantor T130 # uha: UltraStore 14F and 34F # sea: Seagate ST01/02 8 bit controller (slow!) # wds: Western Digital WD7000 controller (no scatter/gather!). # # Note that the order is important in order for Buslogic cards to be # probed correctly. # controller bt0 at isa? port "IO_BT0" bio irq ? vector bt_isa_intr controller aha0 at isa? port "IO_AHA0" bio irq ? drq 5 vector ahaintr controller uha0 at isa? port "IO_UHA0" bio irq ? drq 5 vector uhaintr controller aic0 at isa? port 0x340 bio irq 11 vector aicintr controller nca0 at isa? port 0x1f88 bio irq 10 vector ncaintr controller nca1 at isa? port 0x1f84 controller nca2 at isa? port 0x1f8c controller nca3 at isa? port 0x1e88 controller nca4 at isa? port 0x350 bio irq 5 vector ncaintr controller sea0 at isa? bio irq 5 iomem 0xdc000 iosiz 0x2000 vector seaintr controller wds0 at isa? port 0x350 bio irq 15 drq 6 vector wdsintr # # ST-506, ESDI, and IDE hard disks: `wdc' and `wd' # # NB: ``Enhanced IDE'' is NOT supported at this time. # # The flags fields are used to enable the multi-sector I/O and # the 32BIT I/O modes. The flags may be used in either the controller # definition or in the individual disk definitions. The controller # definition is supported for the boot configuration stuff. # # Each drive has a 16 bit flags value defined: # The low 8 bits are the maximum value for the multi-sector I/O, # where 0xff defaults to the maximum that the drive can handle. # The high bit of the 16 bit flags (0x8000) allows probing for # 32 bit transfers. # # The flags field for the drives can be specified in the controller # specification with the low 16 bits for drive 0, and the high 16 bits # for drive 1. # e.g.: #controller wdc0 at isa? port "IO_WD1" bio irq 14 flags 0x00ff8004 vector wdintr # # specifies that drive 0 will be allowed to probe for 32 bit transfers and # a maximum multi-sector transfer of 4 sectors, and drive 1 will not be # allowed to probe for 32 bit transfers, but will allow multi-sector # transfers up to the maximum that the drive supports. # controller wdc0 at isa? port "IO_WD1" bio irq 14 vector wdintr disk wd0 at wdc0 drive 0 disk wd1 at wdc0 drive 1 controller wdc1 at isa? port "IO_WD2" bio irq 15 vector wdintr disk wd2 at wdc1 drive 0 disk wd3 at wdc1 drive 1 # # Options for `wdc': # # CMD640 enables serializing access to primary and secondary channel # of the CMD640B IDE Chip. The serializing will only take place # if this option is set *and* the chip is probed by the pci-system. # options "CMD640" #Enable work around for CMD640 h/w bug # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus options ATAPI_STATIC #Don't do it as an LKM # IDE CD-ROM driver - requires wdc controller and ATAPI option device wcd0 # # Standard floppy disk controllers and floppy tapes: `fdc', `fd', and `ft' # controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 vector fdintr # # Activate this line instead of the fdc0 line above if you happen to # have an Insight floppy tape. Probing them proved to be dangerous # for people with floppy disks only, so it's "hidden" behind a flag: #controller fdc0 at isa? port "IO_FD1" bio flags 1 irq 6 drq 2 vector fdintr disk fd0 at fdc0 drive 0 disk fd1 at fdc0 drive 1 tape ft0 at fdc0 drive 2 # # Options for `fd': # # FDSEEKWAIT selects a non-default head-settle time (i.e., the time to # wait after a seek is performed). The default value (1/32 s) is # usually sufficient. The units are inverse seconds, so a value of 16 # here means to wait 1/16th of a second; you should choose a power of # two. # XXX: this seems to be missing! options FDSEEKWAIT=16 # # Other standard PC hardware: `lpt', `mse', `psm', `sio', etc. # # lpt: printer port # lpt specials: # port can be specified as ?, this will cause the driver to scan # the BIOS port list; # the irq and vector clauses may be omitted, this # will force the port into polling mode. # mse: Logitech and ATI InPort bus mouse ports # psm: PS/2 mouse port [note: conflicts with sc0/vt0, thus "conflicts" keywd] # sio: serial ports (see sio(4)) device lpt0 at isa? port? tty irq 7 vector lptintr device lpt1 at isa? port "IO_LPT3" tty irq 5 vector lptintr device mse0 at isa? port 0x23c tty irq 5 vector mseintr device psm0 at isa? port "IO_KBD" conflicts tty irq 12 vector psmintr # Options for psm: options PSM_CHECKSYNC #checks the header byte for sync. device sio0 at isa? port "IO_COM1" tty irq 4 vector siointr # Options for sio: options COMCONSOLE #prefer serial console to video console options COM_ESP #code for Hayes ESP options COM_MULTIPORT #code for some cards with shared IRQs options DSI_SOFT_MODEM #code for DSI Softmodems options BREAK_TO_DEBUGGER #a BREAK on a comconsole goes to #DDB, if available. # # Network interfaces: `cx', `ed', `el', `ep', `ie', `is', `le', `lnc' # # ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver (requires sppp) # cx: Cronyx/Sigma multiport sync/async (with Cisco or PPP framing) # ed: Western Digital and SMC 80xx; Novell NE1000 and NE2000; 3Com 3C503 # el: 3Com 3C501 (slow!) # ep: 3Com 3C509 (buggy) # fe: Fujitsu MB86960A/MB86965A Ethernet # ie: AT&T StarLAN 10 and EN100; 3Com 3C507; unknown NI5210 # le: Digital Equipment EtherWorks 2 and EtherWorks 3 (DEPCA, DE100, # DE101, DE200, DE201, DE202, DE203, DE204, DE205, DE422) # lnc: Lance/PCnet cards (Isolan, Novell NE2100, NE32-VL) # sr: RISCom/N2 hdlc sync 1/2 port V.35/X.21 serial driver (requires sppp) # ze: IBM/National Semiconductor PCMCIA ethernet controller. # zp: 3Com PCMCIA Etherlink III (It does not require shared memory for # send/receive operation, but it needs 'iomem' to read/write the # attribute memory) # device ar0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector arintr device cx0 at isa? port 0x240 net irq 15 drq 7 vector cxintr device ed0 at isa? port 0x280 net irq 5 iomem 0xd8000 vector edintr device eg0 at isa? port 0x310 net irq 5 vector egintr device el0 at isa? port 0x300 net irq 9 vector elintr device ep0 at isa? port 0x300 net irq 10 vector epintr device ex0 at isa? port 0x300 net irq 10 iomem 0xd0000 vector exintr device fe0 at isa? port 0x300 net irq ? vector feintr device ie0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector ieintr device ie1 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector le_intr device lnc0 at isa? port 0x300 net irq 10 drq 0 vector lncintr device sr0 at isa? port 0x300 net irq 5 iomem 0xd0000 vector srintr # Needed so that we can (bogusly) include both the dedicated PCCARD # drivers and the generic support options LINT_PCCARD_HACK device ze0 at isa? port 0x300 net irq 5 iomem 0xd8000 vector zeintr device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 vector zpintr # # Audio drivers: `snd', `sb', `pas', `gus', `pca' # # snd: Voxware sound support code # sb: SoundBlaster PCM - SoundBlaster, SB Pro, SB16, ProAudioSpectrum # sbxvi: SoundBlaster 16 # sbmidi: SoundBlaster 16 MIDI interface # pas: ProAudioSpectrum PCM and MIDI # gus: Gravis Ultrasound - Ultrasound, Ultrasound 16, Ultrasound MAX # gusxvi: Gravis Ultrasound 16-bit PCM (do not use) # mss: Microsoft Sound System # opl: Yamaha OPL-2 and OPL-3 FM - SB, SB Pro, SB 16, ProAudioSpectrum # uart: stand-alone 6850 UART for MIDI # mpu: Roland MPU-401 stand-alone card # # Beware! The addresses specified below are also hard-coded in # i386/isa/sound/sound_config.h. If you change the values here, you # must also change the values in the include file. # # pca: PCM audio through your PC speaker # # If you don't have a lpt0 device at IRQ 7, you can remove the # ``conflicts'' specification in the appropriate device entries below. # # If you have a GUS-MAX card and want to use the CS4231 codec on the # card the drqs for the gus max must be 8 bit (1, 2, or 3). # # If you would like to use the full duplex option on the gus, then define # flags to be the ``read dma channel''. # # options BROKEN_BUS_CLOCK #PAS-16 isn't working and OPTI chipset # options SYMPHONY_PAS #PAS-16 isn't working and SYMPHONY chipset # options EXCLUDE_SBPRO #PAS-16 # options SBC_IRQ=5 #PAS-16. Must match irq on sb0 line. # PAS16: The order of the pas0/sb0/opl0 is important since the # sb emulation is enabled in the pas-16 attach. # # The i386/isa/sound/sound.doc has more information. # Controls all sound devices controller snd0 device pas0 at isa? port 0x388 irq 10 drq 6 vector pasintr device sb0 at isa? port 0x220 irq 7 conflicts drq 1 vector sbintr device sbxvi0 at isa? drq 5 device sbmidi0 at isa? port 0x330 #device awe0 at isa? port 0x620 device gus0 at isa? port 0x220 irq 12 drq 1 vector gusintr #device gus0 at isa? port 0x220 irq 12 drq 1 flags 0x3 vector gusintr device mss0 at isa? port 0x530 irq 10 drq 1 vector adintr # Use this line for PAS avoid port conflict device opl0 at isa? port 0x38a # For normal case use next line # device opl0 at isa? port 0x388 device mpu0 at isa? port 0x330 irq 6 drq 0 device uart0 at isa? port 0x330 irq 5 vector "m6850intr" # More undocumented sound devices with bogus configurations for linting. # broken #device sscape0 at isa? port 0x330 irq 6 drq 0 #device trix0 at isa? port 0x330 irq 6 drq 0 vector sscapeintr # Not controlled by `snd' device pca0 at isa? port IO_TIMER1 tty # # Miscellaneous hardware: # # mcd: Mitsumi CD-ROM # scd: Sony CD-ROM # matcd: Matsushita/Panasonic CD-ROM # wt: Wangtek and Archive QIC-02/QIC-36 tape drives # ctx: Cortex-I frame grabber # apm: Laptop Advanced Power Management (experimental) # spigot: The Creative Labs Video Spigot video-acquisition board # meteor: Matrox Meteor video capture board # cy: Cyclades serial driver # dgb: Digiboard PC/Xi and PC/Xe series driver (ALPHA QUALITY!) # gp: National Instruments AT-GPIB and AT-GPIB/TNT board # asc: GI1904-based hand scanners, e.g. the Trust Amiscan Grey # gsc: Genius GS-4500 hand scanner. # joy: joystick # labpc: National Instrument's Lab-PC and Lab-PC+ # rc: RISCom/8 multiport card # tw: TW-523 power line interface for use with X-10 home control products # si: Specialix SI/XIO 4-32 port terminal multiplexor # stl: Stallion EasyIO and EasyConnection 8/32 (cd1400 based) # stli: Stallion EasyConnection 8/64, ONboard, Brumby (intelligent) # # Notes on APM # Some APM implementations will not work with the `statistics clock' # enabled, so it's disabled by default if the APM driver is enabled. # However, this is not true for all laptops. Try removing the option # APM_BROKEN_STATCLOCK and see if suspend/resume work # options APM_IDLE_CPU # Tell APM to idle rather than halt'ing the cpu # # Notes on the spigot: # The video spigot is at 0xad6. This port address can not be changed. # The irq values may only be 10, 11, or 15 # I/O memory is an 8kb region. Possible values are: # 0a0000, 0a2000, ..., 0fffff, f00000, f02000, ..., ffffff # The start address must be on an even boundary. # Add the following option if you want to allow non-root users to be able # to access the spigot. This option is not secure because it allows users # direct access to the I/O page. # options SPIGOT_UNSECURE # # Notes on the Digiboard driver: # # The following flag values have special meanings: # 0x01 - alternate layout of pins # 0x02 - use the windowed PC/Xe in 64K mode # Notes on the Specialix SI/XIO driver: # **This is NOT a Specialix supported Driver!** # The host card is memory, not IO mapped. # The Rev 1 host cards use a 64K chunk, on a 32K boundary. # The Rev 2 host cards use a 32K chunk, on a 32K boundary. # The cards can use an IRQ of 11, 12 or 15. # Notes on the Stallion stl and stli drivers: # See src/i386/isa/README.stl for complete instructions. # This is version 0.0.5alpha, unsupported by Stallion. # The stl driver has a secondary IO port hard coded at 0x280. You need # to change src/i386/isa/stallion.c if you reconfigure this on the boards. # The "flags" and "iosiz" settings on the stli driver depend on the board: # EasyConnection 8/64 ISA: flags 23 iosiz 0x1000 # EasyConnection 8/64 EISA: flags 24 iosiz 0x10000 # EasyConnection 8/64 MCA: flags 25 iosiz 0x1000 # ONboard ISA: flags 4 iosiz 0x10000 # ONboard EISA: flags 7 iosiz 0x10000 # ONboard MCA: flags 3 iosiz 0x10000 # Brumby: flags 2 iosiz 0x4000 # Stallion: flags 1 iosiz 0x10000 device mcd0 at isa? port 0x300 bio irq 10 vector mcdintr # for the Sony CDU31/33A CDROM device scd0 at isa? port 0x230 bio # for the SoundBlaster 16 multicd - up to 4 devices controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 vector wtintr device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 vector spigintr device qcam0 at isa? port "IO_LPT3" tty device apm0 at isa? options APM_BROKEN_STATCLOCK device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port "IO_GAME" device cy0 at isa? tty irq 10 iomem 0xd4000 iosiz 0x2000 vector cyintr device dgb0 at isa? port 0x220 iomem 0xfc0000 iosiz ? tty device labpc0 at isa? port 0x260 tty irq 5 vector labpcintr device rc0 at isa? port 0x220 tty irq 12 vector rcintr # the port and irq for tw0 are fictitious device tw0 at isa? port 0x380 tty irq 11 vector twintr device si0 at isa? iomem 0xd0000 tty irq 12 vector siintr device asc0 at isa? port IO_ASC1 tty drq 3 irq 10 vector ascintr device bqu0 at isa? port 0x150 device stl0 at isa? port 0x2a0 tty irq 10 vector stlintr device stli0 at isa? port 0x2a0 tty iomem 0xcc000 flags 23 iosiz 0x1000 # # EISA devices: # # The EISA bus device is eisa0. It provides auto-detection and # configuration support for all devices on the EISA bus. # # The `ahb' device provides support for the Adaptec 174X adapter. # # The `ahc' device provides support for the Adaptec 274X and 284X # adapters. The 284X, although a VLB card responds to EISA probes. # # fea: DEC DEFEA EISA FDDI adapter # controller eisa0 controller ahb0 controller ahc0 device fea0 # enable tagged command queueing, which is a major performance win on # devices that support it (and controllers with enough SCB's) # # Note that some drives claim to grok tagged commands, but actually # don't. The HP C3725S is a known offender. options AHC_TAGENABLE # enable SCB paging - See the ahc.4 man page for usage warnings. # (IOW: better don't use it by now.) options AHC_SCBPAGING_ENABLE # The aic7xxx driver will attempt to use memory mapped I/O for all PCI # controllers that have it configured only if this option is set. Unfortunately, # this doesn't work on some motherboards, which prevents it from being the # default. options AHC_ALLOW_MEMIO # By default, only 10 EISA slots are probed, since the slot numbers # above clash with the configuration address space of the PCI subsystem, # and the EISA probe is not very smart about this. This is sufficient # for most machines, but in particular the HP NetServer LC series comes # with an onboard AIC7770 dual-channel SCSI controller on EISA slot #11, # thus you need to bump this figure to 12 for them. options "EISA_SLOTS=12" # # PCI devices: # # The main PCI bus device is `pci'. It provides auto-detection and # configuration support for all devices on the PCI bus, using either # configuration mode defined in the PCI specification. # # The `ahc' device provides support for the Adaptec 29/3940(U)(W) # and motherboard based AIC7870/AIC7880 adapters. # # The `ncr' device provides support for the NCR 53C810 and 53C825 # self-contained SCSI host adapters. # # The `amd' device provides support for the Tekram DC-390 and 390T # SCSI host adapters, but is expected to work with any AMD 53c974 # PCI SCSI chip and the AMD Ethernet+SCSI Combo chip, after some # local patches were applied to the sources (that had originally # been written by Tekram and limited to work with their SCSI cards). # # The `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `fxp' device provides support for the Intel EtherExpress Pro/100B # PCI Fast Ethernet adapters. # # The `vx' device provides support for the 3Com 3C590 and 3C595 # early support # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The `meteor' device is a PCI video capture board. It can also have the # following options: # options METEOR_ALLOC_PAGES=xxx preallocate kernel pages for data entry # figure (ROWS*COLUMN*BYTES_PER_PIXEL*FRAME+PAGE_SIZE-1)/PAGE_SIZE # options METEOR_DEALLOC_PAGES remove all allocated pages on close(2) # options METEOR_DEALLOC_ABOVE=xxx remove all allocated pages above the # specified amount. If this value is below the allocated amount no action # taken # option METEOR_SYSTEM_DEFAULT={METEOR_PAL|METEOR_NTSC|METEOR_SECAM}, used # for initialization of fps routine when a signal is not present. # controller pci0 controller ahc1 controller ncr0 controller amd0 device de0 device fxp0 device vx0 device fpa0 device meteor0 # # PCCARD/PCMCIA # # crd: slot controller # pcic: slots controller crd0 controller pcic0 at crd? controller pcic1 at crd? # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardware' # above. # For older notebooks that signal a powerfail condition (external # power supply dropped, or battery state low) by issuing an NMI: options POWERFAIL_NMI # make it beep instead of panicing + +# Kernel BOOTP support + +options BOOTP # Use BOOTP to obtain IP address/hostname +options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info +options "BOOTP_NFSV3" # Use NFS v3 to NFS mount root +options BOOTP_COMPAT # Workaround for broken bootp daemons. # More undocumented options for linting. options CLK_CALIBRATION_LOOP options "CLK_USE_I8254_CALIBRATION" options "CLK_USE_I586_CALIBRATION" options COMPAT_LINUX options DEBUG options DEVFS_ROOT options "EXT2FS" options "I586_CTR_GUPROF" options "I586_PMC_GUPROF=0x70000" options "IBCS2" options KBD_MAXRETRY=4 options KBD_MAXWAIT=6 options KBD_RESETDELAY=201 options KBDIO_DEBUG=2 options MSGMNB=2049 options MSGMNI=41 options MSGSEG=2049 options MSGSSZ=16 options MSGTQL=41 options NBUF=512 options NMBCLUSTERS=1024 options PSM_ACCEL=1 options PSM_DEBUG=1 options PSM_EMULATION options "SCSI_2_DEF" options SCSI_DELAY=8 # Be pessimistic about Joe SCSI device options SCSI_NCR_DEBUG options SCSI_NCR_DFLT_TAGS=4 options SCSI_NCR_MAX_SYNC=10000 options SCSI_NCR_MAX_WIDE=1 options SCSI_NCR_MYADDR=7 options SEMMAP=31 options SEMMNI=11 options SEMMNS=61 options SEMMNU=31 options SEMMSL=61 options SEMOPM=101 options SEMUME=11 options SHOW_BUSYBUFS # List buffers that prevent root unmount options SHMALL=1025 options "SHMMAX=(SHMMAXPGS*PAGE_SIZE+1)" options SHMMAXPGS=1025 options SHMMIN=2 options SHMMNI=33 options SHMSEG=9 options SI_DEBUG options SPX_HACK Index: stable/2.2/sys/i386/i386/autoconf.c =================================================================== --- stable/2.2/sys/i386/i386/autoconf.c (revision 25722) +++ stable/2.2/sys/i386/i386/autoconf.c (revision 25723) @@ -1,420 +1,428 @@ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.56.2.3 1996/12/21 18:55:34 phk Exp $ + * $Id: autoconf.c,v 1.56.2.4 1997/03/04 00:31:13 nate Exp $ */ /* * Setup the system to run on the current machine. * * Configure() is called at boot time and initializes the vba * device tables and the memory controller monitoring. Available * devices are determined (from possibilities mentioned in ioconf.c), * and the drivers are initialized. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* For interrupts */ #include "isa.h" #if NISA > 0 #include #endif #include "eisa.h" #if NEISA > 0 #include #endif #include "pci.h" #if NPCI > 0 #include #endif #include "crd.h" #if NCRD > 0 #include #endif #include "scbus.h" #if NSCBUS > 0 #include #endif static void configure __P((void *)); SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) #ifdef MFS_ROOT extern struct vfsops mfs_vfsops; #endif #ifdef FFS extern struct vfsops ufs_vfsops; #endif #ifdef LFS extern struct vfsops lfs_vfsops; #endif #ifdef NFS extern int nfs_mountroot __P((void *)); #endif #ifdef CD9660 extern int cd9660_mountroot __P((void *)); #endif #ifdef MSDOSFS extern int msdosfs_mountroot __P((void *)); #endif static void configure_finish __P((void)); static void configure_start __P((void)); static int setdumpdev __P((dev_t dev)); static void setroot __P((void)); #ifdef CD9660 /* We need to try out all our potential CDROM drives, so we need a table. */ static struct { char *name; int major; } try_cdrom[] = { { "cd", 6 }, { "mcd", 7 }, { "scd", 16 }, { "matcd", 17 }, { 0, 0} }; static int find_cdrom_root __P((void *)); static int find_cdrom_root(dummy) void *dummy; { int i,j,k; for (j = 0 ; j < 2; j++) for (k = 0 ; try_cdrom[k].name ; k++) { rootdev = makedev(try_cdrom[k].major,j*8); printf("trying rootdev=0x%lx (%s%d)\n", rootdev, try_cdrom[k].name,j); i = (*cd9660_mountroot)((void *)NULL); if (!i) return i; } return EINVAL; } #endif /* CD9660 */ static void configure_start() { #if NSCBUS > 0 scsi_configure_start(); #endif } static void configure_finish() { #if NSCBUS > 0 scsi_configure_finish(); #endif } /* * Determine i/o configuration for a machine. */ static void configure(dummy) void *dummy; { int i; configure_start(); /* Allow all routines to decide for themselves if they want intrs */ enable_intr(); INTREN(IRQ_SLAVE); #if NEISA > 0 eisa_configure(); #endif #if NPCI > 0 pci_configure(); #endif #if NISA > 0 isa_configure(); #endif #if NCRD > 0 /* After everyone else has a chance at grabbing resources */ pccard_configure(); #endif if (setdumpdev(dumpdev) != 0) dumpdev = NODEV; configure_finish(); cninit_finish(); if (bootverbose) { /* * Print out the BIOS's idea of the disk geometries. */ printf("BIOS Geometries:\n"); for (i = 0; i < N_BIOS_GEOM; i++) { unsigned long bios_geom; int max_cylinder, max_head, max_sector; bios_geom = bootinfo.bi_bios_geom[i]; /* * XXX the bootstrap punts a 1200K floppy geometry * when the get-disk-geometry interrupt fails. Skip * drives that have this geometry. */ if (bios_geom == 0x4f010f) continue; printf(" %x:%08lx ", i, bios_geom); max_cylinder = bios_geom >> 16; max_head = (bios_geom >> 8) & 0xff; max_sector = bios_geom & 0xff; printf( "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", max_cylinder, max_cylinder + 1, max_head, max_head + 1, max_sector, max_sector); } printf(" %d accounted for\n", bootinfo.bi_n_bios_used); printf("Device configuration finished.\n"); } #ifdef CD9660 if ((boothowto & RB_CDROM) && !mountroot) { if (bootverbose) printf("Considering CD-ROM root f/s.\n"); mountroot = find_cdrom_root; } #endif #ifdef MFS_ROOT if (!mountroot) { if (bootverbose) printf("Considering MFS root f/s.\n"); mountroot = vfs_mountroot; /* XXX goes away*/ mountrootvfsops = &mfs_vfsops; /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif + +#ifdef BOOTP_NFSROOT + if (!mountroot && !nfs_diskless_valid) { + if (bootverbose) + printf("Considering BOOTP NFS root f/s.\n"); + mountroot = nfs_mountroot; + } +#endif /* BOOTP_NFSROOT */ #ifdef NFS if (!mountroot && nfs_diskless_valid) { if (bootverbose) printf("Considering NFS root f/s.\n"); mountroot = nfs_mountroot; } #endif /* NFS */ #ifdef FFS if (!mountroot) { if (bootverbose) printf("Considering FFS root f/s.\n"); mountroot = vfs_mountroot; /* XXX goes away*/ mountrootvfsops = &ufs_vfsops; /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif #ifdef LFS if (!mountroot) { if (bootverbose) printf("Considering LFS root f/s.\n"); mountroot = vfs_mountroot; /* XXX goes away*/ mountrootvfsops = &lfs_vfsops; /* * Ignore the -a flag if this kernel isn't compiled * with a generic root/swap configuration: if we skip * setroot() and we aren't a generic kernel, chaos * will ensue because setconf() will be a no-op. * (rootdev is always initialized to NODEV in a * generic configuration, so we test for that.) */ if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) setroot(); } #endif if (!mountroot) { panic("Nobody wants to mount my root for me"); } setconf(); cold = 0; if (bootverbose) printf("configure() finished.\n"); } static int setdumpdev(dev) dev_t dev; { int maj, psize; long newdumplo; if (dev == NODEV) { dumpdev = dev; return (0); } maj = major(dev); if (maj >= nblkdev) return (ENXIO); if (bdevsw[maj] == NULL) return (ENXIO); /* XXX is this right? */ if (bdevsw[maj]->d_psize == NULL) return (ENXIO); /* XXX should be ENODEV ? */ psize = bdevsw[maj]->d_psize(dev); if (psize == -1) return (ENXIO); /* XXX should be ENODEV ? */ newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; if (newdumplo < 0) return (ENOSPC); dumpdev = dev; dumplo = newdumplo; return (0); } u_long bootdev = 0; /* not a dev_t - encoding is different */ static char devname[][2] = { {'w','d'}, /* 0 = wd */ {'s','w'}, /* 1 = sw */ #define FDMAJOR 2 {'f','d'}, /* 2 = fd */ {'w','t'}, /* 3 = wt */ {'s','d'}, /* 4 = sd -- new SCSI system */ }; #define PARTITIONMASK 0x7 #define PARTITIONSHIFT 3 #define FDUNITSHIFT 6 #define RAW_PART 2 /* * Attempt to find the device from which we were booted. * If we can do so, and not instructed not to do so, * change rootdev to correspond to the load device. */ static void setroot() { int majdev, mindev, unit, part, adaptor; dev_t orootdev; /*printf("howto %x bootdev %x ", boothowto, bootdev);*/ if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) return; majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; if (majdev > sizeof(devname) / sizeof(devname[0])) return; adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; if (majdev == FDMAJOR) { part = RAW_PART; mindev = unit << FDUNITSHIFT; } else { part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; mindev = (unit << PARTITIONSHIFT) + part; } orootdev = rootdev; rootdev = makedev(majdev, mindev); /* * If the original rootdev is the same as the one * just calculated, don't need to adjust the swap configuration. */ if (rootdev == orootdev) return; printf("changing root device to %c%c%d%c\n", devname[majdev][0], devname[majdev][1], mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), part + 'a'); } static int sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS { int error; dev_t ndumpdev; ndumpdev = dumpdev; error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); if (error == 0 && req->newptr != NULL) error = setdumpdev(ndumpdev); return (error); } SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); Index: stable/2.2/sys/kern/init_main.c =================================================================== --- stable/2.2/sys/kern/init_main.c (revision 25722) +++ stable/2.2/sys/kern/init_main.c (revision 25723) @@ -1,646 +1,653 @@ /* * Copyright (c) 1995 Terrence R. Lambert * All rights reserved. * * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)init_main.c 8.9 (Berkeley) 1/21/94 - * $Id: init_main.c,v 1.51.2.2 1997/05/04 21:10:54 alex Exp $ + * $Id: init_main.c,v 1.51.2.3 1997/05/05 13:24:16 kato Exp $ */ #include "opt_rlimit.h" #include "opt_devfs.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern struct linker_set sysinit_set; /* XXX */ extern void __main __P((void)); extern void main __P((void *framep)); /* Components of the first process -- never freed. */ static struct session session0; static struct pgrp pgrp0; struct proc proc0; static struct pcred cred0; static struct filedesc0 filedesc0; static struct plimit limit0; static struct vmspace vmspace0; struct proc *curproc = &proc0; struct proc *initproc; int cmask = CMASK; extern struct user *proc0paddr; struct vnode *rootvp; int boothowto; struct timeval boottime; SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, CTLFLAG_RW, &boottime, timeval, ""); struct timeval runtime; /* * Promiscuous argument pass for start_init() * * This is a kludge because we use a return from main() rather than a call * to a new routine in locore.s to kick the kernel alive from locore.s. */ static void *init_framep; #if __GNUC__ >= 2 void __main() {} #endif /* * This ensures that there is at least one entry so that the sysinit_set * symbol is not undefined. A sybsystem ID of SI_SUB_DUMMY is never * executed. */ SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL) /* * System startup; initialize the world, create process 0, mount root * filesystem, and fork to create init and pagedaemon. Most of the * hard work is done in the lower-level initialization routines including * startup(), which does memory initialization and autoconfiguration. * * This allows simple addition of new kernel subsystems that require * boot time initialization. It also allows substitution of subsystem * (for instance, a scheduler, kernel profiler, or VM system) by object * module. Finally, it allows for optional "kernel threads", like an LFS * cleaner. */ void main(framep) void *framep; { register struct sysinit **sipp; /* system initialization*/ register struct sysinit **xipp; /* interior loop of sort*/ register struct sysinit *save; /* bubble*/ int rval[2]; /* SI_TYPE_KTHREAD support*/ /* * Save the locore.s frame pointer for start_init(). */ init_framep = framep; /* * Perform a bubble sort of the system initialization objects by * their subsystem (primary key) and order (secondary key). * * Since some things care about execution order, this is the * operation which ensures continued function. */ for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) { for( xipp = sipp + 1; *xipp; xipp++) { if( (*sipp)->subsystem < (*xipp)->subsystem || ( (*sipp)->subsystem == (*xipp)->subsystem && (*sipp)->order < (*xipp)->order)) continue; /* skip*/ save = *sipp; *sipp = *xipp; *xipp = save; } } /* * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. * * The last item on the list is expected to be the scheduler, * which will not return. */ for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) { if( (*sipp)->subsystem == SI_SUB_DUMMY) continue; /* skip dummy task(s)*/ switch( (*sipp)->type) { case SI_TYPE_DEFAULT: /* no special processing*/ (*((*sipp)->func))( (*sipp)->udata); break; case SI_TYPE_KTHREAD: /* kernel thread*/ if (fork(&proc0, NULL, rval)) panic("fork kernel process"); if (rval[1]) { (*((*sipp)->func))( (*sipp)->udata); /* * The call to start "init" returns * here after the scheduler has been * started, and returns to the caller * in i386/i386/locore.s. This is a * necessary part of initialization * and is rather non-obvious. * * No other "kernel threads" should * return here. Call panic() instead. */ return; } break; default: panic( "init_main: unrecognized init type"); } } /* NOTREACHED*/ } /* * Start a kernel process. This is called after a fork() call in * main() in the file kern/init_main.c. * * This function is used to start "internal" daemons. */ /* ARGSUSED*/ void kproc_start(udata) void *udata; { struct kproc_desc *kp = udata; struct proc *p = curproc; /* save a global descriptor, if desired*/ if( kp->global_procpp != NULL) *kp->global_procpp = p; /* this is a non-swapped system process*/ p->p_flag |= P_INMEM | P_SYSTEM; /* set up arg0 for 'ps', et al*/ strcpy( p->p_comm, kp->arg0); /* call the processes' main()...*/ (*kp->func)(); /* NOTREACHED */ panic("kproc_start: %s", kp->arg0); } /* *************************************************************************** **** **** The following SYSINIT's belong elsewhere, but have not yet **** been moved. **** *************************************************************************** */ #ifdef OMIT /* * Handled by vfs_mountroot (bad idea) at this time... should be * done the same as 4.4Lite2. */ SYSINIT(swapinit, SI_SUB_SWAP, SI_ORDER_FIRST, swapinit, NULL) #endif /* OMIT*/ /* * Should get its own file... */ #ifdef HPFPLIB char copyright[] = "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n"; #else char copyright[] = "Copyright (c) 1992-1997 FreeBSD Inc.\n" #ifdef PC98 "Copyright (c) 1994-1997 FreeBSD(98) porting team.\n" "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\n" "Copyright (c) 1992 A.Kojima F.Ukai M.Ishii (KMC).\n" "\tAll rights reserved.\n\n"; #else "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; #endif #endif static void print_caddr_t __P((void *data)); static void print_caddr_t(data) void *data; { printf("%s", (char *)data); } SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright) /* *************************************************************************** **** **** The two following SYSINT's are proc0 specific glue code. I am not **** convinced that they can not be safely combined, but their order of **** operation has been maintained as the same as the original init_main.c **** for right now. **** **** These probably belong in init_proc.c or kern_proc.c, since they **** deal with proc0 (the fork template process). **** *************************************************************************** */ /* ARGSUSED*/ static void proc0_init __P((void *dummy)); static void proc0_init(dummy) void *dummy; { register struct proc *p; register struct filedesc0 *fdp; register unsigned i; /* * Initialize the current process pointer (curproc) before * any possible traps/probes to simplify trap processing. */ p = &proc0; curproc = p; /* XXX redundant*/ /* * Initialize process and pgrp structures. */ procinit(); /* * Initialize sleep queue hash table */ sleepinit(); /* * Create process 0 (the swapper). */ LIST_INSERT_HEAD(&allproc, p, p_list); p->p_pgrp = &pgrp0; LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); LIST_INIT(&pgrp0.pg_members); LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); pgrp0.pg_session = &session0; session0.s_count = 1; session0.s_leader = p; p->p_sysent = &aout_sysvec; p->p_flag = P_INMEM | P_SYSTEM; p->p_stat = SRUN; p->p_nice = NZERO; p->p_rtprio.type = RTP_PRIO_NORMAL; p->p_rtprio.prio = 0; bcopy("swapper", p->p_comm, sizeof ("swapper")); /* Create credentials. */ cred0.p_refcnt = 1; p->p_cred = &cred0; p->p_ucred = crget(); p->p_ucred->cr_ngroups = 1; /* group 0 */ /* Create the file descriptor table. */ fdp = &filedesc0; p->p_fd = &fdp->fd_fd; fdp->fd_fd.fd_refcnt = 1; fdp->fd_fd.fd_cmask = cmask; fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; fdp->fd_fd.fd_nfiles = NDFILE; /* Create the limits structures. */ p->p_limit = &limit0; for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) limit0.pl_rlimit[i].rlim_cur = limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; i = ptoa(cnt.v_free_count); limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; limit0.p_refcnt = 1; /* Allocate a prototype map so we have something to fork. */ p->p_vmspace = &vmspace0; vmspace0.vm_refcnt = 1; pmap_pinit(&vmspace0.vm_pmap); vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS), trunc_page(VM_MAXUSER_ADDRESS), TRUE); vmspace0.vm_map.pmap = &vmspace0.vm_pmap; p->p_addr = proc0paddr; /* XXX */ #define INCOMPAT_LITES2 #ifdef INCOMPAT_LITES2 /* * proc0 needs to have a coherent frame base, too. * This probably makes the identical call for the init proc * that happens later unnecessary since it should inherit * it during the fork. */ cpu_set_init_frame(p, init_framep); /* XXX! */ #endif /* INCOMPAT_LITES2*/ /* * We continue to place resource usage info and signal * actions in the user struct so they're pageable. */ p->p_stats = &p->p_addr->u_stats; p->p_sigacts = &p->p_addr->u_sigacts; /* * Charge root for one process. */ (void)chgproccnt(0, 1); } SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL) /* ARGSUSED*/ static void proc0_post __P((void *dummy)); static void proc0_post(dummy) void *dummy; { struct timeval tv; /* * Now can look at time, having had a chance to verify the time * from the file system. Reset p->p_rtime as it may have been * munched in mi_switch() after the time got set. */ proc0.p_stats->p_start = runtime = mono_time = boottime = time; proc0.p_rtime.tv_sec = proc0.p_rtime.tv_usec = 0; /* * Give the ``random'' number generator a thump. */ microtime(&tv); srandom(tv.tv_sec ^ tv.tv_usec); /* Initialize signal state for process 0. */ siginit(&proc0); } SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL) /* *************************************************************************** **** **** The following SYSINIT's and glue code should be moved to the **** respective files on a per subsystem basis. **** *************************************************************************** */ /* ARGSUSED*/ static void sched_setup __P((void *dummy)); static void sched_setup(dummy) void *dummy; { /* Kick off timeout driven events by calling first time. */ roundrobin(NULL); schedcpu(NULL); } SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL) /* ARGSUSED*/ static void xxx_vfs_mountroot __P((void *dummy)); +#ifdef BOOTP +extern void bootpc_init __P((void)); +#endif static void xxx_vfs_mountroot(dummy) void *dummy; { + /* XXX Add a separate SYSINIT entry */ +#ifdef BOOTP + bootpc_init(); +#endif /* Mount the root file system. */ if ((*mountroot)(mountrootvfsops)) panic("cannot mount root"); } SYSINIT(mountroot, SI_SUB_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot, NULL) /* ARGSUSED*/ static void xxx_vfs_root_fdtab __P((void *dummy)); static void xxx_vfs_root_fdtab(dummy) void *dummy; { register struct filedesc0 *fdp = &filedesc0; /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ if (VFS_ROOT(mountlist.cqh_first, &rootvnode)) panic("cannot find root vnode"); fdp->fd_fd.fd_cdir = rootvnode; VREF(fdp->fd_fd.fd_cdir); VOP_UNLOCK(rootvnode); fdp->fd_fd.fd_rdir = NULL; } SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL) /* *************************************************************************** **** **** The following code probably belongs in another file, like **** kern/init_init.c. It is here for two reasons only: **** **** 1) This code returns to startup the system; this is **** abnormal for a kernel thread. **** 2) This code promiscuously uses init_frame **** *************************************************************************** */ static void kthread_init __P((void *dummy)); SYSINIT_KT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kthread_init, NULL) static void start_init __P((struct proc *p, void *framep)); /* ARGSUSED*/ static void kthread_init(dummy) void *dummy; { /* Create process 1 (init(8)). */ start_init(curproc, init_framep); /* * This is the only kernel thread allowed to return yo the * caller!!! */ return; } /* * List of paths to try when searching for "init". */ static char *initpaths[] = { "/sbin/init", "/sbin/oinit", "/sbin/init.bak", "/stand/sysinstall", NULL, }; /* * Start the initial user process; try exec'ing each pathname in "initpaths". * The program is invoked with one argument containing the boot flags. */ static void start_init(p, framep) struct proc *p; void *framep; { vm_offset_t addr; struct execve_args args; int options, i, retval[2], error; char **pathp, *path, *ucp, **uap, *arg0, *arg1; initproc = p; /* * We need to set the system call frame as if we were entered through * a syscall() so that when we call execve() below, it will be able * to set the entry point (see setregs) when it tries to exec. The * startup code in "locore.s" has allocated space for the frame and * passed a pointer to that space as main's argument. */ cpu_set_init_frame(p, framep); /* * Need just enough stack to hold the faked-up "execve()" arguments. */ addr = trunc_page(VM_MAXUSER_ADDRESS - PAGE_SIZE); if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0) panic("init: couldn't allocate argument space"); p->p_vmspace->vm_maxsaddr = (caddr_t)addr; p->p_vmspace->vm_ssize = 1; for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { /* * Move out the boot flag argument. */ options = 0; ucp = (char *)USRSTACK; (void)subyte(--ucp, 0); /* trailing zero */ if (boothowto & RB_SINGLE) { (void)subyte(--ucp, 's'); options = 1; } #ifdef notyet if (boothowto & RB_FASTBOOT) { (void)subyte(--ucp, 'f'); options = 1; } #endif #ifdef BOOTCDROM (void)subyte(--ucp, 'C'); options = 1; #endif #if defined(DEVFS) && defined(DEVFS_ROOT) (void)subyte(--ucp, 'd'); options = 1; #endif if (options == 0) (void)subyte(--ucp, '-'); (void)subyte(--ucp, '-'); /* leading hyphen */ arg1 = ucp; /* * Move out the file name (also arg 0). */ for (i = strlen(path) + 1; i >= 0; i--) (void)subyte(--ucp, path[i]); arg0 = ucp; /* * Move out the arg pointers. */ uap = (char **)((int)ucp & ~(NBPW-1)); (void)suword((caddr_t)--uap, 0); /* terminator */ (void)suword((caddr_t)--uap, (int)arg1); (void)suword((caddr_t)--uap, (int)arg0); /* * Point at the arguments. */ args.fname = arg0; args.argv = uap; args.envv = NULL; /* * Now try to exec the program. If can't for any reason * other than it doesn't exist, complain. * * Otherwise return to main() which returns to btext * which completes the system startup. */ if ((error = execve(p, &args, &retval[0])) == 0) return; if (error != ENOENT) printf("exec %s: error %d\n", path, error); } printf("init: not found\n"); panic("no init"); } Index: stable/2.2/sys/netinet/ip_input.c =================================================================== --- stable/2.2/sys/netinet/ip_input.c (revision 25722) +++ stable/2.2/sys/netinet/ip_input.c (revision 25723) @@ -1,1414 +1,1418 @@ /* * Copyright (c) 1982, 1986, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * $Id: ip_input.c,v 1.50.2.3 1997/02/03 23:15:47 joerg Exp $ + * $Id: ip_input.c,v 1.50.2.4 1997/02/06 11:33:38 brian Exp $ * $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $ */ #define _IP_VHL #include "opt_ipfw.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef IPFIREWALL #include #endif int rsvp_on = 0; static int ip_rsvp_on; struct socket *ip_rsvpd; static int ipforwarding = 0; SYSCTL_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW, &ipforwarding, 0, ""); static int ipsendredirects = 1; /* XXX */ SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW, &ipsendredirects, 0, ""); int ip_defttl = IPDEFTTL; SYSCTL_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_RW, &ip_defttl, 0, ""); static int ip_dosourceroute = 0; SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW, &ip_dosourceroute, 0, ""); #ifdef DIAGNOSTIC static int ipprintfs = 0; #endif extern struct domain inetdomain; extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; static int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddr *in_ifaddr; /* first inet address */ struct ifqueue ipintrq; SYSCTL_INT(_net_inet_ip, IPCTL_INTRQMAXLEN, intr_queue_maxlen, CTLFLAG_RD, &ipintrq.ifq_maxlen, 0, ""); SYSCTL_INT(_net_inet_ip, IPCTL_INTRQDROPS, intr_queue_drops, CTLFLAG_RD, &ipintrq.ifq_drops, 0, ""); struct ipstat ipstat; static struct ipq ipq; #ifdef IPCTL_DEFMTU SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW, &ip_mtu, 0, ""); #endif #if !defined(COMPAT_IPFW) || COMPAT_IPFW == 1 #undef COMPAT_IPFW #define COMPAT_IPFW 1 #else #undef COMPAT_IPFW #endif #ifdef COMPAT_IPFW /* Firewall hooks */ ip_fw_chk_t *ip_fw_chk_ptr; ip_fw_ctl_t *ip_fw_ctl_ptr; /* IP Network Address Translation (NAT) hooks */ ip_nat_t *ip_nat_ptr; ip_nat_ctl_t *ip_nat_ctl_ptr; #endif /* * We need to save the IP options in case a protocol wants to respond * to an incoming packet over the same route if the packet got here * using IP source routing. This allows connection establishment and * maintenance when the remote end is on a network that is not known * to us. */ static int ip_nhops = 0; static struct ip_srcrt { struct in_addr dst; /* final destination */ char nop; /* one NOP to align */ char srcopt[IPOPT_OFFSET + 1]; /* OPTVAL, OLEN and OFFSET */ struct in_addr route[MAX_IPOPTLEN/sizeof(struct in_addr)]; } ip_srcrt; #ifdef IPDIVERT /* * Shared variable between ip_input() and ip_reass() to communicate * about which packets, once assembled from fragments, get diverted, * and to which port. */ static u_short frag_divert_port; #endif static void save_rte __P((u_char *, struct in_addr)); static void ip_deq __P((struct ipasfrag *)); static int ip_dooptions __P((struct mbuf *)); static void ip_enq __P((struct ipasfrag *, struct ipasfrag *)); static void ip_forward __P((struct mbuf *, int)); static void ip_freef __P((struct ipq *)); static struct ip * ip_reass __P((struct ipasfrag *, struct ipq *)); static struct in_ifaddr * ip_rtaddr __P((struct in_addr)); static void ipintr __P((void)); /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. */ void ip_init() { register struct protosw *pr; register int i; pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == 0) panic("ip_init"); for (i = 0; i < IPPROTO_MAX; i++) ip_protox[i] = pr - inetsw; for (pr = inetdomain.dom_protosw; pr < inetdomain.dom_protoswNPROTOSW; pr++) if (pr->pr_domain->dom_family == PF_INET && pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) ip_protox[pr->pr_protocol] = pr - inetsw; ipq.next = ipq.prev = &ipq; ip_id = time.tv_sec & 0xffff; ipintrq.ifq_maxlen = ipqmaxlen; #ifdef IPFIREWALL ip_fw_init(); #endif #ifdef IPNAT ip_nat_init(); #endif } static struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; static struct route ipforward_rt; /* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ void ip_input(struct mbuf *m) { struct ip *ip; struct ipq *fp; struct in_ifaddr *ia; int hlen; u_short sum; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ip_input no HDR"); #endif /* * If no IP addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. */ if (in_ifaddr == NULL) goto bad; ipstat.ips_total++; if (m->m_pkthdr.len < sizeof(struct ip)) goto tooshort; #ifdef DIAGNOSTIC if (m->m_len < sizeof(struct ip)) panic("ipintr mbuf too short"); #endif if (m->m_len < sizeof (struct ip) && (m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; return; } ip = mtod(m, struct ip *); if (IP_VHL_V(ip->ip_vhl) != IPVERSION) { ipstat.ips_badvers++; goto bad; } hlen = IP_VHL_HL(ip->ip_vhl) << 2; if (hlen < sizeof(struct ip)) { /* minimum header length */ ipstat.ips_badhlen++; goto bad; } if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == 0) { ipstat.ips_badhlen++; return; } ip = mtod(m, struct ip *); } if (hlen == sizeof(struct ip)) { sum = in_cksum_hdr(ip); } else { sum = in_cksum(m, hlen); } if (sum) { ipstat.ips_badsum++; goto bad; } /* * Convert fields to host representation. */ NTOHS(ip->ip_len); if (ip->ip_len < hlen) { ipstat.ips_badlen++; goto bad; } NTOHS(ip->ip_id); NTOHS(ip->ip_off); /* * Check that the amount of data in the buffers * is as at least much as the IP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if (m->m_pkthdr.len < ip->ip_len) { tooshort: ipstat.ips_tooshort++; goto bad; } if (m->m_pkthdr.len > ip->ip_len) { if (m->m_len == m->m_pkthdr.len) { m->m_len = ip->ip_len; m->m_pkthdr.len = ip->ip_len; } else m_adj(m, ip->ip_len - m->m_pkthdr.len); } /* * IpHack's section. * Right now when no processing on packet has done * and it is still fresh out of network we do our black * deals with it. * - Firewall: deny/allow/divert * - Xlate: translate packet's addr/port (NAT). * - Wrap: fake packet's addr/port * - Encapsulate: put it in another IP and send out. */ #ifdef COMPAT_IPFW if (ip_fw_chk_ptr) { int action; #ifdef IPDIVERT action = (*ip_fw_chk_ptr)(&ip, hlen, m->m_pkthdr.rcvif, ip_divert_ignore, &m); ip_divert_ignore = 0; #else action = (*ip_fw_chk_ptr)(&ip, hlen, m->m_pkthdr.rcvif, 0, &m); #endif if (action == -1) return; if (action != 0) { #ifdef IPDIVERT frag_divert_port = action; goto ours; #else goto bad; /* ipfw said divert but we can't */ #endif } } if (ip_nat_ptr && !(*ip_nat_ptr)(&ip, &m, m->m_pkthdr.rcvif, IP_NAT_IN)) return; #endif /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message * to be sent and the original packet to be freed). */ ip_nhops = 0; /* for source routed packets */ if (hlen > sizeof (struct ip) && ip_dooptions(m)) return; /* greedy RSVP, snatches any PATH packet of the RSVP protocol and no * matter if it is destined to another node, or whether it is * a multicast one, RSVP wants it! and prevents it from being forwarded * anywhere else. Also checks if the rsvp daemon is running before * grabbing the packet. */ if (rsvp_on && ip->ip_p==IPPROTO_RSVP) goto ours; /* * Check our list of addresses, to see if the packet is for us. */ for (ia = in_ifaddr; ia; ia = ia->ia_next) { #define satosin(sa) ((struct sockaddr_in *)(sa)) if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; +#ifdef BOOTP_COMPAT + if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY) + goto ours; +#endif if (ia->ia_ifp && ia->ia_ifp->if_flags & IFF_BROADCAST) { if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr) goto ours; } } if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { struct in_multi *inm; if (ip_mrouter) { /* * If we are acting as a multicast router, all * incoming multicast packets are passed to the * kernel-level multicast forwarding function. * The packet is returned (relatively) intact; if * ip_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. * * (The IP ident field is put in the same byte order * as expected when ip_mforward() is called from * ip_output().) */ ip->ip_id = htons(ip->ip_id); if (ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) { ipstat.ips_cantforward++; m_freem(m); return; } ip->ip_id = ntohs(ip->ip_id); /* * The process-level routing demon needs to receive * all multicast IGMP packets, whether or not this * host belongs to their destination groups. */ if (ip->ip_p == IPPROTO_IGMP) goto ours; ipstat.ips_forward++; } /* * See if we belong to the destination multicast group on the * arrival interface. */ IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); if (inm == NULL) { ipstat.ips_cantforward++; m_freem(m); return; } goto ours; } if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST) goto ours; if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; /* * Not for us; forward if possible and desirable. */ if (ipforwarding == 0) { ipstat.ips_cantforward++; m_freem(m); } else ip_forward(m, 0); return; ours: /* * If offset or IP_MF are set, must reassemble. * Otherwise, nothing need be done. * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ if (ip->ip_off &~ IP_DF) { if (m->m_flags & M_EXT) { /* XXX */ if ((m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; #ifdef IPDIVERT frag_divert_port = 0; #endif return; } ip = mtod(m, struct ip *); } /* * Look for queue of fragments * of this datagram. */ for (fp = ipq.next; fp != &ipq; fp = fp->next) if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_p == fp->ipq_p) goto found; fp = 0; found: /* * Adjust ip_len to not reflect header, * set ip_mff if more fragments are expected, * convert offset of this to bytes. */ ip->ip_len -= hlen; ((struct ipasfrag *)ip)->ipf_mff &= ~1; if (ip->ip_off & IP_MF) ((struct ipasfrag *)ip)->ipf_mff |= 1; ip->ip_off <<= 3; /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { ipstat.ips_fragments++; ip = ip_reass((struct ipasfrag *)ip, fp); if (ip == 0) return; ipstat.ips_reassembled++; m = dtom(ip); } else if (fp) ip_freef(fp); } else ip->ip_len -= hlen; #ifdef IPDIVERT /* * Divert packets here to the divert protocol if required */ if (frag_divert_port) { ip_divert_port = frag_divert_port; frag_divert_port = 0; (*inetsw[ip_protox[IPPROTO_DIVERT]].pr_input)(m, hlen); return; } #endif /* * Switch out to protocol's input routine. */ ipstat.ips_delivered++; (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); return; bad: m_freem(m); } /* * IP software interrupt routine - to go away sometime soon */ static void ipintr(void) { int s; struct mbuf *m; while(1) { s = splimp(); IF_DEQUEUE(&ipintrq, m); splx(s); if (m == 0) return; ip_input(m); } } NETISR_SET(NETISR_IP, ipintr); /* * Take incoming datagram fragment and try to * reassemble it into whole datagram. If a chain for * reassembly of this datagram already exists, then it * is given as fp; otherwise have to make a chain. */ static struct ip * ip_reass(ip, fp) register struct ipasfrag *ip; register struct ipq *fp; { register struct mbuf *m = dtom(ip); register struct ipasfrag *q; struct mbuf *t; int hlen = ip->ip_hl << 2; int i, next; /* * Presence of header sizes in mbufs * would confuse code below. */ m->m_data += hlen; m->m_len -= hlen; /* * If first fragment to arrive, create a reassembly queue. */ if (fp == 0) { if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL) goto dropfrag; fp = mtod(t, struct ipq *); insque(fp, &ipq); fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp; fp->ipq_src = ((struct ip *)ip)->ip_src; fp->ipq_dst = ((struct ip *)ip)->ip_dst; #ifdef IPDIVERT fp->ipq_divert = 0; #endif q = (struct ipasfrag *)fp; goto insert; } /* * Find a segment which begins after this one does. */ for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) if (q->ip_off > ip->ip_off) break; /* * If there is a preceding segment, it may provide some of * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ if (q->ipf_prev != (struct ipasfrag *)fp) { i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off; if (i > 0) { if (i >= ip->ip_len) goto dropfrag; m_adj(dtom(ip), i); ip->ip_off += i; ip->ip_len -= i; } } /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ while (q != (struct ipasfrag *)fp && ip->ip_off + ip->ip_len > q->ip_off) { struct mbuf *m0; i = (ip->ip_off + ip->ip_len) - q->ip_off; if (i < q->ip_len) { q->ip_len -= i; q->ip_off += i; m_adj(dtom(q), i); break; } m0 = dtom(q); q = q->ipf_next; ip_deq(q->ipf_prev); m_freem(m0); } insert: #ifdef IPDIVERT /* * Any fragment diverting causes the whole packet to divert */ if (frag_divert_port != 0) fp->ipq_divert = frag_divert_port; frag_divert_port = 0; #endif /* * Stick new segment in its place; * check for complete reassembly. */ ip_enq(ip, q->ipf_prev); next = 0; for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { if (q->ip_off != next) return (0); next += q->ip_len; } if (q->ipf_prev->ipf_mff & 1) return (0); /* * Reassembly is complete. Make sure the packet is a sane size. */ if (next + (IP_VHL_HL(((struct ip *)fp->ipq_next)->ip_vhl) << 2) > IP_MAXPACKET) { ipstat.ips_toolong++; ip_freef(fp); return (0); } /* * Concatenate fragments. */ q = fp->ipq_next; m = dtom(q); t = m->m_next; m->m_next = 0; m_cat(m, t); q = q->ipf_next; while (q != (struct ipasfrag *)fp) { t = dtom(q); q = q->ipf_next; m_cat(m, t); } #ifdef IPDIVERT /* * Record divert port for packet, if any */ frag_divert_port = fp->ipq_divert; #endif /* * Create header for new ip packet by * modifying header of first packet; * dequeue and discard fragment reassembly header. * Make header visible. */ ip = fp->ipq_next; ip->ip_len = next; ip->ipf_mff &= ~1; ((struct ip *)ip)->ip_src = fp->ipq_src; ((struct ip *)ip)->ip_dst = fp->ipq_dst; remque(fp); (void) m_free(dtom(fp)); m = dtom(ip); m->m_len += (ip->ip_hl << 2); m->m_data -= (ip->ip_hl << 2); /* some debugging cruft by sklower, below, will go away soon */ if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */ register int plen = 0; for (t = m; m; m = m->m_next) plen += m->m_len; t->m_pkthdr.len = plen; } return ((struct ip *)ip); dropfrag: ipstat.ips_fragdropped++; m_freem(m); return (0); } /* * Free a fragment reassembly header and all * associated datagrams. */ static void ip_freef(fp) struct ipq *fp; { register struct ipasfrag *q, *p; for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) { p = q->ipf_next; ip_deq(q); m_freem(dtom(q)); } remque(fp); (void) m_free(dtom(fp)); } /* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ static void ip_enq(p, prev) register struct ipasfrag *p, *prev; { p->ipf_prev = prev; p->ipf_next = prev->ipf_next; prev->ipf_next->ipf_prev = p; prev->ipf_next = p; } /* * To ip_enq as remque is to insque. */ static void ip_deq(p) register struct ipasfrag *p; { p->ipf_prev->ipf_next = p->ipf_next; p->ipf_next->ipf_prev = p->ipf_prev; } /* * IP timer processing; * if a timer expires on a reassembly * queue, discard it. */ void ip_slowtimo() { register struct ipq *fp; int s = splnet(); fp = ipq.next; if (fp == 0) { splx(s); return; } while (fp != &ipq) { --fp->ipq_ttl; fp = fp->next; if (fp->prev->ipq_ttl == 0) { ipstat.ips_fragtimeout++; ip_freef(fp->prev); } } splx(s); } /* * Drain off all datagram fragments. */ void ip_drain() { while (ipq.next != &ipq) { ipstat.ips_fragdropped++; ip_freef(ipq.next); } in_rtqdrain(); } /* * Do option processing on a datagram, * possibly discarding it if bad options are encountered, * or forwarding it if source-routed. * Returns 1 if packet has been forwarded/freed, * 0 if the packet should be processed further. */ static int ip_dooptions(m) struct mbuf *m; { register struct ip *ip = mtod(m, struct ip *); register u_char *cp; register struct ip_timestamp *ipt; register struct in_ifaddr *ia; int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0; struct in_addr *sin, dst; n_time ntime; dst = ip->ip_dst; cp = (u_char *)(ip + 1); cnt = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip); for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[IPOPT_OPTVAL]; if (opt == IPOPT_EOL) break; if (opt == IPOPT_NOP) optlen = 1; else { optlen = cp[IPOPT_OLEN]; if (optlen <= 0 || optlen > cnt) { code = &cp[IPOPT_OLEN] - (u_char *)ip; goto bad; } } switch (opt) { default: break; /* * Source routing with record. * Find interface with current destination address. * If none on this machine then drop if strictly routed, * or do nothing if loosely routed. * Record interface address and bring up next address * component. If strictly routed make sure next * address is on directly accessible net. */ case IPOPT_LSRR: case IPOPT_SSRR: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } ipaddr.sin_addr = ip->ip_dst; ia = (struct in_ifaddr *) ifa_ifwithaddr((struct sockaddr *)&ipaddr); if (ia == 0) { if (opt == IPOPT_SSRR) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } /* * Loose routing, and not at next destination * yet; nothing to do except forward. */ break; } off--; /* 0 origin */ if (off > optlen - sizeof(struct in_addr)) { /* * End of source route. Should be for us. */ save_rte(cp, ip->ip_src); break; } if (!ip_dosourceroute) { char buf[4*sizeof "123"]; strcpy(buf, inet_ntoa(ip->ip_dst)); log(LOG_WARNING, "attempted source route from %s to %s\n", inet_ntoa(ip->ip_src), buf); type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } /* * locate outgoing interface */ (void)memcpy(&ipaddr.sin_addr, cp + off, sizeof(ipaddr.sin_addr)); if (opt == IPOPT_SSRR) { #define INA struct in_ifaddr * #define SA struct sockaddr * if ((ia = (INA)ifa_ifwithdstaddr((SA)&ipaddr)) == 0) ia = (INA)ifa_ifwithnet((SA)&ipaddr); } else ia = ip_rtaddr(ipaddr.sin_addr); if (ia == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } ip->ip_dst = ipaddr.sin_addr; (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); /* * Let ip_intr's mcast routing check handle mcast pkts */ forward = !IN_MULTICAST(ntohl(ip->ip_dst.s_addr)); break; case IPOPT_RR: if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) { code = &cp[IPOPT_OFFSET] - (u_char *)ip; goto bad; } /* * If no space remains, ignore. */ off--; /* 0 origin */ if (off > optlen - sizeof(struct in_addr)) break; (void)memcpy(&ipaddr.sin_addr, &ip->ip_dst, sizeof(ipaddr.sin_addr)); /* * locate outgoing interface; if we're the destination, * use the incoming interface (should be same). */ if ((ia = (INA)ifa_ifwithaddr((SA)&ipaddr)) == 0 && (ia = ip_rtaddr(ipaddr.sin_addr)) == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; goto bad; } (void)memcpy(cp + off, &(IA_SIN(ia)->sin_addr), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; case IPOPT_TS: code = cp - (u_char *)ip; ipt = (struct ip_timestamp *)cp; if (ipt->ipt_len < 5) goto bad; if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) { if (++ipt->ipt_oflw == 0) goto bad; break; } sin = (struct in_addr *)(cp + ipt->ipt_ptr - 1); switch (ipt->ipt_flg) { case IPOPT_TS_TSONLY: break; case IPOPT_TS_TSANDADDR: if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; ipaddr.sin_addr = dst; ia = (INA)ifaof_ifpforaddr((SA)&ipaddr, m->m_pkthdr.rcvif); if (ia == 0) continue; (void)memcpy(sin, &IA_SIN(ia)->sin_addr, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); break; case IPOPT_TS_PRESPEC: if (ipt->ipt_ptr + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; (void)memcpy(&ipaddr.sin_addr, sin, sizeof(struct in_addr)); if (ifa_ifwithaddr((SA)&ipaddr) == 0) continue; ipt->ipt_ptr += sizeof(struct in_addr); break; default: goto bad; } ntime = iptime(); (void)memcpy(cp + ipt->ipt_ptr - 1, &ntime, sizeof(n_time)); ipt->ipt_ptr += sizeof(n_time); } } if (forward) { ip_forward(m, 1); return (1); } return (0); bad: ip->ip_len -= IP_VHL_HL(ip->ip_vhl) << 2; /* XXX icmp_error adds in hdr length */ icmp_error(m, type, code, 0, 0); ipstat.ips_badoptions++; return (1); } /* * Given address of next destination (final or next hop), * return internet address info of interface to be used to get there. */ static struct in_ifaddr * ip_rtaddr(dst) struct in_addr dst; { register struct sockaddr_in *sin; sin = (struct sockaddr_in *) &ipforward_rt.ro_dst; if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) { if (ipforward_rt.ro_rt) { RTFREE(ipforward_rt.ro_rt); ipforward_rt.ro_rt = 0; } sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = dst; rtalloc_ign(&ipforward_rt, RTF_PRCLONING); } if (ipforward_rt.ro_rt == 0) return ((struct in_ifaddr *)0); return ((struct in_ifaddr *) ipforward_rt.ro_rt->rt_ifa); } /* * Save incoming source route for use in replies, * to be picked up later by ip_srcroute if the receiver is interested. */ void save_rte(option, dst) u_char *option; struct in_addr dst; { unsigned olen; olen = option[IPOPT_OLEN]; #ifdef DIAGNOSTIC if (ipprintfs) printf("save_rte: olen %d\n", olen); #endif if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) return; bcopy(option, ip_srcrt.srcopt, olen); ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); ip_srcrt.dst = dst; } /* * Retrieve incoming source route for use in replies, * in the same form used by setsockopt. * The first hop is placed before the options, will be removed later. */ struct mbuf * ip_srcroute() { register struct in_addr *p, *q; register struct mbuf *m; if (ip_nhops == 0) return ((struct mbuf *)0); m = m_get(M_DONTWAIT, MT_SOOPTS); if (m == 0) return ((struct mbuf *)0); #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) /* length is (nhops+1)*sizeof(addr) + sizeof(nop + srcrt header) */ m->m_len = ip_nhops * sizeof(struct in_addr) + sizeof(struct in_addr) + OPTSIZ; #ifdef DIAGNOSTIC if (ipprintfs) printf("ip_srcroute: nhops %d mlen %d", ip_nhops, m->m_len); #endif /* * First save first hop for return route */ p = &ip_srcrt.route[ip_nhops - 1]; *(mtod(m, struct in_addr *)) = *p--; #ifdef DIAGNOSTIC if (ipprintfs) printf(" hops %lx", ntohl(mtod(m, struct in_addr *)->s_addr)); #endif /* * Copy option fields and padding (nop) to mbuf. */ ip_srcrt.nop = IPOPT_NOP; ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; (void)memcpy(mtod(m, caddr_t) + sizeof(struct in_addr), &ip_srcrt.nop, OPTSIZ); q = (struct in_addr *)(mtod(m, caddr_t) + sizeof(struct in_addr) + OPTSIZ); #undef OPTSIZ /* * Record return path as an IP source route, * reversing the path (pointers are now aligned). */ while (p >= ip_srcrt.route) { #ifdef DIAGNOSTIC if (ipprintfs) printf(" %lx", ntohl(q->s_addr)); #endif *q++ = *p--; } /* * Last hop goes to final destination. */ *q = ip_srcrt.dst; #ifdef DIAGNOSTIC if (ipprintfs) printf(" %lx\n", ntohl(q->s_addr)); #endif return (m); } /* * Strip out IP options, at higher * level protocol in the kernel. * Second argument is buffer to which options * will be moved, and return value is their length. * XXX should be deleted; last arg currently ignored. */ void ip_stripoptions(m, mopt) register struct mbuf *m; struct mbuf *mopt; { register int i; struct ip *ip = mtod(m, struct ip *); register caddr_t opts; int olen; olen = (IP_VHL_HL(ip->ip_vhl) << 2) - sizeof (struct ip); opts = (caddr_t)(ip + 1); i = m->m_len - (sizeof (struct ip) + olen); bcopy(opts + olen, opts, (unsigned)i); m->m_len -= olen; if (m->m_flags & M_PKTHDR) m->m_pkthdr.len -= olen; ip->ip_vhl = IP_MAKE_VHL(IPVERSION, sizeof(struct ip) >> 2); } u_char inetctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, EMSGSIZE, EHOSTUNREACH, 0, 0, 0, 0, 0, 0, ENOPROTOOPT }; /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful * icmp message because icmp doesn't have a large enough repertoire * of codes and types. * * If not forwarding, just drop the packet. This could be confusing * if ipforwarding was zero but some routing protocol was advancing * us as a gateway to somewhere. However, we must let the routing * protocol deal with that. * * The srcrt parameter indicates whether the packet is being forwarded * via a source route. */ static void ip_forward(m, srcrt) struct mbuf *m; int srcrt; { register struct ip *ip = mtod(m, struct ip *); register struct sockaddr_in *sin; register struct rtentry *rt; int error, type = 0, code = 0; struct mbuf *mcopy; n_long dest; struct ifnet *destifp; dest = 0; #ifdef DIAGNOSTIC if (ipprintfs) printf("forward: src %lx dst %lx ttl %x\n", ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl); #endif if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) { ipstat.ips_cantforward++; m_freem(m); return; } HTONS(ip->ip_id); if (ip->ip_ttl <= IPTTLDEC) { icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); return; } ip->ip_ttl -= IPTTLDEC; sin = (struct sockaddr_in *)&ipforward_rt.ro_dst; if ((rt = ipforward_rt.ro_rt) == 0 || ip->ip_dst.s_addr != sin->sin_addr.s_addr) { if (ipforward_rt.ro_rt) { RTFREE(ipforward_rt.ro_rt); ipforward_rt.ro_rt = 0; } sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; rtalloc_ign(&ipforward_rt, RTF_PRCLONING); if (ipforward_rt.ro_rt == 0) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); return; } rt = ipforward_rt.ro_rt; } /* * Save at most 64 bytes of the packet in case * we need to generate an ICMP message to the src. */ mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64)); /* * If forwarding packet using same interface that it came in on, * perhaps should send a redirect to sender to shortcut a hop. * Only send redirect if source is sending directly to us, * and if packet was not source routed (or has any options). * Also, don't send redirect if forwarding using a default route * or a route modified by a redirect. */ #define satosin(sa) ((struct sockaddr_in *)(sa)) if (rt->rt_ifp == m->m_pkthdr.rcvif && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && satosin(rt_key(rt))->sin_addr.s_addr != 0 && ipsendredirects && !srcrt) { #define RTA(rt) ((struct in_ifaddr *)(rt->rt_ifa)) u_long src = ntohl(ip->ip_src.s_addr); if (RTA(rt) && (src & RTA(rt)->ia_subnetmask) == RTA(rt)->ia_subnet) { if (rt->rt_flags & RTF_GATEWAY) dest = satosin(rt->rt_gateway)->sin_addr.s_addr; else dest = ip->ip_dst.s_addr; /* Router requirements says to only send host redirects */ type = ICMP_REDIRECT; code = ICMP_REDIRECT_HOST; #ifdef DIAGNOSTIC if (ipprintfs) printf("redirect (%d) to %lx\n", code, (u_long)dest); #endif } } error = ip_output(m, (struct mbuf *)0, &ipforward_rt, IP_FORWARDING, 0); if (error) ipstat.ips_cantforward++; else { ipstat.ips_forward++; if (type) ipstat.ips_redirectsent++; else { if (mcopy) m_freem(mcopy); return; } } if (mcopy == NULL) return; destifp = NULL; switch (error) { case 0: /* forwarded, but need redirect */ /* type, code set above */ break; case ENETUNREACH: /* shouldn't happen, checked above */ case EHOSTUNREACH: case ENETDOWN: case EHOSTDOWN: default: type = ICMP_UNREACH; code = ICMP_UNREACH_HOST; break; case EMSGSIZE: type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; if (ipforward_rt.ro_rt) destifp = ipforward_rt.ro_rt->rt_ifp; ipstat.ips_cantfrag++; break; case ENOBUFS: type = ICMP_SOURCEQUENCH; code = 0; break; } icmp_error(mcopy, type, code, dest, destifp); } void ip_savecontrol(inp, mp, ip, m) register struct inpcb *inp; register struct mbuf **mp; register struct ip *ip; register struct mbuf *m; { if (inp->inp_socket->so_options & SO_TIMESTAMP) { struct timeval tv; microtime(&tv); *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } if (inp->inp_flags & INP_RECVDSTADDR) { *mp = sbcreatecontrol((caddr_t) &ip->ip_dst, sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } #ifdef notyet /* XXX * Moving these out of udp_input() made them even more broken * than they already were. */ /* options were tossed already */ if (inp->inp_flags & INP_RECVOPTS) { *mp = sbcreatecontrol((caddr_t) opts_deleted_above, sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } /* ip_srcroute doesn't do what we want here, need to fix */ if (inp->inp_flags & INP_RECVRETOPTS) { *mp = sbcreatecontrol((caddr_t) ip_srcroute(), sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } #endif if (inp->inp_flags & INP_RECVIF) { struct sockaddr_dl sdl; sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]); sdl.sdl_family = AF_LINK; sdl.sdl_index = m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 0; sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0; *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len, IP_RECVIF, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; } } int ip_rsvp_init(struct socket *so) { if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP) return EOPNOTSUPP; if (ip_rsvpd != NULL) return EADDRINUSE; ip_rsvpd = so; /* * This may seem silly, but we need to be sure we don't over-increment * the RSVP counter, in case something slips up. */ if (!ip_rsvp_on) { ip_rsvp_on = 1; rsvp_on++; } return 0; } int ip_rsvp_done(void) { ip_rsvpd = NULL; /* * This may seem silly, but we need to be sure we don't over-decrement * the RSVP counter, in case something slips up. */ if (ip_rsvp_on) { ip_rsvp_on = 0; rsvp_on--; } return 0; } Index: stable/2.2/sys/nfs/bootp_subr.c =================================================================== --- stable/2.2/sys/nfs/bootp_subr.c (nonexistent) +++ stable/2.2/sys/nfs/bootp_subr.c (revision 25723) @@ -0,0 +1,1316 @@ +/* $Id:$ */ + +/* + * Copyright (c) 1995 Gordon Ross, Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * based on: + * nfs/krpc_subr.c + * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */ + +/* + * What is the longest we will wait before re-sending a request? + * Note this is also the frequency of "RPC timeout" messages. + * The re-send loop count sup linearly to this maximum, so the + * first complaint will happen after (1+2+3+4+5)=15 seconds. + */ +#define MAX_RESEND_DELAY 5 /* seconds */ + +/* Definitions from RFC951 */ +struct bootp_packet { + u_int8_t op; + u_int8_t htype; + u_int8_t hlen; + u_int8_t hops; + u_int32_t xid; + u_int16_t secs; + u_int16_t flags; + struct in_addr ciaddr; + struct in_addr yiaddr; + struct in_addr siaddr; + struct in_addr giaddr; + unsigned char chaddr[16]; + char sname[64]; + char file[128]; + unsigned char vend[256]; +}; + +#define IPPORT_BOOTPC 68 +#define IPPORT_BOOTPS 67 + +extern int nfs_diskless_valid; +extern struct nfsv3_diskless nfsv3_diskless; + +/* mountd RPC */ +static int md_mount __P((struct sockaddr_in *mdsin, char *path, + u_char *fhp, int *fhsizep, struct nfs_args *args,struct proc *procp)); +static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path, + u_char *fhp, int *fhsizep, + struct nfs_args *args, + struct proc *procp)); + +#ifdef BOOTP_DEBUG +void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma); +void bootpboot_p_ma(struct sockaddr *ma); +void bootpboot_p_rtentry(struct rtentry *rt); +void bootpboot_p_tree(struct radix_node *rn); +void bootpboot_p_rtlist(void); +void bootpboot_p_iflist(void); +#endif + +int bootpc_call(struct bootp_packet *call, + struct bootp_packet *reply, + struct proc *procp); + +int bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, + struct proc *procp); + +int +bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, + struct sockaddr_in *myaddr, + struct sockaddr_in *netmask, + struct sockaddr_in *gw, + struct proc *procp); + +void bootpc_init(void); + +#ifdef BOOTP_DEBUG +void bootpboot_p_sa(sa,ma) + struct sockaddr *sa; + struct sockaddr *ma; +{ + if (!sa) { + printf("(sockaddr *) "); + return; + } + switch (sa->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + printf("inet %x",ntohl(sin->sin_addr.s_addr)); + if (ma) { + struct sockaddr_in *sin = (struct sockaddr_in *) ma; + printf(" mask %x",ntohl(sin->sin_addr.s_addr)); + } + } + break; + case AF_LINK: + { + struct sockaddr_dl *sli = (struct sockaddr_dl *) sa; + int i; + printf("link %.*s ",sli->sdl_nlen,sli->sdl_data); + for (i=0;isdl_alen;i++) { + if (i>0) + printf(":"); + printf("%x",(unsigned char) sli->sdl_data[i+sli->sdl_nlen]); + } + } + break; + default: + printf("af%d",sa->sa_family); + } +} + +void bootpboot_p_ma(ma) + struct sockaddr *ma; +{ + if (!ma) { + printf(""); + return; + } + printf("%x",*(int*)ma); +} + +void bootpboot_p_rtentry(rt) + struct rtentry *rt; +{ + bootpboot_p_sa(rt_key(rt),rt_mask(rt)); + printf(" "); + bootpboot_p_ma(rt->rt_genmask); + printf(" "); + bootpboot_p_sa(rt->rt_gateway,NULL); + printf(" "); + printf("flags %x",(unsigned short) rt->rt_flags); + printf(" %d",rt->rt_rmx.rmx_expire); + printf(" %s%d\n",rt->rt_ifp->if_name,rt->rt_ifp->if_unit); +} +void bootpboot_p_tree(rn) + struct radix_node *rn; +{ + while (rn) { + if (rn->rn_b < 0) { + if (rn->rn_flags & RNF_ROOT) { + } else { + bootpboot_p_rtentry((struct rtentry *) rn); + } + rn = rn->rn_dupedkey; + } else { + bootpboot_p_tree(rn->rn_l); + bootpboot_p_tree(rn->rn_r); + return; + } + + } +} + +void bootpboot_p_rtlist(void) +{ + printf("Routing table:\n"); + bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); +} + +void bootpboot_p_iflist(void) +{ + struct ifnet *ifp; + struct ifaddr *ifa; + printf("Interface list:\n"); + for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) + { + for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; + ifa=TAILQ_NEXT(ifa,ifa_link)) + if (ifa->ifa_addr->sa_family == AF_INET ) { + printf("%s%d flags %x, addr %x, bcast %x, net %x\n", + ifp->if_name,ifp->if_unit, + (unsigned short) ifp->if_flags, + ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr), + ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr), + ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr) + ); + } + } +} +#endif + +int +bootpc_call(call,reply,procp) + struct bootp_packet *call; + struct bootp_packet *reply; /* output */ + struct proc *procp; +{ + struct socket *so; + struct sockaddr_in *sin,sa; + struct mbuf *m, *nam; + struct uio auio; + struct iovec aio; + int error, rcvflg, timo, secs, len; + u_int tport; + + /* Free at end if not null. */ + nam = NULL; + + /* + * Create socket and set its recieve timeout. + */ + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp))) + goto out; + + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } else { + struct timeval *tv; + tv = mtod(m, struct timeval *); + m->m_len = sizeof(*tv); + tv->tv_sec = 1; + tv->tv_usec = 0; + if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m))) + goto out; + } + + /* + * Enable broadcast. + */ + { + int *on; + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + on = mtod(m, int *); + m->m_len = sizeof(*on); + *on = 1; + if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m))) + goto out; + } + + /* + * Bind the local endpoint to a bootp client port. + */ + m = m_getclr(M_WAIT, MT_SONAME); + sin = mtod(m, struct sockaddr_in *); + sin->sin_len = m->m_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + sin->sin_port = htons(IPPORT_BOOTPC); + error = sobind(so, m); + m_freem(m); + if (error) { + printf("bind failed\n"); + goto out; + } + + /* + * Setup socket address for the server. + */ + nam = m_get(M_WAIT, MT_SONAME); + if (nam == NULL) { + error = ENOBUFS; + goto out; + } + sin = mtod(nam, struct sockaddr_in *); + sin-> sin_len = sizeof(*sin); + sin-> sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_BROADCAST; + sin->sin_port = htons(IPPORT_BOOTPS); + + nam->m_len = sizeof(*sin); + + /* + * Send it, repeatedly, until a reply is received, + * but delay each re-send by an increasing amount. + * If the delay hits the maximum, start complaining. + */ + timo = 0; + for (;;) { + /* Send BOOTP request (or re-send). */ + + aio.iov_base = (caddr_t) call; + aio.iov_len = sizeof(*call); + + auio.uio_iov = &aio; + auio.uio_iovcnt = 1; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_offset = 0; + auio.uio_resid = sizeof(*call); + auio.uio_procp = procp; + + error = sosend(so, nam, &auio, NULL, NULL, 0); + if (error) { + printf("bootpc_call: sosend: %d\n", error); + goto out; + } + + /* Determine new timeout. */ + if (timo < MAX_RESEND_DELAY) + timo++; + else + printf("BOOTP timeout for server 0x%x\n", + ntohl(sin->sin_addr.s_addr)); + + /* + * Wait for up to timo seconds for a reply. + * The socket receive timeout was set to 1 second. + */ + secs = timo; + while (secs > 0) { + aio.iov_base = (caddr_t) reply; + aio.iov_len = sizeof(*reply); + + auio.uio_iov = &aio; + auio.uio_iovcnt = 1; + auio.uio_segflg = UIO_SYSSPACE; + auio.uio_rw = UIO_READ; + auio.uio_offset = 0; + auio.uio_resid = sizeof(*reply); + auio.uio_procp = procp; + + rcvflg = 0; + error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg); + if (error == EWOULDBLOCK) { + secs--; + call->secs=htons(ntohs(call->secs)+1); + continue; + } + if (error) + goto out; + len = sizeof(*reply) - auio.uio_resid; + + /* Does the reply contain at least a header? */ + if (len < MIN_REPLY_HDR) + continue; + + /* Is it the right reply? */ + if (reply->op != 2) + continue; + + if (reply->xid != call->xid) + continue; + + if (reply->hlen != call->hlen) + continue; + + if (bcmp(reply->chaddr,call->chaddr,call->hlen)) + continue; + + goto gotreply; /* break two levels */ + + } /* while secs */ + } /* forever send/receive */ + + error = ETIMEDOUT; + goto out; + + gotreply: + out: + if (nam) m_freem(nam); + soclose(so); + return error; +} + +int +bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, + struct proc *procp) +{ + struct sockaddr_in *sin; + int error; + struct sockaddr_in dst; + struct sockaddr_in gw; + struct sockaddr_in mask; + + /* + * Bring up the interface. + * + * Get the old interface flags and or IFF_UP into them; if + * IFF_UP set blindly, interface selection can be clobbered. + */ + error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); + ireq->ifr_flags |= IFF_UP; + error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); + + /* + * Do enough of ifconfig(8) so that the chosen interface + * can talk to the servers. (just set the address) + */ + + /* addr is 0.0.0.0 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if addr, error=%d", error); + + /* netmask is 0.0.0.0 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if net addr, error=%d", error); + + /* Broadcast is 255.255.255.255 */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_BROADCAST; + error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error); + + /* Add default route to 0.0.0.0 so we can send data */ + + bzero((caddr_t) &dst, sizeof(dst)); + dst.sin_len=sizeof(dst); + dst.sin_family=AF_INET; + dst.sin_addr.s_addr = htonl(0); + + bzero((caddr_t) &gw, sizeof(gw)); + gw.sin_len=sizeof(gw); + gw.sin_family=AF_INET; + gw.sin_addr.s_addr = htonl(0x0); + + bzero((caddr_t) &mask, sizeof(mask)); + mask.sin_len=sizeof(mask); + mask.sin_family=AF_INET; + mask.sin_addr.s_addr = htonl(0); + + error = rtrequest(RTM_ADD, + (struct sockaddr *) &dst, + (struct sockaddr *) &gw, + (struct sockaddr *) &mask, + RTF_UP | RTF_STATIC + , NULL); + if (error) + printf("bootpc_fakeup_interface: add default route, error=%d\n", error); + return error; +} + +int +bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, + struct sockaddr_in *myaddr, + struct sockaddr_in *netmask, + struct sockaddr_in *gw, + struct proc *procp) +{ + int error; + struct sockaddr_in oldgw; + struct sockaddr_in olddst; + struct sockaddr_in oldmask; + struct sockaddr_in *sin; + + /* Remove old default route to 0.0.0.0 */ + + bzero((caddr_t) &olddst, sizeof(olddst)); + olddst.sin_len=sizeof(olddst); + olddst.sin_family=AF_INET; + olddst.sin_addr.s_addr = INADDR_ANY; + + bzero((caddr_t) &oldgw, sizeof(oldgw)); + oldgw.sin_len=sizeof(oldgw); + oldgw.sin_family=AF_INET; + oldgw.sin_addr.s_addr = INADDR_ANY; + + bzero((caddr_t) &oldmask, sizeof(oldmask)); + oldmask.sin_len=sizeof(oldmask); + oldmask.sin_family=AF_INET; + oldmask.sin_addr.s_addr = INADDR_ANY; + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) &olddst, + (struct sockaddr *) &oldgw, + (struct sockaddr *) &oldmask, + (RTF_UP | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del default route, error=%d\n", error); + return error; + } + +#if 0 + olddst.sin_addr.s_addr = INADDR_BROADCAST; + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) &olddst, + (struct sockaddr *) &oldgw, + (struct sockaddr *) NULL, + (RTF_UP | RTF_HOST | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del broadcast route, error=%d\n", error); + } +#endif + + /* + * Do enough of ifconfig(8) so that the chosen interface + * can talk to the servers. (just set the address) + */ + bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask)); + error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); + if (error) + panic("nfs_boot: set if netmask, error=%d", error); + + /* Broadcast is with host part of IP address all 1's */ + + sin = (struct sockaddr_in *)&ireq->ifr_addr; + bzero((caddr_t)sin, sizeof(*sin)); + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr; + error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); + if (error) + panic("bootpc_call: set if broadcast addr, error=%d", error); + + bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr)); + error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); + if (error) + panic("nfs_boot: set if addr, error=%d", error); + + /* Add new default route */ + + error = rtrequest(RTM_ADD, + (struct sockaddr *) &olddst, + (struct sockaddr *) gw, + (struct sockaddr *) &oldmask, + (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: add net route, error=%d\n", error); + return error; + } + +#if 0 + /* Remove default gateway arp entry. This is a kludge, but + somehow the arp entry is added without an arp request + being sent, causing outgoing packets to be dropped onto the floor */ + + error = rtrequest(RTM_DELETE, + (struct sockaddr *) gw, + (struct sockaddr *) NULL, + (struct sockaddr *) NULL, + (RTF_UP | RTF_HOST | RTF_STATIC), NULL); + if (error) { + printf("nfs_boot: del default gateway linklevel route, error=%d\n", error); + } +#endif + + return 0; +} + +void bootp_expand_path(char *str,size_t len,char *hostname, + struct in_addr addr); +void bootp_expand_path(char *str,size_t len,char *hostname, + struct in_addr addr) +{ + char tmpbuf[128]; + char tmpaddr[20]; + + char *p,*q,*savep; + q = tmpbuf; + + savep = NULL; + sprintf(tmpaddr,"%d.%d.%d.%d", + ((unsigned char *) &addr)[0], + ((unsigned char *) &addr)[1], + ((unsigned char *) &addr)[2], + ((unsigned char *) &addr)[3]); + + for (p=str;*p;) { + switch(*p) { + case '%': + if (!savep) { + switch(*++p) { + case 'H': + savep = ++p; + p= hostname; + break; + case 'I': + savep = ++p; + p = tmpaddr; + break; + default: + goto arnej; + } + break; + } + default: + arnej: + if (q+1>=tmpbuf+sizeof(tmpbuf)) + panic("bootp_expand_path: Cannot expand %s\n",str); + else + *q++ = *p++; + if (!*p && savep) { + p = savep; + savep = NULL; + } + } + } + *q++ = 0; + if (q-tmpbuf>len) { + panic("bootp_expand_path: Too long expansion: %s\n",tmpbuf); + } + strcpy(str,tmpbuf); +} + +void +bootpc_init(void) +{ + struct bootp_packet call; + struct bootp_packet reply; + static u_int32_t xid = ~0xFF; + + struct ifreq ireq; + struct ifnet *ifp; + struct socket *so; + int error; + int code,len; + int i,j; + char rootpath[65]; + char swappath[65]; + + struct sockaddr_in myaddr; + struct sockaddr_in netmask; + struct sockaddr_in gw; + struct sockaddr_in server; + int gotgw=0; + int gotnetmask=0; + int gotserver=0; + int gotrootpath=0; + int gotswappath=0; + +#define EALEN 6 + unsigned char ea[EALEN]; + struct ifaddr *ifa; + struct sockaddr_dl *sdl = NULL; + char *delim; + + struct nfsv3_diskless *nd = &nfsv3_diskless; + struct proc *procp = curproc; + + /* + * If already filled in, don't touch it here + */ + if (nfs_diskless_valid) + return; + + /* + * Bump time if 0. + */ + if (!time.tv_sec) + time.tv_sec++; + + /* + * Find a network interface. + */ + for (ifp = ifnet; ifp != 0; ifp = ifp->if_next) + if ((ifp->if_flags & + (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) + break; + if (ifp == NULL) + panic("bootpc_init: no suitable interface"); + bzero(&ireq,sizeof(ireq)); + sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit); + strcpy(nd->myif.ifra_name,ireq.ifr_name); + printf("bootpc_init: using network interface '%s'\n", + ireq.ifr_name); + + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) + panic("nfs_boot: socreate, error=%d", error); + + bootpc_fakeup_interface(&ireq,so,procp); + + printf("Bootpc testing starting\n"); + + /* Get HW address */ + + for (ifa = ifp->if_addrlist;ifa; ifa = ifa->ifa_next) + if (ifa->ifa_addr->sa_family == AF_LINK && + (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) && + sdl->sdl_type == IFT_ETHER) + break; + + if (!sdl) + panic("bootpc: Unable to find HW address"); + if (sdl->sdl_alen != EALEN ) + panic("bootpc: HW address len is %d, expected value is %d", + sdl->sdl_alen,EALEN); +#if 1 + printf("bootpc hw address is "); + delim=""; + for (j=0;jsdl_alen;j++) { + printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]); + delim=":"; + } + printf("\n"); +#endif + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + + bzero((caddr_t) &call, sizeof(call)); + + /* bootpc part */ + call.op = 1; /* BOOTREQUEST */ + call.htype= 1; /* 10mb ethernet */ + call.hlen=sdl->sdl_alen; /* Hardware address length */ + call.hops=0; + xid++; + call.xid = txdr_unsigned(xid); + bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen); + + call.vend[0]=99; + call.vend[1]=130; + call.vend[2]=83; + call.vend[3]=99; + call.vend[4]=255; + + call.secs = 0; + call.flags = htons(0x8000); /* We need an broadcast answer */ + + error = bootpc_call(&call,&reply,procp); + + if (error) { +#ifdef BOOTP_NFSROOT + panic("BOOTP call failed"); +#endif + return; + } + + bzero(&myaddr,sizeof(myaddr)); + bzero(&netmask,sizeof(netmask)); + bzero(&gw,sizeof(gw)); + bzero(&server,sizeof(server)); + + myaddr.sin_len = sizeof(myaddr); + myaddr.sin_family = AF_INET; + + netmask.sin_len = sizeof(netmask); + netmask.sin_family = AF_INET; + + gw.sin_len = sizeof(gw); + gw.sin_family= AF_INET; + + server.sin_len = sizeof(gw); + server.sin_family= AF_INET; + + printf("My new ip address is %x\n",htonl(reply.yiaddr.s_addr)); + + myaddr.sin_addr = reply.yiaddr; + + printf("Server ip address is %x\n",htonl(reply.siaddr.s_addr)); + printf("Gateway ip address is %x\n",htonl(reply.giaddr.s_addr)); + + gw.sin_addr = reply.giaddr; + + if (reply.sname[0]) + printf("Server name is %s\n",reply.sname); + if (reply.file[0]) + printf("boot file is %s\n",reply.file); + if (reply.vend[0]==99 && reply.vend[1]==130 && + reply.vend[2]==83 && reply.vend[3]==99) { + j=4; + while (j=sizeof(reply.vend)) { + printf("Truncated field"); + break; + } + switch (code) { + case 1: + if (len!=4) + panic("bootpc: subnet mask len is %d",len); + bcopy(&reply.vend[j],&netmask.sin_addr,4); + gotnetmask=1; + printf("Subnet mask is %d.%d.%d.%d\n", + reply.vend[j], + reply.vend[j+1], + reply.vend[j+2], + reply.vend[j+3]); + break; + case 2: + /* Time offset */ + break; + case 3: + /* Routers */ + if (len % 4) + panic("bootpc: Router Len is %d",len); + if (len > 0) { + bcopy(&reply.vend[j],&gw.sin_addr,4); + gotgw=1; + } + for (i=0;i=sizeof(rootpath)) + panic("bootpc: rootpath >=%d bytes",sizeof(rootpath)); + strncpy(rootpath,&reply.vend[j],len); + rootpath[len]=0; + gotrootpath=1; + printf("Rootpath is %s\n",rootpath); + break; + case 12: + if (len>=MAXHOSTNAMELEN) + panic("bootpc: hostname >=%d bytes",MAXHOSTNAMELEN); + strncpy(nd->my_hostnam,&reply.vend[j],len); + nd->my_hostnam[len]=0; + strncpy(hostname,&reply.vend[j],len); + hostname[len]=0; + printf("Hostname is %s\n",hostname); + break; + case 128: + if (len>=sizeof(swappath)) + panic("bootpc: swappath >=%d bytes",sizeof(swappath)); + strncpy(swappath,&reply.vend[j],len); + swappath[len]=0; + gotswappath=1; + printf("Swappath is %s\n",swappath); + break; + case 129: + { + int swaplen; + if (len!=4) + panic("bootpc: Expected 4 bytes for swaplen, not %d bytes",len); + bcopy(&reply.vend[j],&swaplen,4); + nd->swap_nblks = ntohl(swaplen); + printf("bootpc: Swap size is %d KB\n",nd->swap_nblks); + } + break; + default: + printf("Ignoring field type %d\n",code); + } + j+=len; + } + } + + if (gotrootpath) { + bootp_expand_path(rootpath,sizeof(rootpath), + hostname, + myaddr.sin_addr); + printf("Rootpath is expanded to %s\n",rootpath); + if (gotswappath) { + bootp_expand_path(swappath,sizeof(swappath), + hostname, + myaddr.sin_addr); + printf("Swappath is expanded to %s\n",swappath); + } + else + nd->swap_nblks = 0; + } else { +#ifdef BOOTP_NFSROOT + panic("bootpc: No root path offered"); +#endif + } + + if (!gotserver) { + server.sin_addr = reply.siaddr ; + } + + if (!gotnetmask) { + if (IN_CLASSA(myaddr.sin_addr.s_addr)) + netmask.sin_addr.s_addr = IN_CLASSA_NET; + else if (IN_CLASSB(myaddr.sin_addr.s_addr)) + netmask.sin_addr.s_addr = IN_CLASSB_NET; + else + netmask.sin_addr.s_addr = IN_CLASSC_NET; + } + if (!gotgw) { + /* Use proxyarp */ + gw.sin_addr.s_addr = myaddr.sin_addr.s_addr; + } + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + error = bootpc_adjust_interface(&ireq,so, + &myaddr,&netmask,&gw,procp); + + soclose(so); + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + + nd->root_args.rsize = 8192; + nd->root_args.wsize = 8192; + nd->root_args.sotype = SOCK_DGRAM; + nd->root_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | + NFSMNT_RESVPORT | NFSMNT_NOCONN); + + nd->swap_args.rsize = 8192; + nd->swap_args.wsize = 8192; + nd->swap_args.sotype = SOCK_DGRAM; + nd->swap_args.flags = (NFSMNT_WSIZE | NFSMNT_RSIZE | + NFSMNT_RESVPORT | NFSMNT_NOCONN); + + if (gotrootpath) { + if (server.sin_addr.s_addr != reply.siaddr.s_addr ) { + sprintf(nd->root_hostnam,"%d.%d.%d.%d", + ((unsigned char *) &server.sin_addr)[0], + ((unsigned char *) &server.sin_addr)[1], + ((unsigned char *) &server.sin_addr)[2], + ((unsigned char *) &server.sin_addr)[3]); + } else + strcpy(nd->root_hostnam,reply.sname); + bcopy(&server, &nd->root_saddr,sizeof(server)); + + error = md_mount(&nd->root_saddr, rootpath, nd->root_fh, &nd->root_fhsize, + &nd->root_args,procp); + if (error) + panic("nfs_boot: mountd root, error=%d", error); + + if (gotswappath) { + + char *p = swappath; + + while (*p) + p++; + while (p>=swappath && *p != '/') + p--; + + strcpy(nd->swap_hostnam, nd->root_hostnam); + + bcopy(&server, &nd->swap_saddr,sizeof(server)); + + if (p>swappath) + *p = '\0'; + error = md_mount(&nd->swap_saddr, + (p>swappath) ? swappath:"/", + nd->swap_fh, &nd->swap_fhsize,&nd->swap_args,procp); + if (error) + panic("nfs_boot: mountd swap, error=%d", error); + if (p>swappath) + *p = '/'; + + if (p>=swappath) + error = md_lookup_swap(&nd->swap_saddr,p+1,nd->swap_fh, + &nd->swap_fhsize, &nd->swap_args,procp); + if (error) + panic("nfs_boot: lookup swap, error=%d", error); + } + nfs_diskless_valid = 3; + } + + + bcopy(&myaddr,&nd->myif.ifra_addr,sizeof(myaddr)); + bcopy(&myaddr,&nd->myif.ifra_broadaddr,sizeof(myaddr)); + ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr = + myaddr.sin_addr.s_addr | ~ netmask.sin_addr.s_addr; + bcopy(&netmask,&nd->myif.ifra_mask,sizeof(netmask)); + +#if 0 + bootpboot_p_iflist(); + bootpboot_p_rtlist(); +#endif + return; +} + +/* + * RPC: mountd/mount + * Given a server pathname, get an NFS file handle. + * Also, sets sin->sin_port to the NFS service port. + */ +static int +md_mount(mdsin, path, fhp, fhsizep, args, procp) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + int *fhsizep; + struct nfs_args *args; + struct proc *procp; +{ + struct mbuf *m; + int error; + int authunixok; + int authcount; + int authver; + +#ifdef BOOTP_NFSV3 + /* First try NFS v3 */ + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3, + &mdsin->sin_port, procp); + if (!error) { + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3, + RPCMNT_MOUNT, &m, NULL, curproc); + } + if (!error) { + args->flags |= NFSMNT_NFSV3; + } else { +#endif + /* Fallback to NFS v2 */ + + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, + &mdsin->sin_port, procp); + if (error) return error; + + m = xdr_string_encode(path, strlen(path)); + + /* Do RPC to mountd. */ + error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1, + RPCMNT_MOUNT, &m, NULL, curproc); + if (error) + return error; /* message already freed */ + +#ifdef BOOTP_NFSV3 + } +#endif + + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + error = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (error) + goto bad; + m_adj(m,sizeof(u_int32_t)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + *fhsizep = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (*fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) + goto bad; + m_adj(m,sizeof(u_int32_t)); + } else + *fhsizep = NFSX_V2FH; + + if (m->m_len < (((*fhsizep)+3)&~3)) { + m = m_pullup(m,(((*fhsizep)+3)&~3)); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, *fhsizep); + m_adj(m,(((*fhsizep)+3)&~3)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + authcount = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + authunixok = 0; + m_adj(m,sizeof(u_int32_t)); + if (authcount<0 || authcount>100) + goto bad; + while (authcount>0) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + authver = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (authver == RPCAUTH_UNIX) + authunixok = 1; + authcount--; + m_adj(m,sizeof(u_int32_t)); + } + if (!authunixok) + goto bad; + } + + /* Set port number for NFS use. */ + error = krpc_portmap(mdsin, NFS_PROG, + (args->flags & NFSMNT_NFSV3)?NFS_VER3:NFS_VER2, + &mdsin->sin_port, procp); + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} + +static int md_lookup_swap(mdsin, path, fhp, fhsizep, args, procp) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + int *fhsizep; + struct nfs_args *args; + struct proc *procp; +{ + struct mbuf *m; + int error; + int size = -1; + int attribs_present; + int status; + + m = m_get(M_WAIT,MT_DATA); + if (!m) + return ENOBUFS; + + if (args->flags & NFSMNT_NFSV3) { + *mtod(m,u_int32_t *) = txdr_unsigned(*fhsizep); + bcopy(fhp,mtod(m,u_char *)+sizeof(u_int32_t),*fhsizep); + m->m_len = *fhsizep + sizeof(u_int32_t); + } else { + bcopy(fhp,mtod(m,u_char *),NFSX_V2FH); + m->m_len = NFSX_V2FH; + } + + m->m_next = xdr_string_encode(path, strlen(path)); + if (!m->m_next) { + error = ENOBUFS; + goto out; + } + + /* Do RPC to nfsd. */ + if (args->flags & NFSMNT_NFSV3) + error = krpc_call(mdsin, NFS_PROG, NFS_VER3, + NFSPROC_LOOKUP, &m, NULL, procp); + else + error = krpc_call(mdsin, NFS_PROG, NFS_VER2, + NFSV2PROC_LOOKUP, &m, NULL, procp); + if (error) + return error; /* message already freed */ + + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + status = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + m_adj(m,sizeof(u_int32_t)); + if (status) { + error = ENOENT; + goto out; + } + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + *fhsizep = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (*fhsizep > NFSX_V3FHMAX || *fhsizep <= 0 ) + goto bad; + m_adj(m,sizeof(u_int32_t)); + } else + *fhsizep = NFSX_V2FH; + + if (m->m_len < (((*fhsizep)+3)&~3)) { + m = m_pullup(m,(((*fhsizep)+3)&~3)); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, *fhsizep); + m_adj(m,(((*fhsizep)+3)&~3)); + + if (args->flags & NFSMNT_NFSV3) { + if (m->m_len < sizeof(u_int32_t)) { + m = m_pullup(m, sizeof(u_int32_t)); + if (m == NULL) + goto bad; + } + attribs_present = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + m_adj(m,sizeof(u_int32_t)); + if (attribs_present) { + if (m->m_len < sizeof(u_int32_t)*21) { + m = m_pullup(m, sizeof(u_int32_t)*21); + if (m == NULL) + goto bad; + } + size = fxdr_unsigned(u_int32_t, mtod(m,u_int32_t *)[6]); + } + } else { + if (m->m_len < sizeof(u_int32_t)*17) { + m = m_pullup(m, sizeof(u_int32_t)*17); + if (m == NULL) + goto bad; + } + size = fxdr_unsigned(u_int32_t, mtod(m,u_int32_t *)[5]); + } + + if (!nfsv3_diskless.swap_nblks && size!= -1) { + nfsv3_diskless.swap_nblks = size/1024; + printf("md_lookup_swap: Swap size is %d KB\n", + nfsv3_diskless.swap_nblks); + } + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} Property changes on: stable/2.2/sys/nfs/bootp_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/2.2/sys/nfs/krpc.h =================================================================== --- stable/2.2/sys/nfs/krpc.h (nonexistent) +++ stable/2.2/sys/nfs/krpc.h (revision 25723) @@ -0,0 +1,30 @@ +/* $NetBSD: krpc.h,v 1.4 1995/12/19 23:07:11 cgd Exp $ */ +/* $Id:$ */ + +#include + +int krpc_call __P((struct sockaddr_in *sin, + u_int prog, u_int vers, u_int func, + struct mbuf **data, struct mbuf **from, struct proc *procp)); + +int krpc_portmap __P((struct sockaddr_in *sin, + u_int prog, u_int vers, u_int16_t *portp, struct proc *procp)); + +struct mbuf *xdr_string_encode __P((char *str, int len)); +struct mbuf *xdr_string_decode __P((struct mbuf *m, char *str, int *len_p)); +struct mbuf *xdr_inaddr_encode __P((struct in_addr *ia)); +struct mbuf *xdr_inaddr_decode __P((struct mbuf *m, struct in_addr *ia)); + + +/* + * RPC definitions for the portmapper + */ +#define PMAPPORT 111 +#define PMAPPROG 100000 +#define PMAPVERS 2 +#define PMAPPROC_NULL 0 +#define PMAPPROC_SET 1 +#define PMAPPROC_UNSET 2 +#define PMAPPROC_GETPORT 3 +#define PMAPPROC_DUMP 4 +#define PMAPPROC_CALLIT 5 Property changes on: stable/2.2/sys/nfs/krpc.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/2.2/sys/nfs/krpc_subr.c =================================================================== --- stable/2.2/sys/nfs/krpc_subr.c (nonexistent) +++ stable/2.2/sys/nfs/krpc_subr.c (revision 25723) @@ -0,0 +1,592 @@ +/* $NetBSD: krpc_subr.c,v 1.12.4.1 1996/06/07 00:52:26 cgd Exp $ */ +/* $Id:$ */ + +/* + * Copyright (c) 1995 Gordon Ross, Adam Glass + * Copyright (c) 1992 Regents of the University of California. + * All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * partially based on: + * libnetboot/rpc.c + * @(#) Header: rpc.c,v 1.12 93/09/28 08:31:56 leres Exp (LBL) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* + * Kernel support for Sun RPC + * + * Used currently for bootstrapping in nfs diskless configurations. + */ + +/* + * Generic RPC headers + */ + +struct auth_info { + u_int32_t authtype; /* auth type */ + u_int32_t authlen; /* auth length */ +}; + +struct auth_unix { + int32_t ua_time; + int32_t ua_hostname; /* null */ + int32_t ua_uid; + int32_t ua_gid; + int32_t ua_gidlist; /* null */ +}; + +struct rpc_call { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (0) */ + u_int32_t rp_rpcvers; /* rpc version (2) */ + u_int32_t rp_prog; /* program */ + u_int32_t rp_vers; /* version */ + u_int32_t rp_proc; /* procedure */ + struct auth_info rpc_auth; + struct auth_unix rpc_unix; + struct auth_info rpc_verf; +}; + +struct rpc_reply { + u_int32_t rp_xid; /* request transaction id */ + int32_t rp_direction; /* call direction (1) */ + int32_t rp_astatus; /* accept status (0: accepted) */ + union { + u_int32_t rpu_errno; + struct { + struct auth_info rok_auth; + u_int32_t rok_status; + } rpu_rok; + } rp_u; +}; +#define rp_errno rp_u.rpu_errno +#define rp_auth rp_u.rpu_rok.rok_auth +#define rp_status rp_u.rpu_rok.rok_status + +#define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */ + +/* + * What is the longest we will wait before re-sending a request? + * Note this is also the frequency of "RPC timeout" messages. + * The re-send loop count sup linearly to this maximum, so the + * first complaint will happen after (1+2+3+4+5)=15 seconds. + */ +#define MAX_RESEND_DELAY 5 /* seconds */ + +/* + * Call portmap to lookup a port number for a particular rpc program + * Returns non-zero error on failure. + */ +int +krpc_portmap(sin, prog, vers, portp, procp) + struct sockaddr_in *sin; /* server address */ + u_int prog, vers; /* host order */ + u_int16_t *portp; /* network order */ + struct proc *procp; +{ + struct sdata { + u_int32_t prog; /* call program */ + u_int32_t vers; /* call version */ + u_int32_t proto; /* call protocol */ + u_int32_t port; /* call port (unused) */ + } *sdata; + struct rdata { + u_int16_t pad; + u_int16_t port; + } *rdata; + struct mbuf *m; + int error; + + /* The portmapper port is fixed. */ + if (prog == PMAPPROG) { + *portp = htons(PMAPPORT); + return 0; + } + + m = m_get(M_WAIT, MT_DATA); + if (m == NULL) + return ENOBUFS; + sdata = mtod(m, struct sdata *); + m->m_len = sizeof(*sdata); + + /* Do the RPC to get it. */ + sdata->prog = txdr_unsigned(prog); + sdata->vers = txdr_unsigned(vers); + sdata->proto = txdr_unsigned(IPPROTO_UDP); + sdata->port = 0; + + sin->sin_port = htons(PMAPPORT); + error = krpc_call(sin, PMAPPROG, PMAPVERS, + PMAPPROC_GETPORT, &m, NULL, procp); + if (error) + return error; + + if (m->m_len < sizeof(*rdata)) { + m = m_pullup(m, sizeof(*rdata)); + if (m == NULL) + return ENOBUFS; + } + rdata = mtod(m, struct rdata *); + *portp = rdata->port; + + m_freem(m); + return 0; +} + +/* + * Do a remote procedure call (RPC) and wait for its reply. + * If from_p is non-null, then we are doing broadcast, and + * the address from whence the response came is saved there. + */ +int +krpc_call(sa, prog, vers, func, data, from_p, procp) + struct sockaddr_in *sa; + u_int prog, vers, func; + struct mbuf **data; /* input/output */ + struct mbuf **from_p; /* output */ + struct proc *procp; +{ + struct socket *so; + struct sockaddr_in *sin; + struct mbuf *m, *nam, *mhead, *from; + struct rpc_call *call; + struct rpc_reply *reply; + struct uio auio; + int error, rcvflg, timo, secs, len; + static u_int32_t xid = ~0xFF; + u_int16_t tport; + + /* + * Validate address family. + * Sorry, this is INET specific... + */ + if (sa->sin_family != AF_INET) + return (EAFNOSUPPORT); + + /* Free at end if not null. */ + nam = mhead = NULL; + from = NULL; + + /* + * Create socket and set its recieve timeout. + */ + if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, procp))) + goto out; + + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } else { + struct timeval *tv; + tv = mtod(m, struct timeval *); + m->m_len = sizeof(*tv); + tv->tv_sec = 1; + tv->tv_usec = 0; + if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m))) + goto out; + } + + /* + * Enable broadcast if necessary. + */ + if (from_p) { + int32_t *on; + m = m_get(M_WAIT, MT_SOOPTS); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + on = mtod(m, int32_t *); + m->m_len = sizeof(*on); + *on = 1; + if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m))) + goto out; + } + + /* + * Bind the local endpoint to a reserved port, + * because some NFS servers refuse requests from + * non-reserved (non-privileged) ports. + */ + m = m_getclr(M_WAIT, MT_SONAME); + sin = mtod(m, struct sockaddr_in *); + sin->sin_len = m->m_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + tport = IPPORT_RESERVED; + do { + tport--; + sin->sin_port = htons(tport); + error = sobind(so, m); + } while (error == EADDRINUSE && + tport > IPPORT_RESERVED / 2); + m_freem(m); + if (error) { + printf("bind failed\n"); + goto out; + } + + /* + * Setup socket address for the server. + */ + nam = m_get(M_WAIT, MT_SONAME); + if (nam == NULL) { + error = ENOBUFS; + goto out; + } + sin = mtod(nam, struct sockaddr_in *); + bcopy((caddr_t)sa, (caddr_t)sin, + (nam->m_len = sa->sin_len)); + + /* + * Prepend RPC message header. + */ + mhead = m_gethdr(M_WAIT, MT_DATA); + mhead->m_next = *data; + call = mtod(mhead, struct rpc_call *); + mhead->m_len = sizeof(*call); + bzero((caddr_t)call, sizeof(*call)); + /* rpc_call part */ + xid++; + call->rp_xid = txdr_unsigned(xid); + /* call->rp_direction = 0; */ + call->rp_rpcvers = txdr_unsigned(2); + call->rp_prog = txdr_unsigned(prog); + call->rp_vers = txdr_unsigned(vers); + call->rp_proc = txdr_unsigned(func); + /* rpc_auth part (auth_unix as root) */ + call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX); + call->rpc_auth.authlen = txdr_unsigned(sizeof(struct auth_unix)); + /* rpc_verf part (auth_null) */ + call->rpc_verf.authtype = 0; + call->rpc_verf.authlen = 0; + + /* + * Setup packet header + */ + len = 0; + m = mhead; + while (m) { + len += m->m_len; + m = m->m_next; + } + mhead->m_pkthdr.len = len; + mhead->m_pkthdr.rcvif = NULL; + + /* + * Send it, repeatedly, until a reply is received, + * but delay each re-send by an increasing amount. + * If the delay hits the maximum, start complaining. + */ + timo = 0; + for (;;) { + /* Send RPC request (or re-send). */ + m = m_copym(mhead, 0, M_COPYALL, M_WAIT); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + error = sosend(so, nam, NULL, m, NULL, 0); + if (error) { + printf("krpc_call: sosend: %d\n", error); + goto out; + } + m = NULL; + + /* Determine new timeout. */ + if (timo < MAX_RESEND_DELAY) + timo++; + else + printf("RPC timeout for server 0x%x\n", + ntohl(sin->sin_addr.s_addr)); + + /* + * Wait for up to timo seconds for a reply. + * The socket receive timeout was set to 1 second. + */ + secs = timo; + while (secs > 0) { + if (from) { + m_freem(from); + from = NULL; + } + if (m) { + m_freem(m); + m = NULL; + } + bzero(&auio,sizeof(auio)); + auio.uio_resid = len = 1<<16; + rcvflg = 0; + error = soreceive(so, &from, &auio, &m, NULL, &rcvflg); + if (error == EWOULDBLOCK) { + secs--; + continue; + } + if (error) + goto out; + len -= auio.uio_resid; + + /* Does the reply contain at least a header? */ + if (len < MIN_REPLY_HDR) + continue; + if (m->m_len < MIN_REPLY_HDR) + continue; + reply = mtod(m, struct rpc_reply *); + + /* Is it the right reply? */ + if (reply->rp_direction != txdr_unsigned(RPC_REPLY)) + continue; + + if (reply->rp_xid != txdr_unsigned(xid)) + continue; + + /* Was RPC accepted? (authorization OK) */ + if (reply->rp_astatus != 0) { + error = fxdr_unsigned(u_int32_t, reply->rp_errno); + printf("rpc denied, error=%d\n", error); + continue; + } + + /* Did the call succeed? */ + if (reply->rp_status != 0) { + error = fxdr_unsigned(u_int32_t, reply->rp_status); + if (error == RPC_PROGMISMATCH) { + error = EBADRPC; + goto out; + } + printf("rpc denied, status=%d\n", error); + continue; + } + + goto gotreply; /* break two levels */ + + } /* while secs */ + } /* forever send/receive */ + + error = ETIMEDOUT; + goto out; + + gotreply: + + /* + * Get RPC reply header into first mbuf, + * get its length, then strip it off. + */ + len = sizeof(*reply); + if (m->m_len < len) { + m = m_pullup(m, len); + if (m == NULL) { + error = ENOBUFS; + goto out; + } + } + reply = mtod(m, struct rpc_reply *); + if (reply->rp_auth.authtype != 0) { + len += fxdr_unsigned(u_int32_t, reply->rp_auth.authlen); + len = (len + 3) & ~3; /* XXX? */ + } + m_adj(m, len); + + /* result */ + *data = m; + if (from_p) { + *from_p = from; + from = NULL; + } + + out: + if (nam) m_freem(nam); + if (mhead) m_freem(mhead); + if (from) m_freem(from); + soclose(so); + return error; +} + +/* + * eXternal Data Representation routines. + * (but with non-standard args...) + */ + +/* + * String representation for RPC. + */ +struct xdr_string { + u_int32_t len; /* length without null or padding */ + char data[4]; /* data (longer, of course) */ + /* data is padded to a long-word boundary */ +}; + +struct mbuf * +xdr_string_encode(str, len) + char *str; + int len; +{ + struct mbuf *m; + struct xdr_string *xs; + int dlen; /* padded string length */ + int mlen; /* message length */ + + dlen = (len + 3) & ~3; + mlen = dlen + 4; + + if (mlen > MCLBYTES) /* If too big, we just can't do it. */ + return (NULL); + + m = m_get(M_WAIT, MT_DATA); + if (mlen > MLEN) { + MCLGET(m, M_WAIT); + if ((m->m_flags & M_EXT) == 0) { + (void) m_free(m); /* There can be only one. */ + return (NULL); + } + } + xs = mtod(m, struct xdr_string *); + m->m_len = mlen; + xs->len = txdr_unsigned(len); + bcopy(str, xs->data, len); + return (m); +} + +struct mbuf * +xdr_string_decode(m, str, len_p) + struct mbuf *m; + char *str; + int *len_p; /* bufsize - 1 */ +{ + struct xdr_string *xs; + int mlen; /* message length */ + int slen; /* string length */ + + if (m->m_len < 4) { + m = m_pullup(m, 4); + if (m == NULL) + return (NULL); + } + xs = mtod(m, struct xdr_string *); + slen = fxdr_unsigned(u_int32_t, xs->len); + mlen = 4 + ((slen + 3) & ~3); + + if (slen > *len_p) + slen = *len_p; + m_copydata(m, 4, slen, str); + m_adj(m, mlen); + + str[slen] = '\0'; + *len_p = slen; + + return (m); +} + + +/* + * Inet address in RPC messages + * (Note, really four ints, NOT chars. Blech.) + */ +struct xdr_inaddr { + u_int32_t atype; + u_int32_t addr[4]; +}; + +struct mbuf * +xdr_inaddr_encode(ia) + struct in_addr *ia; /* already in network order */ +{ + struct mbuf *m; + struct xdr_inaddr *xi; + u_int8_t *cp; + u_int32_t *ip; + + m = m_get(M_WAIT, MT_DATA); + xi = mtod(m, struct xdr_inaddr *); + m->m_len = sizeof(*xi); + xi->atype = txdr_unsigned(1); + ip = xi->addr; + cp = (u_int8_t *)&ia->s_addr; + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + *ip++ = txdr_unsigned(*cp++); + + return (m); +} + +struct mbuf * +xdr_inaddr_decode(m, ia) + struct mbuf *m; + struct in_addr *ia; /* already in network order */ +{ + struct xdr_inaddr *xi; + u_int8_t *cp; + u_int32_t *ip; + + if (m->m_len < sizeof(*xi)) { + m = m_pullup(m, sizeof(*xi)); + if (m == NULL) + return (NULL); + } + xi = mtod(m, struct xdr_inaddr *); + if (xi->atype != txdr_unsigned(1)) { + ia->s_addr = INADDR_ANY; + goto out; + } + ip = xi->addr; + cp = (u_int8_t *)&ia->s_addr; + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + *cp++ = fxdr_unsigned(u_int8_t, *ip++); + +out: + m_adj(m, sizeof(*xi)); + return (m); +} Property changes on: stable/2.2/sys/nfs/krpc_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/2.2/sys/nfs/nfs_vfsops.c =================================================================== --- stable/2.2/sys/nfs/nfs_vfsops.c (revision 25722) +++ stable/2.2/sys/nfs/nfs_vfsops.c (revision 25723) @@ -1,972 +1,1003 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94 - * $Id: nfs_vfsops.c,v 1.30 1996/10/20 15:01:58 phk Exp $ + * $Id: nfs_vfsops.c,v 1.30.2.1 1996/11/09 21:11:03 phk Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int nfs_mountroot __P((void)); extern int nfs_ticks; struct nfsstats nfsstats; SYSCTL_NODE(_vfs, MOUNT_NFS, nfs, CTLFLAG_RW, 0, "NFS filesystem"); SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD, &nfsstats, nfsstats, ""); #ifdef NFS_DEBUG int nfs_debug; SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); #endif static int nfs_iosize __P((struct nfsmount *nmp)); static int mountnfs __P((struct nfs_args *,struct mount *, struct mbuf *,char *,char *,struct vnode **)); static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data, struct nameidata *ndp, struct proc *p)); static int nfs_start __P(( struct mount *mp, int flags, struct proc *p)); static int nfs_unmount __P(( struct mount *mp, int mntflags, struct proc *p)); static int nfs_root __P(( struct mount *mp, struct vnode **vpp)); static int nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid, caddr_t arg, struct proc *p)); static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp, struct proc *p)); static int nfs_sync __P(( struct mount *mp, int waitfor, struct ucred *cred, struct proc *p)); static int nfs_vptofh __P(( struct vnode *vp, struct fid *fhp)); static int nfs_fhtovp __P((struct mount *mp, struct fid *fhp, struct mbuf *nam, struct vnode **vpp, int *exflagsp, struct ucred **credanonp)); static int nfs_vget __P((struct mount *, ino_t, struct vnode **)); /* * nfs vfs operations. */ static struct vfsops nfs_vfsops = { nfs_mount, nfs_start, nfs_unmount, nfs_root, nfs_quotactl, nfs_statfs, nfs_sync, nfs_vget, nfs_fhtovp, nfs_vptofh, nfs_init, }; VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK); /* * This structure must be filled in by a primary bootstrap or bootstrap * server for a diskless/dataless machine. It is initialized below just * to ensure that it is allocated to initialized data (.data not .bss). */ struct nfs_diskless nfs_diskless = { 0 }; +struct nfsv3_diskless nfsv3_diskless = { 0 }; int nfs_diskless_valid = 0; SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, &nfs_diskless_valid, 0, ""); SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, - nfs_diskless.root_hostnam, 0, ""); + nfsv3_diskless.root_hostnam, 0, ""); SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, - &nfs_diskless.root_saddr, sizeof nfs_diskless.root_saddr, + &nfsv3_diskless.root_saddr, sizeof nfsv3_diskless.root_saddr, "%Ssockaddr_in", ""); SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD, - nfs_diskless.swap_hostnam, 0, ""); + nfsv3_diskless.swap_hostnam, 0, ""); SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD, - &nfs_diskless.swap_saddr, sizeof nfs_diskless.swap_saddr, + &nfsv3_diskless.swap_saddr, sizeof nfsv3_diskless.swap_saddr, "%Ssockaddr_in",""); void nfsargs_ntoh __P((struct nfs_args *)); static struct mount *nfs_mountdiskless __P((char *, char *, int, struct sockaddr_in *, struct nfs_args *, register struct vnode **)); +void nfs_convert_diskless __P((void)); static int nfs_iosize(nmp) struct nfsmount* nmp; { int iosize; /* * Calculate the size used for io buffers. Use the larger * of the two sizes to minimise nfs requests but make sure * that it is at least one VM page to avoid wasting buffer * space. */ iosize = max(nmp->nm_rsize, nmp->nm_wsize); if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; return iosize; } +void nfs_convert_diskless() +{ + bcopy(&nfs_diskless.myif, &nfsv3_diskless.myif, + sizeof(struct ifaliasreq)); + bcopy(&nfs_diskless.swap_args,&nfsv3_diskless.swap_args, + sizeof(struct nfs_args)); + nfsv3_diskless.swap_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.swap_fh,nfsv3_diskless.swap_fh,NFSX_V2FH); + bcopy(&nfs_diskless.swap_saddr,&nfsv3_diskless.swap_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.swap_hostnam,nfsv3_diskless.swap_hostnam, + MNAMELEN); + nfsv3_diskless.swap_nblks = nfs_diskless.swap_nblks; + bcopy(&nfs_diskless.swap_ucred, &nfsv3_diskless.swap_ucred, + sizeof(struct ucred)); + bcopy(&nfs_diskless.root_args,&nfsv3_diskless.root_args, + sizeof(struct nfs_args)); + nfsv3_diskless.root_fhsize = NFSX_V2FH; + bcopy(nfs_diskless.root_fh,nfsv3_diskless.root_fh,NFSX_V2FH); + bcopy(&nfs_diskless.root_saddr,&nfsv3_diskless.root_saddr, + sizeof(struct sockaddr_in)); + bcopy(nfs_diskless.root_hostnam,nfsv3_diskless.root_hostnam, + MNAMELEN); + nfsv3_diskless.root_time = nfs_diskless.root_time; + bcopy(nfs_diskless.my_hostnam,nfsv3_diskless.my_hostnam, + MAXHOSTNAMELEN); + nfs_diskless_valid = 3; +} + /* * nfs statfs call */ int nfs_statfs(mp, sbp, p) struct mount *mp; register struct statfs *sbp; struct proc *p; { register struct vnode *vp; register struct nfs_statfs *sfp; register caddr_t cp; register u_long *tl; register long t1, t2; caddr_t bpos, dpos, cp2; struct nfsmount *nmp = VFSTONFS(mp); int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; struct mbuf *mreq, *mrep, *md, *mb, *mb2; struct ucred *cred; struct nfsnode *np; u_quad_t tquad; #ifndef nolint sfp = (struct nfs_statfs *)0; #endif error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return (error); vp = NFSTOV(np); cred = crget(); cred->cr_ngroups = 1; if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, cred, p); nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); nfsm_fhtom(vp, v3); nfsm_request(vp, NFSPROC_FSSTAT, p, cred); if (v3) nfsm_postop_attr(vp, retattr); if (!error) nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); #ifdef __NetBSD__ #ifdef COMPAT_09 sbp->f_type = 2; #else sbp->f_type = 0; #endif #else sbp->f_type = MOUNT_NFS; #endif sbp->f_flags = nmp->nm_flag; sbp->f_iosize = nfs_iosize(nmp); if (v3) { sbp->f_bsize = NFS_FABLKSIZE; fxdr_hyper(&sfp->sf_tbytes, &tquad); sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); fxdr_hyper(&sfp->sf_fbytes, &tquad); sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); fxdr_hyper(&sfp->sf_abytes, &tquad); sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); } else { sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; } if (sbp != &mp->mnt_stat) { bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); } nfsm_reqdone; vput(vp); crfree(cred); return (error); } /* * nfs version 3 fsinfo rpc call */ int nfs_fsinfo(nmp, vp, cred, p) register struct nfsmount *nmp; register struct vnode *vp; struct ucred *cred; struct proc *p; { register struct nfsv3_fsinfo *fsp; register caddr_t cp; register long t1, t2; register u_long *tl, pref, max; caddr_t bpos, dpos, cp2; int error = 0, retattr; struct mbuf *mreq, *mrep, *md, *mb, *mb2; nfsstats.rpccnt[NFSPROC_FSINFO]++; nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); nfsm_fhtom(vp, 1); nfsm_request(vp, NFSPROC_FSINFO, p, cred); nfsm_postop_attr(vp, retattr); if (!error) { nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); pref = fxdr_unsigned(u_long, fsp->fs_wtpref); if (pref < nmp->nm_wsize) nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_long, fsp->fs_wtmax); if (max < nmp->nm_wsize) { nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize == 0) nmp->nm_wsize = max; } pref = fxdr_unsigned(u_long, fsp->fs_rtpref); if (pref < nmp->nm_rsize) nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ~(NFS_FABLKSIZE - 1); max = fxdr_unsigned(u_long, fsp->fs_rtmax); if (max < nmp->nm_rsize) { nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize == 0) nmp->nm_rsize = max; } pref = fxdr_unsigned(u_long, fsp->fs_dtpref); if (pref < nmp->nm_readdirsize) nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) & ~(NFS_DIRBLKSIZ - 1); if (max < nmp->nm_readdirsize) { nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1); if (nmp->nm_readdirsize == 0) nmp->nm_readdirsize = max; } nmp->nm_flag |= NFSMNT_GOTFSINFO; } nfsm_reqdone; return (error); } /* * Mount a remote root fs via. nfs. This depends on the info in the * nfs_diskless structure that has been filled in properly by some primary * bootstrap. * It goes something like this: * - do enough of "ifconfig" by calling ifioctl() so that the system * can talk to the server * - If nfs_diskless.mygateway is filled in, use that address as * a default gateway. * - hand craft the swap nfs vnode hanging off a fake mount point * if swdevt[0].sw_dev == NODEV * - build the rootfs mount point and call mountnfs() to do the rest. */ int nfs_mountroot() { register struct mount *mp; - register struct nfs_diskless *nd = &nfs_diskless; + register struct nfsv3_diskless *nd = &nfsv3_diskless; struct socket *so; struct vnode *vp; struct proc *p = curproc; /* XXX */ int error, i; u_long l; char buf[128]; /* * XXX time must be non-zero when we init the interface or else * the arp code will wedge... */ if (time.tv_sec == 0) time.tv_sec = 1; + if (nfs_diskless_valid==1) + nfs_convert_diskless(); + /* * XXX splnet, so networks will receive... */ splnet(); #ifdef notyet /* Set up swap credentials. */ proc0.p_ucred->cr_uid = ntohl(nd->swap_ucred.cr_uid); proc0.p_ucred->cr_gid = ntohl(nd->swap_ucred.cr_gid); if ((proc0.p_ucred->cr_ngroups = ntohs(nd->swap_ucred.cr_ngroups)) > NGROUPS) proc0.p_ucred->cr_ngroups = NGROUPS; for (i = 0; i < proc0.p_ucred->cr_ngroups; i++) proc0.p_ucred->cr_groups[i] = ntohl(nd->swap_ucred.cr_groups[i]); #endif /* * Do enough of ifconfig(8) so that the critical net interface can * talk to the server. */ error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, p); if (error) panic("nfs_mountroot: socreate(%04x): %d", nd->myif.ifra_addr.sa_family, error); /* * We might not have been told the right interface, so we pass * over the first ten interfaces of the same kind, until we get * one of them configured. */ for (i = strlen(nd->myif.ifra_name) - 1; nd->myif.ifra_name[i] >= '0' && nd->myif.ifra_name[i] <= '9'; nd->myif.ifra_name[i] ++) { error = ifioctl(so, SIOCAIFADDR, (caddr_t)&nd->myif, p); if(!error) break; } if (error) panic("nfs_mountroot: SIOCAIFADDR: %d", error); soclose(so); /* * If the gateway field is filled in, set it as the default route. */ if (nd->mygateway.sin_len != 0) { struct sockaddr_in mask, sin; bzero((caddr_t)&mask, sizeof(mask)); sin = mask; sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); error = rtrequest(RTM_ADD, (struct sockaddr *)&sin, (struct sockaddr *)&nd->mygateway, (struct sockaddr *)&mask, RTF_UP | RTF_GATEWAY, (struct rtentry **)0); if (error) panic("nfs_mountroot: RTM_ADD: %d", error); } if (nd->swap_nblks) { /* Convert to DEV_BSIZE instead of Kilobyte */ nd->swap_nblks *= 2; /* * Create a fake mount point just for the swap vnode so that the * swap file can be on a different server from the rootfs. */ nd->swap_args.fh = nd->swap_fh; /* * If using nfsv3_diskless, replace NFSX_V2FH with * nd->swap_fhsize. */ - nd->swap_args.fhsize = NFSX_V2FH; + nd->swap_args.fhsize = nd->swap_fhsize; l = ntohl(nd->swap_saddr.sin_addr.s_addr); sprintf(buf,"%ld.%ld.%ld.%ld:%s", (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, (l >> 0) & 0xff,nd->swap_hostnam); printf("NFS SWAP: %s\n",buf); (void) nfs_mountdiskless(buf, "/swap", 0, &nd->swap_saddr, &nd->swap_args, &vp); VTONFS(vp)->n_size = VTONFS(vp)->n_vattr.va_size = nd->swap_nblks * DEV_BSIZE ; /* * Since the swap file is not the root dir of a file system, * hack it to a regular file. */ vp->v_type = VREG; vp->v_flag = 0; VREF(vp); swaponvp(p, vp, NODEV, nd->swap_nblks); } /* * Create the rootfs mount point. */ nd->root_args.fh = nd->root_fh; - /* - * If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize. - */ - nd->root_args.fhsize = NFSX_V2FH; + nd->root_args.fhsize = nd->root_fhsize; l = ntohl(nd->root_saddr.sin_addr.s_addr); sprintf(buf,"%ld.%ld.%ld.%ld:%s", (l >> 24) & 0xff, (l >> 16) & 0xff, (l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam); printf("NFS ROOT: %s\n",buf); mp = nfs_mountdiskless(buf, "/", MNT_RDONLY, &nd->root_saddr, &nd->root_args, &vp); if (vfs_lock(mp)) panic("nfs_mountroot: vfs_lock"); CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); mp->mnt_flag |= MNT_ROOTFS; mp->mnt_vnodecovered = NULLVP; vfs_unlock(mp); rootvp = vp; /* * This is not really an nfs issue, but it is much easier to * set hostname here and then let the "/etc/rc.xxx" files * mount the right /var based upon its preset value. */ bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN); hostname[MAXHOSTNAMELEN - 1] = '\0'; for (i = 0; i < MAXHOSTNAMELEN; i++) if (hostname[i] == '\0') break; inittodr(ntohl(nd->root_time)); return (0); } /* * Internal version of mount system call for diskless setup. */ static struct mount * nfs_mountdiskless(path, which, mountflag, sin, args, vpp) char *path; char *which; int mountflag; struct sockaddr_in *sin; struct nfs_args *args; register struct vnode **vpp; { register struct mount *mp; register struct mbuf *m; register int error; mp = (struct mount *)malloc((u_long)sizeof(struct mount), M_MOUNT, M_NOWAIT); if (mp == NULL) panic("nfs_mountroot: %s mount malloc", which); bzero((char *)mp, (u_long)sizeof(struct mount)); mp->mnt_op = &nfs_vfsops; mp->mnt_flag = mountflag; MGET(m, MT_SONAME, M_DONTWAIT); if (m == NULL) panic("nfs_mountroot: %s mount mbuf", which); bcopy((caddr_t)sin, mtod(m, caddr_t), sin->sin_len); m->m_len = sin->sin_len; error = mountnfs(args, mp, m, which, path, vpp); if (error) panic("nfs_mountroot: mount %s on %s: %d", path, which, error); return (mp); } /* * VFS Operations. * * mount system call * It seems a bit dumb to copyinstr() the host and path here and then * bcopy() them in mountnfs(), but I wanted to detect errors before * doing the sockargs() call because sockargs() allocates an mbuf and * an error after that means that I have to release the mbuf. */ /* ARGSUSED */ static int nfs_mount(mp, path, data, ndp, p) struct mount *mp; char *path; caddr_t data; struct nameidata *ndp; struct proc *p; { int error; struct nfs_args args; struct mbuf *nam; struct vnode *vp; char pth[MNAMELEN], hst[MNAMELEN]; u_int len; u_char nfh[NFSX_V3FHMAX]; error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); if (error) return (error); error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); if (error) return (error); error = copyinstr(path, pth, MNAMELEN-1, &len); if (error) return (error); bzero(&pth[len], MNAMELEN - len); error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); if (error) return (error); bzero(&hst[len], MNAMELEN - len); /* sockargs() call must be after above copyin() calls */ error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME); if (error) return (error); args.fh = nfh; error = mountnfs(&args, mp, nam, pth, hst, &vp); return (error); } /* * Common code for mount and mountroot */ static int mountnfs(argp, mp, nam, pth, hst, vpp) register struct nfs_args *argp; register struct mount *mp; struct mbuf *nam; char *pth, *hst; struct vnode **vpp; { register struct nfsmount *nmp; struct nfsnode *np; int error, maxio; struct vattr attrs; if (mp->mnt_flag & MNT_UPDATE) { nmp = VFSTONFS(mp); /* update paths, file handles, etc, here XXX */ m_freem(nam); return (0); } else { MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount), M_NFSMNT, M_WAITOK); bzero((caddr_t)nmp, sizeof (struct nfsmount)); TAILQ_INIT(&nmp->nm_uidlruhead); TAILQ_INIT(&nmp->nm_bufq); mp->mnt_data = (qaddr_t)nmp; } getnewfsid(mp, MOUNT_NFS); nmp->nm_mountp = mp; nmp->nm_flag = argp->flags; if (nmp->nm_flag & NFSMNT_NQNFS) /* * We have to set mnt_maxsymlink to a non-zero value so * that COMPAT_43 routines will know that we are setting * the d_type field in directories (and can zero it for * unsuspecting binaries). */ mp->mnt_maxsymlinklen = 1; nmp->nm_timeo = NFS_TIMEO; nmp->nm_retry = NFS_RETRANS; nmp->nm_wsize = NFS_WSIZE; nmp->nm_rsize = NFS_RSIZE; nmp->nm_readdirsize = NFS_READDIRSIZE; nmp->nm_numgrps = NFS_MAXGRPS; nmp->nm_readahead = NFS_DEFRAHEAD; nmp->nm_leaseterm = NQ_DEFLEASE; nmp->nm_deadthresh = NQ_DEADTHRESH; CIRCLEQ_INIT(&nmp->nm_timerhead); nmp->nm_inprog = NULLVP; nmp->nm_fhsize = argp->fhsize; bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); #ifdef __NetBSD__ #ifdef COMPAT_09 mp->mnt_stat.f_type = 2; #else mp->mnt_stat.f_type = 0; #endif #else mp->mnt_stat.f_type = MOUNT_NFS; #endif bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); nmp->nm_nam = nam; if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; if (nmp->nm_timeo < NFS_MINTIMEO) nmp->nm_timeo = NFS_MINTIMEO; else if (nmp->nm_timeo > NFS_MAXTIMEO) nmp->nm_timeo = NFS_MAXTIMEO; } if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { nmp->nm_retry = argp->retrans; if (nmp->nm_retry > NFS_MAXREXMIT) nmp->nm_retry = NFS_MAXREXMIT; } if (argp->flags & NFSMNT_NFSV3) { if (argp->sotype == SOCK_DGRAM) maxio = NFS_MAXDGRAMDATA; else maxio = NFS_MAXDATA; } else maxio = NFS_V2MAXDATA; if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { nmp->nm_wsize = argp->wsize; /* Round down to multiple of blocksize */ nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_wsize <= 0) nmp->nm_wsize = NFS_FABLKSIZE; } if (nmp->nm_wsize > maxio) nmp->nm_wsize = maxio; if (nmp->nm_wsize > MAXBSIZE) nmp->nm_wsize = MAXBSIZE; if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { nmp->nm_rsize = argp->rsize; /* Round down to multiple of blocksize */ nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); if (nmp->nm_rsize <= 0) nmp->nm_rsize = NFS_FABLKSIZE; } if (nmp->nm_rsize > maxio) nmp->nm_rsize = maxio; if (nmp->nm_rsize > MAXBSIZE) nmp->nm_rsize = MAXBSIZE; if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { nmp->nm_readdirsize = argp->readdirsize; /* Round down to multiple of blocksize */ nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1); if (nmp->nm_readdirsize < NFS_DIRBLKSIZ) nmp->nm_readdirsize = NFS_DIRBLKSIZ; } if (nmp->nm_readdirsize > maxio) nmp->nm_readdirsize = maxio; if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && argp->maxgrouplist <= NFS_MAXGRPS) nmp->nm_numgrps = argp->maxgrouplist; if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && argp->readahead <= NFS_MAXRAHEAD) nmp->nm_readahead = argp->readahead; if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && argp->leaseterm <= NQ_MAXLEASE) nmp->nm_leaseterm = argp->leaseterm; if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && argp->deadthresh <= NQ_NEVERDEAD) nmp->nm_deadthresh = argp->deadthresh; /* Set up the sockets and per-host congestion */ nmp->nm_sotype = argp->sotype; nmp->nm_soproto = argp->proto; /* * For Connection based sockets (TCP,...) defer the connect until * the first request, in case the server is not responding. */ if (nmp->nm_sotype == SOCK_DGRAM && (error = nfs_connect(nmp, (struct nfsreq *)0))) goto bad; /* * This is silly, but it has to be set so that vinifod() works. * We do not want to do an nfs_statfs() here since we can get * stuck on a dead server and we are holding a lock on the mount * point. */ mp->mnt_stat.f_iosize = nfs_iosize(nmp); /* * A reference count is needed on the nfsnode representing the * remote root. If this object is not persistent, then backward * traversals of the mount point (i.e. "..") will not work if * the nfsnode gets flushed out of the cache. Ufs does not have * this problem, because one can identify root inodes by their * number == ROOTINO (2). */ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) goto bad; *vpp = NFSTOV(np); /* * Get file attributes for the mountpoint. This has the side * effect of filling in (*vpp)->v_type with the correct value. */ VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc); /* * Lose the lock but keep the ref. */ VOP_UNLOCK(*vpp); return (0); bad: nfs_disconnect(nmp); free((caddr_t)nmp, M_NFSMNT); m_freem(nam); return (error); } /* * unmount system call */ static int nfs_unmount(mp, mntflags, p) struct mount *mp; int mntflags; struct proc *p; { register struct nfsmount *nmp; struct nfsnode *np; struct vnode *vp; int error, flags = 0; if (mntflags & MNT_FORCE) { if (!doforce) return (EINVAL); flags |= FORCECLOSE; } nmp = VFSTONFS(mp); /* * Goes something like this.. * - Check for activity on the root vnode (other than ourselves). * - Call vflush() to clear out vnodes for this file system, * except for the root vnode. * - Decrement reference on the vnode representing remote root. * - Close the socket * - Free up the data structures */ /* * We need to decrement the ref. count on the nfsnode representing * the remote root. See comment in mountnfs(). The VFS unmount() * has done vput on this vnode, otherwise we would get deadlock! */ error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return(error); vp = NFSTOV(np); if (vp->v_usecount > 2) { vput(vp); return (EBUSY); } /* * Must handshake with nqnfs_clientd() if it is active. */ nmp->nm_flag |= NFSMNT_DISMINPROG; while (nmp->nm_inprog != NULLVP) (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); error = vflush(mp, vp, flags); if (error) { vput(vp); nmp->nm_flag &= ~NFSMNT_DISMINPROG; return (error); } /* * We are now committed to the unmount. * For NQNFS, let the server daemon free the nfsmount structure. */ if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) nmp->nm_flag |= NFSMNT_DISMNT; /* * There are two reference counts and one lock to get rid of here. */ vput(vp); vrele(vp); vgone(vp); nfs_disconnect(nmp); m_freem(nmp->nm_nam); if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0) free((caddr_t)nmp, M_NFSMNT); return (0); } /* * Return root of a filesystem */ static int nfs_root(mp, vpp) struct mount *mp; struct vnode **vpp; { register struct vnode *vp; struct nfsmount *nmp; struct nfsnode *np; int error; nmp = VFSTONFS(mp); error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); if (error) return (error); vp = NFSTOV(np); VOP_UNLOCK(vp); if (vp->v_type == VNON) vp->v_type = VDIR; vp->v_flag = VROOT; *vpp = vp; return (0); } extern int syncprt; /* * Flush out the buffer cache */ /* ARGSUSED */ static int nfs_sync(mp, waitfor, cred, p) struct mount *mp; int waitfor; struct ucred *cred; struct proc *p; { register struct vnode *vp; int error, allerror = 0; /* * Force stale buffer cache information to be flushed. */ loop: for (vp = mp->mnt_vnodelist.lh_first; vp != NULL; vp = vp->v_mntvnodes.le_next) { /* * If the vnode that we are about to sync is no longer * associated with this mount point, start over. */ if (vp->v_mount != mp) goto loop; if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL) continue; if (vget(vp, 1)) goto loop; error = VOP_FSYNC(vp, cred, waitfor, p); if (error) allerror = error; vput(vp); } return (allerror); } /* * NFS flat namespace lookup. * Currently unsupported. */ /* ARGSUSED */ static int nfs_vget(mp, ino, vpp) struct mount *mp; ino_t ino; struct vnode **vpp; { return (EOPNOTSUPP); } /* * At this point, this should never happen */ /* ARGSUSED */ static int nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) register struct mount *mp; struct fid *fhp; struct mbuf *nam; struct vnode **vpp; int *exflagsp; struct ucred **credanonp; { return (EINVAL); } /* * Vnode pointer to File handle, should never happen either */ /* ARGSUSED */ static int nfs_vptofh(vp, fhp) struct vnode *vp; struct fid *fhp; { return (EINVAL); } /* * Vfs start routine, a no-op. */ /* ARGSUSED */ static int nfs_start(mp, flags, p) struct mount *mp; int flags; struct proc *p; { return (0); } /* * Do operations associated with quotas, not supported */ /* ARGSUSED */ static int nfs_quotactl(mp, cmd, uid, arg, p) struct mount *mp; int cmd; uid_t uid; caddr_t arg; struct proc *p; { return (EOPNOTSUPP); } Index: stable/2.2/sys/nfs/rpcv2.h =================================================================== --- stable/2.2/sys/nfs/rpcv2.h (revision 25722) +++ stable/2.2/sys/nfs/rpcv2.h (revision 25723) @@ -1,141 +1,142 @@ /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)rpcv2.h 8.1 (Berkeley) 6/10/93 - * $Id: rpcv2.h,v 1.3 1994/08/21 06:50:15 paul Exp $ + * $Id: rpcv2.h,v 1.4 1995/06/27 11:07:02 dfr Exp $ */ #ifndef _NFS_RPCV2_H_ #define _NFS_RPCV2_H_ /* * Definitions for Sun RPC Version 2, from * "RPC: Remote Procedure Call Protocol Specification" RFC1057 */ /* Version # */ #define RPC_VER2 2 /* Authentication */ #define RPCAUTH_NULL 0 #define RPCAUTH_UNIX 1 #define RPCAUTH_SHORT 2 #define RPCAUTH_KERB4 4 #define RPCAUTH_NQNFS 300000 #define RPCAUTH_MAXSIZ 400 #define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */ #define RPCAUTH_UNIXGIDS 16 /* * Constants associated with authentication flavours. */ #define RPCAKN_FULLNAME 0 #define RPCAKN_NICKNAME 1 /* Rpc Constants */ #define RPC_CALL 0 #define RPC_REPLY 1 #define RPC_MSGACCEPTED 0 #define RPC_MSGDENIED 1 #define RPC_PROGUNAVAIL 1 #define RPC_PROGMISMATCH 2 #define RPC_PROCUNAVAIL 3 #define RPC_GARBAGE 4 /* I like this one */ #define RPC_MISMATCH 0 #define RPC_AUTHERR 1 /* Authentication failures */ #define AUTH_BADCRED 1 #define AUTH_REJECTCRED 2 #define AUTH_BADVERF 3 #define AUTH_REJECTVERF 4 #define AUTH_TOOWEAK 5 /* Give em wheaties */ /* Sizes of rpc header parts */ #define RPC_SIZ 24 #define RPC_REPLYSIZ 28 /* RPC Prog definitions */ #define RPCPROG_MNT 100005 #define RPCMNT_VER1 1 +#define RPCMNT_VER3 3 #define RPCMNT_MOUNT 1 #define RPCMNT_DUMP 2 #define RPCMNT_UMOUNT 3 #define RPCMNT_UMNTALL 4 #define RPCMNT_EXPORT 5 #define RPCMNT_NAMELEN 255 #define RPCMNT_PATHLEN 1024 #define RPCPROG_NFS 100003 /* * Structures used for RPCAUTH_KERB4. */ struct nfsrpc_fullverf { u_long t1; u_long t2; u_long w2; }; struct nfsrpc_fullblock { u_long t1; u_long t2; u_long w1; u_long w2; }; struct nfsrpc_nickverf { u_long kind; struct nfsrpc_fullverf verf; }; /* * and their sizes in bytes.. If sizeof (struct nfsrpc_xx) != these * constants, well then things will break in mount_nfs and nfsd. */ #define RPCX_FULLVERF 12 #define RPCX_FULLBLOCK 16 #define RPCX_NICKVERF 16 #ifdef NFSKERB XXX #else typedef u_char NFSKERBKEY_T[2]; typedef u_char NFSKERBKEYSCHED_T[2]; #endif #define NFS_KERBSRV "rcmd" /* Kerberos Service for NFS */ #define NFS_KERBTTL (30 * 60) /* Credential ttl (sec) */ #define NFS_KERBCLOCKSKEW (5 * 60) /* Clock skew (sec) */ #define NFS_KERBW1(t) (*((u_long *)(&((t).dat[((t).length + 3) & ~0x3])))) #endif