Index: stable/2.1/sys/conf/files =================================================================== --- stable/2.1/sys/conf/files (revision 25720) +++ stable/2.1/sys/conf/files (revision 25721) @@ -1,366 +1,368 @@ 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/vn/vn.c optional vn dev/vx/if_vx.c optional vx device-driver gnu/isdn/iitel.c optional itel device-driver gnu/isdn/iitty.c optional ity device-driver gnu/isdn/if_ii.c optional ii device-driver gnu/isdn/isdn.c optional isdn device-driver gnu/isdn/iispy.c optional ispy device-driver 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_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/kern_acct.c standard kern/kern_clock.c standard kern/kern_descrip.c standard kern/kern_devconf.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_ntptime.c standard kern/kern_physio.c standard kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.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/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_process.c standard kern/sys_socket.c standard kern/sysv_ipc.c optional sysvmsg kern/sysv_ipc.c optional sysvsem kern/sysv_ipc.c optional sysvshm 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/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 optional procfs miscfs/procfs/procfs_mem.c optional procfs miscfs/procfs/procfs_note.c optional procfs miscfs/procfs/procfs_regs.c optional procfs miscfs/procfs/procfs_status.c optional procfs miscfs/procfs/procfs_subr.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/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_ppp.c optional ppp net/if_sl.c optional sl net/if_spppsubr.c optional sppp net/pppcompress.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 sl net/if_tun.c optional tun 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_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/ip_fw.c optional ipfirewall 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 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 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_bio.c optional nfs_client nfs/nfs_bio.c optional nfs_server nfs/nfs_node.c optional nfs nfs/nfs_node.c optional nfs_client nfs/nfs_node.c optional nfs_server nfs/nfs_nqlease.c optional nfs nfs/nfs_nqlease.c optional nfs_client nfs/nfs_nqlease.c optional nfs_server nfs/nfs_serv.c optional nfs nfs/nfs_serv.c optional nfs_client nfs/nfs_serv.c optional nfs_server nfs/nfs_socket.c optional nfs nfs/nfs_socket.c optional nfs_client nfs/nfs_socket.c optional nfs_server nfs/nfs_srvcache.c optional nfs nfs/nfs_srvcache.c optional nfs_client nfs/nfs_srvcache.c optional nfs_server nfs/nfs_subs.c optional nfs nfs/nfs_subs.c optional nfs_client nfs/nfs_subs.c optional nfs_server nfs/nfs_syscalls.c optional nfs nfs/nfs_syscalls.c optional nfs_client nfs/nfs_syscalls.c optional nfs_server nfs/nfs_vfsops.c optional nfs nfs/nfs_vfsops.c optional nfs_client nfs/nfs_vfsops.c optional nfs_server nfs/nfs_vnops.c optional nfs nfs/nfs_vnops.c optional nfs_client nfs/nfs_vnops.c optional nfs_server +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/if_de.c optional de device-driver pci/if_fxp.c optional fxp device-driver pci/if_pdq.c optional fea device-driver pci/if_pdq.c optional fpa 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/pdq.c optional fea device-driver pci/pdq.c optional fpa device-driver scsi/cd.c optional cd scsi/ch.c optional ch scsi/od.c optional od scsi/scsi_base.c optional scbus scsi/scsi_sense.c optional scbus scsi/scsi_ioctl.c optional scbus scsi/scsiconf.c optional scbus scsi/scsi_driver.c optional scbus scsi/uk.c optional scbus scsi/pt.c optional pt scsi/sd.c optional sd scsi/st.c optional st scsi/worm.c optional worm scsi/su.c optional su scsi/ssc.c optional ssc scsi/sctarg.c optional sctarg 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/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.1/sys/i386/conf/LINT =================================================================== --- stable/2.1/sys/i386/conf/LINT (revision 25720) +++ stable/2.1/sys/i386/conf/LINT (revision 25721) @@ -1,865 +1,871 @@ # # 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.184.4.26 1996/11/06 12:41:56 joerg Exp $ +# $Id: LINT,v 1.184.4.27 1996/11/10 11:21:15 asami 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 # machine "i386" cpu "I386_CPU" cpu "I486_CPU" cpu "I586_CPU" # aka Pentium(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 necessary to make the default max # number of processes per user and open files per user more than the # defaults on bootup. (an example is a large news server in which # the uid, news, can sometimes need > 100 simultaneous processes running, # or perhaps a user using lots of windows under X). options "CHILD_MAX=128" options "OPEN_MAX=128" # # 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 #options GPL_MATH_EMULATE #Support for x87 emualtion via #new math emulator # # 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. # options "COMPAT_43" # # Allow user-mode programs to manipulat 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 ##################################################################### # DEBUGGING OPTIONS # # Enable the kernel debugger. # options DDB # # 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 # # 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 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), ISO (OSI), and # CCITT (X.25) families is provided for amusement value, although we # try to ensure that it actually compiles. # options INET #Internet communications protocols options CCITT #X.25 network layer options NS #Xerox NS communications protocols # These are currently broken and don't compile #options ISO #options TPIP #ISO TP class 4 over IP #options TPCONS #ISO TP class 0 over X.25 # # 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'). # 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 options USERCONFIG_BOOT #imply -c and parse info area 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) options NSIP #XNS over IP options LLC #X.25 link layer for Ethernets options HDLC #X.25 link layer for serial lines # broken #options EON #ISO CLNP over IP # # 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. # # GATEWAY allows the machine to forward packets, and also configures # larger static sizes of a number of system tables. # # 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 does # the obvious thing. # # ARP_PROXYALL enables global proxy ARP. Beware! This can burn # your house down! See netinet/if_ether.c for the gory details. # (Eventually there will be a better management interface.) # options "TCP_COMPAT_42" #emulate 4.2BSD TCP bugs options GATEWAY #internetwork gateway options MROUTING # Multicast routing options IPFIREWALL #firewall options IPFIREWALL_VERBOSE #print information about # dropped packets options ARP_PROXYALL # global proxy ARP ##################################################################### # 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 "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 # Make space in the kernel for a MFS rootfilesystem. Define to the number # of kilobytes to reserve for the filesystem. options "MFS_ROOT=10" # 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 ##################################################################### # 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 # XXX # The `od' driver is unsupported in 2.1-stable. The SCSI subsystem # here does not allow for SCSI type overrides (assigning a driver that # differs from the type the SCSI device claims to be), thus it could # not be tested on my reference SONY SMO drive. -- joerg # # However, it will most likely work fine. device od0 # 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 (CD-R) -- untested, but known to work # in the 2.2 development systems # NB: disabled by default since it doesn't work with the # popular HP drives. 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. The `isdn', `ii', `ity', `itel', and `ispy' devices # are all required when ISDN support is used. # 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 non-optional for ISDN pseudo-device isdn pseudo-device ii 4 pseudo-device ity 4 pseudo-device itel 2 pseudo-device ispy 1 ##################################################################### # HARDWARE DEVICE CONFIGURATION # ISA and EISA devices: # Currently there is no separate support for EISA. There should be. # 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 1.25 usec for each interrupt. # No problems are known to be caused by this option. # # AUTO_EOI_2 enables the `automatic EOI' feature for the slave 8259A # interrupt controller. This saves about 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. # # DUMMY_NOPS disables extra delays for some bus operations. The delays # are mostly for older systems and aren't used consistently. Probably # works OK on most EISA bus machines. # # 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. options "AUTO_EOI_1" #options "AUTO_EOI_2" options BOUNCE_BUFFERS options "MAXMEM=(128*1024)" #options DUMMY_NOPS #options "TUNE_1542" #options "BROKEN_KEYBOARD_RESET" # 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 for `sc': # # HARDFONTS allows the driver to load an ISO-8859-1 font to replace # the default font in your display adapter's memory. # options HARDFONTS # # MAXCONS is maximum number of virtual consoles, no more than 16 # default value: 12 # options "MAXCONS=16" device npx0 at isa? port "IO_NPX" irq 13 vector npxintr # # Optional ISA and EISA devices: # # # SCSI host adapters: # # aha: Adaptec 154x # ahb: Adaptec 174x (See Eisa and PCI section below) # ahc: Adaptec 274x/284x/294x (See Eisa and PCI section below) # 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': # # ATAPI enables the support for ATAPI-compatible IDE devices # options ATAPI #Enable ATAPI support for IDE bus # 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. # 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_NO_RESET #don't reset mouse hardware (some laptops) 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_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' # # 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 # fea: DEC DEFEA EISA FDDI adapter # 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) # 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 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 fe0 at isa? port 0x240 net irq ? vector feintr device fea0 at isa? net irq ? vector feaintr device ie0 at isa? port 0x360 net irq 7 iomem 0xd0000 vector ieintr device ix0 at isa? port 0x300 net irq 10 iomem 0xd0000 iosiz 32768 vector ixintr 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 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 # # ISDN drivers - `isdn'. # # Uncomment one (and only one) of the following two drivers for the appropriate # ISDN device you have. For more information on what's considered appropriate # for your given set of circumstances, please read # /usr/src/gnu/usr.sbin/isdn/docs/INSTALL. It's a bit sparse at present, but # it's the best we have right now. The snic driver is also disabled at present, # waiting for someone to upgrade the driver to 2.0 (it's in /sys/gnu/scsi/). # device nic0 at isa? port "IO_COM3" iomem 0xe0000 tty irq 9 vector nicintr device nnic0 at isa? port 0x150 iomem 0xe0000 tty irq 12 vector nnicintr # # 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 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" # 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-aquisition 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 # # # 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 # Note that the start address must be on an even boundary. # 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 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. # controller eisa0 controller ahb0 controller ahc0 # # 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 `de' device provides support for the Digital Equipment DC21040 # self-contained Ethernet adapter. # # The `fpa' device provides support for the Digital DEFPA PCI FDDI # adapter. pseudo-device fddi is also needed. # # The `fxp' device provides support for the Intel EtherExpress Pro/100B # # The `vx' device provides support for the 3Com 3c590 and 3c595 ethernet # adapters. # # The PROBE_VERBOSE option enables a long listing of chip set registers # for supported PCI chip sets (currently only intel Saturn and Mercury). # # 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 # controller pci0 device ncr0 device de0 device fpa0 device fxp0 device vx0 device meteor0 options PROBE_VERBOSE # # Laptop/Notebook options: # # See also: # apm under `Miscellaneous hardare' # options PSM_NO_RESET for the `psm' driver # 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_COMPAT # Workaround for broken bootp daemons. Index: stable/2.1/sys/i386/i386/autoconf.c =================================================================== --- stable/2.1/sys/i386/i386/autoconf.c (revision 25720) +++ stable/2.1/sys/i386/i386/autoconf.c (revision 25721) @@ -1,323 +1,331 @@ /*- * 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.33.4.2 1996/06/02 19:24:05 joerg Exp $ + * $Id: autoconf.c,v 1.33.4.4 1996/06/05 19:48:59 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 /* For interrupts */ static void setroot(void); /* * The following several variables are related to * the configuration process, and are used in initializing * the machine. */ int dkn; /* number of iostat dk numbers assigned so far */ extern int (*mountroot) __P((void)); #ifdef FFS int ffs_mountroot __P((void)); #endif #ifdef NFS int nfs_mountroot __P((void)); #endif #ifdef CD9660 int cd9660_mountroot __P((void)); #endif #ifdef MSDOSFS int msdosfs_mountroot __P((void)); #endif #ifdef MFS_ROOT int mfs_initminiroot __P((u_char *)); u_char mfs_root[MFS_ROOT*1024] = "MFS Filesystem goes here"; u_char end_mfs_root[] = "MFS Filesystem had better STOP here"; #endif #include "eisa.h" #if NEISA > 0 #include #endif #include "pci.h" #if NPCI > 0 #include #endif #include "isa.h" #if NISA > 0 #include #endif #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} }; int find_cdrom_root() { 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)(); if (!i) return i; } return EINVAL; } #endif /* CD9660 */ #include "scbus.h" #if NSCBUS > 0 #include #endif void configure_start() { #if NSCBUS > 0 scsi_configure_start(); #endif } void configure_finish() { #if NSCBUS > 0 scsi_configure_finish(); #endif } /* * Determine i/o configuration for a machine. */ void configure() { 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 configure_finish(); #ifdef MFS_ROOT mfs_initminiroot(mfs_root); #endif /* MFS_ROOT */ if (bootverbose) 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 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 = ffs_mountroot; /* * 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"); } /* * Configure swap area and related system * parameter based on device(s) used. */ if (bootverbose) printf("Configuring root and swap devs.\n"); setconf(); cold = 0; if (bootverbose) printf("configure() finished.\n"); } int setdumpdev(dev) dev_t dev; { int maj, psize; long newdumplo; if (dev == NODEV) { dumpdev = dev; dumplo = 0; return (0); } maj = major(dev); if (maj >= nblkdev) return (ENXIO); if (bdevsw[maj].d_psize == NULL) return (ENXIO); /* XXX should sometimes be ENODEV */ psize = bdevsw[maj].d_psize(dev); if (psize == -1) return (ENXIO); /* XXX should sometimes be ENODEV */ newdumplo = psize - Maxmem * NBPG / 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 temp = 0, orootdev; struct swdevt *swp; /*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'); } Index: stable/2.1/sys/kern/init_main.c =================================================================== --- stable/2.1/sys/kern/init_main.c (revision 25720) +++ stable/2.1/sys/kern/init_main.c (revision 25721) @@ -1,472 +1,478 @@ /* * 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.25 1995/05/19 03:26:43 davidg Exp $ + * $Id: init_main.c,v 1.25.4.1 1996/02/22 11:09:58 davidg Exp $ */ #include #include #include #include #include #ifdef GPROF #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; #endif /* Components of the first process -- never freed. */ struct session session0; struct pgrp pgrp0; struct proc proc0; struct pcred cred0; struct filedesc0 filedesc0; struct plimit limit0; struct vmspace vmspace0; struct proc *curproc = &proc0; struct proc *initproc, *pageproc, *updateproc, *vmproc; int cmask = CMASK; extern struct user *proc0paddr; struct vnode *rootvp; int boothowto; struct timeval boottime; struct timeval runtime; static void start_init __P((struct proc *p, void *framep)); +#ifdef BOOTP +extern void bootpc_init __P((void)); +#endif #if __GNUC__ >= 2 void __main() {} #endif /* * This table is filled in by the linker with functions that need to be * called to initialize various pseudo-devices and whatnot. */ static void dummyinit() {} TEXT_SET(pseudo_set, dummyinit); typedef void (*pseudo_func_t)(void); extern const struct linker_set pseudo_set; static const pseudo_func_t *pseudos = (const pseudo_func_t *)&pseudo_set.ls_items[0]; /* * 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. */ void main(framep) void *framep; { register struct proc *p; register struct filedesc0 *fdp; register int i; int s, rval[2]; /* * Initialize the current process pointer (curproc) before * any possible traps/probes to simplify trap processing. */ p = &proc0; curproc = p; printf(copyright); vm_mem_init(); kmeminit(); cpu_startup(); /* * Create process 0 (the swapper). */ allproc = (volatile struct proc *)p; p->p_prev = (struct proc **)&allproc; p->p_pgrp = &pgrp0; pgrphash[0] = &pgrp0; pgrp0.pg_mem = p; 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_MAX_ADDRESS), TRUE); vmspace0.vm_map.pmap = &vmspace0.vm_pmap; p->p_addr = proc0paddr; /* XXX */ /* * 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, framep); /* XXX! */ /* * 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; /* * Initialize per uid information structure and charge * root for one process. */ usrinfoinit(); (void)chgproccnt(0, 1); rqinit(); /* Configure virtual memory system, set vm rlimits. */ vm_init_limits(p); /* Initialize the file systems. */ vfsinit(); /* Start real time and statistics clocks. */ initclocks(); /* Initialize mbuf's. */ mbinit(); /* Initialize clists. */ clist_init(); #ifdef SYSVSHM /* Initialize System V style shared memory. */ shminit(); #endif #ifdef SYSVSEM /* Initialize System V style semaphores. */ seminit(); #endif #ifdef SYSVMSG /* Initialize System V style message queues. */ msginit(); #endif /* * Attach pseudo-devices. */ while(*pseudos) { (**pseudos++)(); } /* * Initialize protocols. Block reception of incoming packets * until everything is ready. */ s = splimp(); ifinit(); domaininit(); splx(s); #ifdef GPROF /* Initialize kernel profiling. */ kmstartup(); #endif /* Kick off timeout driven events by calling first time. */ roundrobin(NULL); schedcpu(NULL); +#ifdef BOOTP + bootpc_init(); +#endif /* Mount the root file system. */ if ((*mountroot)()) panic("cannot mount root"); /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ if (VFS_ROOT(mountlist.tqh_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; /* * 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. */ p->p_stats->p_start = runtime = mono_time = boottime = time; p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; /* Initialize signal state for process 0. */ siginit(p); /* Create process 1 (init(8)). */ if (fork(p, NULL, rval)) panic("fork init"); if (rval[1]) { start_init(curproc, framep); return; } /* Create process 2 (the pageout daemon). */ if (fork(p, NULL, rval)) panic("fork pager"); if (rval[1]) { /* * Now in process 2. */ p = curproc; pageproc = p; p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); vm_pageout(); /* NOTREACHED */ } #ifndef NO_SWAPPING /* * Start high level vm daemon (process 3). */ if (fork(p, (void *) NULL, rval)) panic("failed fork vm daemon"); if (rval[1]) { p = curproc; vmproc = p; p->p_flag |= P_INMEM | P_SYSTEM; bcopy("vmdaemon", p->p_comm, sizeof("vmdaemon")); vm_daemon(); /*NOTREACHED*/ } #endif /* * Start update daemon (process 4). */ if (fork(p, (void *) NULL, rval)) panic("failed fork update daemon"); if (rval[1]) { p = curproc; updateproc = p; p->p_flag |= P_INMEM | P_SYSTEM; bcopy("update", p->p_comm, sizeof("update")); vfs_update(); /*NOTREACHED*/ } /* The scheduler is an infinite loop. */ scheduler(); /* NOTREACHED */ } /* * 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) != 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 (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. */ 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.1/sys/netinet/ip_input.c =================================================================== --- stable/2.1/sys/netinet/ip_input.c (revision 25720) +++ stable/2.1/sys/netinet/ip_input.c (revision 25721) @@ -1,1282 +1,1286 @@ /* * 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.22.4.5 1996/03/25 17:42:41 phk Exp $ + * $Id: ip_input.c,v 1.22.4.6 1996/09/08 13:46:46 davidg 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 int rsvp_on = 0; int ip_rsvp_on; struct socket *ip_rsvpd; #ifndef IPFORWARDING #ifdef GATEWAY #define IPFORWARDING 1 /* forward IP packets not for us */ #else /* GATEWAY */ #define IPFORWARDING 0 /* don't forward IP packets not for us */ #endif /* GATEWAY */ #endif /* IPFORWARDING */ #ifndef IPSENDREDIRECTS #define IPSENDREDIRECTS 1 #endif int ipforwarding = IPFORWARDING; int ipsendredirects = IPSENDREDIRECTS; int ip_defttl = IPDEFTTL; int ip_dosourceroute = 0; #ifdef DIAGNOSTIC int ipprintfs = 0; #endif extern struct domain inetdomain; extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddr *in_ifaddr; /* first inet address */ struct ifqueue ipintrq; struct ipstat ipstat; struct ipq ipq; /* * The dummy IP-firewall function, and the pointer we access it through */ static int dummy_ip_fw_chk(m, ip, rif, dir) struct mbuf *m; struct ip *ip; struct ifnet *rif; int dir; { return 1; } int (*ip_fw_chk_ptr)(struct mbuf *, struct ip *, struct ifnet *, int dir) = dummy_ip_fw_chk; int (*ip_fw_ctl_ptr)(int, struct mbuf **); /* * 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. */ 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; static void save_rte __P((u_char *, struct in_addr)); /* * 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; #if defined(IPFIREWALL) ip_fw_init(); #endif /* IPFIREWALL */ } struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; struct route ipforward_rt; /* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ void ipintr(void) { register struct ip *ip; register struct mbuf *m; register struct ipq *fp; register struct in_ifaddr *ia; int hlen, s; next: /* * Get next datagram off input queue and get IP header * in first mbuf. */ s = splimp(); IF_DEQUEUE(&ipintrq, m); splx(s); if (m == 0) return; #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ipintr 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_len < sizeof (struct ip) && (m = m_pullup(m, sizeof (struct ip))) == 0) { ipstat.ips_toosmall++; goto next; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { ipstat.ips_badvers++; goto bad; } hlen = ip->ip_hl << 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++; goto next; } ip = mtod(m, struct ip *); } ip->ip_sum = in_cksum(m, hlen); if (ip->ip_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) { 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 * - Wrap: fake packet's addr/port * - Encapsulate: put it in another IP and send out. */ if (!(*ip_fw_chk_ptr)(m,ip,m->m_pkthdr.rcvif,0) ) { goto next; } /* * 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)) goto next; /* 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 && #ifdef DIRECTED_BROADCAST ia->ia_ifp == m->m_pkthdr.rcvif && #endif (ia->ia_ifp->if_flags & IFF_BROADCAST)) { u_long t; 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; /* * Look for all-0's host part (old broadcast addr), * either for subnet or net. */ t = ntohl(ip->ip_dst.s_addr); if (t == ia->ia_subnet) goto ours; if (t == ia->ia_net) 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); goto next; } 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); goto next; } 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); goto next; 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++; goto next; } 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) goto next; ipstat.ips_reassembled++; m = dtom(ip); } else if (fp) ip_freef(fp); } else ip->ip_len -= hlen; /* * Switch out to protocol's input routine. */ ipstat.ips_delivered++; (*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen); goto next; bad: m_freem(m); goto next; } 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. */ 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; 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: /* * 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; 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); } /* * 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. */ 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. */ 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. */ 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); } } /* * 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. */ 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->ip_hl << 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->ip_hl << 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. */ 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; (void)memcpy(ip_srcrt.srcopt, option, 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->ip_hl<<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_hl = 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. */ 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 #ifdef DIRECTED_BROADCAST | IP_ALLOWBROADCAST #endif , 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); } int ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen) int *name; u_int namelen; void *oldp; size_t *oldlenp; void *newp; size_t newlen; { /* All sysctl names at this level are terminal. */ if (namelen != 1) return (ENOTDIR); switch (name[0]) { case IPCTL_FORWARDING: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipforwarding)); case IPCTL_SENDREDIRECTS: return (sysctl_int(oldp, oldlenp, newp, newlen, &ipsendredirects)); case IPCTL_DEFTTL: return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_defttl)); case IPCTL_SOURCEROUTE: return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_dosourceroute)); #ifdef notyet case IPCTL_DEFMTU: return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu)); #endif case IPCTL_RTEXPIRE: return (sysctl_int(oldp, oldlenp, newp, newlen, &rtq_reallyold)); case IPCTL_RTMINEXPIRE: return (sysctl_int(oldp, oldlenp, newp, newlen, &rtq_minreallyold)); case IPCTL_RTMAXCACHE: return (sysctl_int(oldp, oldlenp, newp, newlen, &rtq_toomany)); default: return (EOPNOTSUPP); } /* NOTREACHED */ } 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.1/sys/nfs/bootp_subr.c =================================================================== --- stable/2.1/sys/nfs/bootp_subr.c (nonexistent) +++ stable/2.1/sys/nfs/bootp_subr.c (revision 25721) @@ -0,0 +1,1207 @@ +/* $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 nfs_diskless nfs_diskless; + +/* mountd RPC */ +static int md_mount __P((struct sockaddr_in *mdsin, char *path, + u_char *fhp, struct nfs_args *args)); +static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path, + u_char *fhp, + struct nfs_args *args)); + +#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 = ifnet; ifp != 0; ifp = ifp->if_next) + { + for (ifa = ifp->if_addrlist ;ifa; ifa = ifa->ifa_next) + 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))) + 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 nfs_diskless *nd = &nfs_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)) != 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_args); + 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_args); + 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_args); + if (error) + panic("nfs_boot: lookup swap, error=%d", error); + } + nfs_diskless_valid = 1; + } + + + 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, args) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + struct nfs_args *args; +{ + struct mbuf *m; + int error; + int authunixok; + int authcount; + int authver; + + /* Get port number for MOUNTD. */ + error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1, + &mdsin->sin_port); + 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); + 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; + } + error = fxdr_unsigned(u_int32_t, *mtod(m,u_int32_t *)); + if (error) + goto bad; + m_adj(m,sizeof(u_int32_t)); + + if (m->m_len < NFS_FHSIZE ) { + m = m_pullup(m,NFS_FHSIZE); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, NFS_FHSIZE); + m_adj(m,NFS_FHSIZE); + + /* Set port number for NFS use. */ + error = krpc_portmap(mdsin, NFS_PROG, + NFS_VER2, + &mdsin->sin_port); + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} + +static int md_lookup_swap(mdsin, path, fhp, args) + struct sockaddr_in *mdsin; /* mountd server address */ + char *path; + u_char *fhp; + struct nfs_args *args; +{ + struct mbuf *m; + int error; + int size = -1; + int attribs_present; + int status; + + m = m_get(M_WAIT,MT_DATA); + if (!m) + return ENOBUFS; + + bcopy(fhp,mtod(m,u_char *),NFS_FHSIZE); + m->m_len = NFS_FHSIZE; + + m->m_next = xdr_string_encode(path, strlen(path)); + if (!m->m_next) { + error = ENOBUFS; + goto out; + } + + /* Do RPC to nfsd. */ + error = krpc_call(mdsin, NFS_PROG, NFS_VER2, + NFSPROC_LOOKUP, &m, NULL); + 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 (m->m_len < NFS_FHSIZE) { + m = m_pullup(m, NFS_FHSIZE); + if (m == NULL) + goto bad; + } + bcopy(mtod(m,u_char *), fhp, NFS_FHSIZE); + m_adj(m,NFS_FHSIZE); + + 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 (!nfs_diskless.swap_nblks && size!= -1) { + nfs_diskless.swap_nblks = size/1024; + printf("md_lookup_swap: Swap size is %d KB\n", + nfs_diskless.swap_nblks); + } + + goto out; + +bad: + error = EBADRPC; + +out: + m_freem(m); + return error; +} Property changes on: stable/2.1/sys/nfs/bootp_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/2.1/sys/nfs/krpc.h =================================================================== --- stable/2.1/sys/nfs/krpc.h (nonexistent) +++ stable/2.1/sys/nfs/krpc.h (revision 25721) @@ -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)); + +int krpc_portmap __P((struct sockaddr_in *sin, + u_int prog, u_int vers, u_int16_t *portp)); + +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.1/sys/nfs/krpc.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/2.1/sys/nfs/krpc_subr.c =================================================================== --- stable/2.1/sys/nfs/krpc_subr.c (nonexistent) +++ stable/2.1/sys/nfs/krpc_subr.c (revision 25721) @@ -0,0 +1,590 @@ +/* $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) + struct sockaddr_in *sin; /* server address */ + u_int prog, vers; /* host order */ + u_int16_t *portp; /* network order */ +{ + 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); + 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) + struct sockaddr_in *sa; + u_int prog, vers, func; + struct mbuf **data; /* input/output */ + struct mbuf **from_p; /* output */ +{ + 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))) + 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.1/sys/nfs/krpc_subr.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property