summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-12-20 01:29:19 +0000
committersam <sam@FreeBSD.org>2008-12-20 01:29:19 +0000
commitc3f1faeb23e27c2ffda030cf892c5df698734622 (patch)
tree0b964e87f3cbd93269e72d591d2eb44bc6ace51c
parentcd99ae6c06463359389c703ff069f25d28878ad7 (diff)
parent3fcef6d9c20b6c3577c741e4a0fe24807fd08a66 (diff)
downloadFreeBSD-src-c3f1faeb23e27c2ffda030cf892c5df698734622.zip
FreeBSD-src-c3f1faeb23e27c2ffda030cf892c5df698734622.tar.gz
MFH @ 186335
-rw-r--r--UPDATING17
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII.c83
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII_route.c3
-rw-r--r--contrib/ipfilter/ipsend/44arp.c5
-rw-r--r--contrib/netcat/FREEBSD-vendor4
-rw-r--r--contrib/netcat/nc.116
-rw-r--r--contrib/netcat/netcat.c66
-rw-r--r--etc/Makefile1
-rw-r--r--etc/devd.conf23
-rw-r--r--etc/devd/Makefile9
-rw-r--r--etc/devd/asus.conf52
-rw-r--r--etc/mtree/BSD.root.dist2
-rwxr-xr-xetc/rc.d/defaultroute4
-rw-r--r--etc/regdomain.xml139
-rw-r--r--gnu/usr.bin/groff/tmac/mdoc.local2
-rw-r--r--include/arpa/nameser.h5
-rw-r--r--include/resolv.h6
-rw-r--r--lib/libarchive/archive_read_support_format_ar.c2
-rw-r--r--lib/libarchive/test/main.c2
-rw-r--r--lib/libarchive/test/test_compat_gtar.c13
-rw-r--r--lib/libarchive/test/test_write_compress.c4
-rw-r--r--lib/libarchive/test/test_write_format_ar.c88
-rw-r--r--lib/libc/include/isc/eventlib.h4
-rw-r--r--lib/libc/include/isc/platform.h37
-rw-r--r--lib/libc/inet/inet_net_pton.c6
-rw-r--r--lib/libc/net/rcmd.37
-rw-r--r--lib/libc/resolv/res_debug.c55
-rw-r--r--lib/libc/resolv/res_mkquery.c66
-rw-r--r--lib/libc/resolv/res_query.c14
-rw-r--r--lib/libc/resolv/res_send.c28
-rw-r--r--lib/libfetch/fetch.325
-rw-r--r--lib/libfetch/fetch.c8
-rw-r--r--lib/libfetch/fetch.h1
-rw-r--r--lib/libfetch/http.c28
-rw-r--r--lib/libstand/if_ether.h4
-rw-r--r--lib/libutil/kinfo_getfile.c9
-rw-r--r--lib/libutil/kinfo_getvmmap.c9
-rw-r--r--libexec/bootpd/rtmsg.c1
-rw-r--r--release/doc/en_US.ISO8859-1/hardware/article.sgml108
-rw-r--r--release/picobsd/tinyware/ns/ns.c4
-rw-r--r--sbin/atacontrol/atacontrol.819
-rw-r--r--sbin/devd/devd.cc4
-rw-r--r--sbin/devd/devd.conf.52
-rw-r--r--sbin/geom/misc/subr.c2
-rw-r--r--sbin/ifconfig/ifieee80211.c99
-rw-r--r--sbin/ifconfig/regdomain.c72
-rw-r--r--sbin/ifconfig/regdomain.h1
-rw-r--r--sbin/ipfw/ipfw.82
-rw-r--r--sbin/ipfw/ipfw2.c10
-rw-r--r--sbin/mount/mount.c8
-rw-r--r--sbin/mount/mount_fs.c2
-rw-r--r--sbin/route/route.c6
-rw-r--r--sbin/routed/table.c7
-rw-r--r--share/man/man4/Makefile1
-rw-r--r--share/man/man4/acpi_aiboost.44
-rw-r--r--share/man/man4/acpi_asus.45
-rw-r--r--share/man/man4/fxp.49
-rw-r--r--share/man/man4/route.44
-rw-r--r--share/man/man9/VOP_STRATEGY.94
-rw-r--r--share/man/man9/rtalloc.946
-rw-r--r--share/man/man9/rtentry.961
-rw-r--r--share/man/man9/style.911
-rw-r--r--sys/amd64/amd64/exception.S24
-rw-r--r--sys/amd64/amd64/identcpu.c16
-rw-r--r--sys/amd64/conf/DEFAULTS4
-rw-r--r--sys/amd64/include/elf.h12
-rw-r--r--sys/amd64/include/specialreg.h8
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c2
-rw-r--r--sys/arm/conf/DEFAULTS4
-rw-r--r--sys/arm/conf/EP802191
-rw-r--r--sys/arm/include/elf.h4
-rw-r--r--sys/boot/Makefile2
-rw-r--r--sys/boot/i386/gptzfsboot/Makefile2
-rw-r--r--sys/boot/i386/zfsboot/Makefile2
-rw-r--r--sys/boot/powerpc/uboot/conf.c8
-rw-r--r--sys/boot/uboot/common/main.c1
-rw-r--r--sys/boot/uboot/lib/devicename.c17
-rw-r--r--sys/boot/zfs/zfsimpl.c13
-rw-r--r--sys/cam/cam_periph.c23
-rw-r--r--sys/cam/cam_periph.h1
-rw-r--r--sys/cam/cam_sim.c31
-rw-r--r--sys/cam/cam_sim.h3
-rw-r--r--sys/cam/cam_xpt.c109
-rw-r--r--sys/cam/scsi/scsi_da.c2
-rw-r--r--sys/compat/svr4/svr4_sysvec.c2
-rw-r--r--sys/conf/NOTES2
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/files.powerpc2
-rw-r--r--sys/conf/files.sparc643
-rw-r--r--sys/conf/files.sun4v3
-rw-r--r--sys/contrib/pf/net/pf.c12
-rw-r--r--sys/contrib/pf/net/pf_if.c2
-rw-r--r--sys/contrib/pf/net/pf_subr.c20
-rw-r--r--sys/contrib/rdma/rdma_addr.c6
-rw-r--r--sys/crypto/rc4/rc4.c8
-rw-r--r--sys/dev/acpica/acpi_smbat.c34
-rw-r--r--sys/dev/ata/ata-pci.c30
-rw-r--r--sys/dev/ata/ata-pci.h1
-rw-r--r--sys/dev/ata/chipsets/ata-ahci.c16
-rw-r--r--sys/dev/ata/chipsets/ata-sis.c3
-rw-r--r--sys/dev/ath/ath_hal/ah.c8
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v14.c12
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v3.c6
-rw-r--r--sys/dev/ath/ath_hal/ah_internal.h25
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5111.c4
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_ani.c20
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312.h4
-rw-r--r--sys/dev/ath/ath_hal/ar5312/ar5312_attach.c5
-rw-r--r--sys/dev/atkbdc/psm.c35
-rw-r--r--sys/dev/bce/if_bce.c3
-rw-r--r--sys/dev/cxgb/common/cxgb_ael1002.c134
-rw-r--r--sys/dev/cxgb/cxgb_main.c77
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c3
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_l2t.c48
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_l2t.h2
-rw-r--r--sys/dev/drm/drmP.h22
-rw-r--r--sys/dev/drm/drm_drv.c4
-rw-r--r--sys/dev/drm/drm_scatter.c110
-rw-r--r--sys/dev/fxp/if_fxp.c8
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c13
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c72
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c76
-rw-r--r--sys/dev/isp/isp.c21
-rw-r--r--sys/dev/md/md.c5
-rw-r--r--sys/dev/mfi/mfi.c3
-rw-r--r--sys/dev/mfi/mfi_pci.c2
-rw-r--r--sys/dev/nfe/if_nfe.c2
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c151
-rw-r--r--sys/dev/ofw/ofw_bus_subr.h21
-rw-r--r--sys/dev/ofw/ofw_if.m357
-rw-r--r--sys/dev/ofw/ofw_standard.c763
-rw-r--r--sys/dev/ofw/ofwvar.h89
-rw-r--r--sys/dev/ofw/openfirm.c655
-rw-r--r--sys/dev/ofw/openfirm.h88
-rw-r--r--sys/dev/ofw/openfirmio.c2
-rw-r--r--sys/dev/ofw/openpromio.c2
-rw-r--r--sys/dev/re/if_re.c54
-rw-r--r--sys/dev/snp/snp.c3
-rw-r--r--sys/dev/sound/pci/hda/hdac.c35
-rw-r--r--sys/dev/usb/ucom.c42
-rw-r--r--sys/dev/usb/ucomvar.h1
-rw-r--r--sys/dev/usb/uftdi.c51
-rw-r--r--sys/fs/hpfs/hpfs_vnops.c2
-rw-r--r--sys/fs/msdosfs/msdosfs_vnops.c2
-rw-r--r--sys/fs/ntfs/ntfs_vnops.c2
-rw-r--r--sys/fs/nwfs/nwfs_vnops.c2
-rw-r--r--sys/fs/smbfs/smbfs_vnops.c2
-rw-r--r--sys/geom/geom_vfs.c35
-rw-r--r--sys/gnu/fs/ext2fs/ext2_vnops.c2
-rw-r--r--sys/gnu/fs/reiserfs/reiserfs_vnops.c7
-rw-r--r--sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c2
-rw-r--r--sys/i386/conf/DEFAULTS4
-rw-r--r--sys/i386/i386/exception.s11
-rw-r--r--sys/i386/i386/identcpu.c16
-rw-r--r--sys/i386/include/elf.h12
-rw-r--r--sys/i386/include/specialreg.h8
-rw-r--r--sys/i386/linux/linux_sysvec.c2
-rw-r--r--sys/ia64/include/elf.h12
-rw-r--r--sys/kern/imgact_elf.c10
-rw-r--r--sys/kern/kern_cpu.c9
-rw-r--r--sys/kern/kern_mbuf.c1
-rw-r--r--sys/kern/subr_kobj.c59
-rw-r--r--sys/kern/subr_param.c45
-rw-r--r--sys/kern/subr_trap.c8
-rw-r--r--sys/kern/tty.c25
-rw-r--r--sys/kern/tty_pts.c10
-rw-r--r--sys/kern/vfs_lookup.c4
-rw-r--r--sys/kern/vfs_mount.c45
-rw-r--r--sys/kern/vfs_subr.c2
-rw-r--r--sys/kern/vfs_syscalls.c24
-rw-r--r--sys/mips/conf/DEFAULTS4
-rw-r--r--sys/mips/include/elf.h76
-rw-r--r--sys/mips/mips/elf_machdep.c16
-rw-r--r--sys/modules/Makefile3
-rw-r--r--sys/modules/ath/Makefile86
-rw-r--r--sys/modules/ath_rate_amrr/Makefile40
-rw-r--r--sys/modules/ath_rate_onoe/Makefile40
-rw-r--r--sys/modules/ath_rate_sample/Makefile40
-rw-r--r--sys/modules/cxgb/Makefile2
-rw-r--r--sys/net/ieee8023ad_lacp.c2
-rw-r--r--sys/net/if.c25
-rw-r--r--sys/net/if_arcsubr.c6
-rw-r--r--sys/net/if_atmsubr.c13
-rw-r--r--sys/net/if_ethersubr.c19
-rw-r--r--sys/net/if_fddisubr.c6
-rw-r--r--sys/net/if_fwsubr.c16
-rw-r--r--sys/net/if_iso88025subr.c15
-rw-r--r--sys/net/if_lagg.c27
-rw-r--r--sys/net/if_llatbl.c311
-rw-r--r--sys/net/if_llatbl.h192
-rw-r--r--sys/net/if_media.h12
-rw-r--r--sys/net/if_var.h86
-rw-r--r--sys/net/pfil.c42
-rw-r--r--sys/net/pfil.h3
-rw-r--r--sys/net/radix.c1
-rw-r--r--sys/net/radix_mpath.c4
-rw-r--r--sys/net/route.c602
-rw-r--r--sys/net/route.h19
-rw-r--r--sys/net/rtsock.c46
-rw-r--r--sys/net80211/_ieee80211.h2
-rw-r--r--sys/net80211/ieee80211.c4
-rw-r--r--sys/net80211/ieee80211_acl.c14
-rw-r--r--sys/net80211/ieee80211_crypto.h2
-rw-r--r--sys/net80211/ieee80211_crypto_ccmp.c4
-rw-r--r--sys/net80211/ieee80211_crypto_tkip.c4
-rw-r--r--sys/net80211/ieee80211_crypto_wep.c4
-rw-r--r--sys/net80211/ieee80211_ddb.c5
-rw-r--r--sys/net80211/ieee80211_dfs.h2
-rw-r--r--sys/net80211/ieee80211_freebsd.c4
-rw-r--r--sys/net80211/ieee80211_hostap.c14
-rw-r--r--sys/net80211/ieee80211_input.c10
-rw-r--r--sys/net80211/ieee80211_ioctl.c48
-rw-r--r--sys/net80211/ieee80211_node.c40
-rw-r--r--sys/net80211/ieee80211_node.h1
-rw-r--r--sys/net80211/ieee80211_output.c4
-rw-r--r--sys/net80211/ieee80211_power.c4
-rw-r--r--sys/net80211/ieee80211_proto.c2
-rw-r--r--sys/net80211/ieee80211_regdomain.c2
-rw-r--r--sys/net80211/ieee80211_scan.c4
-rw-r--r--sys/net80211/ieee80211_scan_sta.c17
-rw-r--r--sys/net80211/ieee80211_sta.c2
-rw-r--r--sys/net80211/ieee80211_var.h2
-rw-r--r--sys/netgraph/netflow/netflow.c4
-rw-r--r--sys/netgraph/netgraph.h1
-rw-r--r--sys/netgraph/ng_base.c55
-rw-r--r--sys/netgraph/ng_mppc.c21
-rw-r--r--sys/netgraph/ng_tty.c21
-rw-r--r--sys/netinet/icmp6.h2
-rw-r--r--sys/netinet/icmp_var.h2
-rw-r--r--sys/netinet/if_atm.c6
-rw-r--r--sys/netinet/if_ether.c847
-rw-r--r--sys/netinet/if_ether.h5
-rw-r--r--sys/netinet/in.c242
-rw-r--r--sys/netinet/in_mcast.c2
-rw-r--r--sys/netinet/in_pcb.c8
-rw-r--r--sys/netinet/in_pcb.h8
-rw-r--r--sys/netinet/in_proto.c5
-rw-r--r--sys/netinet/in_rmx.c34
-rw-r--r--sys/netinet/in_var.h16
-rw-r--r--sys/netinet/ip_carp.c8
-rw-r--r--sys/netinet/ip_fastfwd.c2
-rw-r--r--sys/netinet/ip_fw.h2
-rw-r--r--sys/netinet/ip_fw2.c16
-rw-r--r--sys/netinet/ip_fw_pfil.c24
-rw-r--r--sys/netinet/ip_input.c4
-rw-r--r--sys/netinet/ip_output.c1
-rw-r--r--sys/netinet/raw_ip.c5
-rw-r--r--sys/netinet/tcp_hostcache.c8
-rw-r--r--sys/netinet/tcp_input.c7
-rw-r--r--sys/netinet/tcp_subr.c36
-rw-r--r--sys/netinet/tcp_syncache.c39
-rw-r--r--sys/netinet/tcp_timewait.c2
-rw-r--r--sys/netinet/tcp_usrreq.c8
-rw-r--r--sys/netinet/tcp_var.h4
-rw-r--r--sys/netinet/vinet.h2
-rw-r--r--sys/netinet6/icmp6.c60
-rw-r--r--sys/netinet6/in6.c448
-rw-r--r--sys/netinet6/in6_pcb.c12
-rw-r--r--sys/netinet6/in6_rmx.c66
-rw-r--r--sys/netinet6/in6_src.c67
-rw-r--r--sys/netinet6/in6_var.h7
-rw-r--r--sys/netinet6/ip6_input.c40
-rw-r--r--sys/netinet6/ip6_output.c50
-rw-r--r--sys/netinet6/ip6_var.h11
-rw-r--r--sys/netinet6/nd6.c1077
-rw-r--r--sys/netinet6/nd6.h40
-rw-r--r--sys/netinet6/nd6_nbr.c98
-rw-r--r--sys/netinet6/nd6_rtr.c79
-rw-r--r--sys/netinet6/raw_ip6.c40
-rw-r--r--sys/netinet6/raw_ip6.h2
-rw-r--r--sys/netinet6/udp6_usrreq.c18
-rw-r--r--sys/netinet6/vinet6.h1
-rw-r--r--sys/netipsec/ipip_var.h2
-rw-r--r--sys/netipsec/ipsec.c40
-rw-r--r--sys/netipsec/key.c26
-rw-r--r--sys/nfsserver/nfs_serv.c9
-rw-r--r--sys/pc98/conf/DEFAULTS4
-rw-r--r--sys/pci/if_rl.c12
-rw-r--r--sys/pci/if_rlreg.h4
-rw-r--r--sys/powerpc/aim/locore.S11
-rw-r--r--sys/powerpc/aim/machdep.c12
-rw-r--r--sys/powerpc/aim/ofw_machdep.c47
-rw-r--r--sys/powerpc/booke/interrupt.c1
-rw-r--r--sys/powerpc/booke/locore.S450
-rw-r--r--sys/powerpc/booke/machdep.c54
-rw-r--r--sys/powerpc/include/elf.h3
-rw-r--r--sys/powerpc/include/ofw_machdep.h9
-rw-r--r--sys/powerpc/include/param.h3
-rw-r--r--sys/powerpc/include/spr.h18
-rw-r--r--sys/powerpc/mpc85xx/lbc.c268
-rw-r--r--sys/powerpc/mpc85xx/lbc.h44
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.c101
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.h37
-rw-r--r--sys/powerpc/mpc85xx/nexus.c8
-rw-r--r--sys/powerpc/mpc85xx/ocpbus.c58
-rw-r--r--sys/powerpc/ofw/ofw_pcib_pci.c64
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c353
-rw-r--r--sys/powerpc/ofw/ofw_syscons.c149
-rw-r--r--sys/powerpc/ofw/ofw_syscons.h1
-rw-r--r--sys/powerpc/powermac/cuda.c38
-rw-r--r--sys/powerpc/powermac/cudavar.h3
-rw-r--r--sys/powerpc/powermac/grackle.c32
-rw-r--r--sys/powerpc/powermac/gracklevar.h3
-rw-r--r--sys/powerpc/powermac/macio.c2
-rw-r--r--sys/powerpc/powermac/uninorth.c31
-rw-r--r--sys/powerpc/powermac/uninorthvar.h2
-rw-r--r--sys/powerpc/powerpc/pmap_dispatch.c5
-rw-r--r--sys/sparc64/conf/DEFAULTS4
-rw-r--r--sys/sparc64/ebus/ebus.c2
-rw-r--r--sys/sparc64/include/elf.h12
-rw-r--r--sys/sparc64/include/ofw_bus.h53
-rw-r--r--sys/sparc64/include/ofw_machdep.h7
-rw-r--r--sys/sparc64/isa/ofw_isa.c2
-rw-r--r--sys/sparc64/pci/apb.c1
-rw-r--r--sys/sparc64/pci/ofw_pci.h2
-rw-r--r--sys/sparc64/pci/ofw_pcib.c1
-rw-r--r--sys/sparc64/pci/ofw_pcib_subr.c1
-rw-r--r--sys/sparc64/pci/ofw_pcibus.c19
-rw-r--r--sys/sparc64/pci/psycho.c1
-rw-r--r--sys/sparc64/pci/schizo.c46
-rw-r--r--sys/sparc64/sbus/sbus.c1
-rw-r--r--sys/sparc64/sparc64/machdep.c21
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c4
-rw-r--r--sys/sparc64/sparc64/ofw_bus.c198
-rw-r--r--sys/sparc64/sparc64/ofw_machdep.c1
-rw-r--r--sys/sparc64/sparc64/support.S12
-rw-r--r--sys/sparc64/sparc64/trap.c3
-rw-r--r--sys/sparc64/sparc64/vm_machdep.c2
-rw-r--r--sys/sun4v/conf/DEFAULTS4
-rw-r--r--sys/sun4v/include/elf.h12
-rw-r--r--sys/sun4v/include/ofw_bus.h53
-rw-r--r--sys/sun4v/sun4v/machdep.c25
-rw-r--r--sys/sun4v/sun4v/mp_machdep.c2
-rw-r--r--sys/sun4v/sun4v/support.S10
-rw-r--r--sys/sun4v/sun4v/trap.c2
-rw-r--r--sys/sys/buf_ring.h3
-rw-r--r--sys/sys/elf_common.h60
-rw-r--r--sys/sys/imgact_elf.h1
-rw-r--r--sys/sys/kobj.h5
-rw-r--r--sys/sys/mount.h1
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/ttyhook.h2
-rw-r--r--sys/sys/vtoc.h2
-rw-r--r--sys/ufs/ufs/ufs_vfsops.c4
-rw-r--r--sys/ufs/ufs/ufs_vnops.c2
-rw-r--r--tools/tools/nanobsd/nanobsd.sh7
-rw-r--r--tools/tools/tionxcl/Makefile6
-rw-r--r--tools/tools/tionxcl/tionxcl.c101
-rw-r--r--usr.bin/cpuset/cpuset.112
-rw-r--r--usr.bin/fetch/fetch.134
-rw-r--r--usr.bin/fetch/fetch.c45
-rw-r--r--usr.bin/ipcs/ipcs.c10
-rw-r--r--usr.bin/make/globals.h1
-rw-r--r--usr.bin/make/job.c26
-rw-r--r--usr.bin/make/job.h2
-rw-r--r--usr.bin/make/main.c13
-rw-r--r--usr.bin/make/make.c6
-rw-r--r--usr.bin/netstat/route.c38
-rw-r--r--usr.bin/procstat/procstat.12
-rw-r--r--usr.bin/procstat/procstat_files.c2
-rw-r--r--usr.bin/procstat/procstat_vm.c2
-rw-r--r--usr.bin/tar/util.c6
-rw-r--r--usr.sbin/Makefile1
-rw-r--r--usr.sbin/arp/arp.c50
-rw-r--r--usr.sbin/burncd/Makefile2
-rw-r--r--usr.sbin/burncd/burncd.c41
-rw-r--r--usr.sbin/jls/jls.c48
-rw-r--r--usr.sbin/makefs/Makefile28
-rw-r--r--usr.sbin/makefs/compat/pwcache.c623
-rw-r--r--usr.sbin/makefs/compat/pwcache.h73
-rw-r--r--usr.sbin/makefs/compat/strsuftoll.c229
-rw-r--r--usr.sbin/makefs/ffs.c1093
-rw-r--r--usr.sbin/makefs/ffs/buf.c222
-rw-r--r--usr.sbin/makefs/ffs/buf.h67
-rw-r--r--usr.sbin/makefs/ffs/ffs_alloc.c683
-rw-r--r--usr.sbin/makefs/ffs/ffs_balloc.c578
-rw-r--r--usr.sbin/makefs/ffs/ffs_bswap.c270
-rw-r--r--usr.sbin/makefs/ffs/ffs_extern.h77
-rw-r--r--usr.sbin/makefs/ffs/ffs_subr.c202
-rw-r--r--usr.sbin/makefs/ffs/mkfs.c832
-rw-r--r--usr.sbin/makefs/ffs/newfs_extern.h41
-rw-r--r--usr.sbin/makefs/ffs/ufs_bmap.c142
-rw-r--r--usr.sbin/makefs/ffs/ufs_bswap.h94
-rw-r--r--usr.sbin/makefs/ffs/ufs_inode.h97
-rw-r--r--usr.sbin/makefs/getid.c436
-rw-r--r--usr.sbin/makefs/makefs.8288
-rw-r--r--usr.sbin/makefs/makefs.c314
-rw-r--r--usr.sbin/makefs/makefs.h305
-rw-r--r--usr.sbin/makefs/walk.c568
-rwxr-xr-xusr.sbin/mergemaster/mergemaster.sh30
-rw-r--r--usr.sbin/ndp/ndp.c22
-rw-r--r--usr.sbin/ppp/route.c16
-rw-r--r--usr.sbin/route6d/route6d.c14
-rw-r--r--usr.sbin/sysinstall/Makefile2
-rw-r--r--usr.sbin/sysinstall/cdrom.c4
-rw-r--r--usr.sbin/sysinstall/config.c2
-rw-r--r--usr.sbin/sysinstall/devices.c18
-rw-r--r--usr.sbin/sysinstall/dispatch.c3
-rw-r--r--usr.sbin/sysinstall/dist.c55
-rw-r--r--usr.sbin/sysinstall/dist.h4
-rw-r--r--usr.sbin/sysinstall/label.c23
-rw-r--r--usr.sbin/sysinstall/main.c5
-rw-r--r--usr.sbin/sysinstall/media.c55
-rw-r--r--usr.sbin/sysinstall/menus.c64
-rw-r--r--usr.sbin/sysinstall/options.c3
-rw-r--r--usr.sbin/sysinstall/sysinstall.861
-rw-r--r--usr.sbin/sysinstall/sysinstall.h16
-rw-r--r--usr.sbin/sysinstall/system.c17
-rw-r--r--usr.sbin/sysinstall/tape.c119
-rw-r--r--usr.sbin/sysinstall/user.c41
-rw-r--r--usr.sbin/syslogd/Makefile2
-rw-r--r--usr.sbin/syslogd/syslogd.c34
412 files changed, 15255 insertions, 6245 deletions
diff --git a/UPDATING b/UPDATING
index eefee86..a23506b 100644
--- a/UPDATING
+++ b/UPDATING
@@ -22,6 +22,23 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW:
to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.)
+20081219:
+ With __FreeBSD_version 800060 the makefs tool is part of
+ the base system (it was a port).
+
+20081216:
+ The afdata and ifnet locks have been changed from mutexes to
+ rwlocks, network modules will need to be re-compiled.
+
+20081214:
+ __FreeBSD_version 800059 incorporates the new arp-v2 rewrite.
+ RTF_CLONING, RTF_LLINFO and RTF_WASCLONED flags are eliminated.
+ The new code reduced struct rtentry{} by 16 bytes on 32-bit
+ architecture and 40 bytes on 64-bit architecture. The userland
+ applications "arp" and "ndp" have been updated accordingly.
+ The output from "netstat -r" shows only routing entries and
+ none of the L2 information.
+
20081130:
__FreeBSD_version 800057 marks the switchover from the
binary ath hal to source code. Users must add the line:
diff --git a/contrib/bsnmp/snmp_mibII/mibII.c b/contrib/bsnmp/snmp_mibII/mibII.c
index 96bd366..83e2317 100644
--- a/contrib/bsnmp/snmp_mibII/mibII.c
+++ b/contrib/bsnmp/snmp_mibII/mibII.c
@@ -48,8 +48,7 @@ static void *route_fd;
/* if-index allocator */
static uint32_t next_if_index = 1;
-/* re-fetch arp table */
-static int update_arp;
+/* currently fetching the arp table */
static int in_update_arp;
/* OR registrations */
@@ -911,36 +910,6 @@ mib_find_ifa(struct in_addr addr)
}
/*
- * Process a new ARP entry
- */
-static void
-process_arp(const struct rt_msghdr *rtm, const struct sockaddr_dl *sdl,
- const struct sockaddr_in *sa)
-{
- struct mibif *ifp;
- struct mibarp *at;
-
- /* IP arp table entry */
- if (sdl->sdl_alen == 0) {
- update_arp = 1;
- return;
- }
- if ((ifp = mib_find_if_sys(sdl->sdl_index)) == NULL)
- return;
- /* have a valid entry */
- if ((at = mib_find_arp(ifp, sa->sin_addr)) == NULL &&
- (at = mib_arp_create(ifp, sa->sin_addr,
- sdl->sdl_data + sdl->sdl_nlen, sdl->sdl_alen)) == NULL)
- return;
-
- if (rtm->rtm_rmx.rmx_expire == 0)
- at->flags |= MIBARP_PERM;
- else
- at->flags &= ~MIBARP_PERM;
- at->flags |= MIBARP_FOUND;
-}
-
-/*
* Handle a routing socket message.
*/
static void
@@ -1080,46 +1049,12 @@ handle_rtmsg(struct rt_msghdr *rtm)
}
break;
#endif
-
case RTM_GET:
- mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs);
- if (rtm->rtm_flags & RTF_LLINFO) {
- if (addrs[RTAX_DST] == NULL ||
- addrs[RTAX_GATEWAY] == NULL ||
- addrs[RTAX_DST]->sa_family != AF_INET ||
- addrs[RTAX_GATEWAY]->sa_family != AF_LINK)
- break;
- process_arp(rtm,
- (struct sockaddr_dl *)(void *)addrs[RTAX_GATEWAY],
- (struct sockaddr_in *)(void *)addrs[RTAX_DST]);
- } else {
- if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP))
- mib_sroute_process(rtm, addrs[RTAX_GATEWAY],
- addrs[RTAX_DST], addrs[RTAX_NETMASK]);
- }
- break;
-
case RTM_ADD:
- mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs);
- if (rtm->rtm_flags & RTF_LLINFO) {
- if (addrs[RTAX_DST] == NULL ||
- addrs[RTAX_GATEWAY] == NULL ||
- addrs[RTAX_DST]->sa_family != AF_INET ||
- addrs[RTAX_GATEWAY]->sa_family != AF_LINK)
- break;
- process_arp(rtm,
- (struct sockaddr_dl *)(void *)addrs[RTAX_GATEWAY],
- (struct sockaddr_in *)(void *)addrs[RTAX_DST]);
- } else {
- if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP))
- mib_sroute_process(rtm, addrs[RTAX_GATEWAY],
- addrs[RTAX_DST], addrs[RTAX_NETMASK]);
- }
- break;
-
case RTM_DELETE:
mib_extract_addrs(rtm->rtm_addrs, (u_char *)(rtm + 1), addrs);
- if (rtm->rtm_errno == 0 && !(rtm->rtm_flags & RTF_LLINFO))
+
+ if (rtm->rtm_errno == 0 && (rtm->rtm_flags & RTF_UP))
mib_sroute_process(rtm, addrs[RTAX_GATEWAY],
addrs[RTAX_DST], addrs[RTAX_NETMASK]);
break;
@@ -1289,7 +1224,8 @@ update_ifa_info(void)
/*
* Update arp table
- */
+ *
+*/
void
mib_arp_update(void)
{
@@ -1305,11 +1241,11 @@ mib_arp_update(void)
TAILQ_FOREACH(at, &mibarp_list, link)
at->flags &= ~MIBARP_FOUND;
- if ((buf = mib_fetch_rtab(AF_INET, NET_RT_FLAGS, RTF_LLINFO, &needed)) == NULL) {
+ if ((buf = mib_fetch_rtab(AF_INET, NET_RT_FLAGS, 0, &needed)) == NULL) {
in_update_arp = 0;
return;
}
-
+
next = buf;
while (next < buf + needed) {
rtm = (struct rt_msghdr *)(void *)next;
@@ -1326,7 +1262,6 @@ mib_arp_update(void)
at = at1;
}
mibarpticks = get_ticks();
- update_arp = 0;
in_update_arp = 0;
}
@@ -1634,8 +1569,8 @@ mibII_idle(void)
mib_arp_update();
mib_iflist_bad = 0;
}
- if (update_arp)
- mib_arp_update();
+
+ mib_arp_update();
}
diff --git a/contrib/bsnmp/snmp_mibII/mibII_route.c b/contrib/bsnmp/snmp_mibII/mibII_route.c
index e17497d..b11c422 100644
--- a/contrib/bsnmp/snmp_mibII/mibII_route.c
+++ b/contrib/bsnmp/snmp_mibII/mibII_route.c
@@ -186,8 +186,7 @@ mib_sroute_process(struct rt_msghdr *rtm, struct sockaddr *gw,
memcpy(r->index, key.index, sizeof(r->index));
r->ifindex = (ifp == NULL) ? 0 : ifp->index;
- r->type = (rtm->rtm_flags & RTF_LLINFO) ? 3 :
- (rtm->rtm_flags & RTF_REJECT) ? 2 : 4;
+ r->type = (rtm->rtm_flags & RTF_REJECT) ? 2 : 4;
/* cannot really know, what protocol it runs */
r->proto = (rtm->rtm_flags & RTF_LOCAL) ? 2 :
diff --git a/contrib/ipfilter/ipsend/44arp.c b/contrib/ipfilter/ipsend/44arp.c
index 6ee4f1b..5c07fb6 100644
--- a/contrib/ipfilter/ipsend/44arp.c
+++ b/contrib/ipfilter/ipsend/44arp.c
@@ -88,7 +88,12 @@ char *addr, *eaddr;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
+#ifdef RTF_LLINFO
mib[5] = RTF_LLINFO;
+#else
+ mib[5] = 0;
+#endif
+
if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
{
perror("route-sysctl-estimate");
diff --git a/contrib/netcat/FREEBSD-vendor b/contrib/netcat/FREEBSD-vendor
index 8feb50e..6e31d26 100644
--- a/contrib/netcat/FREEBSD-vendor
+++ b/contrib/netcat/FREEBSD-vendor
@@ -1,7 +1,7 @@
# $FreeBSD$
Project: netcat (aka src/usr.bin/nc in OpenBSD)
ProjectURL: http://www.openbsd.org/
-Version: 4.3
+Version: 4.4
VendorTag: OPENBSD
-VersionTag: OPENBSD_4_3
+VersionTag: OPENBSD_4_4
License: BSD
diff --git a/contrib/netcat/nc.1 b/contrib/netcat/nc.1
index 02e11b7..480196a 100644
--- a/contrib/netcat/nc.1
+++ b/contrib/netcat/nc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: nc.1,v 1.45 2007/05/31 19:20:13 jmc Exp $
+.\" $OpenBSD: nc.1,v 1.47 2008/05/06 16:21:03 jmc Exp $
.\"
.\" Copyright (c) 1996 David Sacerdote
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd $Mdocdate$
+.Dd $Mdocdate: May 6 2008 $
.Dt NC 1
.Os
.Sh NAME
@@ -36,9 +36,12 @@
.Sh SYNOPSIS
.Nm nc
.Bk -words
-.Op Fl 46DdEhklnOorStUuvz
+.Op Fl 46DdEhklnorStUuvz
.Op Fl e Ar IPsec_policy
+.Op Fl I Ar length
.Op Fl i Ar interval
+.Op Fl -no-tcpopt
+.Op Fl O Ar length
.Op Fl P Ar proxy_username
.Op Fl p Ar source_port
.Op Fl s Ar source_ip_address
@@ -118,6 +121,8 @@ each direction is needed.
Prints out
.Nm
help.
+.It Fl I Ar length
+Specifies the size of the TCP receive buffer.
.It Fl i Ar interval
Specifies a delay time interval between lines of text sent and received.
Also causes a delay time between connections to multiple ports.
@@ -146,10 +151,13 @@ option are ignored.
.It Fl n
Do not do any DNS or service lookups on any specified addresses,
hostnames or ports.
-.It Fl O
+.It Fl -no-tcpopt
Disables the use of TCP options on the socket, by setting the boolean
TCP_NOOPT
socket option.
+.It Fl O Ar length
+Specifies the size of the TCP send buffer.
+When
.It Fl o
.Dq Once-only mode .
By default,
diff --git a/contrib/netcat/netcat.c b/contrib/netcat/netcat.c
index 4bad8f2..77ee6bd 100644
--- a/contrib/netcat/netcat.c
+++ b/contrib/netcat/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.89 2007/02/20 14:11:17 jmc Exp $ */
+/* $OpenBSD: netcat.c,v 1.91 2008/05/09 09:00:11 markus Exp $ */
/*
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
*
@@ -50,6 +50,7 @@
#include <err.h>
#include <errno.h>
+#include <getopt.h>
#include <netdb.h>
#include <poll.h>
#include <stdarg.h>
@@ -78,7 +79,7 @@ int kflag; /* More than one connect */
int lflag; /* Bind to local port */
int nflag; /* Don't do name look up */
int oflag; /* Once only: stop on EOF */
-int Oflag; /* Do not use TCP options */
+int FreeBSD_Oflag; /* Do not use TCP options */
char *Pflag; /* Proxy username */
char *pflag; /* Localport flag */
int rflag; /* Random ports flag */
@@ -89,6 +90,8 @@ int vflag; /* Verbosity */
int xflag; /* Socks proxy */
int zflag; /* Port Scan Flag */
int Dflag; /* sodebug */
+int Iflag; /* TCP receive buffer size */
+int Oflag; /* TCP send buffer size */
int Sflag; /* TCP MD5 signature option */
int Tflag = -1; /* IP Type of Service */
@@ -129,6 +132,10 @@ main(int argc, char *argv[])
char *proxy;
const char *errstr, *proxyhost = "", *proxyport = NULL;
struct addrinfo proxyhints;
+ struct option longopts[] = {
+ { "no-tcpopt", no_argument, &FreeBSD_Oflag, 1 },
+ { NULL, 0, NULL, 0 }
+ };
ret = 1;
ipsec_count = 0;
@@ -138,8 +145,9 @@ main(int argc, char *argv[])
uport = NULL;
sv = NULL;
- while ((ch = getopt(argc, argv,
- "46e:DEdhi:jklnoOP:p:rSs:tT:Uuvw:X:x:z")) != -1) {
+ while ((ch = getopt_long(argc, argv,
+ "46e:DEdhi:jklnoI:O:P:p:rSs:tT:Uuvw:X:x:z",
+ longopts, NULL)) != -1) {
switch (ch) {
case '4':
family = AF_INET;
@@ -203,9 +211,6 @@ main(int argc, char *argv[])
case 'o':
oflag = 1;
break;
- case 'O':
- Oflag = 1;
- break;
case 'P':
Pflag = optarg;
break;
@@ -244,12 +249,28 @@ main(int argc, char *argv[])
case 'D':
Dflag = 1;
break;
+ case 'I':
+ Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
+ if (errstr != NULL)
+ errx(1, "TCP receive window %s: %s",
+ errstr, optarg);
+ break;
+ case 'O':
+ Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
+ if (errstr != NULL) {
+ if (strcmp(errstr, "invalid") != 0)
+ errx(1, "TCP send window %s: %s",
+ errstr, optarg);
+ }
+ break;
case 'S':
Sflag = 1;
break;
case 'T':
Tflag = parse_iptos(optarg);
break;
+ case 0:
+ break;
default:
usage(1);
}
@@ -512,7 +533,7 @@ int
remote_connect(const char *host, const char *port, struct addrinfo hints)
{
struct addrinfo *res, *res0;
- int s, error;
+ int s, error, on = 1;
if ((error = getaddrinfo(host, port, &hints, &res)))
errx(1, "getaddrinfo: %s", gai_strerror(error));
@@ -533,6 +554,10 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
if (sflag || pflag) {
struct addrinfo ahints, *ares;
+#ifdef SO_BINDANY
+ /* try SO_BINDANY, but don't insist */
+ setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
+#endif
memset(&ahints, 0, sizeof(struct addrinfo));
ahints.ai_family = res0->ai_family;
ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
@@ -604,9 +629,9 @@ local_listen(char *host, char *port, struct addrinfo hints)
if (ipsec_policy[1] != NULL)
add_ipsec_policy(s, ipsec_policy[1]);
#endif
- if (Oflag) {
+ if (FreeBSD_Oflag) {
if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
- &Oflag, sizeof(Oflag)) == -1)
+ &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
err(1, "disable TCP options");
}
@@ -838,9 +863,19 @@ set_common_sockopts(int s)
&Tflag, sizeof(Tflag)) == -1)
err(1, "set IP ToS");
}
+ if (Iflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ &Iflag, sizeof(Iflag)) == -1)
+ err(1, "set TCP receive buffer size");
+ }
if (Oflag) {
- if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
&Oflag, sizeof(Oflag)) == -1)
+ err(1, "set TCP send buffer size");
+ }
+ if (FreeBSD_Oflag) {
+ if (setsockopt(s, IPPROTO_TCP, TCP_NOOPT,
+ &FreeBSD_Oflag, sizeof(FreeBSD_Oflag)) == -1)
err(1, "disable TCP options");
}
}
@@ -878,11 +913,13 @@ help(void)
#endif
fprintf(stderr, "\
\t-h This help text\n\
+ \t-I length TCP receive buffer length\n\
\t-i secs\t Delay interval for lines sent, ports scanned\n\
\t-k Keep inbound sockets open for multiple connects\n\
\t-l Listen mode, for inbound connects\n\
\t-n Suppress name/port resolutions\n\
- \t-O Disable TCP options\n\
+ \t--no-tcpopt Disable TCP options\n\
+ \t-O length TCP send buffer length\n\
\t-o Terminate on EOF on input\n\
\t-P proxyuser\tUsername for proxy authentication\n\
\t-p port\t Specify local port for remote connects\n\
@@ -931,10 +968,11 @@ void
usage(int ret)
{
#ifdef IPSEC
- fprintf(stderr, "usage: nc [-46DdEhklnOorStUuvz] [-e policy] [-i interval] [-P proxy_username] [-p source_port]\n");
+ fprintf(stderr, "usage: nc [-46DdEhklnorStUuvz] [-e policy] [-I receive_buffer_len] [-i interval]\n");
#else
- fprintf(stderr, "usage: nc [-46DdhklnOorStUuvz] [-i interval] [-P proxy_username] [-p source_port]\n");
+ fprintf(stderr, "usage: nc [-46DdhklnorStUuvz] [-I receive_buffer_len] [-i interval]\n");
#endif
+ fprintf(stderr, "\t [-O send_buffer_len] [-P proxy_username] [-p source_port]\n");
fprintf(stderr, "\t [-s source_ip_address] [-T ToS] [-w timeout] [-X proxy_protocol]\n");
fprintf(stderr, "\t [-x proxy_address[:port]] [hostname] [port[s]]\n");
if (ret)
diff --git a/etc/Makefile b/etc/Makefile
index 4fe7649..b7c8220 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -162,6 +162,7 @@ distribution:
${_+_}cd ${.CURDIR}/bluetooth; ${MAKE} install
.endif
${_+_}cd ${.CURDIR}/defaults; ${MAKE} install
+ ${_+_}cd ${.CURDIR}/devd; ${MAKE} install
${_+_}cd ${.CURDIR}/gss; ${MAKE} install
${_+_}cd ${.CURDIR}/periodic; ${MAKE} install
${_+_}cd ${.CURDIR}/rc.d; ${MAKE} install
diff --git a/etc/devd.conf b/etc/devd.conf
index 601e588..2b12af0 100644
--- a/etc/devd.conf
+++ b/etc/devd.conf
@@ -277,29 +277,6 @@ notify 0 {
action "mixer vol +10";
};
-# The next blocks enable volume hotkeys that can be found on the Asus EeePC
-# The four keys above the keyboard notify 0x1a through to 0x1d respectively
-notify 0 {
- match "system" "ACPI";
- match "subsystem" "ASUS-Eee";
- match "notify" "0x13";
- action "mixer 0";
-};
-
-notify 0 {
- match "system" "ACPI";
- match "subsystem" "ASUS-Eee";
- match "notify" "0x14";
- action "mixer vol -10";
-};
-
-notify 0 {
- match "system" "ACPI";
- match "subsystem" "ASUS-Eee";
- match "notify" "0x15";
- action "mixer vol +10";
-};
-
/* EXAMPLES TO END OF FILE
# The following might be an example of something that a vendor might
diff --git a/etc/devd/Makefile b/etc/devd/Makefile
new file mode 100644
index 0000000..f2bb184
--- /dev/null
+++ b/etc/devd/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+FILES= asus.conf
+
+NO_OBJ=
+FILESDIR= /etc/devd
+FILESMODE= 644
+
+.include <bsd.prog.mk>
diff --git a/etc/devd/asus.conf b/etc/devd/asus.conf
new file mode 100644
index 0000000..7671bd1
--- /dev/null
+++ b/etc/devd/asus.conf
@@ -0,0 +1,52 @@
+# $FreeBSD$
+#
+# ASUS specific devd events
+
+# The next blocks enable volume hotkeys that can be found on the Asus EeePC
+notify 0 {
+ match "system" "ACPI";
+ match "subsystem" "ASUS-Eee";
+ match "notify" "0x13";
+ action "mixer 0";
+};
+
+notify 0 {
+ match "system" "ACPI";
+ match "subsystem" "ASUS-Eee";
+ match "notify" "0x14";
+ action "mixer vol -10";
+};
+
+notify 0 {
+ match "system" "ACPI";
+ match "subsystem" "ASUS-Eee";
+ match "notify" "0x15";
+ action "mixer vol +10";
+};
+
+# Enable user hotkeys that can be found on the Asus EeePC
+# The four keys above the keyboard notify 0x1a through to 0x1d respectively
+#notify 0 {
+# match "system" "ACPI";
+# match "subsystem" "ASUS-Eee";
+# match "notify" "0x1a";
+# action "";
+#};
+#notify 0 {
+# match "system" "ACPI";
+# match "subsystem" "ASUS-Eee";
+# match "notify" "0x1b";
+# action "";
+#};
+#notify 0 {
+# match "system" "ACPI";
+# match "subsystem" "ASUS-Eee";
+# match "notify" "0x1c";
+# action "";
+#};
+#notify 0 {
+# match "system" "ACPI";
+# match "subsystem" "ASUS-Eee";
+# match "notify" "0x1d";
+# action "";
+#};
diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist
index 2bbd28c..ce8a456 100644
--- a/etc/mtree/BSD.root.dist
+++ b/etc/mtree/BSD.root.dist
@@ -28,6 +28,8 @@
..
defaults
..
+ devd
+ ..
gnats
..
gss
diff --git a/etc/rc.d/defaultroute b/etc/rc.d/defaultroute
index 876d682..536cb42 100755
--- a/etc/rc.d/defaultroute
+++ b/etc/rc.d/defaultroute
@@ -30,7 +30,7 @@ defaultroute_start()
defif=`get_default_if -inet`
if [ -n "${defif}" ]; then
if [ ${delay} -ne ${if_up_delay} ]; then
- echo "($defif)"
+ echo -n "($defif)"
fi
break
fi
@@ -42,6 +42,8 @@ defaultroute_start()
sleep 1
delay=`expr $delay - 1`
done
+
+ echo
}
load_rc_config $name
diff --git a/etc/regdomain.xml b/etc/regdomain.xml
index 81031aa..95e83bd 100644
--- a/etc/regdomain.xml
+++ b/etc/regdomain.xml
@@ -39,7 +39,7 @@
-->
<rd id="debug">
<name>DEBUG</name>
- <sku>0</sku>
+ <sku>0x1ff</sku>
</rd>
<rd id="fcc">
@@ -1080,6 +1080,75 @@
</band>
</netband>
</rd>
+
+<rd id="sr9">
+ <name>SR9</name>
+ <sku>0x0298</sku>
+ <defcc ref="SR9"/>
+ <netband mode="11g">
+ <band>
+ <freqband ref="S1_907_922_5"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ <band>
+ <freqband ref="S1_907_922_10"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ <band>
+ <freqband ref="S1_912_917"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ </netband>
+</rd>
+
+<rd id="xr9">
+ <name>XR9</name>
+ <sku>0x299</sku>
+ <defcc ref="XR9"/>
+ <netband mode="11g">
+ <band>
+ <freqband ref="S2_907_922_5"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ <band>
+ <freqband ref="S2_907_922_10"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ <band>
+ <freqband ref="S2_912_917"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ </netband>
+</rd>
+
+<rd id="gz901">
+ <name>GZ901</name>
+ <sku>0x29a</sku>
+ <defcc ref="GZ901"/>
+ <netband mode="11g">
+ <band>
+ <freqband ref="S1_908_923_5"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ <band>
+ <freqband ref="S1_913_918_10"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ <band>
+ <freqband ref="S1_913_918"/>
+ <maxpower>30</maxpower>
+ <flags>IEEE80211_CHAN_G</flags>
+ </band>
+ </netband>
+</rd>
</regulatory-domains>
<country-codes>
@@ -1201,6 +1270,9 @@
<country id="GT">
<isocc>320</isocc> <name>Guatemala</name> <rd ref="none"/>
</country>
+<country id="GZ901">
+ <isocc>5002</isocc> <name>ZComax GZ-901</name> <rd ref="gz901"/>
+</country>
<country id="HN">
<isocc>340</isocc> <name>Honduras</name> <rd ref="none"/>
</country>
@@ -1396,6 +1468,12 @@
<country id="TR">
<isocc>792</isocc> <name>Turkey</name> <rd ref="etsi"/>
</country>
+<country id="SR9">
+ <isocc>5000</isocc> <name>Ubiquiti SR9</name> <rd ref="sr9"/>
+</country>
+<country id="XR9">
+ <isocc>5001</isocc> <name>Ubiquiti XR9</name> <rd ref="xr9"/>
+</country>
<country id="UA">
<isocc>804</isocc> <name>Ukraine</name> <rd ref="none"/>
</country>
@@ -1426,6 +1504,10 @@
<country id="ZW">
<isocc>716</isocc> <name>Zimbabwe</name> <rd ref="none"/>
</country>
+
+<country id="DEBUG">
+ <isocc>0</isocc> <name>Debug</name> <rd ref="debug"/>
+</country>
</country-codes>
<!--
@@ -1575,6 +1657,61 @@
<freqstart>2512</freqstart> <freqend>2732</freqend>
<chanwidth>20</chanwidth> <chansep>5</chansep>
</freqband>
+
+<freqband id="S1_907_922_5">
+ <freqstart>2422</freqstart> <freqend>2437</freqend>
+ <chanwidth>5</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+ <flags>IEEE80211_CHAN_QUARTER</flags>
+</freqband>
+<freqband id="S1_907_922_10">
+ <freqstart>2422</freqstart> <freqend>2437</freqend>
+ <chanwidth>10</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+ <flags>IEEE80211_CHAN_HALF</flags>
+</freqband>
+<freqband id="S1_912_917">
+ <freqstart>2427</freqstart> <freqend>2432</freqend>
+ <chanwidth>20</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+</freqband>
+
+<freqband id="S2_907_922_5">
+ <freqstart>2427</freqstart> <freqend>2442</freqend>
+ <chanwidth>5</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+ <flags>IEEE80211_CHAN_QUARTER</flags>
+</freqband>
+<freqband id="S2_907_922_10">
+ <freqstart>2427</freqstart> <freqend>2442</freqend>
+ <chanwidth>10</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+ <flags>IEEE80211_CHAN_HALF</flags>
+</freqband>
+<freqband id="S2_912_917">
+ <freqstart>2432</freqstart> <freqend>2437</freqend>
+ <chanwidth>20</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+</freqband>
+
+<freqband id="S1_908_923_5">
+ <freqstart>2447</freqstart> <freqend>2467</freqend>
+ <chanwidth>5</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+ <flags>IEEE80211_CHAN_QUARTER</flags>
+</freqband>
+<freqband id="S1_913_918_10">
+ <freqstart>2457</freqstart> <freqend>2462</freqend>
+ <chanwidth>10</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+ <flags>IEEE80211_CHAN_HALF</flags>
+</freqband>
+<freqband id="S1_913_918">
+ <freqstart>2457</freqstart> <freqend>2462</freqend>
+ <chanwidth>20</chanwidth> <chansep>5</chansep>
+ <flags>IEEE80211_CHAN_GSM</flags>
+</freqband>
+
</shared-frequency-bands>
</regulatory-data>
diff --git a/gnu/usr.bin/groff/tmac/mdoc.local b/gnu/usr.bin/groff/tmac/mdoc.local
index 46941fc..bfcb654 100644
--- a/gnu/usr.bin/groff/tmac/mdoc.local
+++ b/gnu/usr.bin/groff/tmac/mdoc.local
@@ -69,6 +69,8 @@
.
.\" FreeBSD releases not found in doc-common
.ds doc-operating-system-FreeBSD-6.3 6.3
+.ds doc-operating-system-FreeBSD-6.4 6.4
+.ds doc-operating-system-FreeBSD-7.1 7.1
.ds doc-operating-system-FreeBSD-8.0 8.0
.
.ec
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
index b891026..ce2f2e0 100644
--- a/include/arpa/nameser.h
+++ b/include/arpa/nameser.h
@@ -49,7 +49,7 @@
*/
/*
- * $Id: nameser.h,v 1.7.18.1 2005/04/27 05:00:50 sra Exp $
+ * $Id: nameser.h,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $
* $FreeBSD$
*/
@@ -424,9 +424,10 @@ typedef enum __ns_cert_types {
#define NS_NXT_MAX 127
/*%
- * EDNS0 extended flags, host order.
+ * EDNS0 extended flags and option codes, host order.
*/
#define NS_OPT_DNSSEC_OK 0x8000U
+#define NS_OPT_NSID 3
/*%
* Inline versions of get/put short/long. Pointer is advanced.
diff --git a/include/resolv.h b/include/resolv.h
index ec18f5f..20f7954 100644
--- a/include/resolv.h
+++ b/include/resolv.h
@@ -50,7 +50,7 @@
/*%
* @(#)resolv.h 8.1 (Berkeley) 6/2/93
- * $Id: resolv.h,v 1.19.18.3 2005/08/25 04:43:51 marka Exp $
+ * $Id: resolv.h,v 1.19.18.4 2008/04/03 23:15:15 marka Exp $
* $FreeBSD$
*/
@@ -245,6 +245,7 @@ union res_sockaddr_union {
#define RES_NOCHECKNAME 0x00008000 /*%< do not check names for sanity. */
#define RES_KEEPTSIG 0x00010000 /*%< do not strip TSIG records */
#define RES_BLAST 0x00020000 /*%< blast all recursive servers */
+#define RES_NSID 0x00040000 /*%< request name server ID */
#define RES_NOTLDQUERY 0x00100000 /*%< don't unqualified name as a tld */
#define RES_USE_DNSSEC 0x00200000 /*%< use DNSSEC using OK bit in OPT */
/* #define RES_DEBUG2 0x00400000 */ /* nslookup internal */
@@ -386,6 +387,7 @@ extern const struct res_sym __p_rcode_syms[];
#define sym_ntos __sym_ntos
#define sym_ston __sym_ston
#define res_nopt __res_nopt
+#define res_nopt_rdata __res_nopt_rdata
#define res_ndestroy __res_ndestroy
#define res_nametoclass __res_nametoclass
#define res_nametotype __res_nametotype
@@ -474,6 +476,8 @@ int res_findzonecut2(res_state, const char *, ns_class, int,
union res_sockaddr_union *, int);
void res_nclose(res_state);
int res_nopt(res_state, int, u_char *, int, int);
+int res_nopt_rdata(res_state, int, u_char *, int, u_char *,
+ u_short, u_short, u_char *);
void res_send_setqhook(res_send_qhook);
void res_send_setrhook(res_send_rhook);
int __res_vinit(res_state, int);
diff --git a/lib/libarchive/archive_read_support_format_ar.c b/lib/libarchive/archive_read_support_format_ar.c
index 7f3588c..fed979d 100644
--- a/lib/libarchive/archive_read_support_format_ar.c
+++ b/lib/libarchive/archive_read_support_format_ar.c
@@ -192,7 +192,7 @@ archive_read_format_ar_read_header(struct archive_read *a,
/* Verify the magic signature on the file header. */
if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) {
archive_set_error(&a->archive, EINVAL,
- "Consistency check failed");
+ "Incorrect file header signature");
return (ARCHIVE_WARN);
}
diff --git a/lib/libarchive/test/main.c b/lib/libarchive/test/main.c
index 1de2532..81a0b3a 100644
--- a/lib/libarchive/test/main.c
+++ b/lib/libarchive/test/main.c
@@ -897,7 +897,7 @@ int main(int argc, char **argv)
time_t now;
char *refdir_alloc = NULL;
char *progname, *p;
- char *tmp;
+ const char *tmp;
char tmpdir[256];
char tmpdir_timestamp[256];
diff --git a/lib/libarchive/test/test_compat_gtar.c b/lib/libarchive/test/test_compat_gtar.c
index a083855..bf9817b 100644
--- a/lib/libarchive/test/test_compat_gtar.c
+++ b/lib/libarchive/test/test_compat_gtar.c
@@ -43,6 +43,7 @@ test_compat_gtar_1(void)
char name[] = "test_compat_gtar_1.tgz";
struct archive_entry *ae;
struct archive *a;
+ int r;
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
@@ -51,7 +52,11 @@ test_compat_gtar_1(void)
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240));
/* Read first entry. */
- assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
+ if (r != ARCHIVE_OK) {
+ archive_read_finish(a);
+ return;
+ }
assertEqualString(
"12345678901234567890123456789012345678901234567890"
"12345678901234567890123456789012345678901234567890"
@@ -66,7 +71,11 @@ test_compat_gtar_1(void)
assertEqualInt(0100644, archive_entry_mode(ae));
/* Read second entry. */
- assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_OK, r = archive_read_next_header(a, &ae));
+ if (r != ARCHIVE_OK) {
+ archive_read_finish(a);
+ return;
+ }
assertEqualString(
"abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
"abcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
diff --git a/lib/libarchive/test/test_write_compress.c b/lib/libarchive/test/test_write_compress.c
index a133690..4dc51b8 100644
--- a/lib/libarchive/test/test_write_compress.c
+++ b/lib/libarchive/test/test_write_compress.c
@@ -85,11 +85,11 @@ DEFINE_TEST(test_write_compress)
for (i = 0; i < 100; i++) {
sprintf(path, "file%03d", i);
- assertEqualInt(0, archive_read_next_header(a, &ae));
+ if (!assertEqualInt(0, archive_read_next_header(a, &ae)))
+ break;
assertEqualString(path, archive_entry_pathname(ae));
assertEqualInt(datasize, archive_entry_size(ae));
}
-
assert(0 == archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
archive_read_finish(a);
diff --git a/lib/libarchive/test/test_write_format_ar.c b/lib/libarchive/test/test_write_format_ar.c
index 19a1327..6f54139 100644
--- a/lib/libarchive/test/test_write_format_ar.c
+++ b/lib/libarchive/test/test_write_format_ar.c
@@ -73,8 +73,8 @@ DEFINE_TEST(test_write_format_ar)
archive_entry_copy_pathname(ae, "ggghhhjjjrrrttt.o");
archive_entry_set_filetype(ae, AE_IFREG);
archive_entry_set_size(ae, 7);
- assertA(0 == archive_write_header(a, ae));
- assertA(7 == archive_write_data(a, "7777777", 7));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ assertEqualIntA(a, 7, archive_write_data(a, "7777777", 7));
archive_entry_free(ae);
/* test full pathname */
@@ -82,8 +82,8 @@ DEFINE_TEST(test_write_format_ar)
archive_entry_copy_pathname(ae, "/usr/home/xx/iiijjjdddsssppp.o");
archive_entry_set_mode(ae, S_IFREG | 0755);
archive_entry_set_size(ae, 8);
- assertA(0 == archive_write_header(a, ae));
- assertA(8 == archive_write_data(a, "88877766", 8));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ assertEqualIntA(a, 8, archive_write_data(a, "88877766", 8));
archive_entry_free(ae);
/* trailing "/" should be rejected */
@@ -105,46 +105,46 @@ DEFINE_TEST(test_write_format_ar)
#if ARCHIVE_VERSION_NUMBER < 2000000
archive_write_finish(a);
#else
- assert(0 == archive_write_finish(a));
+ assertEqualInt(0, archive_write_finish(a));
#endif
/*
* Now, read the data back.
*/
assert((a = archive_read_new()) != NULL);
- assertA(0 == archive_read_support_format_all(a));
- assertA(0 == archive_read_support_compression_all(a));
- assertA(0 == archive_read_open_memory(a, buff, used));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));
- assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualInt(0, archive_entry_mtime(ae));
assertEqualString("//", archive_entry_pathname(ae));
assertEqualInt(0, archive_entry_size(ae));
- assertA(0 == archive_read_next_header(a, &ae));
- assert(1 == archive_entry_mtime(ae));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualInt(1, archive_entry_mtime(ae));
assertEqualString("abcdefghijklmn.o", archive_entry_pathname(ae));
- assert(8 == archive_entry_size(ae));
- assertA(8 == archive_read_data(a, buff2, 10));
- assert(0 == memcmp(buff2, "87654321", 8));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "87654321", 8);
- assert(0 == archive_read_next_header(a, &ae));
+ assertEqualInt(ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString("ggghhhjjjrrrttt.o", archive_entry_pathname(ae));
- assert(7 == archive_entry_size(ae));
- assertA(7 == archive_read_data(a, buff2, 11));
- assert(0 == memcmp(buff2, "7777777", 7));
+ assertEqualInt(7, archive_entry_size(ae));
+ assertEqualIntA(a, 7, archive_read_data(a, buff2, 11));
+ assertEqualMem(buff2, "7777777", 7);
- assert(0 == archive_read_next_header(a, &ae));
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualString("iiijjjdddsssppp.o", archive_entry_pathname(ae));
- assert(8 == archive_entry_size(ae));
- assertA(8 == archive_read_data(a, buff2, 17));
- assert(0 == memcmp(buff2, "88877766", 8));
+ assertEqualInt(8, archive_entry_size(ae));
+ assertEqualIntA(a, 8, archive_read_data(a, buff2, 17));
+ assertEqualMem(buff2, "88877766", 8);
- assert(0 == archive_read_close(a));
+ assertEqualIntA(a, 0, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
archive_read_finish(a);
#else
- assert(0 == archive_read_finish(a));
+ assertEqualInt(0, archive_read_finish(a));
#endif
/*
@@ -152,18 +152,18 @@ DEFINE_TEST(test_write_format_ar)
*/
memset(buff, 0, sizeof(buff));
assert((a = archive_write_new()) != NULL);
- assertA(0 == archive_write_set_format_ar_bsd(a));
- assertA(0 == archive_write_set_compression_bzip2(a));
- assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ar_bsd(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_set_compression_bzip2(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff), &used));
/* write a entry need long name extension */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "ttttyyyyuuuuiiii.o");
archive_entry_set_filetype(ae, AE_IFREG);
archive_entry_set_size(ae, 5);
- assertA(0 == archive_write_header(a, ae));
- assertA(5 == archive_entry_size(ae));
- assertA(5 == archive_write_data(a, "12345", 7));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ assertEqualInt(5, archive_entry_size(ae));
+ assertEqualIntA(a, 5, archive_write_data(a, "12345", 7));
archive_entry_free(ae);
/* write a entry with a short name */
@@ -171,41 +171,41 @@ DEFINE_TEST(test_write_format_ar)
archive_entry_copy_pathname(ae, "ttyy.o");
archive_entry_set_filetype(ae, AE_IFREG);
archive_entry_set_size(ae, 6);
- assertA(0 == archive_write_header(a, ae));
- assertA(6 == archive_write_data(a, "555555", 7));
+ assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
+ assertEqualIntA(a, 6, archive_write_data(a, "555555", 7));
archive_entry_free(ae);
archive_write_close(a);
#if ARCHIVE_VERSION_NUMBER < 2000000
archive_write_finish(a);
#else
- assert(0 == archive_write_finish(a));
+ assertEqualInt(0, archive_write_finish(a));
#endif
/* Now, Read the data back */
assert((a = archive_read_new()) != NULL);
- assertA(0 == archive_read_support_format_all(a));
- assertA(0 == archive_read_support_compression_all(a));
- assertA(0 == archive_read_open_memory(a, buff, used));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_compression_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used));
assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualString("ttttyyyyuuuuiiii.o", archive_entry_pathname(ae));
assertEqualInt(5, archive_entry_size(ae));
- assertA(5 == archive_read_data(a, buff2, 10));
- assert(0 == memcmp(buff2, "12345", 5));
+ assertEqualIntA(a, 5, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "12345", 5);
- assert(0 == archive_read_next_header(a, &ae));
+ assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
assertEqualString("ttyy.o", archive_entry_pathname(ae));
- assert(6 == archive_entry_size(ae));
- assertA(6 == archive_read_data(a, buff2, 10));
- assert(0 == memcmp(buff2, "555555", 6));
+ assertEqualInt(6, archive_entry_size(ae));
+ assertEqualIntA(a, 6, archive_read_data(a, buff2, 10));
+ assertEqualMem(buff2, "555555", 6);
/* Test EOF */
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
- assert(0 == archive_read_close(a));
+ assertEqualIntA(a, 0, archive_read_close(a));
#if ARCHIVE_VERSION_NUMBER < 2000000
archive_read_finish(a);
#else
- assert(0 == archive_read_finish(a));
+ assertEqualInt(0, archive_read_finish(a));
#endif
#endif
}
diff --git a/lib/libc/include/isc/eventlib.h b/lib/libc/include/isc/eventlib.h
index 598c71c..5003823 100644
--- a/lib/libc/include/isc/eventlib.h
+++ b/lib/libc/include/isc/eventlib.h
@@ -18,7 +18,7 @@
/* eventlib.h - exported interfaces for eventlib
* vix 09sep95 [initial]
*
- * $Id: eventlib.h,v 1.3.18.2 2005/07/28 07:38:07 marka Exp $
+ * $Id: eventlib.h,v 1.3.18.3 2008/01/23 02:12:01 marka Exp $
*/
#ifndef _EVENTLIB_H
@@ -29,6 +29,8 @@
#include <sys/time.h>
#include <stdio.h>
+#include <isc/platform.h>
+
#ifndef __P
# define __EVENTLIB_P_DEFINED
# ifdef __STDC__
diff --git a/lib/libc/include/isc/platform.h b/lib/libc/include/isc/platform.h
new file mode 100644
index 0000000..a0513be
--- /dev/null
+++ b/lib/libc/include/isc/platform.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: platform.h.in,v 1.2.6.2 2008/01/23 02:15:02 tbox Exp $ */
+/* $FreeBSD$ */
+
+/*! \file */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H
+
+/*
+ * Define if the OS does not define struct timespec.
+ */
+#undef ISC_PLATFORM_NEEDTIMESPEC
+#ifdef ISC_PLATFORM_NEEDTIMESPEC
+#include <time.h> /* For time_t */
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+#endif
+
+#endif
diff --git a/lib/libc/inet/inet_net_pton.c b/lib/libc/inet/inet_net_pton.c
index 06d1da9..74df38b9 100644
--- a/lib/libc/inet/inet_net_pton.c
+++ b/lib/libc/inet/inet_net_pton.c
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.1 2005/04/27 05:00:53 sra Exp $";
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -135,11 +135,11 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
assert(n >= 0 && n <= 9);
bits *= 10;
bits += n;
+ if (bits > 32)
+ goto enoent;
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
if (ch != '\0')
goto enoent;
- if (bits > 32)
- goto emsgsize;
}
/* Firey death and destruction unless we prefetched EOS. */
diff --git a/lib/libc/net/rcmd.3 b/lib/libc/net/rcmd.3
index e0643db..a7d2f8b 100644
--- a/lib/libc/net/rcmd.3
+++ b/lib/libc/net/rcmd.3
@@ -238,6 +238,13 @@ For
.Fn rcmd_af ,
.Dv PF_UNSPEC
is also allowed.
+.Sh ENVIRONMENT
+.Bl -tag -width RSH
+.It Ev RSH
+When using the
+.Fn rcmd
+function, this variable is used as the program to run instead of
+.Xr rsh 1 .
.Sh DIAGNOSTICS
The
.Fn rcmd
diff --git a/lib/libc/resolv/res_debug.c b/lib/libc/resolv/res_debug.c
index a367a61..c2707bb 100644
--- a/lib/libc/resolv/res_debug.c
+++ b/lib/libc/resolv/res_debug.c
@@ -91,7 +91,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_debug.c,v 1.10.18.5 2005/07/28 07:38:11 marka Exp $";
+static const char rcsid[] = "$Id: res_debug.c,v 1.10.18.6 2008/04/03 23:15:15 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -187,10 +187,56 @@ do_section(const res_state statp,
p_type(ns_rr_type(rr)),
p_class(ns_rr_class(rr)));
else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
+ u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr);
u_int32_t ttl = ns_rr_ttl(rr);
+
fprintf(file,
"; EDNS: version: %u, udp=%u, flags=%04x\n",
(ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
+
+ while (rdatalen >= 4) {
+ const u_char *cp = ns_rr_rdata(rr);
+ int i;
+
+ GETSHORT(optcode, cp);
+ GETSHORT(optlen, cp);
+
+ if (optcode == NS_OPT_NSID) {
+ fputs("; NSID: ", file);
+ if (optlen == 0) {
+ fputs("; NSID\n", file);
+ } else {
+ fputs("; NSID: ", file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i])?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ } else {
+ if (optlen == 0) {
+ fprintf(file, "; OPT=%u\n",
+ optcode);
+ } else {
+ fprintf(file, "; OPT=%u: ",
+ optcode);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i]) ?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ }
+ rdatalen -= 4 + optlen;
+ }
} else {
n = ns_sprintrr(handle, &rr, NULL, NULL,
buf, buflen);
@@ -202,7 +248,7 @@ do_section(const res_state statp,
buf = malloc(buflen += 1024);
if (buf == NULL) {
fprintf(file,
- ";; memory allocation failure\n");
+ ";; memory allocation failure\n");
return;
}
continue;
@@ -379,7 +425,7 @@ static const struct res_sym __p_default_section_syms[] = {
{ns_s_an, "ANSWER", (char *)0},
{ns_s_ns, "AUTHORITY", (char *)0},
{ns_s_ar, "ADDITIONAL", (char *)0},
- {0, (char *)0, (char *)0}
+ {0, (char *)0, (char *)0}
};
static const struct res_sym __p_update_section_syms[] = {
@@ -387,7 +433,7 @@ static const struct res_sym __p_update_section_syms[] = {
{S_PREREQ, "PREREQUISITE", (char *)0},
{S_UPDATE, "UPDATE", (char *)0},
{S_ADDT, "ADDITIONAL", (char *)0},
- {0, (char *)0, (char *)0}
+ {0, (char *)0, (char *)0}
};
const struct res_sym __p_key_syms[] = {
@@ -615,6 +661,7 @@ p_option(u_long option) {
case RES_USE_INET6: return "inet6";
#ifdef RES_USE_EDNS0 /*%< KAME extension */
case RES_USE_EDNS0: return "edns0";
+ case RES_NSID: return "nsid";
#endif
#ifdef RES_USE_DNAME
case RES_USE_DNAME: return "dname";
diff --git a/lib/libc/resolv/res_mkquery.c b/lib/libc/resolv/res_mkquery.c
index f823026..7bd9cda 100644
--- a/lib/libc/resolv/res_mkquery.c
+++ b/lib/libc/resolv/res_mkquery.c
@@ -66,7 +66,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_mkquery.c,v 1.5.18.1 2005/04/27 05:01:11 sra Exp $";
+static const char rcsid[] = "$Id: res_mkquery.c,v 1.5.18.2 2008/04/03 23:15:15 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -201,9 +201,6 @@ res_nmkquery(res_state statp,
#ifdef RES_USE_EDNS0
/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
-#ifndef T_OPT
-#define T_OPT 41
-#endif
int
res_nopt(res_state statp,
@@ -228,15 +225,16 @@ res_nopt(res_state statp,
if ((ep - cp) < 1 + RRFIXEDSZ)
return (-1);
- *cp++ = 0; /*%< "." */
- ns_put16(T_OPT, cp); /*%< TYPE */
+ *cp++ = 0; /*%< "." */
+ ns_put16(ns_t_opt, cp); /*%< TYPE */
cp += INT16SZ;
if (anslen > 0xffff)
anslen = 0xffff; /* limit to 16bit value */
- ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
+ ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
cp += INT16SZ;
- *cp++ = NOERROR; /*%< extended RCODE */
- *cp++ = 0; /*%< EDNS version */
+ *cp++ = NOERROR; /*%< extended RCODE */
+ *cp++ = 0; /*%< EDNS version */
+
if (statp->options & RES_USE_DNSSEC) {
#ifdef DEBUG
if (statp->options & RES_DEBUG)
@@ -246,12 +244,60 @@ res_nopt(res_state statp,
}
ns_put16(flags, cp);
cp += INT16SZ;
- ns_put16(0, cp); /*%< RDLEN */
+
+ ns_put16(0U, cp); /*%< RDLEN */
cp += INT16SZ;
+
hp->arcount = htons(ntohs(hp->arcount) + 1);
return (cp - buf);
}
+
+/*
+ * Construct variable data (RDATA) block for OPT psuedo-RR, append it
+ * to the buffer, then update the RDLEN field (previously set to zero by
+ * res_nopt()) with the new RDATA length.
+ */
+int
+res_nopt_rdata(res_state statp,
+ int n0, /*%< current offset in buffer */
+ u_char *buf, /*%< buffer to put query */
+ int buflen, /*%< size of buffer */
+ u_char *rdata, /*%< ptr to start of opt rdata */
+ u_short code, /*%< OPTION-CODE */
+ u_short len, /*%< OPTION-LENGTH */
+ u_char *data) /*%< OPTION_DATA */
+{
+ register u_char *cp, *ep;
+
+#ifdef DEBUG
+ if ((statp->options & RES_DEBUG) != 0U)
+ printf(";; res_nopt_rdata()\n");
+#endif
+
+ cp = buf + n0;
+ ep = buf + buflen;
+
+ if ((ep - cp) < (4 + len))
+ return (-1);
+
+ if (rdata < (buf + 2) || rdata >= ep)
+ return (-1);
+
+ ns_put16(code, cp);
+ cp += INT16SZ;
+
+ ns_put16(len, cp);
+ cp += INT16SZ;
+
+ memcpy(cp, data, len);
+ cp += len;
+
+ len = cp - rdata;
+ ns_put16(len, rdata - 2); /* Update RDLEN field */
+
+ return (cp - buf);
+}
#endif
/*! \file */
diff --git a/lib/libc/resolv/res_query.c b/lib/libc/resolv/res_query.c
index 3813291..746a2be 100644
--- a/lib/libc/resolv/res_query.c
+++ b/lib/libc/resolv/res_query.c
@@ -66,7 +66,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_query.c,v 1.7.18.1 2005/04/27 05:01:11 sra Exp $";
+static const char rcsid[] = "$Id: res_query.c,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -115,8 +115,9 @@ res_nquery(res_state statp,
{
u_char buf[MAXPACKET];
HEADER *hp = (HEADER *) answer;
- int n;
u_int oflags;
+ u_char *rdata;
+ int n;
oflags = statp->_flags;
@@ -131,8 +132,14 @@ again:
buf, sizeof(buf));
#ifdef RES_USE_EDNS0
if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
- (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
+ (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) {
n = res_nopt(statp, n, buf, sizeof(buf), anslen);
+ rdata = &buf[n];
+ if (n > 0 && (statp->options & RES_NSID) != 0U) {
+ n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata,
+ NS_OPT_NSID, 0, NULL);
+ }
+ }
#endif
if (n <= 0) {
#ifdef DEBUG
@@ -142,6 +149,7 @@ again:
RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (n);
}
+
n = res_nsend(statp, buf, n, answer, anslen);
if (n < 0) {
#ifdef RES_USE_EDNS0
diff --git a/lib/libc/resolv/res_send.c b/lib/libc/resolv/res_send.c
index 78410d1..d4f0c33 100644
--- a/lib/libc/resolv/res_send.c
+++ b/lib/libc/resolv/res_send.c
@@ -66,7 +66,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_send.c,v 1.9.18.8 2006/10/16 23:00:58 marka Exp $";
+static const char rcsid[] = "$Id: res_send.c,v 1.9.18.10 2008/01/27 02:06:26 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -302,7 +302,7 @@ int
res_nsend(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz)
{
- int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+ int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
#ifdef USE_KQUEUE
int kq;
#endif
@@ -420,7 +420,7 @@ res_nsend(res_state statp,
/*
* Send request, RETRY times, or until successful.
*/
- for (try = 0; try < statp->retry; try++) {
+ for (tries = 0; tries < statp->retry; tries++) {
for (ns = 0; ns < statp->nscount; ns++) {
struct sockaddr *nsap;
int nsaplen;
@@ -471,7 +471,7 @@ res_nsend(res_state statp,
if (v_circuit) {
/* Use VC; at most one attempt per server. */
- try = statp->retry;
+ tries = statp->retry;
n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
ns);
if (n < 0)
@@ -486,7 +486,7 @@ res_nsend(res_state statp,
kq,
#endif
buf, buflen, ans, anssiz, &terrno,
- ns, try, &v_circuit, &gotsomewhere);
+ ns, tries, &v_circuit, &gotsomewhere);
if (n < 0)
goto fail;
if (n == 0)
@@ -632,6 +632,9 @@ send_vc(res_state statp,
u_short len;
u_char *cp;
void *tmp;
+#ifdef SO_NOSIGPIPE
+ int on = 1;
+#endif
nsap = get_nsaddr(statp, ns);
nsaplen = get_salen(nsap);
@@ -679,6 +682,17 @@ send_vc(res_state statp,
return (-1);
}
}
+#ifdef SO_NOSIGPIPE
+ /*
+ * Disable generation of SIGPIPE when writing to a closed
+ * socket. Write should return -1 and set errno to EPIPE
+ * instead.
+ *
+ * Push on even if setsockopt(SO_NOSIGPIPE) fails.
+ */
+ (void)_setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
+ sizeof(on));
+#endif
errno = 0;
if (_connect(statp->_vcsock, nsap, nsaplen) < 0) {
*terrno = errno;
@@ -811,7 +825,7 @@ send_dg(res_state statp,
int kq,
#endif
const u_char *buf, int buflen, u_char *ans,
- int anssiz, int *terrno, int ns, int try, int *v_circuit,
+ int anssiz, int *terrno, int ns, int tries, int *v_circuit,
int *gotsomewhere)
{
const HEADER *hp = (const HEADER *) buf;
@@ -915,7 +929,7 @@ send_dg(res_state statp,
/*
* Wait for reply.
*/
- seconds = (statp->retrans << try);
+ seconds = (statp->retrans << tries);
if (ns > 0)
seconds /= statp->nscount;
if (seconds <= 0)
diff --git a/lib/libfetch/fetch.3 b/lib/libfetch/fetch.3
index 81b7164..9b312b0 100644
--- a/lib/libfetch/fetch.3
+++ b/lib/libfetch/fetch.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 18, 2007
+.Dd December 14, 2008
.Dt FETCH 3
.Os
.Sh NAME
@@ -165,9 +165,16 @@ struct url {
char *doc;
off_t offset;
size_t length;
+ time_t ims_time;
};
.Ed
.Pp
+The
+.Va ims_time
+field stores the time value for
+.Li If-Modified-Since
+HTTP requests.
+.Pp
The pointer returned by
.Fn fetchMakeURL
or
@@ -353,6 +360,22 @@ and
.Fn fetchPutHTTP
will use a direct connection even if a proxy server is defined.
.Pp
+If the
+.Ql i
+(if-modified-since) flag is specified, and
+the
+.Va ims_time
+field is set in
+.Vt "struct url" ,
+then
+.Fn fetchXGetHTTP
+and
+.Fn fetchGetHTTP
+will send a conditional
+.Li If-Modified-Since
+HTTP header to only fetch the content if it is newer than
+.Va ims_time .
+.Pp
Since there seems to be no good way of implementing the HTTP PUT
method in a manner consistent with the rest of the
.Nm fetch
diff --git a/lib/libfetch/fetch.c b/lib/libfetch/fetch.c
index 6c4901f..5044fe3 100644
--- a/lib/libfetch/fetch.c
+++ b/lib/libfetch/fetch.c
@@ -74,9 +74,7 @@ static struct fetcherr url_errlist[] = {
FILE *
fetchXGet(struct url *URL, struct url_stat *us, const char *flags)
{
- int direct;
- direct = CHECK_FLAG('d');
if (us != NULL) {
us->size = -1;
us->atime = us->mtime = 0;
@@ -110,9 +108,7 @@ fetchGet(struct url *URL, const char *flags)
FILE *
fetchPut(struct url *URL, const char *flags)
{
- int direct;
- direct = CHECK_FLAG('d');
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
return (fetchPutFile(URL, flags));
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
@@ -132,9 +128,7 @@ fetchPut(struct url *URL, const char *flags)
int
fetchStat(struct url *URL, struct url_stat *us, const char *flags)
{
- int direct;
- direct = CHECK_FLAG('d');
if (us != NULL) {
us->size = -1;
us->atime = us->mtime = 0;
@@ -158,9 +152,7 @@ fetchStat(struct url *URL, struct url_stat *us, const char *flags)
struct url_ent *
fetchList(struct url *URL, const char *flags)
{
- int direct;
- direct = CHECK_FLAG('d');
if (strcasecmp(URL->scheme, SCHEME_FILE) == 0)
return (fetchListFile(URL, flags));
else if (strcasecmp(URL->scheme, SCHEME_FTP) == 0)
diff --git a/lib/libfetch/fetch.h b/lib/libfetch/fetch.h
index 10d911a..e620a01 100644
--- a/lib/libfetch/fetch.h
+++ b/lib/libfetch/fetch.h
@@ -46,6 +46,7 @@ struct url {
char *doc;
off_t offset;
size_t length;
+ time_t ims_time;
};
struct url_stat {
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index 39a8cfaa..dd98349 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/socket.h>
+#include <sys/time.h>
#include <ctype.h>
#include <err.h>
@@ -92,6 +93,7 @@ __FBSDID("$FreeBSD$");
#define HTTP_MOVED_PERM 301
#define HTTP_MOVED_TEMP 302
#define HTTP_SEE_OTHER 303
+#define HTTP_NOT_MODIFIED 304
#define HTTP_TEMP_REDIRECT 307
#define HTTP_NEED_AUTH 401
#define HTTP_NEED_PROXY_AUTH 407
@@ -797,20 +799,23 @@ FILE *
http_request(struct url *URL, const char *op, struct url_stat *us,
struct url *purl, const char *flags)
{
+ char timebuf[80];
+ char hbuf[MAXHOSTNAMELEN + 7], *host;
conn_t *conn;
struct url *url, *new;
- int chunked, direct, need_auth, noredirect, verbose;
+ int chunked, direct, ims, need_auth, noredirect, verbose;
int e, i, n, val;
off_t offset, clength, length, size;
time_t mtime;
const char *p;
FILE *f;
hdr_t h;
- char hbuf[MAXHOSTNAMELEN + 7], *host;
+ struct tm *timestruct;
direct = CHECK_FLAG('d');
noredirect = CHECK_FLAG('A');
verbose = CHECK_FLAG('v');
+ ims = CHECK_FLAG('i');
if (direct && purl) {
fetchFreeURL(purl);
@@ -879,6 +884,14 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
op, url->doc);
}
+ if (ims && url->ims_time) {
+ timestruct = gmtime((time_t *)&url->ims_time);
+ (void)strftime(timebuf, 80, "%a, %d %b %Y %T GMT",
+ timestruct);
+ if (verbose)
+ fetch_info("If-Modified-Since: %s", timebuf);
+ http_cmd(conn, "If-Modified-Since: %s", timebuf);
+ }
/* virtual host */
http_cmd(conn, "Host: %s", host);
@@ -940,6 +953,7 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
switch (http_get_reply(conn)) {
case HTTP_OK:
case HTTP_PARTIAL:
+ case HTTP_NOT_MODIFIED:
/* fine */
break;
case HTTP_MOVED_PERM:
@@ -1074,7 +1088,10 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
}
/* we have a hit or an error */
- if (conn->err == HTTP_OK || conn->err == HTTP_PARTIAL || HTTP_ERROR(conn->err))
+ if (conn->err == HTTP_OK
+ || conn->err == HTTP_NOT_MODIFIED
+ || conn->err == HTTP_PARTIAL
+ || HTTP_ERROR(conn->err))
break;
/* all other cases: we got a redirect */
@@ -1102,6 +1119,11 @@ http_request(struct url *URL, const char *op, struct url_stat *us,
(long long)offset, (long long)length,
(long long)size, (long long)clength));
+ if (conn->err == HTTP_NOT_MODIFIED) {
+ http_seterr(HTTP_NOT_MODIFIED);
+ return (NULL);
+ }
+
/* check for inconsistencies */
if (clength != -1 && length != -1 && clength != length) {
http_seterr(HTTP_PROTOCOL_ERROR);
diff --git a/lib/libstand/if_ether.h b/lib/libstand/if_ether.h
index 7783c41..373f95a 100644
--- a/lib/libstand/if_ether.h
+++ b/lib/libstand/if_ether.h
@@ -156,7 +156,7 @@ struct ifqueue arpintrq;
void arpwhohas(struct arpcom *, struct in_addr *);
void arpintr(void);
int arpresolve(struct arpcom *,
- struct rtentry *, struct mbuf *, struct sockaddr *, u_char *);
+ struct rtentry *, struct mbuf *, struct sockaddr *, u_char *, struct llentry **);
void arp_ifinit(struct arpcom *, struct ifaddr *);
void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
@@ -233,7 +233,7 @@ struct ether_multistep {
#ifdef _KERNEL
void arp_rtrequest(int, struct rtentry *, struct sockaddr *);
int arpresolve(struct arpcom *, struct rtentry *, struct mbuf *,
- struct sockaddr *, u_char *);
+ struct sockaddr *, u_char *, struct llentry **);
void arpintr(void);
int arpioctl(u_long, caddr_t);
void arp_ifinit(struct arpcom *, struct ifaddr *);
diff --git a/lib/libutil/kinfo_getfile.c b/lib/libutil/kinfo_getfile.c
index ca0f832..7a7a09e 100644
--- a/lib/libutil/kinfo_getfile.c
+++ b/lib/libutil/kinfo_getfile.c
@@ -19,6 +19,7 @@ kinfo_getfile(pid_t pid, int *cntp)
char *buf, *bp, *eb;
struct kinfo_file *kif, *kp, *kf;
+ *cntp = 0;
len = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
@@ -27,15 +28,15 @@ kinfo_getfile(pid_t pid, int *cntp)
error = sysctl(mib, 4, NULL, &len, NULL, 0);
if (error)
- return (0);
+ return (NULL);
len = len * 4 / 3;
buf = malloc(len);
if (buf == NULL)
- return (0);
+ return (NULL);
error = sysctl(mib, 4, buf, &len, NULL, 0);
if (error) {
free(buf);
- return (0);
+ return (NULL);
}
/* Pass 1: count items */
cnt = 0;
@@ -50,7 +51,7 @@ kinfo_getfile(pid_t pid, int *cntp)
kif = calloc(cnt, sizeof(*kif));
if (kif == NULL) {
free(buf);
- return (0);
+ return (NULL);
}
bp = buf;
eb = buf + len;
diff --git a/lib/libutil/kinfo_getvmmap.c b/lib/libutil/kinfo_getvmmap.c
index 5436108..559182e 100644
--- a/lib/libutil/kinfo_getvmmap.c
+++ b/lib/libutil/kinfo_getvmmap.c
@@ -19,6 +19,7 @@ kinfo_getvmmap(pid_t pid, int *cntp)
char *buf, *bp, *eb;
struct kinfo_vmentry *kiv, *kp, *kv;
+ *cntp = 0;
len = 0;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
@@ -27,15 +28,15 @@ kinfo_getvmmap(pid_t pid, int *cntp)
error = sysctl(mib, 4, NULL, &len, NULL, 0);
if (error)
- return (0);
+ return (NULL);
len = len * 4 / 3;
buf = malloc(len);
if (buf == NULL)
- return (0);
+ return (NULL);
error = sysctl(mib, 4, buf, &len, NULL, 0);
if (error) {
free(buf);
- return (0);
+ return (NULL);
}
/* Pass 1: count items */
cnt = 0;
@@ -50,7 +51,7 @@ kinfo_getvmmap(pid_t pid, int *cntp)
kiv = calloc(cnt, sizeof(*kiv));
if (kiv == NULL) {
free(buf);
- return (0);
+ return (NULL);
}
bp = buf;
eb = buf + len;
diff --git a/libexec/bootpd/rtmsg.c b/libexec/bootpd/rtmsg.c
index 4584569..071a7d1 100644
--- a/libexec/bootpd/rtmsg.c
+++ b/libexec/bootpd/rtmsg.c
@@ -152,7 +152,6 @@ tryagain:
sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
if (sdl->sdl_family == AF_LINK &&
- (rtm->rtm_flags & RTF_LLINFO) &&
!(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
case IFT_ISO88024: case IFT_ISO88025:
diff --git a/release/doc/en_US.ISO8859-1/hardware/article.sgml b/release/doc/en_US.ISO8859-1/hardware/article.sgml
index 05b0b77..d855fd0 100644
--- a/release/doc/en_US.ISO8859-1/hardware/article.sgml
+++ b/release/doc/en_US.ISO8859-1/hardware/article.sgml
@@ -90,22 +90,40 @@
</listitem>
<listitem>
- <para>&intel; 64-bit &xeon; (<quote>Nocona</quote>). This
- processor is fabricated on 90nm process technology, and
- operates with 2.80 to 3.60 GHz (FSB 800MHz) and &intel;
- E7520/E7525/E7320 chipsets.</para>
+ <para>All multi-core &intel; &xeon; processors except
+ Sossaman have EM64T support.</para>
</listitem>
<listitem>
- <para>&intel; &pentium; 4 Processor supporting &intel; EM64T
- (<quote>Prescott</quote>). This is fabricated on 90nm
- process technology, uses FC-LGA775 package, and operates
- with 3.20F/3.40F/3.60F GHz and &intel; 925X Express
- chipsets. The corresponding S-Spec numbers are SL7L9,
- SL7L8, SL7LA, SL7NZ, SL7PZ, and SL7PX. Note that
- processors marked as 5xx numbers do not support
- EM64T.</para>
+ <para>The single-core &intel; &xeon;
+ processors <quote>Nocona</quote>, <quote>Irwindale</quote>,
+ <quote>Potomac</quote>, and <quote>Cranford</quote> have
+ EM64T support.</para>
</listitem>
+
+ <listitem>
+ <para>All &intel; Core 2 (not Core Duo) and later
+ processors</para>
+ </listitem>
+
+ <listitem>
+ <para>All &intel; &pentium; D processors</para>
+ </listitem>
+
+ <listitem>
+ <para>&intel; &pentium; 4s and Celeron Ds using
+ the <quote>Cedar Mill</quote> core have EM64T
+ support.</para>
+ </listitem>
+
+ <listitem>
+ <para>Some &intel; &pentium; 4s and Celeron Ds using
+ the <quote>Prescott</quote> core have EM64T support. See
+ the <ulink url="http://processorfinder.intel.com">Intel
+ Processor Spec Finder</ulink> for the definitive answer about
+ EM64T support in Intel processors.</para>
+ </listitem>
+
</itemizedlist>
<para>&intel; EM64T is an extended version of IA-32 (x86) and
@@ -114,7 +132,7 @@
to &intel; EM64T as <quote>64-bit extension technology</quote>
or <quote>IA-32e</quote>.</para>
- <para>The largest tested memory configuration to date is 8GB.
+ <para>The largest tested memory configuration to date is 64GB.
SMP support has been recently completed and is reasonably
robust.</para>
@@ -760,7 +778,7 @@
&hwlist.tl;
- <para>[&arch.amd64;, &arch.i386, &arch.pc98;] SMC 83c17x
+ <para>[&arch.amd64;, &arch.i386;, &arch.pc98;] SMC 83c17x
(EPIC)-based Ethernet NICs (&man.tx.4; driver)</para>
&hwlist.txp;
@@ -784,7 +802,7 @@
<sect2 id="fddi">
<title>FDDI Interfaces</title>
- <para>[&arch.i386, &arch.pc98;] DEC DEFPA PCI (&man.fpa.4;
+ <para>[&arch.i386;, &arch.pc98;] DEC DEFPA PCI (&man.fpa.4;
driver)</para>
<para>[&arch.i386;] DEC DEFEA EISA (&man.fpa.4; driver)</para>
@@ -793,17 +811,17 @@
<sect2 id="atm">
<title>ATM Interfaces</title>
- <para>[&arch.i386, &arch.pc98;] Midway-based ATM interfaces
+ <para>[&arch.i386;, &arch.pc98;] Midway-based ATM interfaces
(&man.en.4; driver)</para>
- <para>[&arch.i386, &arch.pc98; &arch.sparc64;] FORE Systems,
+ <para>[&arch.i386;, &arch.pc98; &arch.sparc64;] FORE Systems,
Inc. PCA-200E ATM PCI Adapters (hfa and &man.fatm.4;
drivers)</para>
<para>[&arch.i386;, &arch.pc98;] IDT NICStAR 77201/211-based ATM
Adapters (&man.idt.4; driver)</para>
- <para>[&arch.i386, &arch.pc98; &arch.sparc64;] FORE Systems,
+ <para>[&arch.i386;, &arch.pc98; &arch.sparc64;] FORE Systems,
Inc. HE155 and HE622 ATM interfaces (&man.hatm.4;
driver)</para>
@@ -1008,7 +1026,7 @@
<sect2 id="serial">
<title>Serial Interfaces</title>
- <para>[&arch.amd64; &arch.i386;] <quote>PC standard</quote>
+ <para>[&arch.amd64;, &arch.i386;] <quote>PC standard</quote>
8250, 16450, and 16550-based serial ports (&man.sio.4;
driver)</para>
@@ -1016,7 +1034,7 @@
&hwlist.scc;
- <para>[&arch.amd64; &arch.i386;] AST 4 port serial card using
+ <para>[&arch.amd64;, &arch.i386;] AST 4 port serial card using
shared IRQ</para>
<para>[&arch.i386;] ARNET serial cards (&man.ar.4;
@@ -1068,25 +1086,25 @@
<para>[&arch.i386;] DigiBoard intelligent serial cards (digi
driver)</para>
- <para>[&arch.amd64;, &arch.i386, &arch.ia64;] PCI-Based
+ <para>[&arch.amd64;, &arch.i386;, &arch.ia64;] PCI-Based
multi-port serial boards (&man.puc.4; driver)</para>
<itemizedlist>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Actiontech 56K PCI</para>
+ <para>[&arch.amd64;, &arch.i386;] Actiontech 56K PCI</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Avlab Technology, PCI IO 2S
+ <para>[&arch.amd64;, &arch.i386;] Avlab Technology, PCI IO 2S
and PCI IO 4S</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Comtrol RocketPort 550</para>
+ <para>[&arch.amd64;, &arch.i386;] Comtrol RocketPort 550</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Decision Computers PCCOM
+ <para>[&arch.amd64;, &arch.i386;] Decision Computers PCCOM
4-port serial and dual port RS232/422/485</para>
</listitem>
@@ -1095,92 +1113,92 @@
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Dolphin Peripherals
+ <para>[&arch.amd64;, &arch.i386;] Dolphin Peripherals
4025/4035/4036</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] IC Book Labs Dreadnought
+ <para>[&arch.amd64;, &arch.i386;] IC Book Labs Dreadnought
16x Lite and Pro</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Lava Computers
+ <para>[&arch.amd64;, &arch.i386;] Lava Computers
2SP-PCI/DSerial-PCI/Quattro-PCI/Octopus-550</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Middle Digital, Weasle
+ <para>[&arch.amd64;, &arch.i386;] Middle Digital, Weasle
serial port</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Moxa Industio CP-114,
+ <para>[&arch.amd64;, &arch.i386;] Moxa Industio CP-114,
Smartio C104H-PCI and C168H/PCI</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] NEC PK-UG-X001 and
+ <para>[&arch.amd64;, &arch.i386;] NEC PK-UG-X001 and
PK-UG-X008</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Netmos NM9835
+ <para>[&arch.amd64;, &arch.i386;] Netmos NM9835
PCI-2S-550</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Oxford Semiconductor
+ <para>[&arch.amd64;, &arch.i386;] Oxford Semiconductor
OX16PCI954 PCI UART</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Syba Tech SD-LAB
+ <para>[&arch.amd64;, &arch.i386;] Syba Tech SD-LAB
PCI-4S2P-550-ECP</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] SIIG Cyber I/O PCI
+ <para>[&arch.amd64;, &arch.i386;] SIIG Cyber I/O PCI
16C550/16C650/16C850</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] SIIG Cyber 2P1S PCI
+ <para>[&arch.amd64;, &arch.i386;] SIIG Cyber 2P1S PCI
16C550/16C650/16C850</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] SIIG Cyber 2S1P PCI
+ <para>[&arch.amd64;, &arch.i386;] SIIG Cyber 2S1P PCI
16C550/16C650/16C850</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] SIIG Cyber 4S PCI
+ <para>[&arch.amd64;, &arch.i386;] SIIG Cyber 4S PCI
16C550/16C650/16C850</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] SIIG Cyber Serial (Single
+ <para>[&arch.amd64;, &arch.i386;] SIIG Cyber Serial (Single
and Dual) PCI 16C550/16C650/16C850</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Syba Tech
+ <para>[&arch.amd64;, &arch.i386;] Syba Tech
Ltd. PCI-4S2P-550-ECP</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] Titan PCI-200H and
+ <para>[&arch.amd64;, &arch.i386;] Titan PCI-200H and
PCI-800H</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] US Robotics (3Com) 3CP5609
+ <para>[&arch.amd64;, &arch.i386;] US Robotics (3Com) 3CP5609
modem</para>
</listitem>
<listitem>
- <para>[&arch.amd64; &arch.i386;] VScom PCI-400 and
+ <para>[&arch.amd64;, &arch.i386;] VScom PCI-400 and
PCI-800</para>
</listitem>
</itemizedlist>
@@ -1406,7 +1424,7 @@
<para>[&arch.amd64;, &arch.i386;, &arch.ia64;, &arch.pc98;]
Keyboards (&man.ukbd.4; driver)</para>
- <para>[&arch.amd64;, &arch.i386, &arch.pc98;]
+ <para>[&arch.amd64;, &arch.i386;, &arch.pc98;]
Miscellaneous</para>
<itemizedlist>
@@ -1507,7 +1525,7 @@
<para>[&arch.amd64;, &arch.i386;, &arch.pc98;] Floppy drives
(&man.fdc.4; driver)</para>
- <para>[&arch.amd64; &arch.i386;] VGA-compatible video cards
+ <para>[&arch.amd64;, &arch.i386;] VGA-compatible video cards
(&man.vga.4; driver)</para>
<note>
diff --git a/release/picobsd/tinyware/ns/ns.c b/release/picobsd/tinyware/ns/ns.c
index c6e58e2..2ada2a7 100644
--- a/release/picobsd/tinyware/ns/ns.c
+++ b/release/picobsd/tinyware/ns/ns.c
@@ -382,10 +382,6 @@ print_routing(char *proto)
rtm = (struct rt_msghdr *)next;
sa = (struct sockaddr *)(rtm + 1);
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
- if (rtm->rtm_flags & RTF_WASCLONED) {
- if ((rtm->rtm_flags & RTF_LLINFO) == 0)
- continue;
- }
if ((sa = rti_info[RTAX_DST]) != NULL) {
sprintf(fbuf, "%s", sock_ntop(sa, sa->sa_len));
if (((sa1 = rti_info[RTAX_NETMASK]) != NULL)
diff --git a/sbin/atacontrol/atacontrol.8 b/sbin/atacontrol/atacontrol.8
index 8b4967e..31c2899 100644
--- a/sbin/atacontrol/atacontrol.8
+++ b/sbin/atacontrol/atacontrol.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 25, 2008
+.Dd December 14, 2008
.Dt ATACONTROL 8
.Os
.Sh NAME
@@ -63,6 +63,7 @@
.Nm
.Ic mode
.Ar device
+.Op Ar mode
.Nm
.Ic info
.Ar channel
@@ -94,7 +95,7 @@ The
.Ar channel
argument is the ATA channel device (e.g., ata0) on which to operate.
The following commands are supported:
-.Bl -tag -width "rebuild"
+.Bl -tag -width ".Ic addspare"
.It Ic attach
Attach an ATA
.Ar channel .
@@ -162,9 +163,13 @@ Rebuild a RAID1 array on a RAID capable ATA controller.
.It Ic status
Get the status of an ATA RAID.
.It Ic mode
-Without the mode argument, the current transfer modes of the
+Without the
+.Ar mode
+argument, the current transfer mode of the
device are printed.
-If the mode argument is given, the ATA driver
+If the
+.Ar mode
+argument is given, the ATA driver
is asked to change the transfer mode to the one given.
The ATA driver
will reject modes that are not supported by the hardware.
@@ -190,13 +195,12 @@ and
.Cm UDMA6
(alias
.Cm UDMA133 ) .
-The device name and manufacture/version strings are shown.
.It Ic cap
Show detailed info about the device on
.Ar device .
.It Ic spindown
Set or report timeout after which the
-.Ar device
+.Ar device
will be spun down.
To arm the timeout the device needs at least one more request after
setting the timeout.
@@ -205,6 +209,7 @@ No further actions are needed in this case.
.It Ic info
Show info about the attached devices on the
.Ar channel .
+The device name and manufacture/version strings are shown.
.It Ic list
Show info about all attached devices on all active controllers.
.El
@@ -312,7 +317,7 @@ If the system has a pure software array and is not using a "real" ATA
RAID controller, then shut the system down, make sure that the disk
that was still working is moved to the bootable position (channel 0
or whatever the BIOS allows the system to boot from) and the blank disk
-is placed in the secondary position, then boot the system into
+is placed in the secondary position, then boot the system into
single-user mode and issue the command:
.Pp
.Dl "atacontrol addspare ar0 ad6"
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc
index c6ac80c..c3f3ea9 100644
--- a/sbin/devd/devd.cc
+++ b/sbin/devd/devd.cc
@@ -307,7 +307,7 @@ void
config::parse_one_file(const char *fn)
{
if (Dflag)
- printf("Parsing %s\n", fn);
+ fprintf(stderr, "Parsing %s\n", fn);
yyin = fopen(fn, "r");
if (yyin == NULL)
err(1, "Cannot open config file %s", fn);
@@ -325,7 +325,7 @@ config::parse_files_in_dir(const char *dirname)
char path[PATH_MAX];
if (Dflag)
- printf("Parsing files in %s\n", dirname);
+ fprintf(stderr, "Parsing files in %s\n", dirname);
dirp = opendir(dirname);
if (dirp == NULL)
return;
diff --git a/sbin/devd/devd.conf.5 b/sbin/devd/devd.conf.5
index c8de20f..9e4796f 100644
--- a/sbin/devd/devd.conf.5
+++ b/sbin/devd/devd.conf.5
@@ -110,7 +110,7 @@ statement.
.It Ic directory Qq Ar /some/path ;
Adds the given directory to the list of directories from which
.Xr devd 8
-will read
+will read all files named "*.conf" as further
configuration files.
Any number of
.Ic directory
diff --git a/sbin/geom/misc/subr.c b/sbin/geom/misc/subr.c
index 64df7c6..800cdcf 100644
--- a/sbin/geom/misc/subr.c
+++ b/sbin/geom/misc/subr.c
@@ -211,7 +211,7 @@ g_metadata_store(const char *name, u_char *md, size_t size)
sector = NULL;
error = 0;
- fd = open(path, O_WRONLY);
+ fd = open(path, O_RDWR);
if (fd == -1)
return (errno);
mediasize = g_get_mediasize(name);
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
index 8a43659..d496644 100644
--- a/sbin/ifconfig/ifieee80211.c
+++ b/sbin/ifconfig/ifieee80211.c
@@ -425,7 +425,7 @@ setregdomain_cb(int s, void *arg)
struct ieee80211_devcaps_req dc;
struct regdata *rdp = getregdata();
- if (rd->country != 0) {
+ if (rd->country != NO_COUNTRY) {
const struct country *cc;
/*
* Check current country seting to make sure it's
@@ -456,7 +456,7 @@ setregdomain_cb(int s, void *arg)
errx(1, "country %s (%s) is not usable with "
"regdomain %d", cc->isoname, cc->name,
rd->regdomain);
- else if (rp->cc != 0 && rp->cc != cc)
+ else if (rp->cc != NULL && rp->cc != cc)
errx(1, "country %s (%s) is not usable with "
"regdomain %s", cc->isoname, cc->name,
rp->name);
@@ -664,30 +664,38 @@ getchannelflags(const char *val, int freq)
}
static void
-set80211channel(const char *val, int d, int s, const struct afswtch *rafp)
+getchannel(int s, struct ieee80211_channel *chan, const char *val)
{
- struct ieee80211_channel chan;
-
- memset(&chan, 0, sizeof(chan));
- if (!isanyarg(val)) {
- int v, flags;
- char *ep;
+ int v, flags;
+ char *eptr;
- getchaninfo(s);
- v = strtol(val, &ep, 10);
- if (val[0] == '\0' || val == ep || errno == ERANGE ||
- /* channel may be suffixed with nothing, :flag, or /width */
- (ep[0] != '\0' && ep[0] != ':' && ep[0] != '/'))
- errx(1, "invalid channel specification");
- flags = getchannelflags(val, v);
- if (v > 255) { /* treat as frequency */
- mapfreq(&chan, v, flags);
- } else {
- mapchan(&chan, v, flags);
- }
+ memset(chan, 0, sizeof(*chan));
+ if (isanyarg(val)) {
+ chan->ic_freq = IEEE80211_CHAN_ANY;
+ return;
+ }
+ getchaninfo(s);
+ errno = 0;
+ v = strtol(val, &eptr, 10);
+ if (val[0] == '\0' || val == eptr || errno == ERANGE ||
+ /* channel may be suffixed with nothing, :flag, or /width */
+ (eptr[0] != '\0' && eptr[0] != ':' && eptr[0] != '/'))
+ errx(1, "invalid channel specification%s",
+ errno == ERANGE ? " (out of range)" : "");
+ flags = getchannelflags(val, v);
+ if (v > 255) { /* treat as frequency */
+ mapfreq(chan, v, flags);
} else {
- chan.ic_freq = IEEE80211_CHAN_ANY;
+ mapchan(chan, v, flags);
}
+}
+
+static void
+set80211channel(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct ieee80211_channel chan;
+
+ getchannel(s, &chan, val);
set80211(s, IEEE80211_IOC_CURCHAN, 0, sizeof(chan), &chan);
}
@@ -695,17 +703,8 @@ static void
set80211chanswitch(const char *val, int d, int s, const struct afswtch *rafp)
{
struct ieee80211_chanswitch_req csr;
- int v, flags;
- memset(&csr, 0, sizeof(csr));
- getchaninfo(s);
- v = atoi(val);
- flags = getchannelflags(val, v);
- if (v > 255) { /* treat as frequency */
- mapfreq(&csr.csa_chan, v, flags);
- } else {
- mapchan(&csr.csa_chan, v, flags);
- }
+ getchannel(s, &csr.csa_chan, val);
csr.csa_mode = 1;
csr.csa_count = 5;
set80211(s, IEEE80211_IOC_CHANSWITCH, 0, sizeof(csr), &csr);
@@ -1770,14 +1769,21 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci,
printf("%u: skip, flags 0x%x not available\n", freq, chanFlags);
continue;
}
+ /*
+ * NB: don't enforce 1/2 and 1/4 rate channels being
+ * specified in the device's calibration list for
+ * 900MHz cards because most are not self-identifying.
+ */
if ((flags & IEEE80211_CHAN_HALF) &&
- (chanFlags & IEEE80211_CHAN_HALF) == 0) {
+ ((chanFlags & IEEE80211_CHAN_HALF) == 0 &&
+ (flags & IEEE80211_CHAN_GSM) == 0)) {
if (verbose)
printf("%u: skip, device does not support half-rate channels\n", freq);
continue;
}
if ((flags & IEEE80211_CHAN_QUARTER) &&
- (chanFlags & IEEE80211_CHAN_QUARTER) == 0) {
+ ((chanFlags & IEEE80211_CHAN_HALF) == 0 &&
+ (flags & IEEE80211_CHAN_GSM) == 0)) {
if (verbose)
printf("%u: skip, device does not support quarter-rate channels\n", freq);
continue;
@@ -1951,8 +1957,12 @@ DECL_CMD_FUNC(set80211regdomain, val, d)
rd = lib80211_regdomain_findbyname(rdp, val);
if (rd == NULL) {
- rd = lib80211_regdomain_findbysku(rdp, atoi(val));
- if (rd == NULL)
+ char *eptr;
+ long sku = strtol(val, &eptr, 0);
+
+ if (eptr != val)
+ rd = lib80211_regdomain_findbysku(rdp, sku);
+ if (eptr == val || rd == NULL)
errx(1, "unknown regdomain %s", val);
}
getregdomain(s);
@@ -1975,8 +1985,12 @@ DECL_CMD_FUNC(set80211country, val, d)
cc = lib80211_country_findbyname(rdp, val);
if (cc == NULL) {
- cc = lib80211_country_findbycc(rdp, atoi(val));
- if (cc == NULL)
+ char *eptr;
+ long code = strtol(val, &eptr, 0);
+
+ if (eptr != val)
+ cc = lib80211_country_findbycc(rdp, code);
+ if (eptr == val || cc == NULL)
errx(1, "unknown ISO country code %s", val);
}
getregdomain(s);
@@ -3534,8 +3548,12 @@ get80211opmode(int s)
(void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
- if (ifmr.ifm_current & IFM_IEEE80211_ADHOC)
- return IEEE80211_M_IBSS; /* XXX ahdemo */
+ if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
+ if (ifmr.ifm_current & IFM_FLAG0)
+ return IEEE80211_M_AHDEMO;
+ else
+ return IEEE80211_M_IBSS;
+ }
if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
return IEEE80211_M_HOSTAP;
if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
@@ -4244,6 +4262,7 @@ end:
}
}
}
+
if (get80211val(s, IEEE80211_IOC_BEACON_INTERVAL, &val) != -1) {
/* XXX default define not visible */
if (val != 100 || verbose)
diff --git a/sbin/ifconfig/regdomain.c b/sbin/ifconfig/regdomain.c
index a19aae8..5846469 100644
--- a/sbin/ifconfig/regdomain.c
+++ b/sbin/ifconfig/regdomain.c
@@ -48,6 +48,7 @@ static const char rcsid[] = "$FreeBSD$";
#define MAXLEVEL 20
struct mystate {
+ XML_Parser parser;
struct regdata *rdp;
struct regdomain *rd; /* current domain */
struct netband *netband; /* current netband */
@@ -107,7 +108,8 @@ start_element(void *data, const char *name, const char **attr)
}
if (iseq(name, "netband") && mt->curband == NULL && mt->rd != NULL) {
if (mode == NULL) {
- /* XXX complain */
+ warnx("no mode for netband at line %ld",
+ XML_GetCurrentLineNumber(mt->parser));
return;
}
if (iseq(mode, "11b"))
@@ -120,12 +122,16 @@ start_element(void *data, const char *name, const char **attr)
mt->curband = &mt->rd->bands_11ng;
else if (iseq(mode, "11na"))
mt->curband = &mt->rd->bands_11na;
- /* XXX else complain */
+ else
+ warnx("unknown mode \"%s\" at line %ld",
+ __DECONST(char *, mode),
+ XML_GetCurrentLineNumber(mt->parser));
return;
}
if (iseq(name, "band") && mt->netband == NULL) {
if (mt->curband == NULL) {
- /* XXX complain */
+ warnx("band without enclosing netband at line %ld",
+ XML_GetCurrentLineNumber(mt->parser));
return;
}
mt->netband = calloc(1, sizeof(struct netband));
@@ -135,6 +141,8 @@ start_element(void *data, const char *name, const char **attr)
if (iseq(name, "freqband") && mt->freqband == NULL && mt->netband != NULL) {
/* XXX handle inlines and merge into table? */
if (mt->netband->band != NULL) {
+ warnx("duplicate freqband at line %ld ignored",
+ XML_GetCurrentLineNumber(mt->parser));
/* XXX complain */
} else
mt->netband->band = (void *)strdup(ref);
@@ -144,6 +152,7 @@ start_element(void *data, const char *name, const char **attr)
if (iseq(name, "country") && mt->country == NULL) {
mt->country = calloc(1, sizeof(struct country));
mt->country->isoname = strdup(id);
+ mt->country->code = NO_COUNTRY;
mt->nident++;
LIST_INSERT_HEAD(&mt->rdp->countries, mt->country, next);
return;
@@ -159,8 +168,8 @@ start_element(void *data, const char *name, const char **attr)
#undef iseq
}
-static uint32_t
-decode_flag(const char *p, int len)
+static int
+decode_flag(struct mystate *mt, const char *p, int len)
{
#define iseq(a,b) (strcasecmp(a,b) == 0)
static const struct {
@@ -168,7 +177,7 @@ decode_flag(const char *p, int len)
int len;
uint32_t value;
} flags[] = {
-#define FLAG(x) { #x, sizeof(#x), x }
+#define FLAG(x) { #x, sizeof(#x)-1, x }
FLAG(IEEE80211_CHAN_A),
FLAG(IEEE80211_CHAN_B),
FLAG(IEEE80211_CHAN_G),
@@ -205,6 +214,8 @@ decode_flag(const char *p, int len)
for (i = 0; i < sizeof(flags)/sizeof(flags[0]); i++)
if (len == flags[i].len && iseq(p, flags[i].name))
return flags[i].value;
+ warnx("unknown flag \"%.*s\" at line %ld ignored",
+ len, p, XML_GetCurrentLineNumber(mt->parser));
return 0;
#undef iseq
}
@@ -241,11 +252,12 @@ end_element(void *data, const char *name)
}
if (iseq(name, "flags")) {
if (mt->freqband != NULL)
- mt->freqband->flags |= decode_flag(p, len);
+ mt->freqband->flags |= decode_flag(mt, p, len);
else if (mt->netband != NULL)
- mt->netband->flags |= decode_flag(p, len);
+ mt->netband->flags |= decode_flag(mt, p, len);
else {
- /* XXX complain */
+ warnx("flags without freqband or netband at line %ld ignored",
+ XML_GetCurrentLineNumber(mt->parser));
}
goto done;
}
@@ -289,7 +301,8 @@ end_element(void *data, const char *name)
}
if (len != 0) {
- printf("Unexpected XML: name \"%s\" data \"%s\"\n", name, p);
+ warnx("unexpected XML token \"%s\" data \"%s\" at line %ld",
+ name, p, XML_GetCurrentLineNumber(mt->parser));
/* XXX goto done? */
}
/* </freqband> */
@@ -307,15 +320,12 @@ end_element(void *data, const char *name)
/* </band> */
if (iseq(name, "band") && mt->netband != NULL) {
if (mt->netband->band == NULL) {
- printf("No frequency band information at line %d\n",
-#if 0
- XML_GetCurrentLineNumber(parser));
-#else
- 0);
-#endif
+ warnx("no freqbands for band at line %ld",
+ XML_GetCurrentLineNumber(mt->parser));
}
if (mt->netband->maxPower == 0) {
- /* XXX complain */
+ warnx("no maxpower for band at line %ld",
+ XML_GetCurrentLineNumber(mt->parser));
}
/* default max power w/ DFS to max power */
if (mt->netband->maxPowerDFS == 0)
@@ -330,14 +340,17 @@ end_element(void *data, const char *name)
}
/* </country> */
if (iseq(name, "country") && mt->country != NULL) {
- if (mt->country->code == 0) {
- /* XXX must have iso cc */
+ if (mt->country->code == NO_COUNTRY) {
+ warnx("no ISO cc for country at line %ld",
+ XML_GetCurrentLineNumber(mt->parser));
}
if (mt->country->name == NULL) {
- /* XXX must have name */
+ warnx("no name for country at line %ld",
+ XML_GetCurrentLineNumber(mt->parser));
}
if (mt->country->rd == NULL) {
- /* XXX? rd ref? */
+ warnx("no regdomain reference for country at line %ld",
+ XML_GetCurrentLineNumber(mt->parser));
}
mt->country = NULL;
goto done;
@@ -383,7 +396,6 @@ findid(struct regdata *rdp, const void *id, int type)
int
lib80211_regdomain_readconfig(struct regdata *rdp, const void *p, size_t len)
{
- XML_Parser parser;
struct mystate *mt;
struct regdomain *dp;
struct country *cp;
@@ -398,17 +410,17 @@ lib80211_regdomain_readconfig(struct regdata *rdp, const void *p, size_t len)
return ENOMEM;
/* parse the XML input */
mt->rdp = rdp;
- parser = XML_ParserCreate(NULL);
- XML_SetUserData(parser, mt);
- XML_SetElementHandler(parser, start_element, end_element);
- XML_SetCharacterDataHandler(parser, char_data);
- if (XML_Parse(parser, p, len, 1) != XML_STATUS_OK) {
+ mt->parser = XML_ParserCreate(NULL);
+ XML_SetUserData(mt->parser, mt);
+ XML_SetElementHandler(mt->parser, start_element, end_element);
+ XML_SetCharacterDataHandler(mt->parser, char_data);
+ if (XML_Parse(mt->parser, p, len, 1) != XML_STATUS_OK) {
warnx("%s: %s at line %ld", __func__,
- XML_ErrorString(XML_GetErrorCode(parser)),
- XML_GetCurrentLineNumber(parser));
+ XML_ErrorString(XML_GetErrorCode(mt->parser)),
+ XML_GetCurrentLineNumber(mt->parser));
return -1;
}
- XML_ParserFree(parser);
+ XML_ParserFree(mt->parser);
/* setup the identifer table */
rdp->ident = calloc(sizeof(struct ident), mt->nident + 1);
diff --git a/sbin/ifconfig/regdomain.h b/sbin/ifconfig/regdomain.h
index e7046a9..5b37a0b 100644
--- a/sbin/ifconfig/regdomain.h
+++ b/sbin/ifconfig/regdomain.h
@@ -73,6 +73,7 @@ struct regdomain {
struct country {
enum ISOCountryCode code;
+#define NO_COUNTRY 0xffff
const struct regdomain *rd;
const char* isoname;
const char* name;
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index b899c67..83ba7a4 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -69,6 +69,7 @@
.Op Ar number ...
.Pp
.Nm
+.Op Fl q
.Cm nat
.Ar number
.Cm config
@@ -235,6 +236,7 @@ Try to resolve addresses and service names in output.
.It Fl q
While
.Cm add Ns ing ,
+.Cm nat Ns ing ,
.Cm zero Ns ing ,
.Cm resetlog Ns ging
or
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index e382f93..7834783 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -4067,10 +4067,12 @@ config_nat(int ac, char **av)
if (i)
err(1, "setsockopt(%s)", "IP_FW_NAT_CFG");
- /* After every modification, we show the resultant rule. */
- int _ac = 3;
- char *_av[] = {"show", "config", id};
- show_nat(_ac, _av);
+ if (!do_quiet) {
+ /* After every modification, we show the resultant rule. */
+ int _ac = 3;
+ char *_av[] = {"show", "config", id};
+ show_nat(_ac, _av);
+ }
}
static void
diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c
index c42e9db..38a1c8a 100644
--- a/sbin/mount/mount.c
+++ b/sbin/mount/mount.c
@@ -68,6 +68,8 @@ static const char rcsid[] =
#define MOUNT_META_OPTION_FSTAB "fstab"
#define MOUNT_META_OPTION_CURRENT "current"
+#define MAX_ARGS 100
+
int debug, fstab_style, verbose;
char *catopt(char *, const char *);
@@ -501,7 +503,7 @@ int
mountfs(const char *vfstype, const char *spec, const char *name, int flags,
const char *options, const char *mntopts)
{
- char *argv[100];
+ char *argv[MAX_ARGS];
struct statfs sf;
int argc, i, ret;
char *optbuf, execname[PATH_MAX], mntpath[PATH_MAX];
@@ -546,6 +548,10 @@ mountfs(const char *vfstype, const char *spec, const char *name, int flags,
argv[argc++] = strdup(name);
argv[argc] = NULL;
+ if (MAX_ARGS <= argc )
+ errx(1, "Cannot process more than %d mount arguments",
+ MAX_ARGS);
+
if (debug) {
if (use_mountprog(vfstype))
printf("exec: mount_%s", vfstype);
diff --git a/sbin/mount/mount_fs.c b/sbin/mount/mount_fs.c
index 6ab15a3..94b679b 100644
--- a/sbin/mount/mount_fs.c
+++ b/sbin/mount/mount_fs.c
@@ -88,7 +88,7 @@ mount_fs(const char *vfstype, int argc, char *argv[])
char *p, *val;
int ret;
- strncpy(fstype, vfstype, sizeof(fstype));
+ strlcpy(fstype, vfstype, sizeof(fstype));
memset(errmsg, 0, sizeof(errmsg));
getmnt_silent = 1;
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 082ac53..bae9983 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -605,9 +605,6 @@ newroute(argc, argv)
case K_NOSTATIC:
flags &= ~RTF_STATIC;
break;
- case K_LLINFO:
- flags |= RTF_LLINFO;
- break;
case K_LOCK:
locking = 1;
break;
@@ -632,9 +629,6 @@ newroute(argc, argv)
case K_PROXY:
proxy = 1;
break;
- case K_CLONING:
- flags |= RTF_CLONING;
- break;
case K_XRESOLVE:
flags |= RTF_XRESOLVE;
break;
diff --git a/sbin/routed/table.c b/sbin/routed/table.c
index 491c5cf..9fd4cb8 100644
--- a/sbin/routed/table.c
+++ b/sbin/routed/table.c
@@ -1103,12 +1103,13 @@ flush_kern(void)
|| INFO_DST(&info)->sa_family != AF_INET)
continue;
+#if defined (RTF_LLINFO)
/* ignore ARP table entries on systems with a merged route
* and ARP table.
*/
if (rtm->rtm_flags & RTF_LLINFO)
continue;
-
+#endif
#if defined(RTF_WASCLONED) && defined(__FreeBSD__)
/* ignore cloned routes
*/
@@ -1261,11 +1262,13 @@ read_rt(void)
continue;
}
+#if defined(RTF_LLINFO)
if (m.r.rtm.rtm_flags & RTF_LLINFO) {
trace_act("ignore ARP %s", str);
continue;
}
-
+#endif
+
#if defined(RTF_WASCLONED) && defined(__FreeBSD__)
if (m.r.rtm.rtm_flags & RTF_WASCLONED) {
trace_act("ignore cloned %s", str);
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index f91a606..59a233b 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -473,6 +473,7 @@ MLINKS+=edsc.4 if_edsc.4
MLINKS+=ef.4 if_ef.4
MLINKS+=em.4 if_em.4
MLINKS+=en.4 if_en.4
+MLINKS+=enc.4 if_enc.4
MLINKS+=et.4 if_et.4
MLINKS+=faith.4 if_faith.4
MLINKS+=fatm.4 if_fatm.4
diff --git a/share/man/man4/acpi_aiboost.4 b/share/man/man4/acpi_aiboost.4
index c5d918b..a4631a8 100644
--- a/share/man/man4/acpi_aiboost.4
+++ b/share/man/man4/acpi_aiboost.4
@@ -56,8 +56,8 @@ The driver uses ACPI as the backend to fetch sensor values and
descriptions and provides its data via the
.Xr sysctl 8
interface, under dev.acpi_aiboost.0 namespace.
-Descriptions for these values are set to sysctl description,
-which can be see with sysctl -d.
+Descriptions for these values are available
+with sysctl -d.
.Pp
The
.Nm
diff --git a/share/man/man4/acpi_asus.4 b/share/man/man4/acpi_asus.4
index 8216add..a966d7e 100644
--- a/share/man/man4/acpi_asus.4
+++ b/share/man/man4/acpi_asus.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 20, 2008
+.Dd December 17, 2008
.Dt ACPI_ASUS 4 i386
.Os
.Sh NAME
@@ -56,7 +56,8 @@ interface to manipulate the brightness of the LCD panel and the display output
state.
Hotkey events are passed to
.Xr devd 8
-for easy handling in userspace.
+for easy handling in userspace with the default configuration in
+.Pa /etc/devd/asus.conf .
.Pp
Currently, the following Asus laptops are fully supported:
.Pp
diff --git a/share/man/man4/fxp.4 b/share/man/man4/fxp.4
index cf745b4..5057100 100644
--- a/share/man/man4/fxp.4
+++ b/share/man/man4/fxp.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 7, 2007
+.Dd December 15, 2008
.Dt FXP 4
.Os
.Sh NAME
@@ -51,6 +51,13 @@ The
.Nm
driver provides support for Ethernet adapters based on the Intel
i82557, i82558, i82559, i82550, and i82562 chips.
+The driver supports TCP/UDP/IP checksum offload for both transmit
+and receive on i82550 and i82551.
+On i82559 only TCP/UDP checksum offload for receive is supported.
+TCP segmentation offload (TSO) for IPv4 as well as VLAN hardware
+tag insertion/stripping is supported on i82550 and i82551.
+Wake On Lan (WOL) support is provided on all controllers
+except i82557, i82259ER and early i82558 revisions.
.Pp
The
.Nm
diff --git a/share/man/man4/route.4 b/share/man/man4/route.4
index 0e10be5..aaf59e4 100644
--- a/share/man/man4/route.4
+++ b/share/man/man4/route.4
@@ -196,7 +196,7 @@ Messages include:
#define RTM_REDIRECT 0x6 /* Told to use different route */
#define RTM_MISS 0x7 /* Lookup failed on this address */
#define RTM_LOCK 0x8 /* fix specified metrics */
-#define RTM_RESOLVE 0xb /* request to resolve dst to LL addr */
+#define RTM_RESOLVE 0xb /* request to resolve dst to LL addr - unused */
#define RTM_NEWADDR 0xc /* address being added to iface */
#define RTM_DELADDR 0xd /* address being removed from iface */
#define RTM_IFINFO 0xe /* iface going up/down etc. */
@@ -308,7 +308,7 @@ Specifiers for which addresses are present in the messages are:
#define RTA_DST 0x1 /* destination sockaddr present */
#define RTA_GATEWAY 0x2 /* gateway sockaddr present */
#define RTA_NETMASK 0x4 /* netmask sockaddr present */
-#define RTA_GENMASK 0x8 /* cloning mask sockaddr present */
+#define RTA_GENMASK 0x8 /* cloning mask sockaddr present - unused */
#define RTA_IFP 0x10 /* interface name sockaddr present */
#define RTA_IFA 0x20 /* interface addr sockaddr present */
#define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */
diff --git a/share/man/man9/VOP_STRATEGY.9 b/share/man/man9/VOP_STRATEGY.9
index 709a929..8c4fbac 100644
--- a/share/man/man9/VOP_STRATEGY.9
+++ b/share/man/man9/VOP_STRATEGY.9
@@ -53,7 +53,9 @@ This call either reads or writes data from a file, depending on the value of
.Pp
The call may block.
.Sh RETURN VALUES
-Zero is returned on success, otherwise an error is returned.
+Always zero.
+Errors should be signalled by setting BIO_ERROR on b_ioflags field in struct buf,
+and setting b_error to the appropriate errno value.
.Sh SEE ALSO
.\" .Xr buf 9 ,
.Xr vnode 9
diff --git a/share/man/man9/rtalloc.9 b/share/man/man9/rtalloc.9
index 4e7f818..cbd2c5e 100644
--- a/share/man/man9/rtalloc.9
+++ b/share/man/man9/rtalloc.9
@@ -27,7 +27,8 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd October 11, 2004
+.\"
+.Dd December 11, 2008
.Os
.Dt RTALLOC 9
.Sh NAME
@@ -64,21 +65,6 @@ certain protocol\- and interface-specific actions to take place.
.\" XXX - -mdoc should contain a standard request for getting em and
.\" en dashes.
.Pp
-When a route with the flag
-.Dv RTF_CLONING
-is retrieved, and the action of this flag is not masked, the
-.Nm
-facility automatically generates a new route using information in the
-old route as a template, and
-sends an
-.Dv RTM_RESOLVE
-message to the appropriate interface-address route-management routine
-.Pq Fn ifa->ifa_rtrequest .
-This generated route is called
-.Em cloned ,
-and has
-.Dv RTF_WASCLONED
-flag set.
.Dv RTF_PRCLONING
flag is obsolete and thus ignored by facility.
If the
@@ -123,22 +109,19 @@ field.
.Pp
The
.Fn rtalloc_ign
-interface can be used when the default actions of
-.Fn rtalloc
-in the presence of the
-.Dv RTF_CLONING
-flag is undesired.
+interface can be used when the caller does not want to receive
+the returned
+.Fa rtentry
+locked.
The
.Fa ro
argument is the same as
.Fn rtalloc ,
but there is additionally a
.Fa flags
-argument, which lists the flags in the route which are to be
-.Em ignored
-(in most cases this is
-.Dv RTF_CLONING
-flag).
+argument, which is now only used to pass
+.Dv RTF_RNH_LOCKED
+indicating that the radix tree lock is already held.
Both
.Fn rtalloc
and
@@ -163,16 +146,7 @@ directly as the
argument.
The second argument,
.Fa report ,
-controls whether
-.Dv RTM_RESOLVE
-requests are sent to the lower layers when an
-.Dv RTF_CLONING
-or
-.Dv RTF_PRCLONING
-route is cloned.
-Ordinarily a value of one should be passed, except
-in the processing of those lower layers which use the cloning
-facility.
+controls whether the lower layers are notified when a lookup fails.
The third argument,
.Fa flags ,
is a set of flags to ignore, as in
diff --git a/share/man/man9/rtentry.9 b/share/man/man9/rtentry.9
index a1c48a6..0e25b21 100644
--- a/share/man/man9/rtentry.9
+++ b/share/man/man9/rtentry.9
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 7, 2004
+.Dd December 11, 2008
.Os
.Dt RTENTRY 9
.Sh NAME
@@ -76,8 +76,11 @@ right (some protocols will put a link-layer address here), or some
intermediate stop on the way to that destination (if the
.Dv RTF_GATEWAY
flag is set).
-.It Vt "u_long rt_flags" ;
+.It Vt "int rt_flags" ;
See below.
+.It Vt "int rt_refcnt" ;
+Route entries are reference-counted; this field indicates the number
+of external (to the radix tree) references.
.It Vt "struct ifnet *rt_ifp" ;
.It Vt "struct ifaddr *rt_ifa" ;
These two fields represent the
@@ -88,48 +91,18 @@ packet to the destination or set of destinations which this route
represents.
.It Vt "struct rt_metrics_lite rt_rmx" ;
See below.
-.It Vt "long rt_refcnt" ;
-Route entries are reference-counted; this field indicates the number
-of external (to the radix tree) references.
If the
.Dv RTF_UP
flag is not present, the
.Fn rtfree
function will delete the route from the radix tree when the last
reference drops.
-.It Vt "struct sockaddr *rt_genmask" ;
-When the
-.Fn rtalloc
-family of functions performs a cloning operation as requested by the
-.Dv RTF_CLONING
-flag, this field is used as the mask for the new route which is
-inserted into the table.
-If this field is a null pointer, then a host
-route is generated.
-.It Vt "caddr_t rt_llinfo" ;
-When the
-.Dv RTF_LLINFO
-flag is set, this field contains information specific to the link
-layer represented by the named interface address.
-(It is normally managed by the
-.Va rt_ifa->ifa_rtrequest
-routine.)
-Protocols such as
-.Xr arp 4
-use this field to reference per-destination state internal to that
-protocol.
.It Vt "struct rtentry *rt_gwroute" ;
This member is a reference to a route whose destination is
.Va rt_gateway .
It is only used for
.Dv RTF_GATEWAY
routes.
-.It Vt "struct rtentry *rt_parent" ;
-A reference to the route from which this route was cloned, or a null
-pointer if this route was not generated by cloning.
-See also the
-.Dv RTF_WASCLONED
-flag.
.It Vt "struct mtx rt_mtx" ;
Mutex to lock this routing entry.
.El
@@ -162,23 +135,12 @@ This route was modified by
Used only in the
.Xr route 4
protocol, indicating that the request was executed.
-.It Dv RTF_CLONING
-When this route is returned as a result of a lookup, automatically
-create a new route using this one as a template and
-.Va rt_genmask
-(if present) as a mask.
.It Dv RTF_XRESOLVE
When this route is returned as a result of a lookup, send a report on
the
.Xr route 4
interface requesting that an external process perform resolution for
this route.
-(Used in conjunction with
-.Dv RTF_CLONING . )
-.It Dv RTF_LLINFO
-Indicates that this route represents information being managed by a
-link layer's adaptation layer (e.g.,
-.Tn ARP ) .
.It Dv RTF_STATIC
Indicates that this route was manually added by means of the
.Xr route 8
@@ -191,14 +153,6 @@ Requests that output sent via this route be discarded.
Protocol-specific.
.It Dv RTF_PRCLONING
This flag is obsolete and simply ignored by facility.
-.It Dv RTF_WASCLONED
-Indicates that this route was generated as a result of cloning
-requested by the
-.Dv RTF_CLONING
-flag.
-When set, the
-.Va rt_parent
-field indicates the route from which this one was generated.
.It Dv RTF_PINNED
(Reserved for future use to indicate routes which are not to be
modified by a routing protocol.)
@@ -296,8 +250,3 @@ The
and
.Va rmx_filler
fields could be named better.
-.Pp
-There is some disagreement over whether it is legitimate for
-.Dv RTF_LLINFO
-to be set by any process other than
-.Va rt_ifa->ifa_rtrequest .
diff --git a/share/man/man9/style.9 b/share/man/man9/style.9
index c7ccd25..d70868f 100644
--- a/share/man/man9/style.9
+++ b/share/man/man9/style.9
@@ -26,7 +26,7 @@
.\" From: @(#)style 1.14 (Berkeley) 4/28/95
.\" $FreeBSD$
.\"
-.Dd February 10, 2005
+.Dd December 17, 2008
.Dt STYLE 9
.Os
.Sh NAME
@@ -602,11 +602,9 @@ Do YOU understand the following?
k = !(l & FLAGS);
.Ed
.Pp
-Exits should be 0 on success, or according to the predefined
-values in
-.Xr sysexits 3 .
+Exits should be 0 on success, or 1 on failure.
.Bd -literal
- exit(EX_OK); /*
+ exit(0); /*
* Avoid obvious comments such as
* "Exit 0 on success."
*/
@@ -806,7 +804,7 @@ placed in a single set of brackets.
.Ed
.Bd -literal
(void)fprintf(stderr, "usage: f [-ab]\en");
- exit(EX_USAGE);
+ exit(1);
}
.Ed
.Pp
@@ -840,7 +838,6 @@ and produce minimal warnings.
.Xr indent 1 ,
.Xr lint 1 ,
.Xr err 3 ,
-.Xr sysexits 3 ,
.Xr warn 3 ,
.Xr style.Makefile 5
.Sh HISTORY
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index fd0a7ca..80308a9 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -459,9 +459,9 @@ nmi_calltrap:
*/
movq %rsp,%rsi /* source stack pointer */
movq $TF_SIZE,%rcx
- movq PCPU(RSP0),%rbx
- subq %rcx,%rbx
- movq %rbx,%rdi /* destination stack pointer */
+ movq PCPU(RSP0),%rdx
+ subq %rcx,%rdx
+ movq %rdx,%rdi /* destination stack pointer */
shrq $3,%rcx /* trap frame size in long words */
cld
@@ -470,7 +470,7 @@ nmi_calltrap:
movl %ss,%eax
pushq %rax /* tf_ss */
- pushq %rbx /* tf_rsp (on kernel stack) */
+ pushq %rdx /* tf_rsp (on kernel stack) */
pushfq /* tf_rflags */
movl %cs,%eax
pushq %rax /* tf_cs */
@@ -480,16 +480,20 @@ outofnmi:
/*
* At this point the processor has exited NMI mode and is running
* with interrupts turned off on the normal kernel stack.
- * We turn interrupts back on, and take the usual 'doreti' exit
- * path.
*
* If a pending NMI gets recognized at or after this point, it
- * will cause a kernel callchain to be traced. Since this path
- * is only taken for NMI interrupts from user space, our `swapgs'
- * state is correct for taking the doreti path.
+ * will cause a kernel callchain to be traced.
+ *
+ * We turn interrupts back on, and call the user callchain capture hook.
*/
+ movq pmc_hook,%rax
+ orq %rax,%rax
+ jz nocallchain
+ movq PCPU(CURTHREAD),%rdi /* thread */
+ movq $PMC_FN_USER_CALLCHAIN,%rsi /* command */
+ movq %rsp,%rdx /* frame */
sti
- jmp doreti
+ call *%rax
nocallchain:
#endif
testl %ebx,%ebx
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c
index c63339d..f417e0f 100644
--- a/sys/amd64/amd64/identcpu.c
+++ b/sys/amd64/amd64/identcpu.c
@@ -322,15 +322,15 @@ printcpuinfo(void)
"\003SVM" /* Secure Virtual Mode */
"\004ExtAPIC" /* Extended APIC register */
"\005CR8" /* CR8 in legacy mode */
- "\006<b5>"
- "\007<b6>"
- "\010<b7>"
+ "\006ABM" /* LZCNT instruction */
+ "\007SSE4A" /* SSE4A */
+ "\010MAS" /* Misaligned SSE mode */
"\011Prefetch" /* 3DNow! Prefetch/PrefetchW */
- "\012<b9>"
- "\013<b10>"
- "\014<b11>"
- "\015<b12>"
- "\016<b13>"
+ "\012OSVW" /* OS visible workaround */
+ "\013IBS" /* Instruction based sampling */
+ "\014SSE5" /* SSE5 */
+ "\015SKINIT" /* SKINIT/STGI */
+ "\016WDT" /* Watchdog timer */
"\017<b14>"
"\020<b15>"
"\021<b16>"
diff --git a/sys/amd64/conf/DEFAULTS b/sys/amd64/conf/DEFAULTS
index 3477caf..fac8dce 100644
--- a/sys/amd64/conf/DEFAULTS
+++ b/sys/amd64/conf/DEFAULTS
@@ -16,5 +16,5 @@ device io # I/O device
device uart_ns8250
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h
index 0a386be..a4c7f79 100644
--- a/sys/amd64/include/elf.h
+++ b/sys/amd64/include/elf.h
@@ -81,18 +81,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h
index cd9da86..674638c 100644
--- a/sys/amd64/include/specialreg.h
+++ b/sys/amd64/include/specialreg.h
@@ -150,7 +150,15 @@
#define AMDID2_SVM 0x00000004
#define AMDID2_EXT_APIC 0x00000008
#define AMDID2_CR8 0x00000010
+#define AMDID2_ABM 0x00000020
+#define AMDID2_SSE4A 0x00000040
+#define AMDID2_MAS 0x00000080
#define AMDID2_PREFETCH 0x00000100
+#define AMDID2_OSVW 0x00000200
+#define AMDID2_IBS 0x00000400
+#define AMDID2_SSE5 0x00000800
+#define AMDID2_SKINIT 0x00001000
+#define AMDID2_WDT 0x00002000
/*
* CPUID instruction 1 eax info
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 3acee30..aaa7458 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -254,8 +254,6 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
args = (Elf32_Auxargs *)imgp->auxargs;
pos = base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace)
- AUXARGS_ENTRY_32(pos, AT_DEBUG, 1);
if (args->execfd != -1)
AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr);
diff --git a/sys/arm/conf/DEFAULTS b/sys/arm/conf/DEFAULTS
index 606e962..591a0a1 100644
--- a/sys/arm/conf/DEFAULTS
+++ b/sys/arm/conf/DEFAULTS
@@ -7,5 +7,5 @@ machine arm
device mem
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
diff --git a/sys/arm/conf/EP80219 b/sys/arm/conf/EP80219
index 8e2d6cb..8ce5b164 100644
--- a/sys/arm/conf/EP80219
+++ b/sys/arm/conf/EP80219
@@ -57,7 +57,6 @@ options SYSVSEM #SYSV-style semaphores
options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options GEOM_PART_GPT # GUID Partition Tables.
-options GEOM_MBR # DOS/MBR partitioning
options GEOM_LABEL # Providers labelization.
options BOOTP
diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h
index 353be7c..c516864 100644
--- a/sys/arm/include/elf.h
+++ b/sys/arm/include/elf.h
@@ -70,10 +70,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
diff --git a/sys/boot/Makefile b/sys/boot/Makefile
index 27cb7e3..7020ebb 100644
--- a/sys/boot/Makefile
+++ b/sys/boot/Makefile
@@ -12,7 +12,7 @@ SUBDIR+= ficl
.endif
# Build EFI library.
-.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "ia64"
+.if ${MACHINE_ARCH} == "amd64" || ${MACHINE} == "i386" || ${MACHINE_ARCH} == "ia64"
SUBDIR+= efi
.endif
diff --git a/sys/boot/i386/gptzfsboot/Makefile b/sys/boot/i386/gptzfsboot/Makefile
index 930061f..467d312 100644
--- a/sys/boot/i386/gptzfsboot/Makefile
+++ b/sys/boot/i386/gptzfsboot/Makefile
@@ -60,7 +60,7 @@ gptzfsboot.bin: gptzfsboot.out
objcopy -S -O binary gptzfsboot.out ${.TARGET}
gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o
- ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC}
+ ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
zfsboot.o: ${.CURDIR}/../../zfs/zfsimpl.c
diff --git a/sys/boot/i386/zfsboot/Makefile b/sys/boot/i386/zfsboot/Makefile
index 41f1672..1653534 100644
--- a/sys/boot/i386/zfsboot/Makefile
+++ b/sys/boot/i386/zfsboot/Makefile
@@ -80,7 +80,7 @@ zfsboot.bin: zfsboot.out
objcopy -S -O binary zfsboot.out ${.TARGET}
zfsboot.out: ${BTXCRT} zfsboot.o sio.o
- ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC}
+ ${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
zfsboot.o: zfsboot.s
diff --git a/sys/boot/powerpc/uboot/conf.c b/sys/boot/powerpc/uboot/conf.c
index 8bc307a..5a9515a 100644
--- a/sys/boot/powerpc/uboot/conf.c
+++ b/sys/boot/powerpc/uboot/conf.c
@@ -94,8 +94,8 @@ struct netif_driver *netif_drivers[] = {
*/
struct file_format *file_formats[] = {
- &uboot_elf,
- NULL
+ &uboot_elf,
+ NULL
};
/*
@@ -104,6 +104,6 @@ struct file_format *file_formats[] = {
extern struct console uboot_console;
struct console *consoles[] = {
- &uboot_console,
- NULL
+ &uboot_console,
+ NULL
};
diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c
index f7a0745..1ebb097 100644
--- a/sys/boot/uboot/common/main.c
+++ b/sys/boot/uboot/common/main.c
@@ -216,6 +216,7 @@ COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
command_reboot(int argc, char *argv[])
{
+
printf("Resetting...\n");
ub_reset();
diff --git a/sys/boot/uboot/lib/devicename.c b/sys/boot/uboot/lib/devicename.c
index 3183ae1..5d91550 100644
--- a/sys/boot/uboot/lib/devicename.c
+++ b/sys/boot/uboot/lib/devicename.c
@@ -35,7 +35,8 @@ __FBSDID("$FreeBSD$");
#include "bootstrap.h"
#include "libuboot.h"
-static int uboot_parsedev(struct uboot_devdesc **dev, const char *devspec, const char **path);
+static int uboot_parsedev(struct uboot_devdesc **dev, const char *devspec,
+ const char **path);
/*
* Point (dev) at an allocated device specifier for the device matching the
@@ -178,11 +179,11 @@ uboot_parsedev(struct uboot_devdesc **dev, const char *devspec,
} else {
*dev = idev;
}
- return(0);
+ return (0);
fail:
free(idev);
- return(err);
+ return (err);
}
@@ -191,7 +192,7 @@ uboot_fmtdev(void *vdev)
{
struct uboot_devdesc *dev = (struct uboot_devdesc *)vdev;
char *cp;
- static char buf[128]; /* XXX device length constant? */
+ static char buf[128];
switch(dev->d_type) {
case DEVT_NONE:
@@ -220,12 +221,12 @@ uboot_fmtdev(void *vdev)
int
uboot_setcurrdev(struct env_var *ev, int flags, const void *value)
{
- struct uboot_devdesc *ncurr;
- int rv;
+ struct uboot_devdesc *ncurr;
+ int rv;
if ((rv = uboot_parsedev(&ncurr, value, NULL)) != 0)
- return(rv);
+ return (rv);
free(ncurr);
env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
- return(0);
+ return (0);
}
diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c
index a6dc99e..e6695cf 100644
--- a/sys/boot/zfs/zfsimpl.c
+++ b/sys/boot/zfs/zfsimpl.c
@@ -873,17 +873,12 @@ dnode_read(spa_t *spa, const dnode_phys_t *dnode, off_t offset, void *buf, size_
int i, rc;
/*
- * We truncate the offset to 32bits, mainly so that I don't
- * have to find a copy of __divdi3 to put into the bootstrap.
- * I don't think the bootstrap needs to access anything bigger
- * than 2G anyway. Note that block addresses are still 64bit
- * so it doesn't affect the possible size of the media.
- * We still use 64bit block numbers so that the bitshifts
- * work correctly. Note: bsize may not be a power of two here.
+ * Note: bsize may not be a power of two here so we need to do an
+ * actual divide rather than a bitshift.
*/
while (buflen > 0) {
- uint64_t bn = ((int) offset) / bsize;
- int boff = ((int) offset) % bsize;
+ uint64_t bn = offset / bsize;
+ int boff = offset % bsize;
int ibn;
const blkptr_t *indbp;
blkptr_t bp;
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 26fbc6e..3abeed8 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -290,7 +290,7 @@ cam_periph_acquire(struct cam_periph *periph)
}
void
-cam_periph_release(struct cam_periph *periph)
+cam_periph_release_locked(struct cam_periph *periph)
{
if (periph == NULL)
@@ -302,7 +302,21 @@ cam_periph_release(struct cam_periph *periph)
camperiphfree(periph);
}
xpt_unlock_buses();
+}
+
+void
+cam_periph_release(struct cam_periph *periph)
+{
+ struct cam_sim *sim;
+ if (periph == NULL)
+ return;
+
+ sim = periph->sim;
+ mtx_assert(sim->mtx, MA_NOTOWNED);
+ mtx_lock(sim->mtx);
+ cam_periph_release_locked(periph);
+ mtx_unlock(sim->mtx);
}
int
@@ -311,8 +325,6 @@ cam_periph_hold(struct cam_periph *periph, int priority)
struct mtx *mtx;
int error;
- mtx_assert(periph->sim->mtx, MA_OWNED);
-
/*
* Increment the reference count on the peripheral
* while we wait for our lock attempt to succeed
@@ -324,13 +336,14 @@ cam_periph_hold(struct cam_periph *periph, int priority)
return (ENXIO);
mtx = periph->sim->mtx;
+ mtx_assert(mtx, MA_OWNED);
if (mtx == &Giant)
mtx = NULL;
while ((periph->flags & CAM_PERIPH_LOCKED) != 0) {
periph->flags |= CAM_PERIPH_LOCK_WANTED;
if ((error = msleep(periph, mtx, priority, "caplck", 0)) != 0) {
- cam_periph_release(periph);
+ cam_periph_release_locked(periph);
return (error);
}
}
@@ -351,7 +364,7 @@ cam_periph_unhold(struct cam_periph *periph)
wakeup(periph);
}
- cam_periph_release(periph);
+ cam_periph_release_locked(periph);
}
/*
diff --git a/sys/cam/cam_periph.h b/sys/cam/cam_periph.h
index e6073d9..8a45806 100644
--- a/sys/cam/cam_periph.h
+++ b/sys/cam/cam_periph.h
@@ -141,6 +141,7 @@ cam_status cam_periph_alloc(periph_ctor_t *periph_ctor,
struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
cam_status cam_periph_acquire(struct cam_periph *periph);
void cam_periph_release(struct cam_periph *periph);
+void cam_periph_release_locked(struct cam_periph *periph);
int cam_periph_hold(struct cam_periph *periph, int priority);
void cam_periph_unhold(struct cam_periph *periph);
void cam_periph_invalidate(struct cam_periph *periph);
diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c
index cfc2044..adccfa8 100644
--- a/sys/cam/cam_sim.c
+++ b/sys/cam/cam_sim.c
@@ -84,6 +84,7 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
sim->max_tagged_dev_openings = max_tagged_dev_transactions;
sim->max_dev_openings = max_dev_transactions;
sim->flags = 0;
+ sim->refcount = 1;
sim->devq = queue;
sim->mtx = mtx;
if (mtx == &Giant) {
@@ -103,12 +104,42 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
void
cam_sim_free(struct cam_sim *sim, int free_devq)
{
+ int error;
+
+ sim->refcount--;
+ if (sim->refcount > 0) {
+ error = msleep(sim, sim->mtx, PRIBIO, "simfree", 0);
+ KASSERT(error == 0, ("invalid error value for msleep(9)"));
+ }
+
+ KASSERT(sim->refcount == 0, ("sim->refcount == 0"));
+
if (free_devq)
cam_simq_free(sim->devq);
free(sim, M_CAMSIM);
}
void
+cam_sim_release(struct cam_sim *sim)
+{
+ KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
+ mtx_assert(sim->mtx, MA_OWNED);
+
+ sim->refcount--;
+ if (sim->refcount == 0)
+ wakeup(sim);
+}
+
+void
+cam_sim_hold(struct cam_sim *sim)
+{
+ KASSERT(sim->refcount >= 1, ("sim->refcount >= 1"));
+ mtx_assert(sim->mtx, MA_OWNED);
+
+ sim->refcount++;
+}
+
+void
cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id)
{
sim->path_id = path_id;
diff --git a/sys/cam/cam_sim.h b/sys/cam/cam_sim.h
index c2d3c5f..f37c5d5 100644
--- a/sys/cam/cam_sim.h
+++ b/sys/cam/cam_sim.h
@@ -61,6 +61,8 @@ struct cam_sim * cam_sim_alloc(sim_action_func sim_action,
int max_tagged_dev_transactions,
struct cam_devq *queue);
void cam_sim_free(struct cam_sim *sim, int free_devq);
+void cam_sim_hold(struct cam_sim *sim);
+void cam_sim_release(struct cam_sim *sim);
/* Optional sim attributes may be set with these. */
void cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id);
@@ -105,6 +107,7 @@ struct cam_sim {
#define CAM_SIM_ON_DONEQ 0x04
struct callout callout;
struct cam_devq *devq; /* Device Queue to use for this SIM */
+ int refcount; /* References to the SIM. */
/* "Pool" of inactive ccbs managed by xpt_alloc_ccb and xpt_free_ccb */
SLIST_HEAD(,ccb_hdr) ccb_freeq;
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index b400e42..f2a2d9d 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -698,19 +698,6 @@ static struct cdevsw xpt_cdevsw = {
};
-static void dead_sim_action(struct cam_sim *sim, union ccb *ccb);
-static void dead_sim_poll(struct cam_sim *sim);
-
-/* Dummy SIM that is used when the real one has gone. */
-static struct cam_sim cam_dead_sim = {
- .sim_action = dead_sim_action,
- .sim_poll = dead_sim_poll,
- .sim_name = "dead_sim",
-};
-
-#define SIM_DEAD(sim) ((sim) == &cam_dead_sim)
-
-
/* Storage for debugging datastructures */
#ifdef CAMDEBUG
struct cam_path *cam_dpath;
@@ -3023,19 +3010,10 @@ xpt_action(union ccb *start_ccb)
case XPT_ENG_EXEC:
{
struct cam_path *path;
- struct cam_sim *sim;
int runq;
path = start_ccb->ccb_h.path;
- sim = path->bus->sim;
- if (SIM_DEAD(sim)) {
- /* The SIM has gone; just execute the CCB directly. */
- cam_ccbq_send_ccb(&path->device->ccbq, start_ccb);
- (*(sim->sim_action))(sim, start_ccb);
- break;
- }
-
cam_ccbq_insert_ccb(&path->device->ccbq, start_ccb);
if (path->device->qfrozen_cnt == 0)
runq = xpt_schedule_dev_sendq(path->bus, path->device);
@@ -3623,7 +3601,6 @@ void
xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
{
struct cam_ed *device;
- union ccb *work_ccb;
int runq;
mtx_assert(perph->sim->mtx, MA_OWNED);
@@ -3640,15 +3617,6 @@ xpt_schedule(struct cam_periph *perph, u_int32_t new_priority)
new_priority);
}
runq = 0;
- } else if (SIM_DEAD(perph->path->bus->sim)) {
- /* The SIM is gone so just call periph_start directly. */
- work_ccb = xpt_get_ccb(perph->path->device);
- if (work_ccb == NULL)
- return; /* XXX */
- xpt_setup_ccb(&work_ccb->ccb_h, perph->path, new_priority);
- perph->pinfo.priority = new_priority;
- perph->periph_start(perph, work_ccb);
- return;
} else {
/* New entry on the queue */
CAM_DEBUG(perph->path, CAM_DEBUG_SUBTRACE,
@@ -4336,6 +4304,7 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
TAILQ_INIT(&new_bus->et_entries);
new_bus->path_id = sim->path_id;
+ cam_sim_hold(sim);
new_bus->sim = sim;
timevalclear(&new_bus->last_reset);
new_bus->flags = 0;
@@ -4372,15 +4341,8 @@ int32_t
xpt_bus_deregister(path_id_t pathid)
{
struct cam_path bus_path;
- struct cam_ed *device;
- struct cam_ed_qinfo *qinfo;
- struct cam_devq *devq;
- struct cam_periph *periph;
- struct cam_sim *ccbsim;
- union ccb *work_ccb;
cam_status status;
-
status = xpt_compile_path(&bus_path, NULL, pathid,
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
if (status != CAM_REQ_CMP)
@@ -4389,42 +4351,6 @@ xpt_bus_deregister(path_id_t pathid)
xpt_async(AC_LOST_DEVICE, &bus_path, NULL);
xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL);
- /* The SIM may be gone, so use a dummy SIM for any stray operations. */
- devq = bus_path.bus->sim->devq;
- ccbsim = bus_path.bus->sim;
- bus_path.bus->sim = &cam_dead_sim;
-
- /* Execute any pending operations now. */
- while ((qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->send_queue,
- CAMQ_HEAD)) != NULL ||
- (qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->alloc_queue,
- CAMQ_HEAD)) != NULL) {
- do {
- device = qinfo->device;
- work_ccb = cam_ccbq_peek_ccb(&device->ccbq, CAMQ_HEAD);
- if (work_ccb != NULL) {
- devq->active_dev = device;
- cam_ccbq_remove_ccb(&device->ccbq, work_ccb);
- cam_ccbq_send_ccb(&device->ccbq, work_ccb);
- (*(ccbsim->sim_action))(ccbsim, work_ccb);
- }
-
- periph = (struct cam_periph *)camq_remove(&device->drvq,
- CAMQ_HEAD);
- if (periph != NULL)
- xpt_schedule(periph, periph->pinfo.priority);
- } while (work_ccb != NULL || periph != NULL);
- }
-
- /* Make sure all completed CCBs are processed. */
- while (!TAILQ_EMPTY(&ccbsim->sim_doneq)) {
- camisr_runqueue(&ccbsim->sim_doneq);
-
- /* Repeat the async's for the benefit of any new devices. */
- xpt_async(AC_LOST_DEVICE, &bus_path, NULL);
- xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL);
- }
-
/* Release the reference count held while registered. */
xpt_release_bus(bus_path.bus);
xpt_release_path(&bus_path);
@@ -4921,6 +4847,7 @@ xpt_release_bus(struct cam_eb *bus)
TAILQ_REMOVE(&xsoftc.xpt_busses, bus, links);
xsoftc.bus_generation++;
mtx_unlock(&xsoftc.xpt_topo_lock);
+ cam_sim_release(bus->sim);
free(bus, M_CAMXPT);
}
}
@@ -4982,9 +4909,6 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
struct cam_devq *devq;
cam_status status;
- if (SIM_DEAD(bus->sim))
- return (NULL);
-
/* Make space for us in the device queue on our bus */
devq = bus->sim->devq;
status = cam_devq_resize(devq, devq->alloc_queue.array_size + 1);
@@ -5094,11 +5018,9 @@ xpt_release_device(struct cam_eb *bus, struct cam_et *target,
TAILQ_REMOVE(&target->ed_entries, device,links);
target->generation++;
bus->sim->max_ccbs -= device->ccbq.devq_openings;
- if (!SIM_DEAD(bus->sim)) {
- /* Release our slot in the devq */
- devq = bus->sim->devq;
- cam_devq_resize(devq, devq->alloc_queue.array_size - 1);
- }
+ /* Release our slot in the devq */
+ devq = bus->sim->devq;
+ cam_devq_resize(devq, devq->alloc_queue.array_size - 1);
camq_fini(&device->drvq);
camq_fini(&device->ccbq.queue);
free(device, M_CAMXPT);
@@ -6392,7 +6314,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_done(done_ccb);
if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
cam_periph_invalidate(periph);
- cam_periph_release(periph);
+ cam_periph_release_locked(periph);
} else {
probeschedule(periph);
}
@@ -7269,11 +7191,8 @@ camisr_runqueue(void *V_queue)
dev = ccb_h->path->device;
cam_ccbq_ccb_done(&dev->ccbq, (union ccb *)ccb_h);
-
- if (!SIM_DEAD(ccb_h->path->bus->sim)) {
- ccb_h->path->bus->sim->devq->send_active--;
- ccb_h->path->bus->sim->devq->send_openings++;
- }
+ ccb_h->path->bus->sim->devq->send_active--;
+ ccb_h->path->bus->sim->devq->send_openings++;
if (((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0
&& (ccb_h->status&CAM_STATUS_MASK) != CAM_REQUEUE_REQ)
@@ -7317,15 +7236,3 @@ camisr_runqueue(void *V_queue)
}
}
-static void
-dead_sim_action(struct cam_sim *sim, union ccb *ccb)
-{
-
- ccb->ccb_h.status = CAM_DEV_NOT_THERE;
- xpt_done(ccb);
-}
-
-static void
-dead_sim_poll(struct cam_sim *sim)
-{
-}
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index f63a9b0..8797a08 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -772,8 +772,8 @@ daclose(struct disk *dp)
softc->flags &= ~DA_FLAG_OPEN;
cam_periph_unhold(periph);
- cam_periph_release(periph);
cam_periph_unlock(periph);
+ cam_periph_release(periph);
return (0);
}
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 63e8e54..0030e3a 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -218,8 +218,6 @@ svr4_fixup(register_t **stack_base, struct image_params *imgp)
args = (Elf32_Auxargs *)imgp->auxargs;
pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace)
- AUXARGS_ENTRY(pos, AT_DEBUG, 1);
if (args->execfd != -1)
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 4c66d14..6825dd4 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -1958,7 +1958,7 @@ device fatm #Fore PCA200E
device hatm #Fore/Marconi HE155/622
device patm #IDT77252 cards (ProATM and IDT)
device utopia #ATM PHY driver
-options NATM #native ATM
+#options NATM #native ATM
options LIBMBPOOL #needed by patm, iatm
diff --git a/sys/conf/files b/sys/conf/files
index 8c2316fa..68fb14e 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2173,6 +2173,7 @@ net/if_gre.c optional gre
net/if_iso88025subr.c optional token
net/if_lagg.c optional lagg
net/if_loop.c optional loop
+net/if_llatbl.c standard
net/if_media.c standard
net/if_mib.c standard
net/if_ppp.c optional ppp
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 7570d93..901e36d 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -30,9 +30,11 @@ dev/kbd/kbd.c optional sc
dev/ofw/openfirm.c optional aim
dev/ofw/openfirmio.c optional aim
dev/ofw/ofw_bus_if.m optional aim
+dev/ofw/ofw_if.m optional aim
dev/ofw/ofw_bus_subr.c optional aim
dev/ofw/ofw_console.c optional aim
dev/ofw/ofw_disk.c optional ofwd aim
+dev/ofw/ofw_standard.c optional aim
dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
dev/quicc/quicc_bfe_ocp.c optional quicc mpc85xx
dev/scc/scc_bfe_macio.c optional scc powermac
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 93f07ed..311027c 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -42,8 +42,10 @@ dev/kbd/kbd.c optional atkbd | sc | ukbd
dev/le/if_le_lebuffer.c optional le sbus
dev/le/if_le_ledma.c optional le sbus
dev/le/lebuffer_sbus.c optional le sbus
+dev/ofw/ofw_if.m standard
dev/ofw/ofw_bus_if.m standard
dev/ofw/ofw_bus_subr.c standard
+dev/ofw/ofw_standard.c standard
dev/ofw/ofw_console.c optional ofw_console
dev/ofw/openfirm.c standard
dev/ofw/openfirmio.c standard
@@ -111,7 +113,6 @@ sparc64/sparc64/mp_exception.S optional smp \
sparc64/sparc64/mp_locore.S optional smp
sparc64/sparc64/mp_machdep.c optional smp
sparc64/sparc64/nexus.c standard
-sparc64/sparc64/ofw_bus.c standard
sparc64/sparc64/ofw_machdep.c standard
sparc64/sparc64/pmap.c standard
sparc64/sparc64/prof_machdep.c optional profiling-routine
diff --git a/sys/conf/files.sun4v b/sys/conf/files.sun4v
index 03fca35..384c13a 100644
--- a/sys/conf/files.sun4v
+++ b/sys/conf/files.sun4v
@@ -21,8 +21,10 @@ ukbdmap.h optional ukbd_dflt_keymap \
crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
dev/ofw/ofw_bus_if.m standard
+dev/ofw/ofw_if.m standard
dev/ofw/ofw_bus_subr.c standard
dev/ofw/ofw_console.c optional ofw_console
+dev/ofw/ofw_standard.c standard
dev/ofw/openfirm.c standard
dev/ofw/openfirmio.c standard
dev/ofw/openpromio.c standard
@@ -65,7 +67,6 @@ sun4v/sun4v/mp_locore.S optional smp
sun4v/sun4v/mp_machdep.c optional smp
sun4v/sun4v/nexus.c standard
sun4v/cddl/t1_copy.S standard
-sparc64/sparc64/ofw_bus.c standard
sparc64/sparc64/ofw_machdep.c standard
sun4v/sun4v/pmap.c standard
sparc64/sparc64/prof_machdep.c optional profiling-routine
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 2959830..d69372b 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -3162,7 +3162,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
#ifdef RTF_PRCLONING
rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING));
#else /* !RTF_PRCLONING */
- in_rtalloc_ign(&ro, RTF_CLONING, 0);
+ in_rtalloc_ign(&ro, 0, 0);
#endif
#else /* ! __FreeBSD__ */
rtalloc_noclone(&ro, NO_CLONING);
@@ -3183,7 +3183,7 @@ pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
rtalloc_ign((struct route *)&ro6,
(RTF_CLONING | RTF_PRCLONING));
#else /* !RTF_PRCLONING */
- rtalloc_ign((struct route *)&ro6, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro6, 0);
#endif
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro6, NO_CLONING);
@@ -5986,9 +5986,9 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
#ifdef __FreeBSD__
/* XXX MRT not always INET */ /* stick with table 0 though */
if (af == AF_INET)
- in_rtalloc_ign((struct route *)&ro, RTF_CLONING, 0);
+ in_rtalloc_ign((struct route *)&ro, 0, 0);
else
- rtalloc_ign((struct route *)&ro, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro, 0);
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro, NO_CLONING);
#endif
@@ -6068,9 +6068,9 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
rtalloc_ign((struct route *)&ro, (RTF_CLONING|RTF_PRCLONING));
# else /* !RTF_PRCLONING */
if (af == AF_INET)
- in_rtalloc_ign((struct route *)&ro, RTF_CLONING, 0);
+ in_rtalloc_ign((struct route *)&ro, 0, 0);
else
- rtalloc_ign((struct route *)&ro, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro, 0);
# endif
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro, NO_CLONING);
diff --git a/sys/contrib/pf/net/pf_if.c b/sys/contrib/pf/net/pf_if.c
index 62dbbf2..1972edc 100644
--- a/sys/contrib/pf/net/pf_if.c
+++ b/sys/contrib/pf/net/pf_if.c
@@ -115,8 +115,10 @@ void pfi_change_group_event(void * __unused, char *);
void pfi_detach_group_event(void * __unused, struct ifg_group *);
void pfi_ifaddr_event(void * __unused, struct ifnet *);
+#ifdef VIMAGE_GLOBALS
extern struct ifgrouphead ifg_head;
#endif
+#endif
RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
diff --git a/sys/contrib/pf/net/pf_subr.c b/sys/contrib/pf/net/pf_subr.c
index 1ac8b40..a722aef 100644
--- a/sys/contrib/pf/net/pf_subr.c
+++ b/sys/contrib/pf/net/pf_subr.c
@@ -116,22 +116,22 @@ __FBSDID("$FreeBSD$");
#define ISN_STATIC_INCREMENT 4096
#define ISN_RANDOM_INCREMENT (4096 - 1)
-static u_char isn_secret[32];
-static int isn_last_reseed;
-static u_int32_t isn_offset;
-static MD5_CTX isn_ctx;
+static u_char pf_isn_secret[32];
+static int pf_isn_last_reseed;
+static u_int32_t pf_isn_offset;
u_int32_t
pf_new_isn(struct pf_state *s)
{
+ MD5_CTX isn_ctx;
u_int32_t md5_buffer[4];
u_int32_t new_isn;
struct pf_state_host *src, *dst;
/* Seed if this is the first use, reseed if requested. */
- if (isn_last_reseed == 0) {
- read_random(&isn_secret, sizeof(isn_secret));
- isn_last_reseed = ticks;
+ if (pf_isn_last_reseed == 0) {
+ read_random(&pf_isn_secret, sizeof(pf_isn_secret));
+ pf_isn_last_reseed = ticks;
}
if (s->direction == PF_IN) {
@@ -160,11 +160,11 @@ pf_new_isn(struct pf_state *s)
MD5Update(&isn_ctx, (u_char *) &src->addr,
sizeof(struct in_addr));
}
- MD5Update(&isn_ctx, (u_char *) &isn_secret, sizeof(isn_secret));
+ MD5Update(&isn_ctx, (u_char *) &pf_isn_secret, sizeof(pf_isn_secret));
MD5Final((u_char *) &md5_buffer, &isn_ctx);
new_isn = (tcp_seq) md5_buffer[0];
- isn_offset += ISN_STATIC_INCREMENT +
+ pf_isn_offset += ISN_STATIC_INCREMENT +
(arc4random() & ISN_RANDOM_INCREMENT);
- new_isn += isn_offset;
+ new_isn += pf_isn_offset;
return (new_isn);
}
diff --git a/sys/contrib/rdma/rdma_addr.c b/sys/contrib/rdma/rdma_addr.c
index e052b80..971b4de 100644
--- a/sys/contrib/rdma/rdma_addr.c
+++ b/sys/contrib/rdma/rdma_addr.c
@@ -163,6 +163,7 @@ static void addr_send_arp(struct sockaddr_in *dst_in)
struct route iproute;
struct sockaddr_in *dst = (struct sockaddr_in *)&iproute.ro_dst;
char dmac[ETHER_ADDR_LEN];
+ struct llentry *lle;
bzero(&iproute, sizeof iproute);
*dst = *dst_in;
@@ -172,7 +173,7 @@ static void addr_send_arp(struct sockaddr_in *dst_in)
return;
arpresolve(iproute.ro_rt->rt_ifp, iproute.ro_rt, NULL,
- rt_key(iproute.ro_rt), dmac);
+ rt_key(iproute.ro_rt), dmac, &lle);
RTFREE(iproute.ro_rt);
}
@@ -186,6 +187,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in,
struct route iproute;
struct sockaddr_in *dst = (struct sockaddr_in *)&iproute.ro_dst;
char dmac[ETHER_ADDR_LEN];
+ struct llentry *lle;
bzero(&iproute, sizeof iproute);
*dst = *dst_in;
@@ -202,7 +204,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in,
goto put;
}
ret = arpresolve(iproute.ro_rt->rt_ifp, iproute.ro_rt, NULL,
- rt_key(iproute.ro_rt), dmac);
+ rt_key(iproute.ro_rt), dmac, &lle);
if (ret) {
goto put;
}
diff --git a/sys/crypto/rc4/rc4.c b/sys/crypto/rc4/rc4.c
index f94a554..dbdbd7a 100644
--- a/sys/crypto/rc4/rc4.c
+++ b/sys/crypto/rc4/rc4.c
@@ -61,7 +61,7 @@ void
rc4_init(struct rc4_state *const state, const u_char *key, int keylen)
{
u_char j;
- int i;
+ int i, k;
/* Initialize state with identity permutation */
for (i = 0; i < 256; i++)
@@ -70,9 +70,11 @@ rc4_init(struct rc4_state *const state, const u_char *key, int keylen)
state->index2 = 0;
/* Randomize the permutation using key data */
- for (j = i = 0; i < 256; i++) {
- j += state->perm[i] + key[i % keylen];
+ for (j = i = k = 0; i < 256; i++) {
+ j += state->perm[i] + key[k];
swap_bytes(&state->perm[i], &state->perm[j]);
+ if (++k >= keylen)
+ k = 0;
}
}
diff --git a/sys/dev/acpica/acpi_smbat.c b/sys/dev/acpica/acpi_smbat.c
index 5e1c66e..3935a9f 100644
--- a/sys/dev/acpica/acpi_smbat.c
+++ b/sys/dev/acpica/acpi_smbat.c
@@ -61,6 +61,23 @@ static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst);
ACPI_SERIAL_DECL(smbat, "ACPI Smart Battery");
+SYSCTL_DECL(_debug_acpi);
+SYSCTL_NODE(_debug_acpi, OID_AUTO, batt, CTLFLAG_RD, NULL, "Battery debugging");
+
+/* On some laptops with smart batteries, enabling battery monitoring
+ * software causes keystrokes from atkbd to be lost. This has also been
+ * reported on Linux, and is apparently due to the keyboard and I2C line
+ * for the battery being routed through the same chip. Whether that's
+ * accurate or not, adding extra sleeps to the status checking code
+ * causes the problem to go away.
+ *
+ * If you experience that problem, try a value of 10ms and move up
+ * from there.
+ */
+static int batt_sleep_ms;
+SYSCTL_INT(_debug_acpi_batt, OID_AUTO, batt_sleep_ms, CTLFLAG_RW, &batt_sleep_ms, 0,
+ "Sleep during battery status updates to prevent keystroke loss.");
+
static device_method_t acpi_smbat_methods[] = {
/* device interface */
DEVMETHOD(device_probe, acpi_smbat_probe),
@@ -176,6 +193,9 @@ acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
ACPI_SERIAL_ASSERT(smbat);
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
val = addr;
error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
val, 1);
@@ -194,6 +214,9 @@ acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (error)
goto out;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
for (to = SMBUS_TIMEOUT; to != 0; to--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
&val, 1);
@@ -239,6 +262,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
ACPI_SERIAL_ASSERT(smbat);
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
val = addr;
error = ACPI_EC_WRITE(sc->ec_dev, sc->sb_base_addr + SMBUS_ADDR,
val, 1);
@@ -257,6 +283,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (error)
goto out;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
for (to = SMBUS_TIMEOUT; to != 0; to--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_PRTCL,
&val, 1);
@@ -292,6 +321,9 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
if (len > val)
len = val;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
+
while (len--) {
error = ACPI_EC_READ(sc->ec_dev, sc->sb_base_addr + SMBUS_DATA
+ len, &val, 1);
@@ -299,6 +331,8 @@ acpi_smbus_read_multi_1(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
goto out;
ptr[len] = val;
+ if (batt_sleep_ms)
+ AcpiOsSleep(batt_sleep_ms);
}
out:
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 855a1d0..f2e4805 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -92,7 +92,8 @@ ata_pci_attach(device_t dev)
int unit;
/* do chipset specific setups only needed once */
- if (ata_legacy(dev) || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
+ ctlr->legacy = ata_legacy(dev);
+ if (ctlr->legacy || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK)
ctlr->channels = 2;
else
ctlr->channels = 1;
@@ -120,7 +121,7 @@ ata_pci_attach(device_t dev)
/* attach all channels on this controller */
for (unit = 0; unit < ctlr->channels; unit++) {
- if ((unit == 0 || unit == 1) && ata_legacy(dev)) {
+ if ((unit == 0 || unit == 1) && ctlr->legacy) {
device_add_child(dev, "ata", unit);
continue;
}
@@ -192,7 +193,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
if (type == SYS_RES_IOPORT) {
switch (*rid) {
case ATA_IOADDR_RID:
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
count = ATA_IOSIZE;
end = start + count - 1;
@@ -204,7 +205,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
break;
case ATA_CTLADDR_RID:
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET;
count = ATA_CTLIOSIZE;
end = start + count - 1;
@@ -217,7 +218,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
}
if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
int irq = (unit == 0 ? 14 : 15);
res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
@@ -233,6 +234,7 @@ int
ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
+ struct ata_pci_controller *controller = device_get_softc(dev);
int unit = ((struct ata_channel *)device_get_softc(child))->unit;
if (type == SYS_RES_IOPORT) {
@@ -256,7 +258,7 @@ ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
if (rid != ATA_IRQ_RID)
return ENOENT;
- if (ata_legacy(dev)) {
+ if (controller->legacy) {
return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
SYS_RES_IRQ, rid, r);
}
@@ -271,7 +273,9 @@ ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq,
int flags, driver_filter_t *filter, driver_intr_t *function,
void *argument, void **cookiep)
{
- if (ata_legacy(dev)) {
+ struct ata_pci_controller *controller = device_get_softc(dev);
+
+ if (controller->legacy) {
return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
flags, filter, function, argument, cookiep);
}
@@ -294,7 +298,9 @@ int
ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
void *cookie)
{
- if (ata_legacy(dev)) {
+ struct ata_pci_controller *controller = device_get_softc(dev);
+
+ if (controller->legacy) {
return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
}
else {
@@ -352,7 +358,7 @@ ata_pci_allocate(device_t dev)
ch->r_io[i].offset = i;
}
ch->r_io[ATA_CONTROL].res = ctlio;
- ch->r_io[ATA_CONTROL].offset = ata_legacy(device_get_parent(dev)) ? 0 : 2;
+ ch->r_io[ATA_CONTROL].offset = ctlr->legacy ? 0 : 2;
ch->r_io[ATA_IDX_ADDR].res = io;
ata_default_registers(dev);
if (ctlr->r_res1) {
@@ -369,9 +375,11 @@ ata_pci_allocate(device_t dev)
int
ata_pci_status(device_t dev)
{
+ struct ata_pci_controller *controller =
+ device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- if ((dumping || !ata_legacy(device_get_parent(dev))) &&
+ if ((dumping || !controller->legacy) &&
((ch->flags & ATA_ALWAYS_DMASTAT) ||
(ch->dma.flags & ATA_DMA_ACTIVE))) {
int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK;
@@ -652,7 +660,7 @@ ata_setup_interrupt(device_t dev, void *intr_func)
struct ata_pci_controller *ctlr = device_get_softc(dev);
int rid = ATA_IRQ_RID;
- if (!ata_legacy(dev)) {
+ if (!ctlr->legacy) {
if (!(ctlr->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE | RF_ACTIVE))) {
device_printf(dev, "unable to map interrupt\n");
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 0cbb0d5..e5edd87 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -48,6 +48,7 @@ struct ata_pci_controller {
struct resource *r_irq;
void *handle;
struct ata_chip_id *chip;
+ int legacy;
int channels;
int (*chipinit)(device_t);
int (*suspend)(device_t);
diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c
index 4481d9a..4028466 100644
--- a/sys/dev/ata/chipsets/ata-ahci.c
+++ b/sys/dev/ata/chipsets/ata-ahci.c
@@ -73,8 +73,9 @@ ata_ahci_probe(device_t dev)
char buffer[64];
/* is this a possible AHCI candidate ? */
- if (pci_get_subclass(dev) != PCIS_STORAGE_SATA)
- return ENXIO;
+ if (pci_get_class(dev) != PCIC_STORAGE ||
+ pci_get_subclass(dev) != PCIS_STORAGE_SATA)
+ return (ENXIO);
/* is this PCI device flagged as an AHCI compliant chip ? */
if (pci_read_config(dev, PCIR_PROGIF, 1) != PCIP_STORAGE_SATA_AHCI_1_0)
@@ -94,6 +95,7 @@ int
ata_ahci_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
+ int error;
u_int32_t version;
/* if we have a memory BAR(5) we are likely on an AHCI part */
@@ -105,14 +107,19 @@ ata_ahci_chipinit(device_t dev)
/* setup interrupt delivery if not done allready by a vendor driver */
if (!ctlr->r_irq) {
- if (ata_setup_interrupt(dev, ata_generic_intr))
+ if (ata_setup_interrupt(dev, ata_generic_intr)) {
+ bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
return ENXIO;
+ }
}
else
device_printf(dev, "AHCI called from vendor specific driver\n");
/* reset controller */
- ata_ahci_ctlr_reset(dev);
+ if ((error = ata_ahci_ctlr_reset(dev)) != 0) {
+ bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
+ return (error);
+ };
/* get the number of HW channels */
ctlr->channels =
@@ -154,7 +161,6 @@ ata_ahci_ctlr_reset(device_t dev)
ATA_OUTL(ctlr->r_res2, ATA_AHCI_GHC, ATA_AHCI_GHC_HR);
DELAY(1000000);
if (ATA_INL(ctlr->r_res2, ATA_AHCI_GHC) & ATA_AHCI_GHC_HR) {
- bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
device_printf(dev, "AHCI controller reset failure\n");
return ENXIO;
}
diff --git a/sys/dev/ata/chipsets/ata-sis.c b/sys/dev/ata/chipsets/ata-sis.c
index e94bef5..56b194d 100644
--- a/sys/dev/ata/chipsets/ata-sis.c
+++ b/sys/dev/ata/chipsets/ata-sis.c
@@ -105,6 +105,9 @@ ata_sis_probe(device_t dev)
char buffer[64];
int found = 0;
+ if (pci_get_class(dev) != PCIC_STORAGE)
+ return (ENXIO);
+
if (pci_get_vendor(dev) != ATA_SIS_ID)
return ENXIO;
diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
index 18d31ec..668ace7 100644
--- a/sys/dev/ath/ath_hal/ah.c
+++ b/sys/dev/ath/ath_hal/ah.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ah.c,v 1.15 2008/11/15 22:15:44 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -32,7 +32,7 @@ OS_SET_DECLARE(ah_chips, struct ath_hal_chip);
const char*
ath_hal_probe(uint16_t vendorid, uint16_t devid)
{
- struct ath_hal_chip **pchip;
+ struct ath_hal_chip * const *pchip;
OS_SET_FOREACH(pchip, ah_chips) {
const char *name = (*pchip)->probe(vendorid, devid);
@@ -53,7 +53,7 @@ struct ath_hal*
ath_hal_attach(uint16_t devid, HAL_SOFTC sc,
HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *error)
{
- struct ath_hal_chip **pchip;
+ struct ath_hal_chip * const *pchip;
OS_SET_FOREACH(pchip, ah_chips) {
struct ath_hal_chip *chip = *pchip;
@@ -88,7 +88,7 @@ OS_SET_DECLARE(ah_rfs, struct ath_hal_rf);
struct ath_hal_rf *
ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode)
{
- struct ath_hal_rf **prf;
+ struct ath_hal_rf * const *prf;
OS_SET_FOREACH(prf, ah_rfs) {
struct ath_hal_rf *rf = *prf;
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v14.c b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
index 45f998f..8793d3b 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v14.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
@@ -160,18 +160,6 @@ v14EepromDiag(struct ath_hal *ah, int request,
return AH_FALSE;
}
-/* XXX conditionalize by target byte order */
-#ifndef bswap16
-static __inline__ uint16_t
-__bswap16(uint16_t _x)
-{
- return ((uint16_t)(
- (((const uint8_t *)(&_x))[0] ) |
- (((const uint8_t *)(&_x))[1]<< 8))
- );
-}
-#endif
-
/* Do structure specific swaps if Eeprom format is non native to host */
static void
eepromSwap(struct ar5416eeprom *ee)
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v3.c b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
index b2c304b..20adb31 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v3.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v3.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ah_eeprom_v3.c,v 1.4 2008/11/27 22:39:42 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -26,9 +26,9 @@ static void
getPcdacInterceptsFromPcdacMinMax(HAL_EEPROM *ee,
uint16_t pcdacMin, uint16_t pcdacMax, uint16_t *vp)
{
- const static uint16_t intercepts3[] =
+ static const uint16_t intercepts3[] =
{ 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
- const static uint16_t intercepts3_2[] =
+ static const uint16_t intercepts3_2[] =
{ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
const uint16_t *ip = ee->ee_version < AR_EEPROM_VER3_2 ?
intercepts3 : intercepts3_2;
diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h
index da09c68..9feb295 100644
--- a/sys/dev/ath/ath_hal/ah_internal.h
+++ b/sys/dev/ath/ath_hal/ah_internal.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ah_internal.h,v 1.21 2008/11/27 22:29:27 sam Exp $
+ * $FreeBSD$
*/
#ifndef _ATH_AH_INTERAL_H_
#define _ATH_AH_INTERAL_H_
@@ -42,23 +42,6 @@
#define offsetof(type, field) ((size_t)(&((type *)0)->field))
#endif
-/*
- * Remove const in a way that keeps the compiler happy.
- * This works for gcc but may require other magic for
- * other compilers (not sure where this should reside).
- * Note that uintptr_t is C99.
- */
-#ifndef __DECONST
-#ifndef _UINTPTR_T
-#if AH_WORDSIZE == 64
-typedef unsigned long int uintptr_t;
-#else
-typedef unsigned int uintptr_t;
-#endif
-#endif
-#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
-#endif
-
typedef struct {
uint16_t start; /* first register */
uint16_t end; /* ending register or zero */
@@ -114,12 +97,12 @@ struct ath_hal_rf {
};
#ifndef AH_RF
#define AH_RF(_name, _probe, _attach) \
-static struct ath_hal_rf name##_rf = { \
- .name = #_name, \
+static struct ath_hal_rf _name##_rf = { \
+ .name = __STRING(_name), \
.probe = _probe, \
.attach = _attach \
}; \
-OS_DATA_SET(ah_rfs, name##_rf)
+OS_DATA_SET(ah_rfs, _name##_rf)
#endif
struct ath_hal_rf *ath_hal_rfprobe(struct ath_hal *ah, HAL_STATUS *ecode);
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5111.c b/sys/dev/ath/ath_hal/ar5212/ar5111.c
index 95dbbd5..f009ebe 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5111.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5111.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5111.c,v 1.7 2008/11/10 04:08:03 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -90,7 +90,7 @@ ar5111SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
uint16_t channel5111; /* 11a channel for 5111 */
} CHAN_INFO_2GHZ;
- const static CHAN_INFO_2GHZ chan2GHzData[] = {
+ static const CHAN_INFO_2GHZ chan2GHzData[] = {
{ 1, 0x46, 96 }, /* 2312 -19 */
{ 1, 0x46, 97 }, /* 2317 -18 */
{ 1, 0x46, 98 }, /* 2322 -17 */
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
index 645c56c..bef9c28e 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5212_ani.c,v 1.7 2008/11/21 00:16:21 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -267,7 +267,7 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
u_int level = param;
- if (level >= params->maxNoiseImmunityLevel) {
+ if (level > params->maxNoiseImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: level out of range (%u > %u)\n",
__func__, level, params->maxNoiseImmunityLevel);
@@ -342,7 +342,7 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
case HAL_ANI_FIRSTEP_LEVEL: {
u_int level = param;
- if (level >= params->maxFirstepLevel) {
+ if (level > params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: level out of range (%u > %u)\n",
__func__, level, params->maxFirstepLevel);
@@ -360,7 +360,7 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
case HAL_ANI_SPUR_IMMUNITY_LEVEL: {
u_int level = param;
- if (level >= params->maxSpurImmunityLevel) {
+ if (level > params->maxSpurImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: level out of range (%u > %u)\n",
__func__, level, params->maxSpurImmunityLevel);
@@ -433,7 +433,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
aniState = ahp->ah_curani;
params = aniState->params;
/* First, raise noise immunity level, up to max */
- if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+ if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
aniState->noiseImmunityLevel + 1);
ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
@@ -441,7 +441,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
return;
}
/* then, raise spur immunity level, up to max */
- if (aniState->spurImmunityLevel+1 < params->maxSpurImmunityLevel) {
+ if (aniState->spurImmunityLevel+1 <= params->maxSpurImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise SI to %u\n", __func__,
aniState->spurImmunityLevel + 1);
ar5212AniControl(ah, HAL_ANI_SPUR_IMMUNITY_LEVEL,
@@ -470,7 +470,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
* If weak sig detect is already off, as last resort,
* raise firstep level
*/
- if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+ if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI,
"%s: rssi %d raise ST %u\n", __func__, rssi,
aniState->firstepLevel+1);
@@ -490,7 +490,7 @@ ar5212AniOfdmErrTrigger(struct ath_hal *ah)
HAL_ANI_OFDM_WEAK_SIGNAL_DETECTION,
AH_TRUE);
}
- if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+ if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI,
"%s: rssi %d raise ST %u\n", __func__, rssi,
aniState->firstepLevel+1);
@@ -544,7 +544,7 @@ ar5212AniCckErrTrigger(struct ath_hal *ah)
/* first, raise noise immunity level, up to max */
aniState = ahp->ah_curani;
params = aniState->params;
- if (aniState->noiseImmunityLevel+1 < params->maxNoiseImmunityLevel) {
+ if (aniState->noiseImmunityLevel+1 <= params->maxNoiseImmunityLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI, "%s: raise NI to %u\n", __func__,
aniState->noiseImmunityLevel + 1);
ar5212AniControl(ah, HAL_ANI_NOISE_IMMUNITY_LEVEL,
@@ -559,7 +559,7 @@ ar5212AniCckErrTrigger(struct ath_hal *ah)
* Beacon signal in mid and high range,
* raise firstep level.
*/
- if (aniState->firstepLevel+1 < params->maxFirstepLevel) {
+ if (aniState->firstepLevel+1 <= params->maxFirstepLevel) {
HALDEBUG(ah, HAL_DEBUG_ANI,
"%s: rssi %d raise ST %u\n", __func__, rssi,
aniState->firstepLevel+1);
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312.h b/sys/dev/ath/ath_hal/ar5312/ar5312.h
index 4714ea1..4943891 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312.h
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312.h
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5312.h,v 1.5 2008/11/22 07:37:40 sam Exp $
+ * $FreeBSD$
*/
#ifndef _ATH_AR5312_H_
#define _ATH_AR5312_H_
@@ -38,8 +38,6 @@
AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV1 || \
AH_PRIVATE(ah)->ah_devid == AR5212_AR2317_REV2)
-extern struct ath_hal * ar5312Attach(uint16_t devid, HAL_SOFTC sc,
- HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status);
extern HAL_BOOL ar5312IsInterruptPending(struct ath_hal *ah);
/* AR5312 */
diff --git a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
index b5a2dde..e38c50c 100644
--- a/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
+++ b/sys/dev/ath/ath_hal/ar5312/ar5312_attach.c
@@ -14,7 +14,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: ar5312_attach.c,v 1.8 2008/11/27 22:30:03 sam Exp $
+ * $FreeBSD$
*/
#include "opt_ah.h"
@@ -122,7 +122,7 @@ ar5312Attach(uint16_t devid, HAL_SOFTC sc,
/* setup common ini data; rf backends handle remainder */
HAL_INI_INIT(&ahp->ah_ini_modes, ar5212Modes, 6);
- HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 6);
+ HAL_INI_INIT(&ahp->ah_ini_common, ar5212Common, 2);
if (!ar5312ChipReset(ah, AH_NULL)) { /* reset chip */
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
@@ -318,7 +318,6 @@ ar5312Probe(uint16_t vendorid, uint16_t devid)
case AR5212_AR2313_REV8:
return "Atheros 2313 WiSoC";
case AR5212_AR2315_REV6:
- case AR5212_AR2315_REV6:
case AR5212_AR2315_REV7:
return "Atheros 2315 WiSoC";
case AR5212_AR2317_REV1:
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index 2b1117f..338d8f2 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -3956,6 +3956,9 @@ static void
synaptics_sysctl_create_tree(struct psm_softc *sc)
{
+ if (sc->syninfo.sysctl_tree != NULL)
+ return;
+
/* Attach extra synaptics sysctl nodes under hw.psm.synaptics */
sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
@@ -4263,14 +4266,18 @@ enable_synaptics(struct psm_softc *sc)
kbdc = sc->kbdc;
VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n"));
- disable_aux_dev(kbdc);
sc->hw.buttons = 3;
sc->squelch = 0;
- /* Just to be on the safe side */
+ /*
+ * Just to be on the safe side: this avoids troubles with
+ * following mouse_ext_command() when the previous command
+ * was PSMC_SET_RESOLUTION. Set Scaling has no effect on
+ * Synaptics Touchpad behaviour.
+ */
set_mouse_scaling(kbdc, 1);
- /* Identify the Touchpad version */
+ /* Identify the Touchpad version. */
if (mouse_ext_command(kbdc, 0) == 0)
return (FALSE);
if (get_mouse_status(kbdc, status, 0, 3) != 3)
@@ -4290,7 +4297,7 @@ enable_synaptics(struct psm_softc *sc)
return (FALSE);
}
- /* Get the Touchpad model information */
+ /* Get the Touchpad model information. */
if (mouse_ext_command(kbdc, 3) == 0)
return (FALSE);
if (get_mouse_status(kbdc, status, 0, 3) != 3)
@@ -4321,7 +4328,7 @@ enable_synaptics(struct psm_softc *sc)
printf(" infoGeometry: %d\n", sc->synhw.infoGeometry);
}
- /* Read the extended capability bits */
+ /* Read the extended capability bits. */
if (mouse_ext_command(kbdc, 2) == 0)
return (FALSE);
if (get_mouse_status(kbdc, status, 0, 3) != 3)
@@ -4331,7 +4338,7 @@ enable_synaptics(struct psm_softc *sc)
return (FALSE);
}
- /* Set the different capabilities when they exist */
+ /* Set the different capabilities when they exist. */
if ((status[0] & 0x80) >> 7) {
sc->synhw.capExtended = (status[0] & 0x80) >> 7;
sc->synhw.capPassthrough = (status[2] & 0x80) >> 7;
@@ -4355,8 +4362,8 @@ enable_synaptics(struct psm_softc *sc)
}
/*
- * if we have bits set in status[0] & 0x70 - then we can load
- * more information about buttons using query 0x09
+ * If we have bits set in status[0] & 0x70, then we can load
+ * more information about buttons using query 0x09.
*/
if (status[0] & 0x70) {
if (mouse_ext_command(kbdc, 0x09) == 0)
@@ -4376,7 +4383,7 @@ enable_synaptics(struct psm_softc *sc)
}
/*
- * Read the mode byte
+ * Read the mode byte.
*
* XXX: Note the Synaptics documentation also defines the first
* byte of the response to this query to be a constant 0x3b, this
@@ -4391,13 +4398,13 @@ enable_synaptics(struct psm_softc *sc)
return (FALSE);
}
- /* Set the mode byte -- request wmode where available */
+ /* Set the mode byte; request wmode where available. */
if (sc->synhw.capExtended)
mouse_ext_command(kbdc, 0xc1);
else
mouse_ext_command(kbdc, 0xc0);
- /* Reset the sampling rate */
+ /* "Commit" the Set Mode Byte command sent above. */
set_mouse_sampling_rate(kbdc, 20);
/*
@@ -4414,6 +4421,12 @@ enable_synaptics(struct psm_softc *sc)
/* Create sysctl tree. */
synaptics_sysctl_create_tree(sc);
+ /*
+ * The touchpad will have to be reinitialized after
+ * suspend/resume.
+ */
+ sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
+
return (TRUE);
}
diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
index 15dc633..ff78453 100644
--- a/sys/dev/bce/if_bce.c
+++ b/sys/dev/bce/if_bce.c
@@ -5114,7 +5114,7 @@ bce_free_tx_chain(struct bce_softc *sc)
/* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
for (i = 0; i < TOTAL_TX_BD; i++) {
if (sc->tx_mbuf_ptr[i] != NULL) {
- if (sc->tx_mbuf_map != NULL)
+ if (sc->tx_mbuf_map[i] != NULL)
bus_dmamap_sync(sc->tx_mbuf_tag, sc->tx_mbuf_map[i],
BUS_DMASYNC_POSTWRITE);
m_freem(sc->tx_mbuf_ptr[i]);
@@ -7408,7 +7408,6 @@ bce_stats_update(struct bce_softc *sc)
(u_long) sc->stat_IfInMBUFDiscards +
(u_long) sc->stat_Dot3StatsAlignmentErrors +
(u_long) sc->stat_Dot3StatsFCSErrors +
- (u_long) sc->stat_IfInFramesL2FilterDiscards +
(u_long) sc->stat_IfInRuleCheckerDiscards +
(u_long) sc->stat_IfInFTQDiscards +
(u_long) sc->com_no_buffers;
diff --git a/sys/dev/cxgb/common/cxgb_ael1002.c b/sys/dev/cxgb/common/cxgb_ael1002.c
index 55c6421..97d4419 100644
--- a/sys/dev/cxgb/common/cxgb_ael1002.c
+++ b/sys/dev/cxgb/common/cxgb_ael1002.c
@@ -71,6 +71,74 @@ struct reg_val {
unsigned short set_bits;
};
+static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr);
+
+static int get_module_type (struct cphy *phy, int hint)
+{
+ int v;
+
+ v = hint ? hint : ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0);
+ if (v < 0)
+ return v;
+
+ if (v == 0x3) {
+ /* SFP: see SFF-8472 for below */
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3);
+ if (v < 0)
+ return v;
+
+ if (v == 0x1)
+ return phy_modtype_twinax;
+ if (v == 0x10)
+ return phy_modtype_sr;
+ if (v == 0x20)
+ return phy_modtype_lr;
+ if (v == 0x40)
+ return phy_modtype_lrm;
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6);
+ if (v < 0)
+ return v;
+ if (v != 4)
+ return phy_modtype_unknown;
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10);
+ if (v < 0)
+ return v;
+
+ if (v & 0x80) {
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
+ if (v < 0)
+ return v;
+ return v > 10 ? phy_modtype_twinax_long :
+ phy_modtype_twinax;
+ }
+ } else if (v == 0x6) {
+ /* XFP: See INF-8077i for details. */
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 127);
+ if (v < 0)
+ return v;
+
+ if (v != 1) {
+ /* XXX: set page select to table 1 yourself */
+ return phy_modtype_unknown;
+ }
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 131);
+ if (v < 0)
+ return v;
+ if (v == 0x10)
+ return phy_modtype_lrm;
+ if (v == 0x40)
+ return phy_modtype_lr;
+ if (v == 0x80)
+ return phy_modtype_sr;
+ }
+
+ return phy_modtype_unknown;
+}
+
static int set_phy_regs(struct cphy *phy, const struct reg_val *rv)
{
int err;
@@ -107,6 +175,18 @@ static int ael1002_power_down(struct cphy *phy, int enable)
return err;
}
+static int ael1002_get_module_type(struct cphy *phy, int delay_ms)
+{
+ int v;
+
+ if (delay_ms)
+ msleep(delay_ms);
+
+ v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0);
+
+ return v == -ETIMEDOUT ? phy_modtype_none : get_module_type(phy, v);
+}
+
static int ael1002_reset(struct cphy *phy, int wait)
{
int err;
@@ -119,6 +199,11 @@ static int ael1002_reset(struct cphy *phy, int wait)
(err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN,
0, 1 << 5)))
return err;
+
+ err = ael1002_get_module_type(phy, 300);
+ if (err >= 0)
+ phy->modtype = err;
+
return 0;
}
@@ -182,10 +267,17 @@ static struct cphy_ops ael1002_ops = {
int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
const struct mdio_ops *mdio_ops)
{
+ int err;
+
cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops,
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE,
"10GBASE-R");
ael100x_txon(phy);
+
+ err = ael1002_get_module_type(phy, 0);
+ if (err >= 0)
+ phy->modtype = err;
+
return 0;
}
@@ -983,7 +1075,7 @@ static int ael2005_i2c_rd(struct cphy *phy, int dev_addr, int word_addr)
return -ETIMEDOUT;
}
-static int get_module_type(struct cphy *phy, int delay_ms)
+static int ael2005_get_module_type(struct cphy *phy, int delay_ms)
{
int v;
unsigned int stat;
@@ -998,36 +1090,8 @@ static int get_module_type(struct cphy *phy, int delay_ms)
if (delay_ms)
msleep(delay_ms);
- /* see SFF-8472 for below */
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 3);
- if (v < 0)
- return v;
-
- if (v == 0x10)
- return phy_modtype_sr;
- if (v == 0x20)
- return phy_modtype_lr;
- if (v == 0x40)
- return phy_modtype_lrm;
-
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 6);
- if (v < 0)
- return v;
- if (v != 4)
- goto unknown;
-
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 10);
- if (v < 0)
- return v;
+ return get_module_type(phy, 0);
- if (v & 0x80) {
- v = ael2005_i2c_rd(phy, MODULE_DEV_ADDR, 0x12);
- if (v < 0)
- return v;
- return v > 10 ? phy_modtype_twinax_long : phy_modtype_twinax;
- }
-unknown:
- return phy_modtype_unknown;
}
static int ael2005_intr_enable(struct cphy *phy)
@@ -1084,7 +1148,7 @@ static int ael2005_reset(struct cphy *phy, int wait)
msleep(50);
- err = get_module_type(phy, 0);
+ err = ael2005_get_module_type(phy, 0);
if (err < 0)
return err;
phy->modtype = (u8)err;
@@ -1122,7 +1186,7 @@ static int ael2005_intr_handler(struct cphy *phy)
return ret;
/* modules have max 300 ms init time after hot plug */
- ret = get_module_type(phy, 300);
+ ret = ael2005_get_module_type(phy, 300);
if (ret < 0)
return ret;
@@ -1176,10 +1240,16 @@ static struct cphy_ops ael2005_ops = {
int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
const struct mdio_ops *mdio_ops)
{
+ int err;
cphy_init(phy, adapter, phy_addr, &ael2005_ops, mdio_ops,
SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE |
SUPPORTED_IRQ, "10GBASE-R");
msleep(125);
+
+ err = ael2005_get_module_type(phy, 0);
+ if (err >= 0)
+ phy->modtype = err;
+
return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL_OPT_SETTINGS, 0,
1 << 5);
}
diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c
index 2cbd801..90df817 100644
--- a/sys/dev/cxgb/cxgb_main.c
+++ b/sys/dev/cxgb/cxgb_main.c
@@ -90,6 +90,7 @@ static void cxgb_stop_locked(struct port_info *);
static void cxgb_set_rxmode(struct port_info *);
static int cxgb_ioctl(struct ifnet *, unsigned long, caddr_t);
static int cxgb_media_change(struct ifnet *);
+static int cxgb_ifm_type(int);
static void cxgb_media_status(struct ifnet *, struct ifmediareq *);
static int setup_sge_qsets(adapter_t *);
static void cxgb_async_intr(void *);
@@ -976,7 +977,7 @@ cxgb_port_attach(device_t dev)
} else if (!strcmp(p->phy.desc, "10GBASE-SR")) {
media_flags = IFM_ETHER | IFM_10G_SR | IFM_FDX;
} else if (!strcmp(p->phy.desc, "10GBASE-R")) {
- media_flags = IFM_ETHER | IFM_10G_LR | IFM_FDX;
+ media_flags = cxgb_ifm_type(p->phy.modtype);
} else if (!strcmp(p->phy.desc, "10/100/1000BASE-T")) {
ifmedia_add(&p->media, IFM_ETHER | IFM_10_T, 0, NULL);
ifmedia_add(&p->media, IFM_ETHER | IFM_10_T | IFM_FDX,
@@ -992,6 +993,9 @@ cxgb_port_attach(device_t dev)
/*
* XXX: This is not very accurate. Fix when common code
* returns more specific value - eg 1000BASE-SX, LX, etc.
+ *
+ * XXX: In the meantime, don't lie. Consider setting IFM_AUTO
+ * instead of SX.
*/
media_flags = IFM_ETHER | IFM_1000_SX | IFM_FDX;
} else {
@@ -999,7 +1003,13 @@ cxgb_port_attach(device_t dev)
return (ENXIO);
}
if (media_flags) {
- ifmedia_add(&p->media, media_flags, 0, NULL);
+ /*
+ * Note the modtype on which we based our flags. If modtype
+ * changes, we'll redo the ifmedia for this ifp. modtype may
+ * change when transceivers are plugged in/out, and in other
+ * situations.
+ */
+ ifmedia_add(&p->media, media_flags, p->phy.modtype, NULL);
ifmedia_set(&p->media, media_flags);
} else {
ifmedia_add(&p->media, IFM_ETHER | IFM_AUTO, 0, NULL);
@@ -1827,7 +1837,7 @@ cxgb_init_locked(struct port_info *p)
cxgb_link_start(p);
t3_link_changed(sc, p->port_id);
#endif
- ifp->if_baudrate = p->link_config.speed * 1000000;
+ ifp->if_baudrate = IF_Mbps(p->link_config.speed);
device_printf(sc->dev, "enabling interrupts on port=%d\n", p->port_id);
t3_port_intr_enable(sc, p->port_id);
@@ -1990,7 +2000,9 @@ cxgb_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
+ PORT_LOCK(p);
error = ifmedia_ioctl(ifp, ifr, &p->media, command);
+ PORT_UNLOCK(p);
break;
case SIOCSIFCAP:
PORT_LOCK(p);
@@ -2066,10 +2078,64 @@ cxgb_media_change(struct ifnet *ifp)
return (ENXIO);
}
+/*
+ * Translates from phy->modtype to IFM_TYPE.
+ */
+static int
+cxgb_ifm_type(int phymod)
+{
+ int rc = IFM_ETHER | IFM_FDX;
+
+ switch (phymod) {
+ case phy_modtype_sr:
+ rc |= IFM_10G_SR;
+ break;
+ case phy_modtype_lr:
+ rc |= IFM_10G_LR;
+ break;
+ case phy_modtype_lrm:
+#ifdef IFM_10G_LRM
+ rc |= IFM_10G_LRM;
+#endif
+ break;
+ case phy_modtype_twinax:
+#ifdef IFM_10G_TWINAX
+ rc |= IFM_10G_TWINAX;
+#endif
+ break;
+ case phy_modtype_twinax_long:
+#ifdef IFM_10G_TWINAX_LONG
+ rc |= IFM_10G_TWINAX_LONG;
+#endif
+ break;
+ case phy_modtype_none:
+ rc = IFM_ETHER | IFM_NONE;
+ break;
+ case phy_modtype_unknown:
+ break;
+ }
+
+ return (rc);
+}
+
static void
cxgb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct port_info *p = ifp->if_softc;
+ struct ifmedia_entry *cur = p->media.ifm_cur;
+ int m;
+
+ if (cur->ifm_data != p->phy.modtype) {
+ /* p->media about to be rebuilt, must hold lock */
+ PORT_LOCK_ASSERT_OWNED(p);
+
+ m = cxgb_ifm_type(p->phy.modtype);
+ ifmedia_removeall(&p->media);
+ ifmedia_add(&p->media, m, p->phy.modtype, NULL);
+ ifmedia_set(&p->media, m);
+ cur = p->media.ifm_cur; /* ifmedia_set modified ifm_cur */
+ ifmr->ifm_current = m;
+ }
ifmr->ifm_status = IFM_AVALID;
ifmr->ifm_active = IFM_ETHER;
@@ -2089,6 +2155,9 @@ cxgb_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
case 1000:
ifmr->ifm_active |= IFM_1000_T;
break;
+ case 10000:
+ ifmr->ifm_active |= IFM_SUBTYPE(cur->ifm_media);
+ break;
}
if (p->link_config.duplex)
@@ -2140,7 +2209,7 @@ check_link_status(adapter_t *sc)
if (!(p->phy.caps & SUPPORTED_IRQ))
t3_link_changed(sc, i);
- p->ifp->if_baudrate = p->link_config.speed * 1000000;
+ p->ifp->if_baudrate = IF_Mbps(p->link_config.speed);
}
}
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
index 334f315..f11aaf0 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
@@ -3269,8 +3269,6 @@ syncache_add_accept_req(struct cpl_pass_accept_req *req, struct socket *lso, str
toep->tp_iss = toep->tp_delack_seq = toep->tp_rcv_wup = toep->tp_copied_seq = rcv_isn + 1;
-
- inc.inc_isipv6 = 0;
inc.inc_len = 0;
inc.inc_faddr.s_addr = req->peer_ip;
inc.inc_laddr.s_addr = req->local_ip;
@@ -3610,7 +3608,6 @@ syncache_expand_establish_req(struct cpl_pass_establish *req, struct socket **so
th.th_seq = req->rcv_isn;
th.th_flags = TH_ACK;
- inc.inc_isipv6 = 0;
inc.inc_len = 0;
inc.inc_faddr.s_addr = req->peer_ip;
inc.inc_laddr.s_addr = req->local_ip;
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_l2t.c b/sys/dev/cxgb/ulp/tom/cxgb_l2t.c
index 67856e6..2484923 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_l2t.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_l2t.c
@@ -93,15 +93,15 @@ arp_hash(u32 key, int ifindex, const struct l2t_data *d)
}
static inline void
-neigh_replace(struct l2t_entry *e, struct rtentry *rt)
+neigh_replace(struct l2t_entry *e, struct llentry *neigh)
{
- RT_LOCK(rt);
- RT_ADDREF(rt);
- RT_UNLOCK(rt);
+ LLE_WLOCK(neigh);
+ LLE_ADDREF(neigh);
+ LLE_WUNLOCK(neigh);
if (e->neigh)
- RTFREE(e->neigh);
- e->neigh = rt;
+ LLE_FREE(e->neigh);
+ e->neigh = neigh;
}
/*
@@ -164,7 +164,7 @@ arpq_enqueue(struct l2t_entry *e, struct mbuf *m)
int
t3_l2t_send_slow(struct t3cdev *dev, struct mbuf *m, struct l2t_entry *e)
{
- struct rtentry *rt = e->neigh;
+ struct llentry *lle = e->neigh;
struct sockaddr_in sin;
bzero(&sin, sizeof(struct sockaddr_in));
@@ -177,7 +177,7 @@ again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac);
+ (struct sockaddr *)&sin, e->dmac, &lle);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE)
e->state = L2T_STATE_VALID;
@@ -201,7 +201,7 @@ again:
* entries when there's no memory.
*/
if (arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac) == 0) {
+ (struct sockaddr *)&sin, e->dmac, &lle) == 0) {
CTR6(KTR_CXGB, "mac=%x:%x:%x:%x:%x:%x\n",
e->dmac[0], e->dmac[1], e->dmac[2], e->dmac[3], e->dmac[4], e->dmac[5]);
@@ -222,12 +222,12 @@ again:
void
t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e)
{
- struct rtentry *rt;
struct mbuf *m0;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_addr.s_addr = e->addr;
+ struct llentry *lle;
if ((m0 = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
return;
@@ -237,7 +237,7 @@ again:
switch (e->state) {
case L2T_STATE_STALE: /* entry is stale, kick off revalidation */
arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac);
+ (struct sockaddr *)&sin, e->dmac, &lle);
mtx_lock(&e->lock);
if (e->state == L2T_STATE_STALE) {
e->state = L2T_STATE_VALID;
@@ -263,7 +263,7 @@ again:
* entries when there's no memory.
*/
arpresolve(rt->rt_ifp, rt, NULL,
- (struct sockaddr *)&sin, e->dmac);
+ (struct sockaddr *)&sin, e->dmac, &lle);
}
return;
@@ -321,18 +321,18 @@ found:
void
t3_l2e_free(struct l2t_data *d, struct l2t_entry *e)
{
- struct rtentry *rt = NULL;
-
+ struct llentry *lle;
+
mtx_lock(&e->lock);
if (atomic_load_acq_int(&e->refcnt) == 0) { /* hasn't been recycled */
- rt = e->neigh;
+ lle = e->neigh;
e->neigh = NULL;
}
mtx_unlock(&e->lock);
atomic_add_int(&d->nfree, 1);
- if (rt)
- RTFREE(rt);
+ if (lle)
+ LLE_FREE(lle);
}
@@ -341,11 +341,8 @@ t3_l2e_free(struct l2t_data *d, struct l2t_entry *e)
* Must be called with softirqs disabled.
*/
static inline void
-reuse_entry(struct l2t_entry *e, struct rtentry *neigh)
+reuse_entry(struct l2t_entry *e, struct llentry *neigh)
{
- struct llinfo_arp *la;
-
- la = (struct llinfo_arp *)neigh->rt_llinfo;
mtx_lock(&e->lock); /* avoid race with t3_l2t_free */
if (neigh != e->neigh)
@@ -362,13 +359,13 @@ reuse_entry(struct l2t_entry *e, struct rtentry *neigh)
}
struct l2t_entry *
-t3_l2t_get(struct t3cdev *dev, struct rtentry *neigh, struct ifnet *ifp,
+t3_l2t_get(struct t3cdev *dev, struct llentry *neigh, struct ifnet *ifp,
struct sockaddr *sa)
{
struct l2t_entry *e;
struct l2t_data *d = L2DATA(dev);
u32 addr = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
- int ifidx = neigh->rt_ifp->if_index;
+ int ifidx = ifp->if_index;
int hash = arp_hash(addr, ifidx, d);
unsigned int smt_idx = ((struct port_info *)ifp->if_softc)->port_id;
@@ -448,20 +445,19 @@ handle_failed_resolution(struct t3cdev *dev, struct mbuf *arpq)
}
void
-t3_l2t_update(struct t3cdev *dev, struct rtentry *neigh,
+t3_l2t_update(struct t3cdev *dev, struct llentry *neigh,
uint8_t *enaddr, struct sockaddr *sa)
{
struct l2t_entry *e;
struct mbuf *arpq = NULL;
struct l2t_data *d = L2DATA(dev);
u32 addr = *(u32 *) &((struct sockaddr_in *)sa)->sin_addr;
- int ifidx = neigh->rt_ifp->if_index;
int hash = arp_hash(addr, ifidx, d);
struct llinfo_arp *la;
rw_rlock(&d->lock);
for (e = d->l2tab[hash].first; e; e = e->next)
- if (e->addr == addr && e->ifindex == ifidx) {
+ if (e->addr == addr) {
mtx_lock(&e->lock);
goto found;
}
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_l2t.h b/sys/dev/cxgb/ulp/tom/cxgb_l2t.h
index 1d547d3..308ba66 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_l2t.h
+++ b/sys/dev/cxgb/ulp/tom/cxgb_l2t.h
@@ -68,7 +68,7 @@ struct l2t_entry {
int ifindex; /* neighbor's net_device's ifindex */
uint16_t smt_idx; /* SMT index */
uint16_t vlan; /* VLAN TCI (id: bits 0-11, prio: 13-15 */
- struct rtentry *neigh; /* associated neighbour */
+ struct llentry *neigh; /* associated neighbour */
struct l2t_entry *first; /* start of hash chain */
struct l2t_entry *next; /* next l2t_entry on chain */
struct mbuf *arpq_head; /* queue of packets awaiting resolution */
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
index eb91214..25a3fa8 100644
--- a/sys/dev/drm/drmP.h
+++ b/sys/dev/drm/drmP.h
@@ -87,6 +87,7 @@ struct drm_file;
#include <sys/agpio.h>
#include <sys/mutex.h>
#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
#include <sys/selinfo.h>
#include <sys/bus.h>
@@ -211,15 +212,6 @@ enum {
#define DRM_MTRR_WC MDF_WRITECOMBINE
#define jiffies ticks
-/* Capabilities taken from src/sys/dev/pci/pcireg.h. */
-#ifndef PCIY_AGP
-#define PCIY_AGP 0x02
-#endif
-
-#ifndef PCIY_EXPRESS
-#define PCIY_EXPRESS 0x10
-#endif
-
typedef unsigned long dma_addr_t;
typedef u_int64_t u64;
typedef u_int32_t u32;
@@ -473,11 +465,13 @@ typedef struct drm_agp_head {
} drm_agp_head_t;
typedef struct drm_sg_mem {
- unsigned long handle;
- void *virtual;
- int pages;
- dma_addr_t *busaddr;
- drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */
+ unsigned long handle;
+ void *virtual;
+ int pages;
+ dma_addr_t *busaddr;
+ struct drm_dma_handle *sg_dmah; /* Handle for sg_pages */
+ struct drm_dma_handle *dmah; /* Handle to PCI memory */
+ /* for ATI PCIGART table */
} drm_sg_mem_t;
typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
index 8a0cdf4..63be19b 100644
--- a/sys/dev/drm/drm_drv.c
+++ b/sys/dev/drm/drm_drv.c
@@ -152,6 +152,10 @@ int drm_probe(device_t dev, drm_pci_id_list_t *idlist)
device = pci_get_device(dev);
#endif
+ if (pci_get_class(dev) != PCIC_DISPLAY
+ || pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
+ return ENXIO;
+
id_entry = drm_find_description(vendor, device, idlist);
if (id_entry != NULL) {
device_set_desc(dev, id_entry->name);
diff --git a/sys/dev/drm/drm_scatter.c b/sys/dev/drm/drm_scatter.c
index c94976a..bf0cbeb 100644
--- a/sys/dev/drm/drm_scatter.c
+++ b/sys/dev/drm/drm_scatter.c
@@ -39,20 +39,16 @@ __FBSDID("$FreeBSD$");
#include "dev/drm/drmP.h"
-#define DEBUG_SCATTER 0
+static void drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs,
+ int nsegs, int error);
-void drm_sg_cleanup(drm_sg_mem_t *entry)
+int
+drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request)
{
- free((void *)entry->handle, DRM_MEM_PAGES);
- free(entry->busaddr, DRM_MEM_PAGES);
- free(entry, DRM_MEM_SGLISTS);
-}
-
-int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request)
-{
- drm_sg_mem_t *entry;
+ struct drm_sg_mem *entry;
+ struct drm_dma_handle *dmah;
unsigned long pages;
- int i;
+ int ret;
if (dev->sg)
return EINVAL;
@@ -69,21 +65,56 @@ int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request)
entry->busaddr = malloc(pages * sizeof(*entry->busaddr), DRM_MEM_PAGES,
M_WAITOK | M_ZERO);
if (!entry->busaddr) {
- drm_sg_cleanup(entry);
+ free(entry, DRM_MEM_SGLISTS);
return ENOMEM;
}
- entry->handle = (long)malloc(pages << PAGE_SHIFT, DRM_MEM_PAGES,
- M_WAITOK | M_ZERO);
- if (entry->handle == 0) {
- drm_sg_cleanup(entry);
+ dmah = malloc(sizeof(struct drm_dma_handle), DRM_MEM_DMA,
+ M_ZERO | M_NOWAIT);
+ if (dmah == NULL) {
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
+ return ENOMEM;
+ }
+
+ ret = bus_dma_tag_create(NULL, PAGE_SIZE, 0, /* tag, align, boundary */
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, /* lowaddr, highaddr */
+ NULL, NULL, /* filtfunc, filtfuncargs */
+ request->size, pages, /* maxsize, nsegs */
+ PAGE_SIZE, 0, /* maxsegsize, flags */
+ NULL, NULL, /* lockfunc, lockfuncargs */
+ &dmah->tag);
+ if (ret != 0) {
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
return ENOMEM;
}
- for (i = 0; i < pages; i++) {
- entry->busaddr[i] = vtophys(entry->handle + i * PAGE_SIZE);
+ ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr,
+ BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_NOCACHE, &dmah->map);
+ if (ret != 0) {
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
+ return ENOMEM;
}
+ ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
+ request->size, drm_sg_alloc_cb, entry, 0);
+ if (ret != 0) {
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
+ return ENOMEM;
+ }
+
+ entry->sg_dmah = dmah;
+ entry->handle = (unsigned long)dmah->vaddr;
+
DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
entry->virtual = (void *)entry->handle;
@@ -101,22 +132,49 @@ int drm_sg_alloc(struct drm_device * dev, struct drm_scatter_gather * request)
return 0;
}
-int drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
+static void
+drm_sg_alloc_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct drm_sg_mem *entry = arg;
+ int i;
+
+ if (error != 0)
+ return;
+
+ for(i = 0 ; i < nsegs ; i++) {
+ entry->busaddr[i] = segs[i].ds_addr;
+ }
+}
+
+int
+drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
{
struct drm_scatter_gather *request = data;
- int ret;
- DRM_DEBUG("%s\n", __FUNCTION__);
+ DRM_DEBUG("\n");
+
+ return drm_sg_alloc(dev, request);
+}
- ret = drm_sg_alloc(dev, request);
- return ret;
+void
+drm_sg_cleanup(struct drm_sg_mem *entry)
+{
+ struct drm_dma_handle *dmah = entry->sg_dmah;
+
+ bus_dmamap_unload(dmah->tag, dmah->map);
+ bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
+ bus_dma_tag_destroy(dmah->tag);
+ free(dmah, DRM_MEM_DMA);
+ free(entry->busaddr, DRM_MEM_PAGES);
+ free(entry, DRM_MEM_SGLISTS);
}
-int drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int
+drm_sg_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
struct drm_scatter_gather *request = data;
- drm_sg_mem_t *entry;
+ struct drm_sg_mem *entry;
DRM_LOCK();
entry = dev->sg;
diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c
index f79282e..9a6851c 100644
--- a/sys/dev/fxp/if_fxp.c
+++ b/sys/dev/fxp/if_fxp.c
@@ -1540,8 +1540,8 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
* the chip is an 82550/82551 or not.
*/
if (sc->flags & FXP_FLAG_EXT_RFA) {
- cbp->tbd[i + 2].tb_addr = htole32(segs[i].ds_addr);
- cbp->tbd[i + 2].tb_size = htole32(segs[i].ds_len);
+ cbp->tbd[i + 1].tb_addr = htole32(segs[i].ds_addr);
+ cbp->tbd[i + 1].tb_size = htole32(segs[i].ds_len);
} else {
cbp->tbd[i].tb_addr = htole32(segs[i].ds_addr);
cbp->tbd[i].tb_size = htole32(segs[i].ds_len);
@@ -1550,13 +1550,13 @@ fxp_encap(struct fxp_softc *sc, struct mbuf **m_head)
if (sc->flags & FXP_FLAG_EXT_RFA) {
/* Configure dynamic TBD for 82550/82551. */
cbp->tbd_number = 0xFF;
- cbp->tbd[nseg + 1].tb_size |= htole32(0x8000);
+ cbp->tbd[nseg].tb_size |= htole32(0x8000);
} else
cbp->tbd_number = nseg;
/* Configure TSO. */
if (m->m_pkthdr.csum_flags & CSUM_TSO) {
cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16);
- cbp->tbd[1].tb_size = htole32(tcp_payload << 16);
+ cbp->tbd[1].tb_size |= htole32(tcp_payload << 16);
cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE |
FXP_IPCB_IP_CHECKSUM_ENABLE |
FXP_IPCB_TCP_PACKET |
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index c34a969..8d17679 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -1491,17 +1491,18 @@ core_intr(int cpu, struct trapframe *tf)
PMCDBG(MDP,INT, 1, "cpu=%d tf=0x%p um=%d", cpu, (void *) tf,
TRAPF_USERMODE(tf));
+ found_interrupt = 0;
cc = core_pcpu[cpu];
for (ri = 0; ri < core_iap_npmc; ri++) {
- if (!iap_pmc_has_overflowed(ri))
- continue;
-
if ((pm = cc->pc_corepmcs[ri].phw_pmc) == NULL ||
!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
continue;
+ if (!iap_pmc_has_overflowed(ri))
+ continue;
+
found_interrupt = 1;
if (pm->pm_state != PMC_STATE_RUNNING)
@@ -1560,7 +1561,9 @@ core2_intr(int cpu, struct trapframe *tf)
PMCDBG(MDP,INT, 1, "cpu=%d intrstatus=%jx", cpu,
(uintmax_t) intrstatus);
+ found_interrupt = 0;
cc = core_pcpu[cpu];
+
KASSERT(cc != NULL, ("[core,%d] null pcpu", __LINE__));
cc->pc_globalctrl &= ~intrenable;
@@ -1574,7 +1577,6 @@ core2_intr(int cpu, struct trapframe *tf)
IA_GLOBAL_STATUS_FLAG_OVFBUF |
IA_GLOBAL_STATUS_FLAG_CONDCHG);
-
/*
* Look for interrupts from fixed function PMCs.
*/
@@ -1634,9 +1636,6 @@ core2_intr(int cpu, struct trapframe *tf)
wrmsr(IAP_PMC0 + n, v);
}
- KASSERT(found_interrupt,
- ("[core,%d] no interrupting PMCs were found", __LINE__));
-
/*
* Reenable all non-stalled PMCs.
*/
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index cef1453..6612203 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -199,7 +199,7 @@ pmclog_get_buffer(struct pmc_owner *po)
mtx_assert(&po->po_mtx, MA_OWNED);
KASSERT(po->po_curbuf == NULL,
- ("[pmc,%d] po=%p current buffer still valid", __LINE__, po));
+ ("[pmclog,%d] po=%p current buffer still valid", __LINE__, po));
mtx_lock_spin(&pmc_bufferlist_mtx);
if ((plb = TAILQ_FIRST(&pmc_bufferlist)) != NULL)
@@ -212,7 +212,7 @@ pmclog_get_buffer(struct pmc_owner *po)
if (plb)
KASSERT(plb->plb_ptr == plb->plb_base &&
plb->plb_base < plb->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p "
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p "
"base=%p fence=%p", __LINE__, po, plb->plb_ptr,
plb->plb_base, plb->plb_fence));
#endif
@@ -224,7 +224,7 @@ pmclog_get_buffer(struct pmc_owner *po)
if (plb == NULL)
atomic_add_int(&pmc_stats.pm_buffer_requests_failed, 1);
- return plb ? 0 : ENOMEM;
+ return (plb ? 0 : ENOMEM);
}
/*
@@ -256,7 +256,7 @@ pmclog_loop(void *arg)
PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
KASSERT(po->po_kthread == curthread->td_proc,
- ("[pmc,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
+ ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
po, po->po_kthread, curthread->td_proc));
lb = NULL;
@@ -381,10 +381,10 @@ static void
pmclog_release(struct pmc_owner *po)
{
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base,
- ("[pmc,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base));
KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence));
/* schedule an I/O if we've filled a buffer */
@@ -423,15 +423,15 @@ pmclog_reserve(struct pmc_owner *po, int length)
if (po->po_curbuf == NULL)
if (pmclog_get_buffer(po) != 0) {
mtx_unlock_spin(&po->po_mtx);
- return NULL;
+ return (NULL);
}
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] po=%p no current buffer", __LINE__, po));
+ ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base &&
po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
__LINE__, po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base,
po->po_curbuf->plb_fence));
@@ -439,7 +439,7 @@ pmclog_reserve(struct pmc_owner *po, int length)
newptr = oldptr + length;
KASSERT(oldptr != (uintptr_t) NULL,
- ("[pmc,%d] po=%p Null log buffer pointer", __LINE__, po));
+ ("[pmclog,%d] po=%p Null log buffer pointer", __LINE__, po));
/*
* If we have space in the current buffer, return a pointer to
@@ -458,18 +458,18 @@ pmclog_reserve(struct pmc_owner *po, int length)
if (pmclog_get_buffer(po) != 0) {
mtx_unlock_spin(&po->po_mtx);
- return NULL;
+ return (NULL);
}
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] po=%p no current buffer", __LINE__, po));
+ ("[pmclog,%d] po=%p no current buffer", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr != NULL,
- ("[pmc,%d] null return from pmc_get_log_buffer", __LINE__));
+ ("[pmclog,%d] null return from pmc_get_log_buffer", __LINE__));
KASSERT(po->po_curbuf->plb_ptr == po->po_curbuf->plb_base &&
po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
+ ("[pmclog,%d] po=%p buffer invariants: ptr=%p base=%p fence=%p",
__LINE__, po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base,
po->po_curbuf->plb_fence));
@@ -481,7 +481,7 @@ pmclog_reserve(struct pmc_owner *po, int length)
getnanotime(&ts); /* fill in the timestamp */
*lh++ = ts.tv_sec & 0xFFFFFFFF;
*lh++ = ts.tv_nsec & 0xFFFFFFF;
- return (uint32_t *) oldptr;
+ return ((uint32_t *) oldptr);
}
/*
@@ -494,13 +494,13 @@ static void
pmclog_schedule_io(struct pmc_owner *po)
{
KASSERT(po->po_curbuf != NULL,
- ("[pmc,%d] schedule_io with null buffer po=%p", __LINE__, po));
+ ("[pmclog,%d] schedule_io with null buffer po=%p", __LINE__, po));
KASSERT(po->po_curbuf->plb_ptr >= po->po_curbuf->plb_base,
- ("[pmc,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p base=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_base));
KASSERT(po->po_curbuf->plb_ptr <= po->po_curbuf->plb_fence,
- ("[pmc,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
+ ("[pmclog,%d] buffer invariants po=%p ptr=%p fenc=%p", __LINE__,
po, po->po_curbuf->plb_ptr, po->po_curbuf->plb_fence));
PMCDBG(LOG,SIO, 1, "po=%p", po);
@@ -558,13 +558,13 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
/* return EBUSY if a log file was already present */
if (po->po_flags & PMC_PO_OWNS_LOGFILE)
- return EBUSY;
+ return (EBUSY);
KASSERT(po->po_kthread == NULL,
- ("[pmc,%d] po=%p kthread (%p) already present", __LINE__, po,
+ ("[pmclog,%d] po=%p kthread (%p) already present", __LINE__, po,
po->po_kthread));
KASSERT(po->po_file == NULL,
- ("[pmc,%d] po=%p file (%p) already present", __LINE__, po,
+ ("[pmclog,%d] po=%p file (%p) already present", __LINE__, po,
po->po_file));
/* get a reference to the file state */
@@ -591,7 +591,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
PMCLOG_EMIT32(md->pmd_cputype);
PMCLOG_DESPATCH(po);
- return 0;
+ return (0);
error:
/* shutdown the thread */
@@ -600,15 +600,15 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
pmclog_stop_kthread(po);
mtx_unlock(&pmc_kthread_mtx);
- KASSERT(po->po_kthread == NULL, ("[pmc,%d] po=%p kthread not stopped",
- __LINE__, po));
+ KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
+ "stopped", __LINE__, po));
if (po->po_file)
(void) fdrop(po->po_file, curthread);
po->po_file = NULL; /* clear file and error state */
po->po_error = 0;
- return error;
+ return (error);
}
@@ -626,12 +626,12 @@ pmclog_deconfigure_log(struct pmc_owner *po)
PMCDBG(LOG,CFG,1, "de-config po=%p", po);
if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
- return EINVAL;
+ return (EINVAL);
KASSERT(po->po_sscount == 0,
- ("[pmc,%d] po=%p still owning SS PMCs", __LINE__, po));
+ ("[pmclog,%d] po=%p still owning SS PMCs", __LINE__, po));
KASSERT(po->po_file != NULL,
- ("[pmc,%d] po=%p no log file", __LINE__, po));
+ ("[pmclog,%d] po=%p no log file", __LINE__, po));
/* stop the kthread, this will reset the 'OWNS_LOGFILE' flag */
mtx_lock(&pmc_kthread_mtx);
@@ -640,7 +640,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
mtx_unlock(&pmc_kthread_mtx);
KASSERT(po->po_kthread == NULL,
- ("[pmc,%d] po=%p kthread not stopped", __LINE__, po));
+ ("[pmclog,%d] po=%p kthread not stopped", __LINE__, po));
/* return all queued log buffers to the global pool */
while ((lb = TAILQ_FIRST(&po->po_logbuffers)) != NULL) {
@@ -664,7 +664,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
po->po_file = NULL;
po->po_error = 0;
- return error;
+ return (error);
}
/*
@@ -683,7 +683,7 @@ pmclog_flush(struct pmc_owner *po)
* return that.
*/
if (po->po_error)
- return po->po_error;
+ return (po->po_error);
error = 0;
@@ -709,12 +709,14 @@ pmclog_flush(struct pmc_owner *po)
po->po_flags |= PMC_PO_IN_FLUSH; /* ask for a wakeup */
error = msleep(po->po_kthread, &pmc_kthread_mtx, PWAIT,
"pmcflush", 0);
+ if (error == 0)
+ error = po->po_error;
}
error:
mtx_unlock(&pmc_kthread_mtx);
- return error;
+ return (error);
}
@@ -948,7 +950,7 @@ pmclog_process_userlog(struct pmc_owner *po, struct pmc_op_writelog *wl)
PMCLOG_DESPATCH(po);
error:
- return error;
+ return (error);
}
/*
@@ -964,8 +966,8 @@ pmclog_initialize()
struct pmclog_buffer *plb;
if (pmclog_buffer_size <= 0) {
- (void) printf("hwpmc: tunable logbuffersize=%d must be greater "
- "than zero.\n", pmclog_buffer_size);
+ (void) printf("hwpmc: tunable logbuffersize=%d must be "
+ "greater than zero.\n", pmclog_buffer_size);
pmclog_buffer_size = PMC_LOG_BUFFER_SIZE;
}
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index a38921f..c239a69 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -1863,8 +1863,11 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
/*
* Record a call chain.
*/
+ KASSERT(td == curthread, ("[pmc,%d] td != curthread",
+ __LINE__));
pmc_capture_user_callchain(PCPU_GET(cpuid),
(struct trapframe *) arg);
+ td->td_pflags &= ~TDP_CALLCHAIN;
break;
default:
@@ -3794,30 +3797,28 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
*/
static void
-pmc_post_callchain_ast(void)
+pmc_post_callchain_callback(void)
{
struct thread *td;
td = curthread;
+ KASSERT((td->td_pflags & TDP_CALLCHAIN) == 0,
+ ("[pmc,%d] thread %p already marked for callchain capture",
+ __LINE__, (void *) td));
+
/*
- * Mark this thread as needing processing in ast().
- * td->td_pflags will be safe to touch as the process was in
- * user space when it was interrupted.
+ * Mark this thread as needing callchain capture.
+ * `td->td_pflags' will be safe to touch because this thread
+ * was in user space when it was interrupted.
*/
td->td_pflags |= TDP_CALLCHAIN;
/*
- * Again, since we've entered this function directly from
- * userland, `td' is guaranteed to be not locked by this CPU,
- * so its safe to try acquire the thread lock even though we
- * are executing in an NMI context. We need to acquire this
- * lock before touching `td_flags' because other CPUs may be
- * in the process of touching this field.
+ * Don't let this thread migrate between CPUs until callchain
+ * capture completes.
*/
- thread_lock(td);
- td->td_flags |= TDF_ASTPENDING;
- thread_unlock(td);
+ sched_pin();
return;
}
@@ -3869,6 +3870,10 @@ pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
(int) (psb->ps_write - psb->ps_samples),
(int) (psb->ps_read - psb->ps_samples));
+ KASSERT(pm->pm_runcount >= 0,
+ ("[pmc,%d] pm=%p runcount %d", __LINE__, (void *) pm,
+ pm->pm_runcount));
+
atomic_add_rel_32(&pm->pm_runcount, 1); /* hold onto PMC */
ps->ps_pmc = pm;
if ((td = curthread) && td->td_proc)
@@ -3876,6 +3881,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
else
ps->ps_pid = -1;
ps->ps_cpu = cpu;
+ ps->ps_td = td;
ps->ps_flags = inuserspace ? PMC_CC_F_USERSPACE : 0;
callchaindepth = (pm->pm_flags & PMC_F_CALLCHAIN) ?
@@ -3893,7 +3899,7 @@ pmc_process_interrupt(int cpu, struct pmc *pm, struct trapframe *tf,
pmc_save_kernel_callchain(ps->ps_pc,
callchaindepth, tf);
else {
- pmc_post_callchain_ast();
+ pmc_post_callchain_callback();
callchaindepth = PMC_SAMPLE_INUSE;
}
}
@@ -3925,20 +3931,41 @@ pmc_capture_user_callchain(int cpu, struct trapframe *tf)
{
int i;
struct pmc *pm;
+ struct thread *td;
struct pmc_sample *ps;
struct pmc_samplebuffer *psb;
+#ifdef INVARIANTS
+ int ncallchains;
+#endif
+
+ sched_unpin(); /* Can migrate safely now. */
psb = pmc_pcpu[cpu]->pc_sb;
+ td = curthread;
+
+ KASSERT(td->td_pflags & TDP_CALLCHAIN,
+ ("[pmc,%d] Retrieving callchain for thread that doesn't want it",
+ __LINE__));
+
+#ifdef INVARIANTS
+ ncallchains = 0;
+#endif
/*
* Iterate through all deferred callchain requests.
*/
- for (i = 0; i < pmc_nsamples; i++) {
+ ps = psb->ps_samples;
+ for (i = 0; i < pmc_nsamples; i++, ps++) {
- ps = &psb->ps_samples[i];
if (ps->ps_nsamples != PMC_SAMPLE_INUSE)
continue;
+ if (ps->ps_td != td)
+ continue;
+
+ KASSERT(ps->ps_cpu == cpu,
+ ("[pmc,%d] cpu mismatch ps_cpu=%d pcpu=%d", __LINE__,
+ ps->ps_cpu, PCPU_GET(cpuid)));
pm = ps->ps_pmc;
@@ -3946,14 +3973,26 @@ pmc_capture_user_callchain(int cpu, struct trapframe *tf)
("[pmc,%d] Retrieving callchain for PMC that doesn't "
"want it", __LINE__));
+ KASSERT(pm->pm_runcount > 0,
+ ("[pmc,%d] runcount %d", __LINE__, pm->pm_runcount));
+
/*
* Retrieve the callchain and mark the sample buffer
* as 'processable' by the timer tick sweep code.
*/
ps->ps_nsamples = pmc_save_user_callchain(ps->ps_pc,
pmc_callchaindepth, tf);
+
+#ifdef INVARIANTS
+ ncallchains++;
+#endif
+
}
+ KASSERT(ncallchains > 0,
+ ("[pmc,%d] cpu %d didn't find a sample to collect", __LINE__,
+ cpu));
+
return;
}
@@ -3991,6 +4030,11 @@ pmc_process_samples(int cpu)
}
pm = ps->ps_pmc;
+
+ KASSERT(pm->pm_runcount > 0,
+ ("[pmc,%d] pm=%p runcount %d", __LINE__, (void *) pm,
+ pm->pm_runcount));
+
po = pm->pm_owner;
KASSERT(PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)),
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index e22b7bf..1ad4e91 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -335,6 +335,23 @@ isp_reset(ispsoftc_t *isp)
/*
* XXX: Should probably do some bus sensing.
*/
+ } else if (IS_ULTRA3(isp)) {
+ sdparam *sdp = isp->isp_param;
+
+ isp->isp_clock = 100;
+
+ if (IS_10160(isp))
+ btype = "10160";
+ else if (IS_12160(isp))
+ btype = "12160";
+ else
+ btype = "<UNKLVD>";
+ sdp->isp_lvdmode = 1;
+
+ if (IS_DUALBUS(isp)) {
+ sdp++;
+ sdp->isp_lvdmode = 1;
+ }
} else if (IS_ULTRA2(isp)) {
static const char m[] = "bus %d is in %s Mode";
uint16_t l;
@@ -346,10 +363,6 @@ isp_reset(ispsoftc_t *isp)
btype = "1280";
else if (IS_1080(isp))
btype = "1080";
- else if (IS_10160(isp))
- btype = "10160";
- else if (IS_12160(isp))
- btype = "12160";
else
btype = "<UNKLVD>";
diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c
index f4230a2..bb9e64b 100644
--- a/sys/dev/md/md.c
+++ b/sys/dev/md/md.c
@@ -374,8 +374,11 @@ g_md_access(struct g_provider *pp, int r, int w, int e)
struct md_s *sc;
sc = pp->geom->softc;
- if (sc == NULL)
+ if (sc == NULL) {
+ if (r <= 0 && w <= 0 && e <= 0)
+ return (0);
return (ENXIO);
+ }
r += pp->acr;
w += pp->acw;
e += pp->ace;
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index a2af0ba..7cdb304 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -296,7 +296,8 @@ mfi_attach(struct mfi_softc *sc)
uint32_t status;
int error, commsz, framessz, sensesz;
int frames, unit, max_fw_sge;
- device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 2.00 \n");
+
+ device_printf(sc->mfi_dev, "Megaraid SAS driver Ver 3.00 \n");
mtx_init(&sc->mfi_io_lock, "MFI I/O lock", NULL, MTX_DEF);
sx_init(&sc->mfi_config_lock, "MFI config");
diff --git a/sys/dev/mfi/mfi_pci.c b/sys/dev/mfi/mfi_pci.c
index 902dce5..5f0b341 100644
--- a/sys/dev/mfi/mfi_pci.c
+++ b/sys/dev/mfi/mfi_pci.c
@@ -123,7 +123,7 @@ struct mfi_ident {
{0x1000, 0x0079, 0x1028, 0x1f18, MFI_FLAGS_GEN2, "Dell PERC H700 Modular"},
{0x1000, 0x0079, 0x1028, 0x1f19, MFI_FLAGS_GEN2, "Dell PERC H700"},
{0x1000, 0x0079, 0x1028, 0x1f1b, MFI_FLAGS_GEN2, "Dell PERC H800"},
- {0x1000, 0x0079, 0x1028, 0xffff, MFI_FLAGS_GEN2, "Dell PERC H700/H800"},
+ {0x1000, 0x0079, 0x1028, 0xffff, MFI_FLAGS_GEN2, "Dell PERC Gen2"},
{0x1000, 0x0079, 0xffff, 0xffff, MFI_FLAGS_GEN2, "LSI MegaSAS Gen2"},
{0x1000, 0x007c, 0xffff, 0xffff, MFI_FLAGS_1078, "LSI MegaSAS 1078"},
{0x1000, 0x0411, 0xffff, 0xffff, MFI_FLAGS_1064R, "LSI MegaSAS 1064R"}, /* Brocton IOP */
diff --git a/sys/dev/nfe/if_nfe.c b/sys/dev/nfe/if_nfe.c
index 7a36a2e..e5a5294 100644
--- a/sys/dev/nfe/if_nfe.c
+++ b/sys/dev/nfe/if_nfe.c
@@ -3080,7 +3080,7 @@ nfe_sysctl_node(struct nfe_softc *sc)
&stats->rx_unicast, "Unicast Frames");
NFE_SYSCTL_STAT_ADD32(ctx, child, "multicast",
&stats->rx_multicast, "Multicast Frames");
- NFE_SYSCTL_STAT_ADD32(ctx, child, "brocadcast",
+ NFE_SYSCTL_STAT_ADD32(ctx, child, "broadcast",
&stats->rx_broadcast, "Broadcast Frames");
if ((sc->nfe_flags & NFE_MIB_V2) != 0) {
NFE_SYSCTL_STAT_ADD64(ctx, child, "octets",
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index 7a394c1..19de2b97 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
* Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
* All rights reserved.
*
@@ -33,7 +34,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/errno.h>
+#include <sys/libkern.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
@@ -71,6 +74,22 @@ ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *obd)
free(obd->obd_type, M_OFWPROP);
}
+int
+ofw_bus_gen_child_pnpinfo_str(device_t cbdev, device_t child, char *buf,
+ size_t buflen)
+{
+ if (ofw_bus_get_name(child) != NULL) {
+ strlcat(buf, "name=", buflen);
+ strlcat(buf, ofw_bus_get_name(child), buflen);
+ }
+
+ if (ofw_bus_get_compat(child) != NULL) {
+ strlcat(buf, " compat=", buflen);
+ strlcat(buf, ofw_bus_get_compat(child), buflen);
+ }
+
+ return (0);
+};
const char *
ofw_bus_gen_get_compat(device_t bus, device_t dev)
@@ -126,3 +145,135 @@ ofw_bus_gen_get_type(device_t bus, device_t dev)
return (NULL);
return (obd->obd_type);
}
+
+static int
+ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
+{
+ int rv;
+
+ for (; node != 0; node = OF_parent(node)) {
+ if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
+ return (rv);
+ }
+ return (-1);
+}
+
+void
+ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
+{
+ pcell_t addrc;
+ int msksz;
+
+ if (OF_getprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1)
+ addrc = 2;
+ ii->opi_addrc = addrc * sizeof(pcell_t);
+
+ ii->opi_imapsz = OF_getprop_alloc(node, "interrupt-map", 1,
+ (void **)&ii->opi_imap);
+ if (ii->opi_imapsz > 0) {
+ msksz = OF_getprop_alloc(node, "interrupt-map-mask", 1,
+ (void **)&ii->opi_imapmsk);
+ /*
+ * Failure to get the mask is ignored; a full mask is used then.
+ * Barf on bad mask sizes, however.
+ */
+ if (msksz != -1 && msksz != ii->opi_addrc + intrsz) {
+ panic("ofw_bus_setup_iinfo: bad interrupt-map-mask "
+ "property!");
+ }
+ }
+
+}
+
+int
+ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg,
+ int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz,
+ void *maskbuf)
+{
+ int rv;
+
+ if (ii->opi_imapsz <= 0)
+ return (0);
+ KASSERT(regsz >= ii->opi_addrc,
+ ("ofw_bus_lookup_imap: register size too small: %d < %d",
+ regsz, ii->opi_addrc));
+ rv = OF_getprop(node, "reg", reg, regsz);
+ if (rv < regsz)
+ panic("ofw_bus_lookup_imap: could not get reg property");
+ return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc,
+ ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr,
+ mintrsz));
+}
+
+/*
+ * Map an interrupt using the firmware reg, interrupt-map and
+ * interrupt-map-mask properties.
+ * The interrupt property to be mapped must be of size intrsz, and pointed to
+ * by intr. The regs property of the node for which the mapping is done must
+ * be passed as regs. This property is an array of register specifications;
+ * the size of the address part of such a specification must be passed as
+ * physsz. Only the first element of the property is used.
+ * imap and imapsz hold the interrupt mask and it's size.
+ * imapmsk is a pointer to the interrupt-map-mask property, which must have
+ * a size of physsz + intrsz; it may be NULL, in which case a full mask is
+ * assumed.
+ * maskbuf must point to a buffer of length physsz + intrsz.
+ * The interrupt is returned in result, which must point to a buffer of length
+ * rintrsz (which gives the expected size of the mapped interrupt).
+ * Returns 1 if a mapping was found, 0 otherwise.
+ */
+int
+ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
+ void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result,
+ int rintrsz)
+{
+ phandle_t parent;
+ u_int8_t *ref = maskbuf;
+ u_int8_t *uiintr = intr;
+ u_int8_t *uiregs = regs;
+ u_int8_t *uiimapmsk = imapmsk;
+ u_int8_t *mptr;
+ pcell_t pintrsz;
+ int i, rsz, tsz;
+
+ rsz = -1;
+ if (imapmsk != NULL) {
+ for (i = 0; i < physsz; i++)
+ ref[i] = uiregs[i] & uiimapmsk[i];
+ for (i = 0; i < intrsz; i++)
+ ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i];
+ } else {
+ bcopy(regs, ref, physsz);
+ bcopy(intr, ref + physsz, intrsz);
+ }
+
+ mptr = imap;
+ i = imapsz;
+ tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
+ while (i > 0) {
+ KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
+ bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
+ if (ofw_bus_searchprop(parent, "#interrupt-cells",
+ &pintrsz, sizeof(pintrsz)) == -1)
+ pintrsz = 1; /* default */
+ pintrsz *= sizeof(pcell_t);
+ if (pintrsz != rintrsz)
+ panic("ofw_bus_search_intrmap: expected interrupt cell "
+ "size incorrect: %d > %d", rintrsz, pintrsz);
+
+ /*
+ * XXX: Apple hardware uses a second cell to set information
+ * on the interrupt trigger type. This information should
+ * be used somewhere to program the PIC.
+ */
+
+ if (bcmp(ref, mptr, physsz + intrsz) == 0) {
+ bcopy(mptr + physsz + intrsz + sizeof(parent),
+ result, rintrsz);
+ return (1);
+ }
+ mptr += tsz;
+ i -= tsz;
+ }
+ return (0);
+}
diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h
index 6096b3e..58dd587 100644
--- a/sys/dev/ofw/ofw_bus_subr.h
+++ b/sys/dev/ofw/ofw_bus_subr.h
@@ -37,9 +37,30 @@
#include "ofw_bus_if.h"
+#define ORIP_NOINT -1
+#define ORIR_NOTFOUND 0xffffffff
+
+struct ofw_bus_iinfo {
+ u_int8_t *opi_imap;
+ u_int8_t *opi_imapmsk;
+ int opi_imapsz;
+ pcell_t opi_addrc;
+};
+
int ofw_bus_gen_setup_devinfo(struct ofw_bus_devinfo *, phandle_t);
void ofw_bus_gen_destroy_devinfo(struct ofw_bus_devinfo *);
+/* Helper method to report interesting OF properties in pnpinfo */
+int ofw_bus_gen_child_pnpinfo_str(device_t, device_t, char *, size_t);
+
+/* Routines for processing firmware interrupt maps */
+
+void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
+int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
+ void *, int, void *, int, void *);
+int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
+ void *, void *, int);
+
ofw_bus_get_compat_t ofw_bus_gen_get_compat;
ofw_bus_get_model_t ofw_bus_gen_get_model;
ofw_bus_get_name_t ofw_bus_gen_get_name;
diff --git a/sys/dev/ofw/ofw_if.m b/sys/dev/ofw/ofw_if.m
new file mode 100644
index 0000000..431ac91
--- /dev/null
+++ b/sys/dev/ofw/ofw_if.m
@@ -0,0 +1,357 @@
+#-
+# Copyright (c) 2008 Nathan Whitehorn
+# 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.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+#
+# $FreeBSD$
+#
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+
+/**
+ * @defgroup OFW ofw - KObj methods for Open Firmware RTAS implementations
+ * @brief A set of methods to implement the Open Firmware client side interface.
+ *@{
+ */
+
+INTERFACE ofw;
+
+/**
+ * @brief Initialize OFW client interface
+ *
+ * @param _cookie A handle to the client interface, generally the OF
+ * callback routine.
+ */
+METHOD void init {
+ ofw_t _ofw;
+ void *_cookie;
+};
+
+/**
+ * @brief Return next sibling of node
+ *
+ * @param _node Selected node
+ */
+METHOD phandle_t peer {
+ ofw_t _ofw;
+ phandle_t _node;
+};
+
+/**
+ * @brief Return parent of node
+ *
+ * @param _node Selected node
+ */
+METHOD phandle_t parent {
+ ofw_t _ofw;
+ phandle_t _node;
+};
+
+/**
+ * @brief Return first child of node
+ *
+ * @param _node Selected node
+ */
+METHOD phandle_t child {
+ ofw_t _ofw;
+ phandle_t _node;
+};
+
+/**
+ * @brief Return package corresponding to instance
+ *
+ * @param _handle Selected instance
+ */
+METHOD phandle_t instance_to_package {
+ ofw_t _ofw;
+ ihandle_t _handle;
+};
+
+/**
+ * @brief Return length of node property
+ *
+ * @param _node Selected node
+ * @param _prop Property name
+ */
+METHOD ssize_t getproplen {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+};
+
+/**
+ * @brief Read node property
+ *
+ * @param _node Selected node
+ * @param _prop Property name
+ * @param _buf Pointer to buffer
+ * @param _size Size of buffer
+ */
+METHOD ssize_t getprop {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+ void *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Get next property name
+ *
+ * @param _node Selected node
+ * @param _prop Current property name
+ * @param _buf Buffer for next property name
+ * @param _size Size of buffer
+ */
+METHOD int nextprop {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+ char *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Set property
+ *
+ * @param _node Selected node
+ * @param _prop Property name
+ * @param _buf Value to set
+ * @param _size Size of buffer
+ */
+METHOD int setprop {
+ ofw_t _ofw;
+ phandle_t _node;
+ const char *_prop;
+ const void *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Canonicalize path
+ *
+ * @param _path Path to canonicalize
+ * @param _buf Buffer for canonicalized path
+ * @param _size Size of buffer
+ */
+METHOD ssize_t canon {
+ ofw_t _ofw;
+ const char *_path;
+ char *_buf;
+ size_t _size;
+};
+
+/**
+ * @brief Return phandle for named device
+ *
+ * @param _path Device path
+ */
+METHOD phandle_t finddevice {
+ ofw_t _ofw;
+ const char *_path;
+};
+
+/**
+ * @brief Return path for node instance
+ *
+ * @param _handle Instance handle
+ * @param _path Buffer for path
+ * @param _size Size of buffer
+ */
+METHOD ssize_t instance_to_path {
+ ofw_t _ofw;
+ ihandle_t _handle;
+ char *_path;
+ size_t _size;
+};
+
+/**
+ * @brief Return path for node
+ *
+ * @param _node Package node
+ * @param _path Buffer for path
+ * @param _size Size of buffer
+ */
+METHOD ssize_t package_to_path {
+ ofw_t _ofw;
+ phandle_t _node;
+ char *_path;
+ size_t _size;
+};
+
+
+# Methods for OF method calls (optional)
+
+/**
+ * @brief Test to see if a service exists.
+ *
+ * @param _name name of the service
+ */
+METHOD int test {
+ ofw_t _ofw;
+ const char *_name;
+};
+
+/**
+ * @brief Call method belonging to an instance handle
+ *
+ * @param _instance Instance handle
+ * @param _method Method name
+ * @param _nargs Number of arguments
+ * @param _nreturns Number of return values
+ * @param _args_and_returns Values for arguments, followed by returns
+ */
+
+METHOD int call_method {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ const char *_method;
+ int _nargs;
+ int _nreturns;
+
+ unsigned long *_args_and_returns;
+};
+
+/**
+ * @brief Interpret a forth command
+ *
+ * @param _cmd Command
+ * @param _nreturns Number of return values
+ * @param _returns Values for returns
+ */
+
+METHOD int interpret {
+ ofw_t _ofw;
+ const char *_cmd;
+ int _nreturns;
+ unsigned long *_returns;
+};
+
+# Device I/O Functions (optional)
+
+/**
+ * @brief Open node, returning instance handle
+ *
+ * @param _path Path to node
+ */
+METHOD ihandle_t open {
+ ofw_t _ofw;
+ const char *_path;
+}
+
+/**
+ * @brief Close node instance
+ *
+ * @param _instance Instance to close
+ */
+METHOD void close {
+ ofw_t _ofw;
+ ihandle_t _instance;
+}
+
+/**
+ * @brief Read from device
+ *
+ * @param _instance Device instance
+ * @param _buf Buffer to read to
+ * @param _size Size of buffer
+ */
+METHOD ssize_t read {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ void *_buf;
+ size_t size;
+}
+
+/**
+ * @brief Write to device
+ *
+ * @param _instance Device instance
+ * @param _buf Buffer to write from
+ * @param _size Size of buffer
+ */
+METHOD ssize_t write {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ const void *_buf;
+ size_t size;
+}
+
+/**
+ * @brief Seek device
+ *
+ * @param _instance Device instance
+ * @param _off Offset to which to seek
+ */
+METHOD int seek {
+ ofw_t _ofw;
+ ihandle_t _instance;
+ uint64_t _off;
+}
+
+# Open Firmware memory management
+
+/**
+ * @brief Claim virtual memory
+ *
+ * @param _addr Requested memory location (NULL for first available)
+ * @param _size Requested size in bytes
+ * @param _align Requested alignment
+ */
+METHOD caddr_t claim {
+ ofw_t _ofw;
+ void *_addr;
+ size_t _size;
+ u_int _align;
+}
+
+/**
+ * @brief Release virtual memory
+ *
+ * @param _addr Memory location
+ * @param _size Size in bytes
+ */
+METHOD void release {
+ ofw_t _ofw;
+ void *_addr;
+ size_t _size;
+};
+
+# Commands for returning control to the firmware
+
+/**
+ * @brief Temporarily return control to firmware
+ */
+METHOD void enter {
+ ofw_t _ofw;
+};
+
+/**
+ * @brief Halt and return control to firmware
+ */
+METHOD void exit {
+ ofw_t _ofw;
+};
+
+
diff --git a/sys/dev/ofw/ofw_standard.c b/sys/dev/ofw/ofw_standard.c
new file mode 100644
index 0000000..e097145
--- /dev/null
+++ b/sys/dev/ofw/ofw_standard.c
@@ -0,0 +1,763 @@
+/* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
+
+/*-
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * 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 TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
+ */
+/*-
+ * Copyright (C) 2000 Benno Rice.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``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 TOOLS GMBH 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <machine/stdarg.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+#include "ofw_if.h"
+
+static void ofw_std_init(ofw_t ofw, void *openfirm);
+static int ofw_std_test(ofw_t ofw, const char *name);
+static int ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns,
+ unsigned long *returns);
+static phandle_t ofw_std_peer(ofw_t ofw, phandle_t node);
+static phandle_t ofw_std_child(ofw_t ofw, phandle_t node);
+static phandle_t ofw_std_parent(ofw_t ofw, phandle_t node);
+static phandle_t ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance);
+static ssize_t ofw_std_getproplen(ofw_t ofw, phandle_t package,
+ const char *propname);
+static ssize_t ofw_std_getprop(ofw_t ofw, phandle_t package,
+ const char *propname, void *buf, size_t buflen);
+static int ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous,
+ char *buf, size_t);
+static int ofw_std_setprop(ofw_t ofw, phandle_t package, char *propname,
+ void *buf, size_t len);
+static ssize_t ofw_std_canon(ofw_t ofw, const char *device, char *buf,
+ size_t len);
+static phandle_t ofw_std_finddevice(ofw_t ofw, const char *device);
+static ssize_t ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance,
+ char *buf, size_t len);
+static ssize_t ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf,
+ size_t len);
+static int ofw_std_call_method(ofw_t ofw, ihandle_t instance,
+ const char *method, int nargs, int nreturns,
+ unsigned long *args_and_returns);
+static ihandle_t ofw_std_open(ofw_t ofw, const char *device);
+static void ofw_std_close(ofw_t ofw, ihandle_t instance);
+static ssize_t ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr,
+ size_t len);
+static ssize_t ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr,
+ size_t len);
+static int ofw_std_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos);
+static caddr_t ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align);
+static void ofw_std_release(ofw_t ofw, void *virt, size_t size);
+static void ofw_std_enter(ofw_t ofw);
+static void ofw_std_exit(ofw_t ofw);
+
+static ofw_method_t ofw_std_methods[] = {
+ OFWMETHOD(ofw_init, ofw_std_init),
+ OFWMETHOD(ofw_peer, ofw_std_peer),
+ OFWMETHOD(ofw_child, ofw_std_child),
+ OFWMETHOD(ofw_parent, ofw_std_parent),
+ OFWMETHOD(ofw_instance_to_package, ofw_std_instance_to_package),
+ OFWMETHOD(ofw_getproplen, ofw_std_getproplen),
+ OFWMETHOD(ofw_getprop, ofw_std_getprop),
+ OFWMETHOD(ofw_nextprop, ofw_std_nextprop),
+ OFWMETHOD(ofw_setprop, ofw_std_setprop),
+ OFWMETHOD(ofw_canon, ofw_std_canon),
+ OFWMETHOD(ofw_finddevice, ofw_std_finddevice),
+ OFWMETHOD(ofw_instance_to_path, ofw_std_instance_to_path),
+ OFWMETHOD(ofw_package_to_path, ofw_std_package_to_path),
+
+ OFWMETHOD(ofw_test, ofw_std_test),
+ OFWMETHOD(ofw_call_method, ofw_std_call_method),
+ OFWMETHOD(ofw_interpret, ofw_std_interpret),
+ OFWMETHOD(ofw_open, ofw_std_open),
+ OFWMETHOD(ofw_close, ofw_std_close),
+ OFWMETHOD(ofw_read, ofw_std_read),
+ OFWMETHOD(ofw_write, ofw_std_write),
+ OFWMETHOD(ofw_seek, ofw_std_seek),
+ OFWMETHOD(ofw_claim, ofw_std_claim),
+ OFWMETHOD(ofw_release, ofw_std_release),
+ OFWMETHOD(ofw_enter, ofw_std_enter),
+ OFWMETHOD(ofw_exit, ofw_std_exit),
+
+ { 0, 0 }
+};
+
+static ofw_def_t ofw_std = {
+ OFW_STD_DIRECT,
+ ofw_std_methods,
+ 0
+};
+OFW_DEF(ofw_std);
+
+static int (*openfirmware)(void *);
+
+/* Initialiser */
+
+static void
+ofw_std_init(ofw_t ofw, void *openfirm)
+{
+ openfirmware = (int (*)(void *))openfirm;
+}
+
+/*
+ * Generic functions
+ */
+
+/* Test to see if a service exists. */
+static int
+ofw_std_test(ofw_t ofw, const char *name)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t service;
+ cell_t missing;
+ } args = {
+ (cell_t)"test",
+ 1,
+ 1,
+ };
+
+ args.service = (cell_t)name;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.missing);
+}
+
+static int
+ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns,
+ unsigned long *returns)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t slot[16];
+ } args = {
+ (cell_t)"interpret",
+ 1,
+ };
+ cell_t status;
+ int i = 0, j = 0;
+
+ args.nreturns = ++nreturns;
+ args.slot[i++] = (cell_t)cmd;
+ if (openfirmware(&args) == -1) {
+ return (-1);
+ }
+ status = args.slot[i++];
+ while (i < 1 + nreturns)
+ returns[j] = args.slot[i++];
+ return (status);
+}
+
+/*
+ * Device tree functions
+ */
+
+/* Return the next sibling of this node or 0. */
+static phandle_t
+ofw_std_peer(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t next;
+ } args = {
+ (cell_t)"peer",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.next);
+}
+
+/* Return the first child of this node or 0. */
+static phandle_t
+ofw_std_child(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t child;
+ } args = {
+ (cell_t)"child",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.child);
+}
+
+/* Return the parent of this node or 0. */
+static phandle_t
+ofw_std_parent(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t parent;
+ } args = {
+ (cell_t)"parent",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.parent);
+}
+
+/* Return the package handle that corresponds to an instance handle. */
+static phandle_t
+ofw_std_instance_to_package(ofw_t ofw, ihandle_t instance)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t package;
+ } args = {
+ (cell_t)"instance-to-package",
+ 1,
+ 1,
+ };
+
+ args.instance = instance;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.package);
+}
+
+/* Get the length of a property of a package. */
+static ssize_t
+ofw_std_getproplen(ofw_t ofw, phandle_t package, const char *propname)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t proplen;
+ } args = {
+ (cell_t)"getproplen",
+ 2,
+ 1,
+ };
+
+ args.package = package;
+ args.propname = (cell_t)propname;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.proplen);
+}
+
+/* Get the value of a property of a package. */
+static ssize_t
+ofw_std_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
+ size_t buflen)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t buf;
+ cell_t buflen;
+ cell_t size;
+ } args = {
+ (cell_t)"getprop",
+ 4,
+ 1,
+ };
+
+ args.package = package;
+ args.propname = (cell_t)propname;
+ args.buf = (cell_t)buf;
+ args.buflen = buflen;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Get the next property of a package. */
+static int
+ofw_std_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf,
+ size_t size)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t previous;
+ cell_t buf;
+ cell_t flag;
+ } args = {
+ (cell_t)"nextprop",
+ 3,
+ 1,
+ };
+
+ args.package = package;
+ args.previous = (cell_t)previous;
+ args.buf = (cell_t)buf;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.flag);
+}
+
+/* Set the value of a property of a package. */
+/* XXX Has a bug on FirePower */
+static int
+ofw_std_setprop(ofw_t ofw, phandle_t package, char *propname, void *buf,
+ size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"setprop",
+ 4,
+ 1,
+ };
+
+ args.package = package;
+ args.propname = (cell_t)propname;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Convert a device specifier to a fully qualified pathname. */
+static ssize_t
+ofw_std_canon(ofw_t ofw, const char *device, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"canon",
+ 3,
+ 1,
+ };
+
+ args.device = (cell_t)device;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Return a package handle for the specified device. */
+static phandle_t
+ofw_std_finddevice(ofw_t ofw, const char *device)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t package;
+ } args = {
+ (cell_t)"finddevice",
+ 1,
+ 1,
+ };
+
+ args.device = (cell_t)device;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.package);
+}
+
+/* Return the fully qualified pathname corresponding to an instance. */
+static ssize_t
+ofw_std_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"instance-to-path",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Return the fully qualified pathname corresponding to a package. */
+static ssize_t
+ofw_std_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"package-to-path",
+ 3,
+ 1,
+ };
+
+ args.package = package;
+ args.buf = (cell_t)buf;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.size);
+}
+
+/* Call the method in the scope of a given instance. */
+static int
+ofw_std_call_method(ofw_t ofw, ihandle_t instance, const char *method,
+ int nargs, int nreturns, unsigned long *args_and_returns)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t method;
+ cell_t instance;
+ cell_t args_n_results[12];
+ } args = {
+ (cell_t)"call-method",
+ 2,
+ 1,
+ };
+ cell_t *cp;
+ unsigned long *ap;
+ int n;
+
+ if (nargs > 6)
+ return (-1);
+ args.nargs = nargs + 2;
+ args.nreturns = nreturns + 1;
+ args.method = (cell_t)method;
+ args.instance = instance;
+
+ ap = args_and_returns;
+ for (cp = args.args_n_results + (n = nargs); --n >= 0;)
+ *--cp = *(ap++);
+ if (openfirmware(&args) == -1)
+ return (-1);
+ if (args.args_n_results[nargs])
+ return (args.args_n_results[nargs]);
+ for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
+ *(ap++) = *--cp;
+ return (0);
+}
+
+/*
+ * Device I/O functions
+ */
+
+/* Open an instance for a device. */
+static ihandle_t
+ofw_std_open(ofw_t ofw, const char *device)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t instance;
+ } args = {
+ (cell_t)"open",
+ 1,
+ 1,
+ };
+
+ args.device = (cell_t)device;
+ if (openfirmware(&args) == -1 || args.instance == 0) {
+ return (-1);
+ }
+ return (args.instance);
+}
+
+/* Close an instance. */
+static void
+ofw_std_close(ofw_t ofw, ihandle_t instance)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ } args = {
+ (cell_t)"close",
+ 1,
+ };
+
+ args.instance = instance;
+ openfirmware(&args);
+}
+
+/* Read from an instance. */
+static ssize_t
+ofw_std_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t addr;
+ cell_t len;
+ cell_t actual;
+ } args = {
+ (cell_t)"read",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.addr = (cell_t)addr;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+
+ return (args.actual);
+}
+
+/* Write to an instance. */
+static ssize_t
+ofw_std_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t addr;
+ cell_t len;
+ cell_t actual;
+ } args = {
+ (cell_t)"write",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.addr = (cell_t)addr;
+ args.len = len;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.actual);
+}
+
+/* Seek to a position. */
+static int
+ofw_std_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t poshi;
+ cell_t poslo;
+ cell_t status;
+ } args = {
+ (cell_t)"seek",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.poshi = pos >> 32;
+ args.poslo = pos;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.status);
+}
+
+/*
+ * Memory functions
+ */
+
+/* Claim an area of memory. */
+static caddr_t
+ofw_std_claim(ofw_t ofw, void *virt, size_t size, u_int align)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t virt;
+ cell_t size;
+ cell_t align;
+ cell_t baseaddr;
+ } args = {
+ (cell_t)"claim",
+ 3,
+ 1,
+ };
+
+ args.virt = (cell_t)virt;
+ args.size = size;
+ args.align = align;
+ if (openfirmware(&args) == -1)
+ return ((void *)-1);
+ return ((void *)args.baseaddr);
+}
+
+/* Release an area of memory. */
+static void
+ofw_std_release(ofw_t ofw, void *virt, size_t size)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t virt;
+ cell_t size;
+ } args = {
+ (cell_t)"release",
+ 2,
+ };
+
+ args.virt = (cell_t)virt;
+ args.size = size;
+ openfirmware(&args);
+}
+
+/*
+ * Control transfer functions
+ */
+
+/* Suspend and drop back to the Open Firmware interface. */
+static void
+ofw_std_enter(ofw_t ofw)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ } args = {
+ (cell_t)"enter",
+ };
+
+ openfirmware(&args);
+ /* We may come back. */
+}
+
+/* Shut down and drop back to the Open Firmware interface. */
+static void
+ofw_std_exit(ofw_t ofw)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ } args = {
+ (cell_t)"exit",
+ };
+
+ openfirmware(&args);
+ for (;;) /* just in case */
+ ;
+}
+
diff --git a/sys/dev/ofw/ofwvar.h b/sys/dev/ofw/ofwvar.h
new file mode 100644
index 0000000..950dded
--- /dev/null
+++ b/sys/dev/ofw/ofwvar.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2005 Peter Grehan
+ * Copyright (c) 2008 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _OFW_OFWVAR_H_
+#define _OFW_OFWVAR_H_
+
+/*
+ * An Open Firmware client implementation is declared with a kernel object and
+ * an associated method table, similar to a device driver.
+ *
+ * e.g.
+ *
+ * static ofw_method_t fdt_methods[] = {
+ * OFWMETHOD(ofw_init, fdt_init),
+ * OFWMETHOD(ofw_finddevice, fdt_finddevice),
+ * ...
+ * OFWMETHOD(ofw_nextprop, fdt_nextprop),
+ * { 0, 0 }
+ * };
+ *
+ * static ofw_def_t ofw_fdt = {
+ * "ofw_fdt",
+ * fdt_methods,
+ * sizeof(fdt_softc), // or 0 if no softc
+ * };
+ *
+ * OFW_DEF(ofw_fdt);
+ */
+
+#include <sys/kobj.h>
+
+struct ofw_kobj {
+ /*
+ * An OFW instance is a kernel object.
+ */
+ KOBJ_FIELDS;
+
+ /*
+ * Utility elements that an instance may use
+ */
+ struct mtx ofw_mtx; /* available for instance use */
+ void *ofw_iptr; /* instance data pointer */
+
+ /*
+ * Opaque data that can be overlaid with an instance-private
+ * structure. OFW code can test that this is large enough at
+ * compile time with a sizeof() test againt it's softc. There
+ * is also a run-time test when the MMU kernel object is
+ * registered.
+ */
+#define OFW_OPAQUESZ 64
+ u_int ofw_opaque[OFW_OPAQUESZ];
+};
+
+typedef struct ofw_kobj *ofw_t;
+typedef struct kobj_class ofw_def_t;
+
+#define ofw_method_t kobj_method_t
+#define OFWMETHOD KOBJMETHOD
+
+#define OFW_DEF(name) DATA_SET(ofw_set, name)
+
+#endif /* _OFW_OFWVAR_H_ */
diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c
index ff889e5..c7b2203 100644
--- a/sys/dev/ofw/openfirm.c
+++ b/sys/dev/ofw/openfirm.c
@@ -66,23 +66,70 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+
+#include "ofw_if.h"
MALLOC_DEFINE(M_OFWPROP, "openfirm", "Open Firmware properties");
static ihandle_t stdout;
+static ofw_def_t *ofw_def_impl;
+static ofw_t ofw_obj;
+static struct ofw_kobj ofw_kernel_obj;
+static struct kobj_ops ofw_kernel_kops;
+
+/*
+ * OFW install routines. Highest priority wins, equal priority also
+ * overrides allowing last-set to win.
+ */
+SET_DECLARE(ofw_set, ofw_def_t);
+
+boolean_t
+OF_install(char *name, int prio)
+{
+ ofw_def_t **ofwpp, *ofwp;
+ static int curr_prio = 0;
+
+ /*
+ * Try and locate the OFW kobj corresponding to the name
+ */
+ SET_FOREACH(ofwpp, ofw_set) {
+ ofwp = *ofwpp;
+
+ if (ofwp->name &&
+ !strcmp(ofwp->name, name) &&
+ prio >= curr_prio) {
+ curr_prio = prio;
+ ofw_def_impl = ofwp;
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+
/* Initialiser */
void
-OF_init(int (*openfirm)(void *))
+OF_init(void *cookie)
{
phandle_t chosen;
- set_openfirm_callback(openfirm);
+ ofw_obj = &ofw_kernel_obj;
+ /*
+ * Take care of compiling the selected class, and
+ * then statically initialize the OFW object
+ */
+ kobj_class_compile_static(ofw_def_impl, &ofw_kernel_kops);
+ kobj_init((kobj_t)ofw_obj, ofw_def_impl);
+
+ OFW_INIT(ofw_obj, cookie);
+
if ((chosen = OF_finddevice("/chosen")) == -1)
OF_exit();
if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1)
- OF_exit();
+ stdout = -1;
}
void
@@ -103,75 +150,27 @@ OF_printf(const char *fmt, ...)
/* Test to see if a service exists. */
int
-OF_test(char *name)
+OF_test(const char *name)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t service;
- cell_t missing;
- } args = {
- (cell_t)"test",
- 1,
- 1,
- };
-
- args.service = (cell_t)name;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.missing);
+ return (OFW_TEST(ofw_obj, name));
}
int
-OF_interpret(char *cmd, int nreturns, ...)
+OF_interpret(const char *cmd, int nreturns, ...)
{
va_list ap;
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t slot[16];
- } args = {
- (cell_t)"interpret",
- 1,
- };
- cell_t status;
+ unsigned long slots[16];
int i = 0;
+ int status;
+
+ status = OFW_INTERPRET(ofw_obj, cmd, nreturns, slots);
va_start(ap, nreturns);
- args.nreturns = ++nreturns;
- args.slot[i++] = (cell_t)cmd;
- while (i < 1)
- args.slot[i++] = va_arg(ap, cell_t);
- if (openfirmware(&args) == -1) {
- va_end(ap);
- return (-1);
- }
- status = args.slot[i++];
while (i < 1 + nreturns)
- *va_arg(ap, cell_t *) = args.slot[i++];
+ *va_arg(ap, cell_t *) = slots[i++];
va_end(ap);
- return (status);
-}
-/* Return firmware millisecond count. */
-int
-OF_milliseconds()
-{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t ms;
- } args = {
- (cell_t)"milliseconds",
- 0,
- 1,
- };
-
- openfirmware(&args);
- return (args.ms);
+ return (status);
}
/*
@@ -182,140 +181,42 @@ OF_milliseconds()
phandle_t
OF_peer(phandle_t node)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t node;
- cell_t next;
- } args = {
- (cell_t)"peer",
- 1,
- 1,
- };
-
- args.node = node;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.next);
+ return (OFW_PEER(ofw_obj, node));
}
/* Return the first child of this node or 0. */
phandle_t
OF_child(phandle_t node)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t node;
- cell_t child;
- } args = {
- (cell_t)"child",
- 1,
- 1,
- };
-
- args.node = node;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.child);
+ return (OFW_CHILD(ofw_obj, node));
}
/* Return the parent of this node or 0. */
phandle_t
OF_parent(phandle_t node)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t node;
- cell_t parent;
- } args = {
- (cell_t)"parent",
- 1,
- 1,
- };
-
- args.node = node;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.parent);
+ return (OFW_PARENT(ofw_obj, node));
}
/* Return the package handle that corresponds to an instance handle. */
phandle_t
OF_instance_to_package(ihandle_t instance)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t package;
- } args = {
- (cell_t)"instance-to-package",
- 1,
- 1,
- };
-
- args.instance = instance;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.package);
+ return (OFW_INSTANCE_TO_PACKAGE(ofw_obj, instance));
}
/* Get the length of a property of a package. */
-int
-OF_getproplen(phandle_t package, char *propname)
+ssize_t
+OF_getproplen(phandle_t package, const char *propname)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t propname;
- cell_t proplen;
- } args = {
- (cell_t)"getproplen",
- 2,
- 1,
- };
-
- args.package = package;
- args.propname = (cell_t)propname;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.proplen);
+ return (OFW_GETPROPLEN(ofw_obj, package, propname));
}
/* Get the value of a property of a package. */
-int
-OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
+ssize_t
+OF_getprop(phandle_t package, const char *propname, void *buf, size_t buflen)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t propname;
- cell_t buf;
- cell_t buflen;
- cell_t size;
- } args = {
- (cell_t)"getprop",
- 4,
- 1,
- };
-
- args.package = package;
- args.propname = (cell_t)propname;
- args.buf = (cell_t)buf;
- args.buflen = buflen;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_GETPROP(ofw_obj, package, propname, buf, buflen));
}
/*
@@ -323,8 +224,8 @@ OF_getprop(phandle_t package, char *propname, void *buf, int buflen)
* (using the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a
* single element, the number of elements is return in number.
*/
-int
-OF_getprop_alloc(phandle_t package, char *propname, int elsz, void **buf)
+ssize_t
+OF_getprop_alloc(phandle_t package, const char *propname, int elsz, void **buf)
{
int len;
@@ -344,194 +245,69 @@ OF_getprop_alloc(phandle_t package, char *propname, int elsz, void **buf)
/* Get the next property of a package. */
int
-OF_nextprop(phandle_t package, char *previous, char *buf)
+OF_nextprop(phandle_t package, const char *previous, char *buf, size_t size)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t previous;
- cell_t buf;
- cell_t flag;
- } args = {
- (cell_t)"nextprop",
- 3,
- 1,
- };
-
- args.package = package;
- args.previous = (cell_t)previous;
- args.buf = (cell_t)buf;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.flag);
+ return (OFW_NEXTPROP(ofw_obj, package, previous, buf, size));
}
/* Set the value of a property of a package. */
-/* XXX Has a bug on FirePower */
int
-OF_setprop(phandle_t package, char *propname, void *buf, int len)
+OF_setprop(phandle_t package, const char *propname, const void *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t propname;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"setprop",
- 4,
- 1,
- };
-
- args.package = package;
- args.propname = (cell_t)propname;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_SETPROP(ofw_obj, package, propname, buf,len));
}
/* Convert a device specifier to a fully qualified pathname. */
-int
-OF_canon(const char *device, char *buf, int len)
+ssize_t
+OF_canon(const char *device, char *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t device;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"canon",
- 3,
- 1,
- };
-
- args.device = (cell_t)device;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_CANON(ofw_obj, device, buf, len));
}
/* Return a package handle for the specified device. */
phandle_t
OF_finddevice(const char *device)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t device;
- cell_t package;
- } args = {
- (cell_t)"finddevice",
- 1,
- 1,
- };
-
- args.device = (cell_t)device;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.package);
+ return (OFW_FINDDEVICE(ofw_obj, device));
}
/* Return the fully qualified pathname corresponding to an instance. */
-int
-OF_instance_to_path(ihandle_t instance, char *buf, int len)
+ssize_t
+OF_instance_to_path(ihandle_t instance, char *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"instance-to-path",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_INSTANCE_TO_PATH(ofw_obj, instance, buf, len));
}
/* Return the fully qualified pathname corresponding to a package. */
-int
-OF_package_to_path(phandle_t package, char *buf, int len)
+ssize_t
+OF_package_to_path(phandle_t package, char *buf, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t package;
- cell_t buf;
- cell_t len;
- cell_t size;
- } args = {
- (cell_t)"package-to-path",
- 3,
- 1,
- };
-
- args.package = package;
- args.buf = (cell_t)buf;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.size);
+ return (OFW_PACKAGE_TO_PATH(ofw_obj, package, buf, len));
}
/* Call the method in the scope of a given instance. */
int
-OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
+OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns,
+ ...)
{
va_list ap;
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t method;
- cell_t instance;
- cell_t args_n_results[12];
- } args = {
- (cell_t)"call-method",
- 2,
- 1,
- };
- cell_t *cp;
- int n;
+ unsigned long args_n_results[12];
+ int n, status;
if (nargs > 6)
return (-1);
- args.nargs = nargs + 2;
- args.nreturns = nreturns + 1;
- args.method = (cell_t)method;
- args.instance = instance;
va_start(ap, nreturns);
- for (cp = args.args_n_results + (n = nargs); --n >= 0;)
- *--cp = va_arg(ap, cell_t);
- if (openfirmware(&args) == -1)
- return (-1);
- if (args.args_n_results[nargs])
- return (args.args_n_results[nargs]);
- for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
- *va_arg(ap, cell_t *) = *--cp;
+ for (n = 0; n < nargs; n++)
+ args_n_results[n] = va_arg(ap, unsigned long);
+
+ status = OFW_CALL_METHOD(ofw_obj, instance, method, nargs, nreturns,
+ args_n_results);
+
+ if (status != 0)
+ return (status);
+
+ for (; n < nargs + nreturns; n++)
+ *va_arg(ap, unsigned long *) = args_n_results[n];
va_end(ap);
return (0);
}
@@ -542,122 +318,37 @@ OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
/* Open an instance for a device. */
ihandle_t
-OF_open(char *device)
+OF_open(const char *device)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t device;
- cell_t instance;
- } args = {
- (cell_t)"open",
- 1,
- 1,
- };
-
- args.device = (cell_t)device;
- if (openfirmware(&args) == -1 || args.instance == 0) {
- return (-1);
- }
- return (args.instance);
+ return (OFW_OPEN(ofw_obj, device));
}
/* Close an instance. */
void
OF_close(ihandle_t instance)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- } args = {
- (cell_t)"close",
- 1,
- };
-
- args.instance = instance;
- openfirmware(&args);
+ OFW_CLOSE(ofw_obj, instance);
}
/* Read from an instance. */
-int
-OF_read(ihandle_t instance, void *addr, int len)
+ssize_t
+OF_read(ihandle_t instance, void *addr, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t addr;
- cell_t len;
- cell_t actual;
- } args = {
- (cell_t)"read",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.addr = (cell_t)addr;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
-
- return (args.actual);
+ return (OFW_READ(ofw_obj, instance, addr, len));
}
/* Write to an instance. */
-int
-OF_write(ihandle_t instance, void *addr, int len)
+ssize_t
+OF_write(ihandle_t instance, const void *addr, size_t len)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t addr;
- cell_t len;
- cell_t actual;
- } args = {
- (cell_t)"write",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.addr = (cell_t)addr;
- args.len = len;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.actual);
+ return (OFW_WRITE(ofw_obj, instance, addr, len));
}
/* Seek to a position. */
int
-OF_seek(ihandle_t instance, u_int64_t pos)
+OF_seek(ihandle_t instance, uint64_t pos)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t instance;
- cell_t poshi;
- cell_t poslo;
- cell_t status;
- } args = {
- (cell_t)"seek",
- 3,
- 1,
- };
-
- args.instance = instance;
- args.poshi = pos >> 32;
- args.poslo = pos;
- if (openfirmware(&args) == -1)
- return (-1);
- return (args.status);
+ return (OFW_SEEK(ofw_obj, instance, pos));
}
/*
@@ -666,145 +357,37 @@ OF_seek(ihandle_t instance, u_int64_t pos)
/* Claim an area of memory. */
void *
-OF_claim(void *virt, u_int size, u_int align)
+OF_claim(void *virt, size_t size, u_int align)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t virt;
- cell_t size;
- cell_t align;
- cell_t baseaddr;
- } args = {
- (cell_t)"claim",
- 3,
- 1,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- args.align = align;
- if (openfirmware(&args) == -1)
- return ((void *)-1);
- return ((void *)args.baseaddr);
+ return (OFW_CLAIM(ofw_obj, virt, size, align));
}
/* Release an area of memory. */
void
-OF_release(void *virt, u_int size)
+OF_release(void *virt, size_t size)
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t virt;
- cell_t size;
- } args = {
- (cell_t)"release",
- 2,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- openfirmware(&args);
+ OFW_RELEASE(ofw_obj, virt, size);
}
/*
* Control transfer functions
*/
-/* Reset the system and call "boot <bootspec>". */
-void
-OF_boot(char *bootspec)
-{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t bootspec;
- } args = {
- (cell_t)"boot",
- 1,
- };
-
- args.bootspec = (cell_t)bootspec;
- openfirmware(&args);
- for (;;) /* just in case */
- ;
-}
-
/* Suspend and drop back to the Open Firmware interface. */
void
OF_enter()
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- } args = {
- (cell_t)"enter",
- };
-
- openfirmware(&args);
- /* We may come back. */
+ OFW_ENTER(ofw_obj);
}
/* Shut down and drop back to the Open Firmware interface. */
void
OF_exit()
{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- } args = {
- (cell_t)"exit",
- };
-
- openfirmware(&args);
+ /* Should not return */
+ OFW_EXIT(ofw_obj);
+
for (;;) /* just in case */
;
}
-/* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
-#if 0
-void
-OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
-{
- static struct {
- cell_t name;
- cell_t nargs;
- cell_t nreturns;
- cell_t virt;
- cell_t size;
- cell_t entry;
- cell_t arg;
- cell_t len;
- } args = {
- (cell_t)"chain",
- 5,
- };
-
- args.virt = (cell_t)virt;
- args.size = size;
- args.entry = (cell_t)entry;
- args.arg = (cell_t)arg;
- args.len = len;
- openfirmware(&args);
-}
-#else
-void
-OF_chain(void *virt, u_int size,
- void (*entry)(void *, u_int, void *, void *, u_int), void *arg, u_int len)
-{
- /*
- * This is a REALLY dirty hack till the firmware gets this going
- */
-#if 0
- if (size > 0)
- OF_release(virt, size);
-#endif
- entry(0, 0, openfirmware, arg, len);
-}
-#endif
diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h
index a8c0633..08a0544 100644
--- a/sys/dev/ofw/openfirm.h
+++ b/sys/dev/ofw/openfirm.h
@@ -60,78 +60,82 @@
#ifndef _OPENFIRM_H_
#define _OPENFIRM_H_
+#include <sys/types.h>
+
/*
* Prototypes for Open Firmware Interface Routines
*/
-typedef unsigned long cell_t;
-
-typedef unsigned int ihandle_t;
-typedef unsigned int phandle_t;
+typedef uint32_t ihandle_t;
+typedef uint32_t phandle_t;
+typedef uint32_t pcell_t;
#ifdef _KERNEL
-#include <sys/cdefs.h>
-#include <sys/types.h>
#include <sys/malloc.h>
+#include <machine/ofw_machdep.h>
+
MALLOC_DECLARE(M_OFWPROP);
/*
- * Stuff that is used by the Open Firmware code.
+ * Open Firmware interface initialization. OF_install installs the named
+ * interface as the Open Firmware access mechanism, OF_init initializes it.
*/
-void set_openfirm_callback(int (*)(void *));
-int openfirmware(void *);
+
+boolean_t OF_install(char *name, int prio);
+void OF_init(void *cookie);
/*
- * This isn't actually an Open Firmware function, but it seemed like the right
- * place for it to go.
+ * Known Open Firmware interface names
*/
-void OF_init(int (*openfirm)(void *));
+
+#define OFW_STD_DIRECT "ofw_std" /* Standard OF interface */
+#define OFW_STD_REAL "ofw_real" /* Real-mode OF interface */
+#define OFW_FDT "ofw_fdt" /* Flattened Device Tree */
/* Generic functions */
-int OF_test(char *);
+int OF_test(const char *);
void OF_printf(const char *, ...);
/* Device tree functions */
-phandle_t OF_peer(phandle_t);
-phandle_t OF_child(phandle_t);
-phandle_t OF_parent(phandle_t);
-phandle_t OF_instance_to_package(ihandle_t);
-int OF_getproplen(phandle_t, char *);
-int OF_getprop(phandle_t, char *, void *, int);
-int OF_getprop_alloc(phandle_t package, char *propname, int elsz,
- void **buf);
-int OF_nextprop(phandle_t, char *, char *);
-int OF_setprop(phandle_t, char *, void *, int);
-int OF_canon(const char *, char *, int);
-phandle_t OF_finddevice(const char *);
-int OF_instance_to_path(ihandle_t, char *, int);
-int OF_package_to_path(phandle_t, char *, int);
-int OF_call_method(char *, ihandle_t, int, int, ...);
+phandle_t OF_peer(phandle_t node);
+phandle_t OF_child(phandle_t node);
+phandle_t OF_parent(phandle_t node);
+ssize_t OF_getproplen(phandle_t node, const char *propname);
+ssize_t OF_getprop(phandle_t node, const char *propname, void *buf,
+ size_t len);
+ssize_t OF_getprop_alloc(phandle_t node, const char *propname,
+ int elsz, void **buf);
+int OF_nextprop(phandle_t node, const char *propname, char *buf,
+ size_t len);
+int OF_setprop(phandle_t node, const char *name, const void *buf,
+ size_t len);
+ssize_t OF_canon(const char *path, char *buf, size_t len);
+phandle_t OF_finddevice(const char *path);
+ssize_t OF_package_to_path(phandle_t node, char *buf, size_t len);
/* Device I/O functions */
-ihandle_t OF_open(char *);
-void OF_close(ihandle_t);
-int OF_read(ihandle_t, void *, int);
-int OF_write(ihandle_t, void *, int);
-int OF_seek(ihandle_t, u_quad_t);
+ihandle_t OF_open(const char *path);
+void OF_close(ihandle_t instance);
+ssize_t OF_read(ihandle_t instance, void *buf, size_t len);
+ssize_t OF_write(ihandle_t instance, const void *buf, size_t len);
+int OF_seek(ihandle_t instance, uint64_t where);
+
+phandle_t OF_instance_to_package(ihandle_t instance);
+ssize_t OF_instance_to_path(ihandle_t instance, char *buf, size_t len);
+int OF_call_method(const char *method, ihandle_t instance,
+ int nargs, int nreturns, ...);
/* Memory functions */
-void *OF_claim(void *, u_int, u_int);
-void OF_release(void *, u_int);
+void *OF_claim(void *virtrequest, size_t size, u_int align);
+void OF_release(void *virt, size_t size);
/* Control transfer functions */
-void OF_boot(char *);
void OF_enter(void);
void OF_exit(void) __attribute__((noreturn));
-void OF_chain(void *, u_int,
- void (*)(void *, u_int, void *, void *, u_int), void *, u_int);
/* User interface functions */
-int OF_interpret(char *, int, ...);
-
-/* Time function */
-int OF_milliseconds(void);
+int OF_interpret(const char *cmd, int nreturns, ...);
#endif /* _KERNEL */
#endif /* _OPENFIRM_H_ */
diff --git a/sys/dev/ofw/openfirmio.c b/sys/dev/ofw/openfirmio.c
index 47f2517..d042f02 100644
--- a/sys/dev/ofw/openfirmio.c
+++ b/sys/dev/ofw/openfirmio.c
@@ -221,7 +221,7 @@ openfirm_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
if (error)
break;
}
- ok = OF_nextprop(node, name, newname);
+ ok = OF_nextprop(node, name, newname, sizeof(newname));
if (ok == 0) {
error = ENOENT;
break;
diff --git a/sys/dev/ofw/openpromio.c b/sys/dev/ofw/openpromio.c
index cb7343f..8ba6d3a 100644
--- a/sys/dev/ofw/openpromio.c
+++ b/sys/dev/ofw/openpromio.c
@@ -174,7 +174,7 @@ openprom_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
error = OF_getprop(node, prop, buf, proplen);
break;
case OPROMNXTPROP:
- error = OF_nextprop(node, prop, buf);
+ error = OF_nextprop(node, prop, buf, OPROMMAXPARAM);
proplen = strlen(buf);
break;
}
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 6709d6d..2ad55fd 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -1157,6 +1157,7 @@ re_attach(device_t dev)
msic = 0;
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
+ sc->rl_flags |= RL_FLAG_PCIE;
msic = pci_msi_count(dev);
if (bootverbose)
device_printf(dev, "MSI count : %d\n", msic);
@@ -1262,8 +1263,13 @@ re_attach(device_t dev)
sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE |
RL_FLAG_MACSTAT;
break;
- case RL_HWREV_8168C:
case RL_HWREV_8168C_SPIN2:
+ sc->rl_flags |= RL_FLAG_MACSLEEP;
+ /* FALLTHROUGH */
+ case RL_HWREV_8168C:
+ if ((hwrev & 0x00700000) == 0x00200000)
+ sc->rl_flags |= RL_FLAG_MACSLEEP;
+ /* FALLTHROUGH */
case RL_HWREV_8168CP:
case RL_HWREV_8168D:
sc->rl_flags |= RL_FLAG_INVMAR | RL_FLAG_PHYWAKE |
@@ -1351,6 +1357,16 @@ re_attach(device_t dev)
goto fail;
}
+ /* Take controller out of deep sleep mode. */
+ if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) {
+ if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80)
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) | 0x01);
+ else
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) & ~0x01);
+ }
+
/* Take PHY out of power down mode. */
if ((sc->rl_flags & RL_FLAG_PHYWAKE) != 0) {
re_gmii_writereg(dev, 1, 0x1f, 0);
@@ -2027,16 +2043,6 @@ re_txeof(struct rl_softc *sc)
/* No changes made to the TX ring, so no flush needed */
if (sc->rl_ldata.rl_tx_free != sc->rl_ldata.rl_tx_desc_cnt) {
- /*
- * Some chips will ignore a second TX request issued
- * while an existing transmission is in progress. If
- * the transmitter goes idle but there are still
- * packets waiting to be sent, we need to restart the
- * channel here to flush them out. This only seems to
- * be required with the PCIe devices.
- */
- CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
-
#ifdef RE_TX_MODERATION
/*
* If not all descriptors have been reaped yet, reload
@@ -2100,6 +2106,9 @@ re_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
return;
if (status)
CSR_WRITE_2(sc, RL_ISR, status);
+ if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) &&
+ (sc->rl_flags & RL_FLAG_PCIE))
+ CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
/*
* XXX check behaviour on receiver stalls.
@@ -2161,6 +2170,17 @@ re_int_task(void *arg, int npending)
if (status & (RL_ISR_RX_OK|RL_ISR_RX_ERR|RL_ISR_FIFO_OFLOW))
rval = re_rxeof(sc);
+ /*
+ * Some chips will ignore a second TX request issued
+ * while an existing transmission is in progress. If
+ * the transmitter goes idle but there are still
+ * packets waiting to be sent, we need to restart the
+ * channel here to flush them out. This only seems to
+ * be required with the PCIe devices.
+ */
+ if ((status & (RL_ISR_TX_OK | RL_ISR_TX_DESC_UNAVAIL)) &&
+ (sc->rl_flags & RL_FLAG_PCIE))
+ CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
if (status & (
#ifdef RE_TX_MODERATION
RL_ISR_TIMEOUT_EXPIRED|
@@ -2963,6 +2983,12 @@ re_resume(device_t dev)
RL_LOCK(sc);
ifp = sc->rl_ifp;
+ /* Take controller out of sleep mode. */
+ if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) {
+ if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80)
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) | 0x01);
+ }
/* reinitialize interface if necessary */
if (ifp->if_flags & IFF_UP)
@@ -3018,6 +3044,12 @@ re_setwol(struct rl_softc *sc)
return;
ifp = sc->rl_ifp;
+ /* Put controller into sleep mode. */
+ if ((sc->rl_flags & RL_FLAG_MACSLEEP) != 0) {
+ if ((CSR_READ_1(sc, RL_MACDBG) & 0x80) == 0x80)
+ CSR_WRITE_1(sc, RL_GPIO,
+ CSR_READ_1(sc, RL_GPIO) & ~0x01);
+ }
if ((ifp->if_capenable & IFCAP_WOL) != 0 &&
(sc->rl_flags & RL_FLAG_WOLRXENB) != 0)
CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RX_ENB);
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index f2dcc1b..8d6485c 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/poll.h>
+#include <sys/proc.h>
#include <sys/snoop.h>
#include <sys/sx.h>
#include <sys/systm.h>
@@ -246,7 +247,7 @@ snp_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
sx_xunlock(&snp_register_lock);
return (EBUSY);
}
- error = ttyhook_register(&ss->snp_tty, td, *(int *)data,
+ error = ttyhook_register(&ss->snp_tty, td->td_proc, *(int *)data,
&snp_hook, ss);
sx_xunlock(&snp_register_lock);
if (error != 0)
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index 4be21fb1..a185f51 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -83,7 +83,7 @@
#include "mixer_if.h"
-#define HDA_DRV_TEST_REV "20081123_0118"
+#define HDA_DRV_TEST_REV "20081219_0119"
SND_DECLARE_FILE("$FreeBSD$");
@@ -180,6 +180,11 @@ SND_DECLARE_FILE("$FreeBSD$");
#define HDA_SIS_966 HDA_MODEL_CONSTRUCT(SIS, 0x7502)
#define HDA_SIS_ALL HDA_MODEL_CONSTRUCT(SIS, 0xffff)
+/* ULI */
+#define ULI_VENDORID 0x10b9
+#define HDA_ULI_M5461 HDA_MODEL_CONSTRUCT(ULI, 0x5461)
+#define HDA_ULI_ALL HDA_MODEL_CONSTRUCT(ULI, 0xffff)
+
/* OEM/subvendors */
/* Intel */
@@ -467,12 +472,14 @@ static const struct {
{ HDA_ATI_SB600, "ATI SB600" },
{ HDA_VIA_VT82XX, "VIA VT8251/8237A" },
{ HDA_SIS_966, "SiS 966" },
+ { HDA_ULI_M5461, "ULI M5461" },
/* Unknown */
{ HDA_INTEL_ALL, "Intel (Unknown)" },
{ HDA_NVIDIA_ALL, "NVidia (Unknown)" },
{ HDA_ATI_ALL, "ATI (Unknown)" },
{ HDA_VIA_ALL, "VIA (Unknown)" },
{ HDA_SIS_ALL, "SiS (Unknown)" },
+ { HDA_ULI_ALL, "ULI (Unknown)" },
};
#define HDAC_DEVICES_LEN (sizeof(hdac_devices) / sizeof(hdac_devices[0]))
@@ -635,6 +642,7 @@ static const struct {
/* Silicon Image */
#define SII_VENDORID 0x1095
+#define HDA_CODEC_SII1392 HDA_CODEC_CONSTRUCT(SII, 0x1392)
#define HDA_CODEC_SIIXXXX HDA_CODEC_CONSTRUCT(SII, 0xffff)
/* Lucent/Agere */
@@ -669,9 +677,21 @@ static const struct {
#define HDA_CODEC_VT1709_5 HDA_CODEC_CONSTRUCT(VIA, 0xe715)
#define HDA_CODEC_VT1709_6 HDA_CODEC_CONSTRUCT(VIA, 0xe716)
#define HDA_CODEC_VT1709_7 HDA_CODEC_CONSTRUCT(VIA, 0xe717)
+#define HDA_CODEC_VT1708B_0 HDA_CODEC_CONSTRUCT(VIA, 0xe720)
+#define HDA_CODEC_VT1708B_1 HDA_CODEC_CONSTRUCT(VIA, 0xe721)
+#define HDA_CODEC_VT1708B_2 HDA_CODEC_CONSTRUCT(VIA, 0xe722)
+#define HDA_CODEC_VT1708B_3 HDA_CODEC_CONSTRUCT(VIA, 0xe723)
+#define HDA_CODEC_VT1708B_4 HDA_CODEC_CONSTRUCT(VIA, 0xe724)
+#define HDA_CODEC_VT1708B_5 HDA_CODEC_CONSTRUCT(VIA, 0xe725)
+#define HDA_CODEC_VT1708B_6 HDA_CODEC_CONSTRUCT(VIA, 0xe726)
+#define HDA_CODEC_VT1708B_7 HDA_CODEC_CONSTRUCT(VIA, 0xe727)
#define HDA_CODEC_VTXXXX HDA_CODEC_CONSTRUCT(VIA, 0xffff)
/* ATI */
+#define HDA_CODEC_ATIRS600_1 HDA_CODEC_CONSTRUCT(ATI, 0x793c)
+#define HDA_CODEC_ATIRS600_2 HDA_CODEC_CONSTRUCT(ATI, 0x7919)
+#define HDA_CODEC_ATIRS690 HDA_CODEC_CONSTRUCT(ATI, 0x791a)
+#define HDA_CODEC_ATIR6XX HDA_CODEC_CONSTRUCT(ATI, 0xaa01)
#define HDA_CODEC_ATIXXXX HDA_CODEC_CONSTRUCT(ATI, 0xffff)
/* NVIDIA */
@@ -774,6 +794,19 @@ static const struct {
{ HDA_CODEC_VT1709_5, "VIA VT1709_5" },
{ HDA_CODEC_VT1709_6, "VIA VT1709_6" },
{ HDA_CODEC_VT1709_7, "VIA VT1709_7" },
+ { HDA_CODEC_VT1708B_0, "VIA VT1708B_0" },
+ { HDA_CODEC_VT1708B_1, "VIA VT1708B_1" },
+ { HDA_CODEC_VT1708B_2, "VIA VT1708B_2" },
+ { HDA_CODEC_VT1708B_3, "VIA VT1708B_3" },
+ { HDA_CODEC_VT1708B_4, "VIA VT1708B_4" },
+ { HDA_CODEC_VT1708B_5, "VIA VT1708B_5" },
+ { HDA_CODEC_VT1708B_6, "VIA VT1708B_6" },
+ { HDA_CODEC_VT1708B_7, "VIA VT1708B_7" },
+ { HDA_CODEC_ATIRS600_1,"ATI RS600 HDMI" },
+ { HDA_CODEC_ATIRS600_2,"ATI RS600 HDMI" },
+ { HDA_CODEC_ATIRS690, "ATI RS690/780 HDMI" },
+ { HDA_CODEC_ATIR6XX, "ATI R6xx HDMI" },
+ { HDA_CODEC_SII1392, "Silicon Image SiI1392 HDMI" },
/* Unknown codec */
{ HDA_CODEC_ALCXXXX, "Realtek (Unknown)" },
{ HDA_CODEC_ADXXXX, "Analog Devices (Unknown)" },
diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c
index 7496d40..ae263a0 100644
--- a/sys/dev/usb/ucom.c
+++ b/sys/dev/usb/ucom.c
@@ -700,6 +700,29 @@ ucomstartread(struct ucom_softc *sc)
return (USBD_NORMAL_COMPLETION);
}
+void
+ucomrxchars(struct ucom_softc *sc, u_char *cp, u_int32_t cc)
+{
+ struct tty *tp = sc->sc_tty;
+
+ /* Give characters to tty layer. */
+ if (ttydisc_can_bypass(tp)) {
+ DPRINTFN(7, ("ucomreadcb: buf = %*D\n", cc, cp, ""));
+ cc -= ttydisc_rint_bypass(tp, cp, cc);
+ } else {
+ while (cc > 0) {
+ DPRINTFN(7, ("ucomreadcb: char = 0x%02x\n", *cp));
+ if (ttydisc_rint(tp, *cp, 0) == -1)
+ break;
+ cc--;
+ cp++;
+ }
+ }
+ if (cc > 0)
+ device_printf(sc->sc_dev, "lost %d chars\n", cc);
+ ttydisc_rint_done(tp);
+}
+
static void
ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
{
@@ -709,6 +732,7 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
u_int32_t cc;
u_char *cp;
+ (void)tp; /* Used for debugging */
DPRINTF(("ucomreadcb: status = %d\n", status));
if (status != USBD_NORMAL_COMPLETION) {
@@ -737,22 +761,8 @@ ucomreadcb(usbd_xfer_handle xfer, usbd_private_handle p, usbd_status status)
device_get_nameunit(sc->sc_dev), cc);
goto resubmit;
}
- if (cc < 1)
- goto resubmit;
-
- /* Give characters to tty layer. */
- while (cc > 0) {
- DPRINTFN(7, ("ucomreadcb: char = 0x%02x\n", *cp));
- if (ttydisc_rint(tp, *cp, 0) == -1) {
- /* XXX what should we do? */
- printf("%s: lost %d chars\n",
- device_get_nameunit(sc->sc_dev), cc);
- break;
- }
- cc--;
- cp++;
- }
- ttydisc_rint_done(tp);
+ if (cc > 0)
+ ucomrxchars(sc, cp, cc);
resubmit:
err = ucomstartread(sc);
diff --git a/sys/dev/usb/ucomvar.h b/sys/dev/usb/ucomvar.h
index 0fcd7f3..4433a1a 100644
--- a/sys/dev/usb/ucomvar.h
+++ b/sys/dev/usb/ucomvar.h
@@ -166,3 +166,4 @@ void ucom_attach_tty(struct ucom_softc *, char*, int);
int ucom_attach(struct ucom_softc *);
int ucom_detach(struct ucom_softc *);
void ucom_status_change(struct ucom_softc *);
+void ucomrxchars(struct ucom_softc *sc, u_char *cp, u_int32_t cc);
diff --git a/sys/dev/usb/uftdi.c b/sys/dev/usb/uftdi.c
index 5a9921b..c32bfa6 100644
--- a/sys/dev/usb/uftdi.c
+++ b/sys/dev/usb/uftdi.c
@@ -100,7 +100,7 @@ SYSCTL_INT(_hw_usb_uftdi, OID_AUTO, debug, CTLFLAG_RW,
* These are the maximum number of bytes transferred per frame.
* The output buffer size cannot be increased due to the size encoding.
*/
-#define UFTDIIBUFSIZE 64
+#define UFTDIIBUFSIZE 256
#define UFTDIOBUFSIZE 64
struct uftdi_softc {
@@ -458,32 +458,33 @@ uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count)
{
struct uftdi_softc *sc = vsc;
u_char msr, lsr;
+ unsigned l;
+
+ DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n",
+ sc, portno, *count));
+ while (*count > 0) {
+ l = *count;
+ if (l > 64)
+ l = 64;
+
+ msr = FTDI_GET_MSR(*ptr);
+ lsr = FTDI_GET_LSR(*ptr);
+
+ if (sc->sc_msr != msr ||
+ (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
+ DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) "
+ "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr,
+ lsr, sc->sc_lsr));
+ sc->sc_msr = msr;
+ sc->sc_lsr = lsr;
+ ucom_status_change(&sc->sc_ucom);
+ }
- DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n", sc, portno,
- *count));
-
- msr = FTDI_GET_MSR(*ptr);
- lsr = FTDI_GET_LSR(*ptr);
-
-#ifdef USB_DEBUG
- if (*count != 2)
- DPRINTFN(10,("uftdi_read: sc=%p, port=%d count=%d data[0]="
- "0x%02x\n", sc, portno, *count, (*ptr)[2]));
-#endif
-
- if (sc->sc_msr != msr ||
- (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
- DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) "
- "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr,
- lsr, sc->sc_lsr));
- sc->sc_msr = msr;
- sc->sc_lsr = lsr;
- ucom_status_change(&sc->sc_ucom);
+ if (l > 2)
+ ucomrxchars(&sc->sc_ucom, (*ptr) + 2, l - 2);
+ *ptr += l;
+ *count -= l;
}
-
- /* Pick up status and adjust data part. */
- *ptr += 2;
- *count -= 2;
}
static size_t
diff --git a/sys/fs/hpfs/hpfs_vnops.c b/sys/fs/hpfs/hpfs_vnops.c
index c5a2a06..4ec6b1e 100644
--- a/sys/fs/hpfs/hpfs_vnops.c
+++ b/sys/fs/hpfs/hpfs_vnops.c
@@ -661,7 +661,7 @@ hpfs_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c
index ccbd0b1..9dc547f 100644
--- a/sys/fs/msdosfs/msdosfs_vnops.c
+++ b/sys/fs/msdosfs/msdosfs_vnops.c
@@ -1880,7 +1880,7 @@ msdosfs_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/fs/ntfs/ntfs_vnops.c b/sys/fs/ntfs/ntfs_vnops.c
index 76c3c64..ee62a5c 100644
--- a/sys/fs/ntfs/ntfs_vnops.c
+++ b/sys/fs/ntfs/ntfs_vnops.c
@@ -339,7 +339,7 @@ ntfs_strategy(ap)
}
}
bufdone(bp);
- return (error);
+ return (0);
}
static int
diff --git a/sys/fs/nwfs/nwfs_vnops.c b/sys/fs/nwfs/nwfs_vnops.c
index 9dcd9aa..ca0a887 100644
--- a/sys/fs/nwfs/nwfs_vnops.c
+++ b/sys/fs/nwfs/nwfs_vnops.c
@@ -804,7 +804,7 @@ static int nwfs_strategy (ap)
*/
if ((bp->b_flags & B_ASYNC) == 0 )
error = nwfs_doio(ap->a_vp, bp, cr, td);
- return (error);
+ return (0);
}
diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c
index e34ebe2..9b1e76d 100644
--- a/sys/fs/smbfs/smbfs_vnops.c
+++ b/sys/fs/smbfs/smbfs_vnops.c
@@ -864,7 +864,7 @@ smbfs_strategy (ap)
if ((bp->b_flags & B_ASYNC) == 0 )
error = smbfs_doio(ap->a_vp, bp, cr, td);
- return error;
+ return (0);
}
int
diff --git a/sys/geom/geom_vfs.c b/sys/geom/geom_vfs.c
index 0621eff..86c909d 100644
--- a/sys/geom/geom_vfs.c
+++ b/sys/geom/geom_vfs.c
@@ -93,10 +93,23 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp)
{
struct g_consumer *cp;
struct bio *bip;
+ int vfslocked;
cp = bo->bo_private;
G_VALID_CONSUMER(cp);
+ /*
+ * If the the provider has orphaned us, just return EXIO.
+ */
+ if (cp->provider == NULL) {
+ bp->b_error = ENXIO;
+ bp->b_ioflags |= BIO_ERROR;
+ vfslocked = VFS_LOCK_GIANT(((struct mount *)NULL));
+ bufdone(bp);
+ VFS_UNLOCK_GIANT(vfslocked);
+ return;
+ }
+
bip = g_alloc_bio();
bip->bio_cmd = bp->b_iocmd;
bip->bio_offset = bp->b_iooffset;
@@ -110,18 +123,20 @@ g_vfs_strategy(struct bufobj *bo, struct buf *bp)
static void
g_vfs_orphan(struct g_consumer *cp)
{
+ struct g_geom *gp;
+ struct bufobj *bo;
+
+ g_topology_assert();
+
+ gp = cp->geom;
+ bo = gp->softc;
+ g_trace(G_T_TOPOLOGY, "g_vfs_orphan(%p(%s))", cp, gp->name);
+ if (cp->acr > 0 || cp->acw > 0 || cp->ace > 0)
+ g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+ g_detach(cp);
/*
- * Don't do anything here yet.
- *
- * Ideally we should detach the consumer already now, but that
- * leads to a locking requirement in the I/O path to see if we have
- * a consumer or not. Considering how ugly things are going to get
- * anyway as none of our filesystems are graceful about i/o errors,
- * this is not important right now.
- *
- * Down the road, this is the place where we could give the user
- * a "Abort, Retry or Ignore" option to replace the media again.
+ * Do not destroy the geom. Filesystem will do this during unmount.
*/
}
diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c
index f81d509..1b5023c 100644
--- a/sys/gnu/fs/ext2fs/ext2_vnops.c
+++ b/sys/gnu/fs/ext2fs/ext2_vnops.c
@@ -1399,7 +1399,7 @@ ext2_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/gnu/fs/reiserfs/reiserfs_vnops.c b/sys/gnu/fs/reiserfs/reiserfs_vnops.c
index e6323ea..12fe409 100644
--- a/sys/gnu/fs/reiserfs/reiserfs_vnops.c
+++ b/sys/gnu/fs/reiserfs/reiserfs_vnops.c
@@ -350,8 +350,13 @@ reiserfs_strategy(struct vop_strategy_args /* {
bp->b_ioflags |= BIO_ERROR;
}
+ if (error) {
+ bp->b_ioflags |= BIO_ERROR;
+ bp->b_error = error;
+ }
+
bufdone(bp);
- return (error);
+ return (0);
}
/*
diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
index d0efcf2..6d8d4eb 100644
--- a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
+++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c
@@ -1136,7 +1136,7 @@ _xfs_strategy(
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/sys/i386/conf/DEFAULTS b/sys/i386/conf/DEFAULTS
index 2450f82..1411f09 100644
--- a/sys/i386/conf/DEFAULTS
+++ b/sys/i386/conf/DEFAULTS
@@ -20,8 +20,8 @@ device io # I/O device
device uart_ns8250
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
# enable support for native hardware
options NATIVE
diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s
index 0ad2597..1451fa8 100644
--- a/sys/i386/i386/exception.s
+++ b/sys/i386/i386/exception.s
@@ -438,9 +438,18 @@ doreti_nmi:
iret
outofnmi:
/*
- * Clear interrupts and jump to AST handling code.
+ * Call the callchain capture hook after turning interrupts back on.
*/
+ movl pmc_hook,%ecx
+ orl %ecx,%ecx
+ jz doreti_exit
+ pushl %esp /* frame pointer */
+ pushl $PMC_FN_USER_CALLCHAIN /* command */
+ movl PCPU(CURTHREAD),%eax
+ pushl %eax /* curthread */
sti
+ call *%ecx
+ addl $12,%esp
jmp doreti_ast
ENTRY(end_exceptions)
#endif
diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c
index 67ff943..cf70af7 100644
--- a/sys/i386/i386/identcpu.c
+++ b/sys/i386/i386/identcpu.c
@@ -826,15 +826,15 @@ printcpuinfo(void)
"\003SVM" /* Secure Virtual Mode */
"\004ExtAPIC" /* Extended APIC register */
"\005CR8" /* CR8 in legacy mode */
- "\006<b5>"
- "\007<b6>"
- "\010<b7>"
+ "\006ABM" /* LZCNT instruction */
+ "\007SSE4A" /* SSE4A */
+ "\010MAS" /* Misaligned SSE mode */
"\011Prefetch" /* 3DNow! Prefetch/PrefetchW */
- "\012<b9>"
- "\013<b10>"
- "\014<b11>"
- "\015<b12>"
- "\016<b13>"
+ "\012OSVW" /* OS visible workaround */
+ "\013IBS" /* Instruction based sampling */
+ "\014SSE5" /* SSE5 */
+ "\015SKINIT" /* SKINIT/STGI */
+ "\016WDT" /* Watchdog timer */
"\017<b14>"
"\020<b15>"
"\021<b16>"
diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h
index cf2a2d2..1470173 100644
--- a/sys/i386/include/elf.h
+++ b/sys/i386/include/elf.h
@@ -84,18 +84,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h
index b4842e9..c3cbec7 100644
--- a/sys/i386/include/specialreg.h
+++ b/sys/i386/include/specialreg.h
@@ -147,7 +147,15 @@
#define AMDID2_SVM 0x00000004
#define AMDID2_EXT_APIC 0x00000008
#define AMDID2_CR8 0x00000010
+#define AMDID2_ABM 0x00000020
+#define AMDID2_SSE4A 0x00000040
+#define AMDID2_MAS 0x00000080
#define AMDID2_PREFETCH 0x00000100
+#define AMDID2_OSVW 0x00000200
+#define AMDID2_IBS 0x00000400
+#define AMDID2_SSE5 0x00000800
+#define AMDID2_SKINIT 0x00001000
+#define AMDID2_WDT 0x00002000
/*
* CPUID instruction 1 eax info
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 7444901..42365fb 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -245,8 +245,6 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
args = (Elf32_Auxargs *)imgp->auxargs;
pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace)
- AUXARGS_ENTRY(pos, AT_DEBUG, 1);
if (args->execfd != -1)
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h
index ec22512..faab8d1 100644
--- a/sys/ia64/include/elf.h
+++ b/sys/ia64/include/elf.h
@@ -82,18 +82,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index af78e55..431ee38 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -97,9 +97,6 @@ SYSCTL_INT(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO,
TUNABLE_INT("kern.elf" __XSTRING(__ELF_WORD_SIZE) ".fallback_brand",
&__elfN(fallback_brand));
-static int elf_trace = 0;
-SYSCTL_INT(_debug, OID_AUTO, __elfN(trace), CTLFLAG_RW, &elf_trace, 0, "");
-
static int elf_legacy_coredump = 0;
SYSCTL_INT(_debug, OID_AUTO, __elfN(legacy_coredump), CTLFLAG_RW,
&elf_legacy_coredump, 0, "");
@@ -839,7 +836,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
elf_auxargs->base = addr;
elf_auxargs->flags = 0;
elf_auxargs->entry = entry;
- elf_auxargs->trace = elf_trace;
imgp->auxargs = elf_auxargs;
imgp->interpreted = 0;
@@ -894,12 +890,8 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
base = (Elf_Addr *)*stack_base;
pos = base + (imgp->args->argc + imgp->args->envc + 2);
- if (args->trace) {
- AUXARGS_ENTRY(pos, AT_DEBUG, 1);
- }
- if (args->execfd != -1) {
+ if (args->execfd != -1)
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
- }
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
diff --git a/sys/kern/kern_cpu.c b/sys/kern/kern_cpu.c
index 50fff53..7b0b588 100644
--- a/sys/kern/kern_cpu.c
+++ b/sys/kern/kern_cpu.c
@@ -144,7 +144,9 @@ static int
cpufreq_attach(device_t dev)
{
struct cpufreq_softc *sc;
+ struct pcpu *pc;
device_t parent;
+ uint64_t rate;
int numdevs;
CF_DEBUG("initializing %s\n", device_get_nameunit(dev));
@@ -156,7 +158,12 @@ cpufreq_attach(device_t dev)
CF_MTX_INIT(&sc->lock);
sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN;
SLIST_INIT(&sc->saved_freq);
- sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
+ /* Try to get current CPU freq to use it as maximum later if needed */
+ pc = cpu_get_pcpu(dev);
+ if (cpu_est_clockrate(pc->pc_cpuid, &rate) == 0)
+ sc->max_mhz = rate / 1000000;
+ else
+ sc->max_mhz = CPUFREQ_VAL_UNKNOWN;
/*
* Only initialize one set of sysctls for all CPUs. In the future,
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index 03581a4..a7810ef 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -120,7 +120,6 @@ tunable_mbinit(void *dummy)
}
SYSINIT(tunable_mbinit, SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_mbinit, NULL);
-/* XXX: These should be tuneables. Can't change UMA limits on the fly. */
static int
sysctl_nmbclusters(SYSCTL_HANDLER_ARGS)
{
diff --git a/sys/kern/subr_kobj.c b/sys/kern/subr_kobj.c
index 4e2f096..bc36667 100644
--- a/sys/kern/subr_kobj.c
+++ b/sys/kern/subr_kobj.c
@@ -60,6 +60,19 @@ static struct mtx kobj_mtx;
static int kobj_mutex_inited;
static int kobj_next_id = 1;
+/*
+ * In the event that kobj_mtx has not been initialized yet,
+ * we will ignore it, and run without locks in order to support
+ * use of KOBJ before mutexes are available. This early in the boot
+ * process, everything is single threaded and so races should not
+ * happen. This is used to provide the PMAP layer on PowerPC, as well
+ * as board support.
+ */
+
+#define KOBJ_LOCK() if (kobj_mutex_inited) mtx_lock(&kobj_mtx);
+#define KOBJ_UNLOCK() if (kobj_mutex_inited) mtx_unlock(&kobj_mtx);
+#define KOBJ_ASSERT(what) if (kobj_mutex_inited) mtx_assert(&kobj_mtx,what);
+
SYSCTL_UINT(_kern, OID_AUTO, kobj_methodcount, CTLFLAG_RD,
&kobj_next_id, 0, "");
@@ -74,12 +87,6 @@ kobj_init_mutex(void *arg)
SYSINIT(kobj, SI_SUB_LOCK, SI_ORDER_ANY, kobj_init_mutex, NULL);
-void
-kobj_machdep_init(void)
-{
- kobj_init_mutex(NULL);
-}
-
/*
* This method structure is used to initialise new caches. Since the
* desc pointer is NULL, it is guaranteed never to match any read
@@ -99,8 +106,8 @@ kobj_error_method(void)
static void
kobj_register_method(struct kobjop_desc *desc)
{
+ KOBJ_ASSERT(MA_OWNED);
- mtx_assert(&kobj_mtx, MA_OWNED);
if (desc->id == 0) {
desc->id = kobj_next_id++;
}
@@ -117,7 +124,7 @@ kobj_class_compile_common(kobj_class_t cls, kobj_ops_t ops)
kobj_method_t *m;
int i;
- mtx_assert(&kobj_mtx, MA_OWNED);
+ KOBJ_ASSERT(MA_OWNED);
/*
* Don't do anything if we are already compiled.
@@ -145,7 +152,7 @@ kobj_class_compile(kobj_class_t cls)
{
kobj_ops_t ops;
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
+ KOBJ_ASSERT(MA_NOTOWNED);
/*
* Allocate space for the compiled ops table.
@@ -154,7 +161,7 @@ kobj_class_compile(kobj_class_t cls)
if (!ops)
panic("kobj_compile_methods: out of memory");
- mtx_lock(&kobj_mtx);
+ KOBJ_LOCK();
/*
* We may have lost a race for kobj_class_compile here - check
@@ -162,28 +169,30 @@ kobj_class_compile(kobj_class_t cls)
* class.
*/
if (cls->ops) {
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
free(ops, M_KOBJ);
return;
}
kobj_class_compile_common(cls, ops);
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
}
void
kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops)
{
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
+ KOBJ_ASSERT(MA_NOTOWNED);
/*
* Increment refs to make sure that the ops table is not freed.
*/
- mtx_lock(&kobj_mtx);
+ KOBJ_LOCK();
+
cls->refs++;
kobj_class_compile_common(cls, ops);
- mtx_unlock(&kobj_mtx);
+
+ KOBJ_UNLOCK();
}
static kobj_method_t*
@@ -254,8 +263,8 @@ kobj_class_free(kobj_class_t cls)
kobj_method_t *m;
void* ops = 0;
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
- mtx_lock(&kobj_mtx);
+ KOBJ_ASSERT(MA_NOTOWNED);
+ KOBJ_LOCK();
/*
* Protect against a race between kobj_create and
@@ -275,7 +284,7 @@ kobj_class_free(kobj_class_t cls)
cls->ops = 0;
}
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
if (ops)
free(ops, M_KOBJ);
@@ -302,9 +311,9 @@ kobj_create(kobj_class_t cls,
void
kobj_init(kobj_t obj, kobj_class_t cls)
{
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
+ KOBJ_ASSERT(MA_NOTOWNED);
retry:
- mtx_lock(&kobj_mtx);
+ KOBJ_LOCK();
/*
* Consider compiling the class' method table.
@@ -315,7 +324,7 @@ kobj_init(kobj_t obj, kobj_class_t cls)
* because of the call to malloc - we drop the lock
* and re-try.
*/
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
kobj_class_compile(cls);
goto retry;
}
@@ -323,7 +332,7 @@ kobj_init(kobj_t obj, kobj_class_t cls)
obj->ops = cls->ops;
cls->refs++;
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
}
void
@@ -337,11 +346,11 @@ kobj_delete(kobj_t obj, struct malloc_type *mtype)
* after its last instance is deleted. As an optimisation, we
* should defer this for a short while to avoid thrashing.
*/
- mtx_assert(&kobj_mtx, MA_NOTOWNED);
- mtx_lock(&kobj_mtx);
+ KOBJ_ASSERT(MA_NOTOWNED);
+ KOBJ_LOCK();
cls->refs--;
refs = cls->refs;
- mtx_unlock(&kobj_mtx);
+ KOBJ_UNLOCK();
if (!refs)
kobj_class_free(cls);
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index 3701fda..6a0745f 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -73,6 +73,10 @@ __FBSDID("$FreeBSD$");
#define MAXFILES (maxproc * 2)
#endif
+enum VM_GUEST { VM_GUEST_NO, VM_GUEST_VM, VM_GUEST_XEN };
+
+static int sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS);
+
int hz;
int tick;
int maxusers; /* base tunable */
@@ -86,6 +90,7 @@ int nswbuf;
int maxswzone; /* max swmeta KVA storage */
int maxbcache; /* max buffer cache KVA storage */
int maxpipekva; /* Limit on pipe KVA */
+int vm_guest; /* Running as virtual machine guest? */
u_long maxtsiz; /* max text size */
u_long dfldsiz; /* initial data size limit */
u_long maxdsiz; /* max data size */
@@ -110,6 +115,9 @@ SYSCTL_ULONG(_kern, OID_AUTO, maxssiz, CTLFLAG_RDTUN, &maxssiz, 0,
"max stack size");
SYSCTL_ULONG(_kern, OID_AUTO, sgrowsiz, CTLFLAG_RDTUN, &sgrowsiz, 0,
"amount to grow stack");
+SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING,
+ NULL, 0, sysctl_kern_vm_guest, "A",
+ "Virtual machine detected? (none|generic|xen)");
/*
* These have to be allocated somewhere; allocating
@@ -133,7 +141,18 @@ static const char *const vm_pnames[] = {
NULL
};
-static int
+static const char *const vm_guest_sysctl_names[] = {
+ "none",
+ "generic",
+ "xen",
+ NULL
+};
+
+
+/*
+ * Detect known Virtual Machine hosts by inspecting the emulated BIOS.
+ */
+static enum VM_GUEST
detect_virtual(void)
{
char *sysenv;
@@ -144,7 +163,7 @@ detect_virtual(void)
for (i = 0; vm_bnames[i] != NULL; i++)
if (strcmp(sysenv, vm_bnames[i]) == 0) {
freeenv(sysenv);
- return (1);
+ return (VM_GUEST_VM);
}
freeenv(sysenv);
}
@@ -153,11 +172,11 @@ detect_virtual(void)
for (i = 0; vm_pnames[i] != NULL; i++)
if (strcmp(sysenv, vm_pnames[i]) == 0) {
freeenv(sysenv);
- return (1);
+ return (VM_GUEST_VM);
}
freeenv(sysenv);
}
- return (0);
+ return (VM_GUEST_NO);
}
/*
@@ -166,11 +185,15 @@ detect_virtual(void)
void
init_param1(void)
{
-
+#ifndef XEN
+ vm_guest = detect_virtual();
+#else
+ vm_guest = VM_GUEST_XEN;
+#endif
hz = -1;
TUNABLE_INT_FETCH("kern.hz", &hz);
if (hz == -1)
- hz = detect_virtual() ? HZ_VM : HZ;
+ hz = vm_guest > VM_GUEST_NO ? HZ_VM : HZ;
tick = 1000000 / hz;
#ifdef VM_SWZONE_SIZE_MAX
@@ -257,3 +280,13 @@ init_param3(long kmempages)
maxpipekva = 512 * 1024;
TUNABLE_INT_FETCH("kern.ipc.maxpipekva", &maxpipekva);
}
+
+/*
+ * Sysctl stringiying handler for kern.vm_guest.
+ */
+static int
+sysctl_kern_vm_guest(SYSCTL_HANDLER_ARGS)
+{
+ return (SYSCTL_OUT(req, vm_guest_sysctl_names[vm_guest],
+ strlen(vm_guest_sysctl_names[vm_guest])));
+}
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index e7e8120..ba54524 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -44,7 +44,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_hwpmc_hooks.h"
#include "opt_ktrace.h"
#include "opt_mac.h"
#ifdef __i386__
@@ -179,13 +178,6 @@ ast(struct trapframe *framep)
td->td_profil_ticks = 0;
td->td_pflags &= ~TDP_OWEUPC;
}
-#if defined(HWPMC_HOOKS)
- if (td->td_pflags & TDP_CALLCHAIN) {
- PMC_CALL_HOOK_UNLOCKED(td, PMC_FN_USER_CALLCHAIN,
- (void *) framep);
- td->td_pflags &= ~TDP_CALLCHAIN;
- }
-#endif
if (flags & TDF_ALRMPEND) {
PROC_LOCK(p);
psignal(p, SIGVTALRM);
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index e0045ce..d6735fa 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cons.h>
#include <sys/fcntl.h>
#include <sys/file.h>
+#include <sys/filedesc.h>
#include <sys/filio.h>
#ifdef COMPAT_43TTY
#include <sys/ioctl_compat.h>
@@ -870,10 +871,10 @@ tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
tty_init_termios(tp);
- cv_init(&tp->t_inwait, "tty input");
- cv_init(&tp->t_outwait, "tty output");
- cv_init(&tp->t_bgwait, "tty background");
- cv_init(&tp->t_dcdwait, "tty dcd");
+ cv_init(&tp->t_inwait, "ttyinp");
+ cv_init(&tp->t_outwait, "ttyout");
+ cv_init(&tp->t_bgwait, "ttybgw");
+ cv_init(&tp->t_dcdwait, "ttydcd");
ttyinq_init(&tp->t_inq);
ttyoutq_init(&tp->t_outq);
@@ -883,7 +884,7 @@ tty_alloc(struct ttydevsw *tsw, void *sc, struct mtx *mutex)
tp->t_mtx = mutex;
} else {
tp->t_mtx = &tp->t_mtxobj;
- mtx_init(&tp->t_mtxobj, "tty lock", NULL, MTX_DEF);
+ mtx_init(&tp->t_mtxobj, "ttylck", NULL, MTX_DEF);
}
knlist_init(&tp->t_inpoll.si_note, tp->t_mtx, NULL, NULL, NULL);
@@ -1673,18 +1674,24 @@ ttyhook_defrint(struct tty *tp, char c, int flags)
}
int
-ttyhook_register(struct tty **rtp, struct thread *td, int fd,
+ttyhook_register(struct tty **rtp, struct proc *p, int fd,
struct ttyhook *th, void *softc)
{
struct tty *tp;
struct file *fp;
struct cdev *dev;
struct cdevsw *cdp;
+ struct filedesc *fdp;
int error;
/* Validate the file descriptor. */
- if (fget(td, fd, &fp) != 0)
- return (EINVAL);
+ if ((fdp = p->p_fd) == NULL)
+ return (EBADF);
+ FILEDESC_SLOCK(fdp);
+ if ((fp = fget_locked(fdp, fd)) == NULL || fp->f_ops == &badfileops) {
+ FILEDESC_SUNLOCK(fdp);
+ return (EBADF);
+ }
/* Make sure the vnode is bound to a character device. */
error = EINVAL;
@@ -1723,7 +1730,7 @@ ttyhook_register(struct tty **rtp, struct thread *td, int fd,
done3: tty_unlock(tp);
done2: dev_relthread(dev);
-done1: fdrop(fp, td);
+done1: FILEDESC_SUNLOCK(fdp);
return (error);
}
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index 9e81a6d..c767daa 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -273,6 +273,16 @@ ptsdev_ioctl(struct file *fp, u_long cmd, void *data,
case FIONBIO:
/* This device supports non-blocking operation. */
return (0);
+ case FIONREAD:
+ tty_lock(tp);
+ if (psc->pts_flags & PTS_FINISHED) {
+ /* Force read() to be called. */
+ *(int *)data = 1;
+ } else {
+ *(int *)data = ttydisc_getc_poll(tp);
+ }
+ tty_unlock(tp);
+ return (0);
case FIODGNAME: {
struct fiodgname_arg *fgn;
const char *p;
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 06682d5..c4840ce 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -814,6 +814,10 @@ success:
if ((cnp->cn_flags & (ISLASTCN | LOCKSHARED | LOCKLEAF)) ==
(ISLASTCN | LOCKLEAF) && VOP_ISLOCKED(dp) != LK_EXCLUSIVE) {
vn_lock(dp, LK_UPGRADE | LK_RETRY);
+ if (dp->v_iflag & VI_DOOMED) {
+ error = ENOENT;
+ goto bad2;
+ }
}
if (vfslocked && dvfslocked)
VFS_UNLOCK_GIANT(dvfslocked); /* Only need one */
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 12368c9..2b870f0 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -507,29 +507,20 @@ vfs_mount_destroy(struct mount *mp)
{
MNT_ILOCK(mp);
+ mp->mnt_kern_flag |= MNTK_REFEXPIRE;
+ if (mp->mnt_kern_flag & MNTK_MWAIT) {
+ mp->mnt_kern_flag &= ~MNTK_MWAIT;
+ wakeup(mp);
+ }
while (mp->mnt_ref)
msleep(mp, MNT_MTX(mp), PVFS, "mntref", 0);
- if (mp->mnt_writeopcount > 0) {
- printf("Waiting for mount point write ops\n");
- while (mp->mnt_writeopcount > 0) {
- mp->mnt_kern_flag |= MNTK_SUSPEND;
- msleep(&mp->mnt_writeopcount,
- MNT_MTX(mp),
- PZERO, "mntdestroy2", 0);
- }
- printf("mount point write ops completed\n");
- }
- if (mp->mnt_secondary_writes > 0) {
- printf("Waiting for mount point secondary write ops\n");
- while (mp->mnt_secondary_writes > 0) {
- mp->mnt_kern_flag |= MNTK_SUSPEND;
- msleep(&mp->mnt_secondary_writes,
- MNT_MTX(mp),
- PZERO, "mntdestroy3", 0);
- }
- printf("mount point secondary write ops completed\n");
- }
- MNT_IUNLOCK(mp);
+ KASSERT(mp->mnt_ref == 0,
+ ("%s: invalid refcount in the drain path @ %s:%d", __func__,
+ __FILE__, __LINE__));
+ if (mp->mnt_writeopcount != 0)
+ panic("vfs_mount_destroy: nonzero writeopcount");
+ if (mp->mnt_secondary_writes != 0)
+ panic("vfs_mount_destroy: nonzero secondary_writes");
mp->mnt_vfc->vfc_refcount--;
if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) {
struct vnode *vp;
@@ -538,18 +529,10 @@ vfs_mount_destroy(struct mount *mp)
vprint("", vp);
panic("unmount: dangling vnode");
}
- MNT_ILOCK(mp);
- if (mp->mnt_kern_flag & MNTK_MWAIT)
- wakeup(mp);
- if (mp->mnt_writeopcount != 0)
- panic("vfs_mount_destroy: nonzero writeopcount");
- if (mp->mnt_secondary_writes != 0)
- panic("vfs_mount_destroy: nonzero secondary_writes");
if (mp->mnt_nvnodelistsize != 0)
panic("vfs_mount_destroy: nonzero nvnodelistsize");
- mp->mnt_writeopcount = -1000;
- mp->mnt_nvnodelistsize = -1000;
- mp->mnt_secondary_writes = -1000;
+ if (mp->mnt_lockref != 0)
+ panic("vfs_mount_destroy: nonzero lock refcount");
MNT_IUNLOCK(mp);
#ifdef MAC
mac_mount_destroy(mp);
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 16373b1..eb02693 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -345,7 +345,7 @@ vfs_busy(struct mount *mp, int flags)
MNT_ILOCK(mp);
MNT_REF(mp);
if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
- if (flags & MBF_NOWAIT) {
+ if (flags & MBF_NOWAIT || mp->mnt_kern_flag & MNTK_REFEXPIRE) {
MNT_REL(mp);
MNT_IUNLOCK(mp);
return (ENOENT);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index e4f4f8b..198009d 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -200,19 +200,21 @@ quotactl(td, uap)
AUDIT_ARG(uid, uap->uid);
if (jailed(td->td_ucred) && !prison_quotas)
return (EPERM);
- NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1,
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
mp = nd.ni_vp->v_mount;
- if ((error = vfs_busy(mp, 0))) {
- vrele(nd.ni_vp);
+ vfs_ref(mp);
+ vput(nd.ni_vp);
+ error = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (error) {
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
- vrele(nd.ni_vp);
error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td);
vfs_unbusy(mp);
VFS_UNLOCK_GIANT(vfslocked);
@@ -306,6 +308,12 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
vfs_ref(mp);
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_vp);
+ error = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (error) {
+ VFS_UNLOCK_GIANT(vfslocked);
+ return (error);
+ }
#ifdef MAC
error = mac_mount_check_stat(td->td_ucred, mp);
if (error)
@@ -329,7 +337,7 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
}
*buf = *sp;
out:
- vfs_rel(mp);
+ vfs_unbusy(mp);
VFS_UNLOCK_GIANT(vfslocked);
if (mtx_owned(&Giant))
printf("statfs(%d): %s: %d\n", vfslocked, path, error);
@@ -391,6 +399,10 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
error = EBADF;
goto out;
}
+ error = vfs_busy(mp, 0);
+ vfs_rel(mp);
+ if (error)
+ goto out;
#ifdef MAC
error = mac_mount_check_stat(td->td_ucred, mp);
if (error)
@@ -415,7 +427,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
*buf = *sp;
out:
if (mp)
- vfs_rel(mp);
+ vfs_unbusy(mp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
diff --git a/sys/mips/conf/DEFAULTS b/sys/mips/conf/DEFAULTS
index 18a9a26..dc480ce 100644
--- a/sys/mips/conf/DEFAULTS
+++ b/sys/mips/conf/DEFAULTS
@@ -9,5 +9,5 @@ device mem
device uart_ns8250
-options GEOM_BSD
-options GEOM_MBR
+options GEOM_PART_BSD
+options GEOM_PART_MBR
diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h
index fc1035e..6e48ec1 100644
--- a/sys/mips/include/elf.h
+++ b/sys/mips/include/elf.h
@@ -40,9 +40,11 @@
/* Information taken from MIPS ABI supplemental */
-#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
-
+#ifndef __ELF_WORD_SIZE
#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */
+#endif
+#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
+#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
#include <sys/elf_generic.h>
#define ELF_ARCH EM_MIPS
@@ -114,6 +116,16 @@ typedef union {
Elf32_Word gt_bytes; /* This many bytes would be used */
} gt_entry; /* Subsequent entries in section */
} Elf32_gptab;
+typedef union {
+ struct {
+ Elf64_Word gt_current_g_value; /* -G val used in compilation */
+ Elf64_Word gt_unused; /* Not used */
+ } gt_header; /* First entry in section */
+ struct {
+ Elf64_Word gt_g_value; /* If this val were used for -G */
+ Elf64_Word gt_bytes; /* This many bytes would be used */
+ } gt_entry; /* Subsequent entries in section */
+} Elf64_gptab;
/*
* Entry found in sections of type SHT_MIPS_REGINFO.
@@ -123,6 +135,11 @@ typedef struct {
Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
Elf32_Sword ri_gp_value; /* $gp register value */
} Elf32_RegInfo;
+typedef struct {
+ Elf64_Word ri_gprmask; /* General registers used */
+ Elf64_Word ri_cprmask[4]; /* Coprocessor registers used */
+ Elf64_Sword ri_gp_value; /* $gp register value */
+} Elf64_RegInfo;
/*
@@ -147,10 +164,38 @@ typedef struct {
#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */
#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */
-#define R_TYPE(name) __CONCAT(R_MIPS_,name)
+/*
+ * These are from the 64-bit Irix ELF ABI
+ */
+#define R_MIPS_SHIFT5 16
+#define R_MIPS_SHIFT6 17
+#define R_MIPS_64 18
+#define R_MIPS_GOT_DISP 19
+#define R_MIPS_GOT_PAGE 20
+#define R_MIPS_GOT_OFST 21
+#define R_MIPS_GOT_HI16 22
+#define R_MIPS_GOT_LO16 23
+#define R_MIPS_SUB 24
+#define R_MIPS_INSERT_A 25
+#define R_MIPS_INSERT_B 26
+#define R_MIPS_DELETE 27
+#define R_MIPS_HIGHER 28
+#define R_MIPS_HIGHEST 29
+#define R_MIPS_SCN_DISP 32
+#define R_MIPS_REL16 33
+#define R_MIPS_ADD_IMMEDIATE 34
+#define R_MIPS_PJUMP 35
+#define R_MIPS_ERLGOT 36
+
+#define R_MIPS_max 37
+#define R_TYPE(name) __CONCAT(R_MIPS_,name)
/* Define "machine" characteristics */
+#if __ELF_WORD_SIZE == 32
#define ELF_TARG_CLASS ELFCLASS32
+#else
+#define ELF_TARG_CLASS ELFCLASS64
+#endif
#ifdef __MIPSEB__
#define ELF_TARG_DATA ELFDATA2MSB
#else
@@ -159,23 +204,30 @@ typedef struct {
#define ELF_TARG_MACH EM_MIPS
#define ELF_TARG_VER 1
-
/*
* Auxiliary vector entries for passing information to the interpreter.
*
* The i386 supplement to the SVR4 ABI specification names this "auxv_t",
* but POSIX lays claim to all symbols ending with "_t".
*/
-
typedef struct { /* Auxiliary vector entry on initial stack */
int a_type; /* Entry type. */
union {
- long a_val; /* Integer value. */
+ int a_val; /* Integer value. */
void *a_ptr; /* Address. */
void (*a_fcn)(void); /* Function pointer (not used). */
} a_un;
} Elf32_Auxinfo;
+typedef struct { /* Auxiliary vector entry on initial stack */
+ long a_type; /* Entry type. */
+ union {
+ long a_val; /* Integer value. */
+ void *a_ptr; /* Address. */
+ void (*a_fcn)(void); /* Function pointer (not used). */
+ } a_un;
+} Elf64_Auxinfo;
+
__ElfType(Auxinfo);
/* Values for a_type. */
@@ -189,18 +241,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define AT_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c
index dc08bc2..163d0ee 100644
--- a/sys/mips/mips/elf_machdep.c
+++ b/sys/mips/mips/elf_machdep.c
@@ -93,22 +93,6 @@ SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t) elf32_insert_brand_entry,
&freebsd_brand_info);
-static Elf32_Brandinfo freebsd_brand_oinfo = {
- .brand = ELFOSABI_FREEBSD,
- .machine = EM_MIPS,
- .compat_3_brand = "FreeBSD",
- .emul_path = NULL,
- .interp_path = "/usr/libexec/ld-elf.so.1",
- .sysvec = &elf32_freebsd_sysvec,
- .interp_newpath = NULL,
- .flags = 0
-};
-
-SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
- (sysinit_cfunc_t) elf32_insert_brand_entry,
- &freebsd_brand_oinfo);
-
-
void
elf32_dump_thread(struct thread *td __unused, void *dst __unused,
size_t *off __unused)
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index eee15c1..97d7cf2 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -30,9 +30,6 @@ SUBDIR= ${_3dfx} \
${_asr} \
ata \
ath \
- ath_rate_amrr \
- ath_rate_onoe \
- ath_rate_sample \
aue \
${_auxio} \
axe \
diff --git a/sys/modules/ath/Makefile b/sys/modules/ath/Makefile
index 4f478f6..068d337 100644
--- a/sys/modules/ath/Makefile
+++ b/sys/modules/ath/Makefile
@@ -29,44 +29,80 @@
# $FreeBSD$
#
-.PATH: ${.CURDIR}/../../dev/ath \
- ${.CURDIR}/../../dev/ath/ath_hal \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5210 \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5211 \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5212 \
- ${.CURDIR}/../../dev/ath/ath_hal/ar5416
+ATH_RATE?= sample # tx rate control algorithm
-AR5210_SRCS=ah_eeprom_v1.c \
+.PATH: ${.CURDIR}/../../dev/ath
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal
+
+KMOD= if_ath
+SRCS= if_ath.c if_ath_pci.c
+# NB: v3 eeprom support used by both AR5211 and AR5212; just include it
+SRCS+= ah_osdep.c ah.c ah_regdomain.c ah_eeprom_v3.c
+SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h
+
+#
+# AR5210 support; these are first generation 11a-only devices.
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5210
+SRCS+= ah_eeprom_v1.c \
ar5210_attach.c ar5210_beacon.c ar5210_interrupts.c \
ar5210_keycache.c ar5210_misc.c ar5210_phy.c ar5210_power.c \
ar5210_recv.c ar5210_reset.c ar5210_xmit.c
-AR5211_SRCS=ar5211_attach.c ar5211_beacon.c ar5211_interrupts.c \
+
+#
+# AR5211 support; these are second generation 11b/g/a devices
+# (but 11g was OFDM only and is not supported).
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5211
+SRCS+= ar5211_attach.c ar5211_beacon.c ar5211_interrupts.c \
ar5211_keycache.c ar5211_misc.c ar5211_phy.c ar5211_power.c \
ar5211_recv.c ar5211_reset.c ar5211_xmit.c
-AR5212_SRCS=ar5212_ani.c ar5212_attach.c ar5212_beacon.c ar5212_eeprom.c \
+
+#
+# AR5212 support; this covers all other pci/cardbus legacy parts.
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5212
+SRCS+= ar5212_ani.c ar5212_attach.c ar5212_beacon.c ar5212_eeprom.c \
ar5212_gpio.c ar5212_interrupts.c ar5212_keycache.c ar5212_misc.c \
ar5212_phy.c ar5212_power.c ar5212_recv.c ar5212_reset.c \
- ar5212_rfgain.c ar5212_xmit.c \
- ar2413.c ar2425.c ar5111.c ar5112.c ar5413.c
-AR5416_SRCS=ah_eeprom_v14.c \
+ ar5212_rfgain.c ar5212_xmit.c
+# RF backends
+SRCS+= ar5111.c
+SRCS+= ar5112.c
+SRCS+= ar2413.c
+SRCS+= ar2425.c
+SRCS+= ar5413.c
+
+#
+# AR5416, AR9160 support; these are 11n parts but only really
+# supported (right now) operating in legacy mode. Note enabling
+# this support requires defining AH_SUPPORT_AR5416 in opt_ah.h
+# so the 11n tx/rx descriptor format is handled.
+#
+# NB: 9160 depends on 5416 but 5416 does not require 9160
+#
+.PATH: ${.CURDIR}/../../dev/ath/ath_hal/ar5416
+SRCS+= ah_eeprom_v14.c \
ar5416_ani.c ar5416_attach.c ar5416_beacon.c ar5416_cal.c \
ar5416_cal_iq.c ar5416_cal_adcgain.c ar5416_cal_adcdc.c \
ar5416_eeprom.c ar5416_gpio.c ar5416_interrupts.c ar5416_keycache.c \
ar5416_misc.c ar5416_phy.c ar5416_power.c ar5416_recv.c \
- ar5416_reset.c ar5416_xmit.c \
- ar2133.c
-AR9160_SRCS=ar9160_attach.c
+ ar5416_reset.c ar5416_xmit.c
+SRCS+= ar9160_attach.c
+# RF backend for 5416 and 9160
+SRCS+= ar2133.c
-KMOD= if_ath
-SRCS= if_ath.c if_ath_pci.c
-# NB: v3 eeprom support used by both AR5211 and AR5212; just include it
-SRCS+= ah_osdep.c ah.c ah_regdomain.c ah_eeprom_v3.c
-SRCS+= ${AR5210_SRCS}
-SRCS+= ${AR5211_SRCS}
-SRCS+= ${AR5212_SRCS}
-SRCS+= ${AR5416_SRCS}
-SRCS+= ${AR9160_SRCS}
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h
+# NB: rate control is bound to the driver by symbol names so only pick one
+.if ${ATH_RATE} == "sample"
+.PATH: ${.CURDIR}/../../dev/ath/ath_rate/sample
+SRCS+= sample.c opt_wlan.h
+.elif ${ATH_RATE} == "onoe"
+.PATH: ${.CURDIR}/../../dev/ath/ath_rate/onoe
+SRCS+= onoe.c
+.elif ${ATH_RATE} == "amrr"
+.PATH: ${.CURDIR}/../../dev/ath/ath_rate/amrr
+SRCS+= amrr.c
+.endif
CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
diff --git a/sys/modules/ath_rate_amrr/Makefile b/sys/modules/ath_rate_amrr/Makefile
deleted file mode 100644
index cbeea9c..0000000
--- a/sys/modules/ath_rate_amrr/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2004-2008 Sam Leffler, Errno Consulting
-# 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,
-# without modification.
-# 2. Redistributions in binary form must reproduce at minimum a disclaimer
-# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
-# redistribution must be conditioned upon including a substantially
-# similar Disclaimer requirement for further binary redistribution.
-#
-# NO WARRANTY
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
-# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
-#
-# $FreeBSD$
-#
-
-.PATH: ${.CURDIR}/../../dev/ath/ath_rate/amrr
-
-KMOD= ath_rate
-SRCS= amrr.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ah.h opt_wlan.h
-
-CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/ath_rate_onoe/Makefile b/sys/modules/ath_rate_onoe/Makefile
deleted file mode 100644
index fe725e4..0000000
--- a/sys/modules/ath_rate_onoe/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2004-2008 Sam Leffler, Errno Consulting
-# 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,
-# without modification.
-# 2. Redistributions in binary form must reproduce at minimum a disclaimer
-# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
-# redistribution must be conditioned upon including a substantially
-# similar Disclaimer requirement for further binary redistribution.
-#
-# NO WARRANTY
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
-# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
-#
-# $FreeBSD$
-#
-
-.PATH: ${.CURDIR}/../../dev/ath/ath_rate/onoe
-
-KMOD= ath_rate
-SRCS= onoe.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ah.h opt_wlan.h
-
-CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/ath_rate_sample/Makefile b/sys/modules/ath_rate_sample/Makefile
deleted file mode 100644
index c179d10..0000000
--- a/sys/modules/ath_rate_sample/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2004-2008 Sam Leffler, Errno Consulting
-# 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,
-# without modification.
-# 2. Redistributions in binary form must reproduce at minimum a disclaimer
-# similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
-# redistribution must be conditioned upon including a substantially
-# similar Disclaimer requirement for further binary redistribution.
-#
-# NO WARRANTY
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
-# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-# THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
-#
-# $FreeBSD$
-#
-
-.PATH: ${.CURDIR}/../../dev/ath/ath_rate/sample
-
-KMOD= ath_rate
-SRCS= sample.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ah.h opt_wlan.h
-
-CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/cxgb/Makefile b/sys/modules/cxgb/Makefile
index 7d56988..71cbb7a 100644
--- a/sys/modules/cxgb/Makefile
+++ b/sys/modules/cxgb/Makefile
@@ -25,7 +25,7 @@ _toe_header = ${_sysdir}/netinet/toedev.h
.if exists(${_toe_header})
_toecore = toecore
-_tom = tom
+#_tom = tom
.endif
.if ${MACHINE_ARCH} == "i386" && exists(${_toe_header})
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c
index 27cf480..bd44e23 100644
--- a/sys/net/ieee8023ad_lacp.c
+++ b/sys/net/ieee8023ad_lacp.c
@@ -901,6 +901,7 @@ lacp_aggregator_bandwidth(struct lacp_aggregator *la)
static void
lacp_select_active_aggregator(struct lacp_softc *lsc)
{
+ struct lagg_softc *sc = lsc->lsc_softc;
struct lacp_aggregator *la;
struct lacp_aggregator *best_la = NULL;
uint64_t best_speed = 0;
@@ -956,6 +957,7 @@ lacp_select_active_aggregator(struct lacp_softc *lsc)
#endif /* defined(LACP_DEBUG) */
if (lsc->lsc_active_aggregator != best_la) {
+ sc->sc_ifp->if_baudrate = best_speed;
lsc->lsc_active_aggregator = best_la;
lacp_update_portmap(lsc);
if (best_la) {
diff --git a/sys/net/if.c b/sys/net/if.c
index 5142a5c..070202c 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -60,6 +60,7 @@
#include <sys/jail.h>
#include <sys/vimage.h>
#include <machine/stdarg.h>
+#include <vm/uma.h>
#include <net/if.h>
#include <net/if_arp.h>
@@ -157,7 +158,7 @@ static struct knlist ifklist;
#endif
int ifqmaxlen = IFQ_MAXLEN;
-struct mtx ifnet_lock;
+struct rwlock ifnet_lock;
static if_com_alloc_t *if_com_alloc[256];
static if_com_free_t *if_com_free[256];
@@ -190,14 +191,23 @@ MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals");
MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
+static struct ifnet *
+ifnet_byindex_locked(u_short idx)
+{
+ INIT_VNET_NET(curvnet);
+ struct ifnet *ifp;
+
+ ifp = V_ifindex_table[idx].ife_ifnet;
+ return (ifp);
+}
+
struct ifnet *
ifnet_byindex(u_short idx)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
IFNET_RLOCK();
- ifp = V_ifindex_table[idx].ife_ifnet;
+ ifp = ifnet_byindex_locked(idx);
IFNET_RUNLOCK();
return (ifp);
}
@@ -218,7 +228,7 @@ ifaddr_byindex(u_short idx)
struct ifaddr *ifa;
IFNET_RLOCK();
- ifa = ifnet_byindex(idx)->if_addr;
+ ifa = ifnet_byindex_locked(idx)->if_addr;
IFNET_RUNLOCK();
return (ifa);
}
@@ -498,7 +508,7 @@ if_free_type(struct ifnet *ifp, u_char type)
ifnet_setbyindex(ifp->if_index, NULL);
/* XXX: should be locked with if_findindex() */
- while (V_if_index > 0 && ifnet_byindex(V_if_index) == NULL)
+ while (V_if_index > 0 && ifnet_byindex_locked(V_if_index) == NULL)
V_if_index--;
IFNET_WUNLOCK();
@@ -1110,7 +1120,7 @@ if_rtdel(struct radix_node *rn, void *arg)
return (0);
err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
- rt_mask(rt), rt->rt_flags,
+ rt_mask(rt), rt->rt_flags|RTF_RNH_LOCKED,
(struct rtentry **) NULL, rt->rt_fibnum);
if (err) {
log(LOG_WARNING, "if_rtdel: error %d\n", err);
@@ -1366,6 +1376,9 @@ done:
return (ifa);
}
+#include <net/route.h>
+#include <net/if_llatbl.h>
+
/*
* Default action when installing a route with a Link Level gateway.
* Lookup an appropriate real ifa to point to.
diff --git a/sys/net/if_arcsubr.c b/sys/net/if_arcsubr.c
index 0f5fef3..0089d13 100644
--- a/sys/net/if_arcsubr.c
+++ b/sys/net/if_arcsubr.c
@@ -64,6 +64,7 @@
#include <net/if_arc.h>
#include <net/if_arp.h>
#include <net/bpf.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -108,6 +109,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
u_int8_t atype, adst;
int loop_copy = 0;
int isphds;
+ struct llentry *lle;
if (!((ifp->if_flags & IFF_UP) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)))
@@ -127,7 +129,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
else if (ifp->if_flags & IFF_NOARP)
adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF;
else {
- error = arpresolve(ifp, rt0, m, dst, &adst);
+ error = arpresolve(ifp, rt0, m, dst, &adst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -165,7 +167,7 @@ arc_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)&adst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)&adst, &lle);
if (error)
return (error);
atype = ARCTYPE_INET6;
diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c
index 9d1a7fa..7e36187 100644
--- a/sys/net/if_atmsubr.c
+++ b/sys/net/if_atmsubr.c
@@ -153,22 +153,11 @@ atm_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
case AF_INET:
case AF_INET6:
{
- struct rtentry *rt = NULL;
- /*
- * check route
- */
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
-
if (dst->sa_family == AF_INET6)
etype = ETHERTYPE_IPV6;
else
etype = ETHERTYPE_IP;
- if (!atmresolve(rt, m, dst, &atmdst)) {
+ if (!atmresolve(rt0, m, dst, &atmdst)) {
m = NULL;
/* XXX: atmresolve already free'd it */
senderr(EHOSTUNREACH);
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 4524fdd..73a08dd 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -64,6 +64,7 @@
#include <net/ethernet.h>
#include <net/if_bridgevar.h>
#include <net/if_vlan_var.h>
+#include <net/if_llatbl.h>
#include <net/pf_mtag.h>
#include <net/vnet.h>
@@ -87,6 +88,7 @@
#include <netipx/ipx.h>
#include <netipx/ipx_if.h>
#endif
+
int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m);
int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp,
struct sockaddr *dst, short *tp, int *hlen);
@@ -151,6 +153,7 @@ static int ether_ipfw;
#endif
#endif
+
/*
* Ethernet output routine.
* Encapsulate a packet of type family for the local net.
@@ -164,6 +167,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
short type;
int error, hdrcmplt = 0;
u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN];
+ struct llentry *lle = NULL;
struct ether_header *eh;
struct pf_mtag *t;
int loop_copy = 1;
@@ -186,7 +190,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -221,7 +225,7 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
#endif
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
if (error)
return error;
type = htons(ETHERTYPE_IPV6);
@@ -289,6 +293,17 @@ ether_output(struct ifnet *ifp, struct mbuf *m,
senderr(EAFNOSUPPORT);
}
+ if (lle != NULL && (lle->la_flags & LLE_IFADDR)) {
+ int csum_flags = 0;
+ if (m->m_pkthdr.csum_flags & CSUM_IP)
+ csum_flags |= (CSUM_IP_CHECKED|CSUM_IP_VALID);
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)
+ csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR);
+ m->m_pkthdr.csum_flags |= csum_flags;
+ m->m_pkthdr.csum_data = 0xffff;
+ return (if_simloop(ifp, m, dst->sa_family, 0));
+ }
+
/*
* Add local net header. If no space in first mbuf,
* allocate another.
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index e37d7ae..438a6e8 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -55,6 +55,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/ethernet.h>
#include <net/netisr.h>
@@ -120,6 +121,7 @@ fddi_output(ifp, m, dst, rt0)
int loop_copy = 0, error = 0, hdrcmplt = 0;
u_char esrc[FDDI_ADDR_LEN], edst[FDDI_ADDR_LEN];
struct fddi_header *fh;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -137,7 +139,7 @@ fddi_output(ifp, m, dst, rt0)
switch (dst->sa_family) {
#ifdef INET
case AF_INET: {
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
type = htons(ETHERTYPE_IP);
@@ -173,7 +175,7 @@ fddi_output(ifp, m, dst, rt0)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
if (error)
return (error); /* Something bad happened */
type = htons(ETHERTYPE_IPV6);
diff --git a/sys/net/if_fwsubr.c b/sys/net/if_fwsubr.c
index 77e7b70..9d7b95b 100644
--- a/sys/net/if_fwsubr.c
+++ b/sys/net/if_fwsubr.c
@@ -51,6 +51,7 @@
#include <net/if_types.h>
#include <net/bpf.h>
#include <net/firewire.h>
+#include <net/if_llatbl.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -80,7 +81,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
{
struct fw_com *fc = IFP2FWC(ifp);
int error, type;
- struct rtentry *rt = NULL;
struct m_tag *mtag;
union fw_encap *enc;
struct fw_hwaddr *destfw;
@@ -89,6 +89,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct mbuf *mtail;
int unicast, dgl, foff;
static int next_dgl;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -102,13 +103,6 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
goto bad;
}
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
-
/*
* For unicast, we make a tag to store the lladdr of the
* destination. This might not be the first time we have seen
@@ -144,7 +138,7 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
* doesn't fit into the arp model.
*/
if (unicast) {
- error = arpresolve(ifp, rt, m, dst, (u_char *) destfw);
+ error = arpresolve(ifp, rt0, m, dst, (u_char *) destfw, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
}
@@ -173,8 +167,8 @@ firewire_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
#ifdef INET6
case AF_INET6:
if (unicast) {
- error = nd6_storelladdr(fc->fc_ifp, rt, m, dst,
- (u_char *) destfw);
+ error = nd6_storelladdr(fc->fc_ifp, m, dst,
+ (u_char *) destfw, &lle);
if (error)
return (error);
}
diff --git a/sys/net/if_iso88025subr.c b/sys/net/if_iso88025subr.c
index 00e323a..ff82e10 100644
--- a/sys/net/if_iso88025subr.c
+++ b/sys/net/if_iso88025subr.c
@@ -59,6 +59,7 @@
#include <net/if_dl.h>
#include <net/if_llc.h>
#include <net/if_types.h>
+#include <net/if_llatbl.h>
#include <net/ethernet.h>
#include <net/netisr.h>
@@ -243,7 +244,7 @@ iso88025_output(ifp, m, dst, rt0)
struct iso88025_header *th;
struct iso88025_header gen_th;
struct sockaddr_dl *sdl = NULL;
- struct rtentry *rt = NULL;
+ struct llentry *lle;
#ifdef MAC
error = mac_ifnet_check_transmit(ifp, m);
@@ -260,14 +261,8 @@ iso88025_output(ifp, m, dst, rt0)
/* Calculate routing info length based on arp table entry */
/* XXX any better way to do this ? */
- if (rt0 != NULL) {
- error = rt_check(&rt, &rt0, dst);
- if (error)
- goto bad;
- RT_UNLOCK(rt);
- }
- if (rt && (sdl = (struct sockaddr_dl *)rt->rt_gateway))
+ if (rt0 && (sdl = (struct sockaddr_dl *)rt0->rt_gateway))
if (SDL_ISO88025(sdl)->trld_rcf != 0)
rif_len = TR_RCF_RIFLEN(SDL_ISO88025(sdl)->trld_rcf);
@@ -289,7 +284,7 @@ iso88025_output(ifp, m, dst, rt0)
switch (dst->sa_family) {
#ifdef INET
case AF_INET:
- error = arpresolve(ifp, rt0, m, dst, edst);
+ error = arpresolve(ifp, rt0, m, dst, edst, &lle);
if (error)
return (error == EWOULDBLOCK ? 0 : error);
snap_type = ETHERTYPE_IP;
@@ -324,7 +319,7 @@ iso88025_output(ifp, m, dst, rt0)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- error = nd6_storelladdr(ifp, rt0, m, dst, (u_char *)edst);
+ error = nd6_storelladdr(ifp, m, dst, (u_char *)edst, &lle);
if (error)
return (error);
snap_type = ETHERTYPE_IPV6;
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index be6e0b8..0ab96b3 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -310,6 +310,7 @@ lagg_capabilities(struct lagg_softc *sc)
{
struct lagg_port *lp;
int cap = ~0, ena = ~0;
+ u_long hwa = ~0UL;
LAGG_WLOCK_ASSERT(sc);
@@ -317,14 +318,18 @@ lagg_capabilities(struct lagg_softc *sc)
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
cap &= lp->lp_ifp->if_capabilities;
ena &= lp->lp_ifp->if_capenable;
+ hwa &= lp->lp_ifp->if_hwassist;
}
cap = (cap == ~0 ? 0 : cap);
ena = (ena == ~0 ? 0 : ena);
+ hwa = (hwa == ~0 ? 0 : hwa);
if (sc->sc_ifp->if_capabilities != cap ||
- sc->sc_ifp->if_capenable != ena) {
+ sc->sc_ifp->if_capenable != ena ||
+ sc->sc_ifp->if_hwassist != hwa) {
sc->sc_ifp->if_capabilities = cap;
sc->sc_ifp->if_capenable = ena;
+ sc->sc_ifp->if_hwassist = hwa;
getmicrotime(&sc->sc_ifp->if_lastchange);
if (sc->sc_ifflags & IFF_DEBUG)
@@ -1206,6 +1211,7 @@ lagg_linkstate(struct lagg_softc *sc)
{
struct lagg_port *lp;
int new_link = LINK_STATE_DOWN;
+ uint64_t speed;
/* Our link is considered up if at least one of our ports is active */
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
@@ -1215,6 +1221,25 @@ lagg_linkstate(struct lagg_softc *sc)
}
}
if_link_state_change(sc->sc_ifp, new_link);
+
+ /* Update if_baudrate to reflect the max possible speed */
+ switch (sc->sc_proto) {
+ case LAGG_PROTO_FAILOVER:
+ sc->sc_ifp->if_baudrate = sc->sc_primary != NULL ?
+ sc->sc_primary->lp_ifp->if_baudrate : 0;
+ break;
+ case LAGG_PROTO_ROUNDROBIN:
+ case LAGG_PROTO_LOADBALANCE:
+ case LAGG_PROTO_ETHERCHANNEL:
+ speed = 0;
+ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
+ speed += lp->lp_ifp->if_baudrate;
+ sc->sc_ifp->if_baudrate = speed;
+ break;
+ case LAGG_PROTO_LACP:
+ /* LACP updates if_baudrate itself */
+ break;
+ }
}
static void
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
new file mode 100644
index 0000000..a3d1b05
--- /dev/null
+++ b/sys/net/if_llatbl.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
+ * Copyright (c) 2004-2008 Qing Li. All rights reserved.
+ * Copyright (c) 2008 Kip Macy. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/vimage.h>
+
+#include <vm/uma.h>
+
+#include <netinet/in.h>
+#include <net/if_llatbl.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_var.h>
+#include <net/route.h>
+#include <netinet/if_ether.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
+
+static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables);
+
+extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
+ u_char *);
+
+/*
+ * Dump arp state for a specific address family.
+ */
+int
+lltable_sysctl_dumparp(int af, struct sysctl_req *wr)
+{
+ struct lltable *llt;
+ int error = 0;
+
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af == af) {
+ error = llt->llt_dump(llt, wr);
+ if (error != 0)
+ goto done;
+ }
+ }
+done:
+ IFNET_RUNLOCK();
+ return (error);
+}
+
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+void
+llentry_free(struct llentry *lle)
+{
+
+ LLE_WLOCK_ASSERT(lle);
+ LIST_REMOVE(lle, lle_next);
+
+ if (lle->la_hold != NULL)
+ m_freem(lle->la_hold);
+
+ LLE_FREE_LOCKED(lle);
+}
+
+/*
+ * Free all entries from given table and free itself.
+ * Since lltables collects from all of the intefaces,
+ * the caller of this function must acquire IFNET_WLOCK().
+ */
+void
+lltable_free(struct lltable *llt)
+{
+ struct llentry *lle, *next;
+ int i;
+
+ KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
+
+ IFNET_WLOCK();
+ SLIST_REMOVE(&lltables, llt, lltable, llt_link);
+ IFNET_WUNLOCK();
+
+ for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH_SAFE(lle, &llt->lle_head[i], lle_next, next) {
+
+ callout_drain(&lle->la_timer);
+ LLE_WLOCK(lle);
+ llentry_free(lle);
+ }
+ }
+
+ free(llt, M_LLTABLE);
+}
+
+void
+lltable_drain(int af)
+{
+ struct lltable *llt;
+ struct llentry *lle;
+ register int i;
+
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af != af)
+ continue;
+
+ for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
+ if (lle->la_hold) {
+ m_freem(lle->la_hold);
+ lle->la_hold = NULL;
+ }
+ }
+ }
+ }
+ IFNET_RUNLOCK();
+}
+
+/*
+ * Create a new lltable.
+ */
+struct lltable *
+lltable_init(struct ifnet *ifp, int af)
+{
+ struct lltable *llt;
+ register int i;
+
+ llt = malloc(sizeof(struct lltable), M_LLTABLE, M_WAITOK);
+ if (llt == NULL)
+ return (NULL);
+
+ llt->llt_af = af;
+ llt->llt_ifp = ifp;
+ for (i = 0; i < LLTBL_HASHTBL_SIZE; i++)
+ LIST_INIT(&llt->lle_head[i]);
+
+ IFNET_WLOCK();
+ SLIST_INSERT_HEAD(&lltables, llt, llt_link);
+ IFNET_WUNLOCK();
+
+ return (llt);
+}
+
+/*
+ * Called in route_output when adding/deleting a route to an interface.
+ */
+int
+lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
+{
+ struct sockaddr_dl *dl =
+ (struct sockaddr_dl *)info->rti_info[RTAX_GATEWAY];
+ struct sockaddr *dst = (struct sockaddr *)info->rti_info[RTAX_DST];
+ struct ifnet *ifp;
+ struct lltable *llt;
+ struct llentry *lle;
+ u_int laflags = 0, flags = 0;
+ int error = 0;
+
+ if (dl == NULL || dl->sdl_family != AF_LINK) {
+ log(LOG_INFO, "%s: invalid dl\n", __func__);
+ return EINVAL;
+ }
+ ifp = ifnet_byindex(dl->sdl_index);
+ if (ifp == NULL) {
+ log(LOG_INFO, "%s: invalid ifp (sdl_index %d)\n",
+ __func__, dl->sdl_index);
+ return EINVAL;
+ }
+
+ switch (rtm->rtm_type) {
+ case RTM_ADD:
+ if (rtm->rtm_flags & RTF_ANNOUNCE) {
+ flags |= LLE_PUB;
+#ifdef INET
+ if (dst->sa_family == AF_INET &&
+ ((struct sockaddr_inarp *)dst)->sin_other != 0) {
+ struct rtentry *rt = rtalloc1(dst, 0, 0);
+ if (rt == NULL || !(rt->rt_flags & RTF_HOST)) {
+ log(LOG_INFO, "%s: RTM_ADD publish "
+ "(proxy only) is invalid\n",
+ __func__);
+ RTFREE(rt);
+ return EINVAL;
+ }
+ RTFREE(rt);
+
+ flags |= LLE_PROXY;
+ }
+#endif
+ }
+ flags |= LLE_CREATE;
+ break;
+
+ case RTM_DELETE:
+ flags |= LLE_DELETE;
+ break;
+
+ case RTM_CHANGE:
+ break;
+
+ default:
+ return EINVAL; /* XXX not implemented yet */
+ }
+
+ /* XXX linked list may be too expensive */
+ IFNET_RLOCK();
+ SLIST_FOREACH(llt, &lltables, llt_link) {
+ if (llt->llt_af == dst->sa_family &&
+ llt->llt_ifp == ifp)
+ break;
+ }
+ IFNET_RUNLOCK();
+ KASSERT(llt != NULL, ("Yep, ugly hacks are bad\n"));
+
+ if (flags && LLE_CREATE)
+ flags |= LLE_EXCLUSIVE;
+
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(llt, flags, dst);
+ IF_AFDATA_UNLOCK(ifp);
+ if (LLE_IS_VALID(lle)) {
+ if (flags & LLE_CREATE) {
+ /*
+ * If we delay the delete, then a subsequent
+ * "arp add" should look up this entry, reset the
+ * LLE_DELETED flag, and reset the expiration timer
+ */
+ bcopy(LLADDR(dl), &lle->ll_addr, ifp->if_addrlen);
+ lle->la_flags |= LLE_VALID;
+ lle->la_flags &= ~LLE_DELETED;
+#ifdef INET6
+ /*
+ * ND6
+ */
+ if (dst->sa_family == AF_INET6)
+ lle->ln_state = ND6_LLINFO_REACHABLE;
+#endif
+ /*
+ * NB: arp and ndp always set (RTF_STATIC | RTF_HOST)
+ */
+
+ if (rtm->rtm_rmx.rmx_expire == 0) {
+ lle->la_flags |= LLE_STATIC;
+ lle->la_expire = 0;
+ } else
+ lle->la_expire = rtm->rtm_rmx.rmx_expire;
+ laflags = lle->la_flags;
+ LLE_WUNLOCK(lle);
+#ifdef INET
+ /* gratuitous ARP */
+ if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) {
+ arprequest(ifp,
+ &((struct sockaddr_in *)dst)->sin_addr,
+ &((struct sockaddr_in *)dst)->sin_addr,
+ ((laflags & LLE_PROXY) ?
+ (u_char *)IF_LLADDR(ifp) :
+ (u_char *)LLADDR(dl)));
+ }
+#endif
+ } else {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(lle);
+ else
+ LLE_RUNLOCK(lle);
+ }
+ } else if ((lle == NULL) && (flags & LLE_DELETE))
+ error = EINVAL;
+
+
+ return (error);
+}
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
new file mode 100644
index 0000000..50e617d
--- /dev/null
+++ b/sys/net/if_llatbl.h
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved.
+ * Copyright (c) 2004-2008 Qing Li. All rights reserved.
+ * Copyright (c) 2008 Kip Macy. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _NET_IF_LLATBL_H_
+#define _NET_IF_LLATBL_H_
+
+#include <sys/_rwlock.h>
+#include <netinet/in.h>
+
+struct ifnet;
+struct sysctl_req;
+struct rt_msghdr;
+struct rt_addrinfo;
+
+struct llentry;
+LIST_HEAD(llentries, llentry);
+
+/*
+ * Code referencing llentry must at least hold
+ * a shared lock
+ */
+struct llentry {
+ LIST_ENTRY(llentry) lle_next;
+ struct rwlock lle_lock;
+ struct lltable *lle_tbl;
+ struct llentries *lle_head;
+ struct mbuf *la_hold;
+ time_t la_expire;
+ uint16_t la_flags;
+ uint16_t la_asked;
+ uint16_t la_preempt;
+ uint16_t ln_byhint;
+ int16_t ln_state; /* IPv6 has ND6_LLINFO_NOSTATE == -2 */
+ uint16_t ln_router;
+ time_t ln_ntick;
+ int lle_refcnt;
+
+ union {
+ uint64_t mac_aligned;
+ uint16_t mac16[3];
+ } ll_addr;
+
+ /* XXX af-private? */
+ union {
+ struct callout ln_timer_ch;
+ struct callout la_timer;
+ } lle_timer;
+ /* NB: struct sockaddr must immediately follow */
+};
+
+#define LLE_WLOCK(lle) rw_wlock(&(lle)->lle_lock)
+#define LLE_RLOCK(lle) rw_rlock(&(lle)->lle_lock)
+#define LLE_WUNLOCK(lle) rw_wunlock(&(lle)->lle_lock)
+#define LLE_RUNLOCK(lle) rw_runlock(&(lle)->lle_lock)
+#define LLE_DOWNGRADE(lle) rw_downgrade(&(lle)->lle_lock)
+#define LLE_TRY_UPGRADE(lle) rw_try_upgrade(&(lle)->lle_lock)
+#define LLE_LOCK_INIT(lle) rw_init_flags(&(lle)->lle_lock, "lle", RW_DUPOK)
+#define LLE_LOCK_DESTROY(lle) rw_destroy(&(lle)->lle_lock)
+#define LLE_WLOCK_ASSERT(lle) rw_assert(&(lle)->lle_lock, RA_WLOCKED)
+
+#define LLE_IS_VALID(lle) (((lle) != NULL) && ((lle) != (void *)-1))
+
+#define LLE_ADDREF(lle) do { \
+ LLE_WLOCK_ASSERT(lle); \
+ KASSERT((lle)->lle_refcnt >= 0, \
+ ("negative refcnt %d", (lle)->lle_refcnt)); \
+ (lle)->lle_refcnt++; \
+} while (0)
+
+#define LLE_REMREF(lle) do { \
+ LLE_WLOCK_ASSERT(lle); \
+ KASSERT((lle)->lle_refcnt > 1, \
+ ("bogus refcnt %d", (lle)->lle_refcnt)); \
+ (lle)->lle_refcnt--; \
+} while (0)
+
+#define LLE_FREE_LOCKED(lle) do { \
+ if ((lle)->lle_refcnt <= 1) \
+ (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\
+ else { \
+ (lle)->lle_refcnt--; \
+ LLE_WUNLOCK(lle); \
+ } \
+ /* guard against invalid refs */ \
+ lle = 0; \
+} while (0)
+
+#define LLE_FREE(lle) do { \
+ LLE_WLOCK(lle); \
+ if ((lle)->lle_refcnt <= 1) \
+ (lle)->lle_tbl->llt_free((lle)->lle_tbl, (lle));\
+ else { \
+ (lle)->lle_refcnt--; \
+ LLE_WUNLOCK(lle); \
+ } \
+ /* guard against invalid refs */ \
+ lle = NULL; \
+} while (0)
+
+
+#define ln_timer_ch lle_timer.ln_timer_ch
+#define la_timer lle_timer.la_timer
+
+/* XXX bad name */
+#define L3_ADDR(lle) ((struct sockaddr *)(&lle[1]))
+#define L3_ADDR_LEN(lle) (((struct sockaddr *)(&lle[1]))->sa_len)
+
+#ifndef LLTBL_HASHTBL_SIZE
+#define LLTBL_HASHTBL_SIZE 32 /* default 32 ? */
+#endif
+
+#ifndef LLTBL_HASHMASK
+#define LLTBL_HASHMASK (LLTBL_HASHTBL_SIZE - 1)
+#endif
+
+struct lltable {
+ SLIST_ENTRY(lltable) llt_link;
+ struct llentries lle_head[LLTBL_HASHTBL_SIZE];
+ int llt_af;
+ struct ifnet *llt_ifp;
+
+ struct llentry * (*llt_new)(const struct sockaddr *, u_int);
+ void (*llt_free)(struct lltable *, struct llentry *);
+ struct llentry * (*llt_lookup)(struct lltable *, u_int flags,
+ const struct sockaddr *l3addr);
+ int (*llt_rtcheck)(struct ifnet *,
+ const struct sockaddr *);
+ int (*llt_dump)(struct lltable *,
+ struct sysctl_req *);
+};
+MALLOC_DECLARE(M_LLTABLE);
+
+/*
+ * flags to be passed to arplookup.
+ */
+#define LLE_DELETED 0x0001 /* entry must be deleted */
+#define LLE_STATIC 0x0002 /* entry is static */
+#define LLE_IFADDR 0x0004 /* entry is interface addr */
+#define LLE_VALID 0x0008 /* ll_addr is valid */
+#define LLE_PROXY 0x0010 /* proxy entry ??? */
+#define LLE_PUB 0x0020 /* publish entry ??? */
+#define LLE_DELETE 0x4000 /* delete on a lookup - match LLE_IFADDR */
+#define LLE_CREATE 0x8000 /* create on a lookup miss */
+#define LLE_EXCLUSIVE 0x2000 /* return lle xlocked */
+
+#define LLATBL_HASH(key, mask) \
+ (((((((key >> 8) ^ key) >> 8) ^ key) >> 8) ^ key) & mask)
+
+struct lltable *lltable_init(struct ifnet *, int);
+void lltable_free(struct lltable *);
+void lltable_drain(int);
+int lltable_sysctl_dumparp(int, struct sysctl_req *);
+
+void llentry_free(struct llentry *);
+
+/*
+ * Generic link layer address lookup function.
+ */
+static __inline struct llentry *
+lla_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
+{
+ return llt->llt_lookup(llt, flags, l3addr);
+}
+
+int lla_rt_output(struct rt_msghdr *, struct rt_addrinfo *);
+#endif /* _NET_IF_LLATBL_H_ */
diff --git a/sys/net/if_media.h b/sys/net/if_media.h
index 18726da..f4b3d81 100644
--- a/sys/net/if_media.h
+++ b/sys/net/if_media.h
@@ -145,6 +145,11 @@ uint64_t ifmedia_baudrate(int);
#define IFM_10G_SR 19 /* 10GBase-SR 850nm Multi-mode */
#define IFM_10G_CX4 20 /* 10GBase CX4 copper */
#define IFM_2500_SX 21 /* 2500BaseSX - multi-mode fiber */
+#define IFM_10G_TWINAX 22 /* 10GBase Twinax copper */
+#define IFM_10G_TWINAX_LONG 23 /* 10GBase Twinax Long copper */
+#define IFM_10G_LRM 24 /* 10GBase-LRM 850nm Multi-mode */
+#define IFM_UNKNOWN 25 /* New media types that have not been defined yet */
+
/* note 31 is the max! */
@@ -349,6 +354,10 @@ struct ifmedia_description {
{ IFM_10G_SR, "10Gbase-SR" }, \
{ IFM_10G_CX4, "10Gbase-CX4" }, \
{ IFM_2500_SX, "2500BaseSX" }, \
+ { IFM_10G_LRM, "10Gbase-LRM" }, \
+ { IFM_10G_TWINAX, "10Gbase-Twinax" }, \
+ { IFM_10G_TWINAX_LONG, "10Gbase-Twinax-Long" }, \
+ { IFM_UNKNOWN, "Unknown" }, \
{ 0, NULL }, \
}
@@ -603,6 +612,9 @@ struct ifmedia_baudrate {
{ IFM_ETHER | IFM_10G_SR, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_10G_CX4, IF_Gbps(10ULL) }, \
{ IFM_ETHER | IFM_2500_SX, IF_Mbps(2500ULL) }, \
+ { IFM_ETHER | IFM_10G_TWINAX, IF_Gbps(10ULL) }, \
+ { IFM_ETHER | IFM_10G_TWINAX_LONG, IF_Gbps(10ULL) }, \
+ { IFM_ETHER | IFM_10G_LRM, IF_Gbps(10ULL) }, \
\
{ IFM_TOKEN | IFM_TOK_STP4, IF_Mbps(4) }, \
{ IFM_TOKEN | IFM_TOK_STP16, IF_Mbps(16) }, \
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 0724488..250bed9 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -77,9 +77,11 @@ struct ifvlantrunk;
#ifdef _KERNEL
#include <sys/mbuf.h>
#include <sys/eventhandler.h>
+#include <sys/buf_ring.h>
#endif /* _KERNEL */
#include <sys/lock.h> /* XXX */
#include <sys/mutex.h> /* XXX */
+#include <sys/rwlock.h> /* XXX */
#include <sys/event.h> /* XXX */
#include <sys/_task.h>
@@ -169,25 +171,24 @@ struct ifnet {
void *if_bridge; /* bridge glue */
- struct lltable *lltables; /* list of L3-L2 resolution tables */
-
struct label *if_label; /* interface MAC label */
/* these are only used by IPv6 */
struct ifprefixhead if_prefixhead; /* list of prefixes per if */
void *if_afdata[AF_MAX];
int if_afdata_initialized;
- struct mtx if_afdata_mtx;
+ struct rwlock if_afdata_lock;
struct task if_starttask; /* task for IFF_NEEDSGIANT */
struct task if_linktask; /* task for link change events */
struct mtx if_addr_mtx; /* mutex to protect address lists */
+
LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */
TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */
/* protected by if_addr_mtx */
void *if_pf_kif;
void *if_lagg; /* lagg glue */
- void *if_pspare[8]; /* multiq/TOE 3; vimage 3; general use 4 */
- void (*if_qflush) /* flush any queues */
+ void *if_pspare[8]; /* TOE 3; vimage 3; general use 4 */
+ void (*if_qflush) /* flush any queues */
(struct ifnet *);
int (*if_transmit) /* initiate output routine */
(struct ifnet *, struct mbuf *);
@@ -359,11 +360,19 @@ typedef void (*group_change_event_handler_t)(void *, const char *);
EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
#define IF_AFDATA_LOCK_INIT(ifp) \
- mtx_init(&(ifp)->if_afdata_mtx, "if_afdata", NULL, MTX_DEF)
-#define IF_AFDATA_LOCK(ifp) mtx_lock(&(ifp)->if_afdata_mtx)
-#define IF_AFDATA_TRYLOCK(ifp) mtx_trylock(&(ifp)->if_afdata_mtx)
-#define IF_AFDATA_UNLOCK(ifp) mtx_unlock(&(ifp)->if_afdata_mtx)
-#define IF_AFDATA_DESTROY(ifp) mtx_destroy(&(ifp)->if_afdata_mtx)
+ rw_init(&(ifp)->if_afdata_lock, "if_afdata")
+
+#define IF_AFDATA_WLOCK(ifp) rw_wlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_RLOCK(ifp) rw_rlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_WUNLOCK(ifp) rw_wunlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_RUNLOCK(ifp) rw_runlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_LOCK(ifp) IF_AFDATA_WLOCK(ifp)
+#define IF_AFDATA_UNLOCK(ifp) IF_AFDATA_WUNLOCK(ifp)
+#define IF_AFDATA_TRYLOCK(ifp) rw_try_wlock(&(ifp)->if_afdata_lock)
+#define IF_AFDATA_DESTROY(ifp) rw_destroy(&(ifp)->if_afdata_lock)
+
+#define IF_AFDATA_LOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_LOCKED)
+#define IF_AFDATA_UNLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_UNLOCKED)
#define IFF_LOCKGIANT(ifp) do { \
if ((ifp)->if_flags & IFF_NEEDSGIANT) \
@@ -540,6 +549,45 @@ do { \
IFQ_PURGE(ifq); \
} while (0)
+#ifdef _KERNEL
+static __inline void
+drbr_stats_update(struct ifnet *ifp, int len, int mflags)
+{
+
+ ifp->if_obytes += len;
+ if (mflags & M_MCAST)
+ ifp->if_omcasts++;
+}
+
+static __inline int
+drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
+{
+ int error = 0;
+ int len = m->m_pkthdr.len;
+ int mflags = m->m_flags;
+
+ if ((error = buf_ring_enqueue(br, m)) == ENOBUFS) {
+ br->br_drops++;
+ _IF_DROP(&ifp->if_snd);
+ m_freem(m);
+ } else
+ drbr_stats_update(ifp, len, mflags);
+
+ return (error);
+}
+
+static __inline void
+drbr_free(struct buf_ring *br, struct malloc_type *type)
+{
+ struct mbuf *m;
+
+ while ((m = buf_ring_dequeue_sc(br)) != NULL)
+ m_freem(m);
+
+ buf_ring_free(br, type);
+}
+#endif
+
/*
* 72 was chosen below because it is the size of a TCP/IP
* header (40) + the minimum mss (32).
@@ -635,14 +683,14 @@ struct ifmultiaddr {
IFA_UNLOCK(ifa); \
} while (0)
-extern struct mtx ifnet_lock;
+extern struct rwlock ifnet_lock;
#define IFNET_LOCK_INIT() \
- mtx_init(&ifnet_lock, "ifnet", NULL, MTX_DEF | MTX_RECURSE)
-#define IFNET_WLOCK() mtx_lock(&ifnet_lock)
-#define IFNET_WUNLOCK() mtx_unlock(&ifnet_lock)
-#define IFNET_WLOCK_ASSERT() mtx_assert(&ifnet_lock, MA_OWNED)
-#define IFNET_RLOCK() IFNET_WLOCK()
-#define IFNET_RUNLOCK() IFNET_WUNLOCK()
+ rw_init_flags(&ifnet_lock, "ifnet", RW_RECURSE)
+#define IFNET_WLOCK() rw_wlock(&ifnet_lock)
+#define IFNET_WUNLOCK() rw_wunlock(&ifnet_lock)
+#define IFNET_WLOCK_ASSERT() rw_assert(&ifnet_lock, RA_LOCKED)
+#define IFNET_RLOCK() rw_rlock(&ifnet_lock)
+#define IFNET_RUNLOCK() rw_runlock(&ifnet_lock)
struct ifindex_entry {
struct ifnet *ife_ifnet;
@@ -659,10 +707,12 @@ struct ifnet *ifnet_byindex(u_short idx);
struct ifaddr *ifaddr_byindex(u_short idx);
struct cdev *ifdev_byindex(u_short idx);
+#ifdef VIMAGE_GLOBALS
extern struct ifnethead ifnet;
-extern int ifqmaxlen;
extern struct ifnet *loif; /* first loopback interface */
extern int if_index;
+#endif
+extern int ifqmaxlen;
int if_addgroup(struct ifnet *, const char *);
int if_delgroup(struct ifnet *, const char *);
diff --git a/sys/net/pfil.c b/sys/net/pfil.c
index bb82bb3..3018eb9 100644
--- a/sys/net/pfil.c
+++ b/sys/net/pfil.c
@@ -97,33 +97,26 @@ pfil_head_register(struct pfil_head *ph)
struct pfil_head *lph;
PFIL_LIST_LOCK();
- LIST_FOREACH(lph, &pfil_head_list, ph_list)
+ LIST_FOREACH(lph, &pfil_head_list, ph_list) {
if (ph->ph_type == lph->ph_type &&
ph->ph_un.phu_val == lph->ph_un.phu_val) {
PFIL_LIST_UNLOCK();
return EEXIST;
}
- PFIL_LIST_UNLOCK();
-
+ }
PFIL_LOCK_INIT(ph);
- PFIL_WLOCK(ph);
ph->ph_nhooks = 0;
-
TAILQ_INIT(&ph->ph_in);
TAILQ_INIT(&ph->ph_out);
-
- PFIL_LIST_LOCK();
LIST_INSERT_HEAD(&pfil_head_list, ph, ph_list);
PFIL_LIST_UNLOCK();
-
- PFIL_WUNLOCK(ph);
-
return (0);
}
/*
- * pfil_head_unregister() removes a pfil_head from the packet filter
- * hook mechanism.
+ * pfil_head_unregister() removes a pfil_head from the packet filter hook
+ * mechanism. The producer of the hook promises that all outstanding
+ * invocations of the hook have completed before it unregisters the hook.
*/
int
pfil_head_unregister(struct pfil_head *ph)
@@ -131,21 +124,13 @@ pfil_head_unregister(struct pfil_head *ph)
struct packet_filter_hook *pfh, *pfnext;
PFIL_LIST_LOCK();
- /*
- * LIST_REMOVE is safe for unlocked pfil_heads in ph_list.
- * No need to WLOCK all of them.
- */
LIST_REMOVE(ph, ph_list);
PFIL_LIST_UNLOCK();
-
- PFIL_WLOCK(ph);
-
TAILQ_FOREACH_SAFE(pfh, &ph->ph_in, pfil_link, pfnext)
free(pfh, M_IFADDR);
TAILQ_FOREACH_SAFE(pfh, &ph->ph_out, pfil_link, pfnext)
free(pfh, M_IFADDR);
PFIL_LOCK_DESTROY(ph);
-
return (0);
}
@@ -175,14 +160,13 @@ pfil_head_get(int type, u_long val)
* PFIL_WAITOK OK to call malloc with M_WAITOK.
*/
int
-pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *),
- void *arg, int flags, struct pfil_head *ph)
+pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int,
+ struct inpcb *), void *arg, int flags, struct pfil_head *ph)
{
struct packet_filter_hook *pfh1 = NULL;
struct packet_filter_hook *pfh2 = NULL;
int err;
- /* Get memory */
if (flags & PFIL_IN) {
pfh1 = (struct packet_filter_hook *)malloc(sizeof(*pfh1),
M_IFADDR, (flags & PFIL_WAITOK) ? M_WAITOK : M_NOWAIT);
@@ -199,17 +183,13 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct in
goto error;
}
}
-
- /* Lock */
PFIL_WLOCK(ph);
-
- /* Add */
if (flags & PFIL_IN) {
pfh1->pfil_func = func;
pfh1->pfil_arg = arg;
err = pfil_list_add(&ph->ph_in, pfh1, flags & ~PFIL_OUT);
if (err)
- goto done;
+ goto locked_error;
ph->ph_nhooks++;
}
if (flags & PFIL_OUT) {
@@ -219,15 +199,13 @@ pfil_add_hook(int (*func)(void *, struct mbuf **, struct ifnet *, int, struct in
if (err) {
if (flags & PFIL_IN)
pfil_list_remove(&ph->ph_in, func, arg);
- goto done;
+ goto locked_error;
}
ph->ph_nhooks++;
}
-
PFIL_WUNLOCK(ph);
-
return 0;
-done:
+locked_error:
PFIL_WUNLOCK(ph);
error:
if (pfh1 != NULL)
diff --git a/sys/net/pfil.h b/sys/net/pfil.h
index 22d3d16..5db9e55 100644
--- a/sys/net/pfil.h
+++ b/sys/net/pfil.h
@@ -49,7 +49,8 @@ struct inpcb;
*/
struct packet_filter_hook {
TAILQ_ENTRY(packet_filter_hook) pfil_link;
- int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int, struct inpcb *);
+ int (*pfil_func)(void *, struct mbuf **, struct ifnet *, int,
+ struct inpcb *);
void *pfil_arg;
int pfil_flags;
};
diff --git a/sys/net/radix.c b/sys/net/radix.c
index e70d17d..39b198e 100644
--- a/sys/net/radix.c
+++ b/sys/net/radix.c
@@ -1087,6 +1087,7 @@ rn_walktree(h, f, w)
* while applying the function f to it, so we need to calculate
* the successor node in advance.
*/
+
/* First time through node, go left */
while (rn->rn_bit >= 0)
rn = rn->rn_left;
diff --git a/sys/net/radix_mpath.c b/sys/net/radix_mpath.c
index 68233fe..8d94d01 100644
--- a/sys/net/radix_mpath.c
+++ b/sys/net/radix_mpath.c
@@ -266,8 +266,8 @@ rtalloc_mpath_fib(struct route *ro, u_int32_t hash, u_int fibnum)
* be done for sendto(3) case?
*/
if (ro->ro_rt && ro->ro_rt->rt_ifp && (ro->ro_rt->rt_flags & RTF_UP))
- return; /* XXX */
- ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, RTF_CLONING, fibnum);
+ return;
+ ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, 0, fibnum);
/* if the route does not exist or it is not multipath, don't care */
if (ro->ro_rt == NULL)
diff --git a/sys/net/route.c b/sys/net/route.c
index be71e13..1f3e096 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -41,6 +41,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/syslog.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
@@ -53,6 +54,7 @@
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/route.h>
#ifdef RADIX_MPATH
@@ -269,8 +271,7 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
struct radix_node *rn;
struct rtentry *newrt;
struct rt_addrinfo info;
- u_long nflags;
- int needresolve = 0, err = 0, msgtype = RTM_MISS;
+ int err = 0, msgtype = RTM_MISS;
int needlock;
KASSERT((fibnum < rt_numfibs), ("rtalloc1_fib: bad fibnum"));
@@ -283,10 +284,9 @@ rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
*/
if (rnh == NULL) {
V_rtstat.rts_unreach++;
- goto miss2;
+ goto miss;
}
needlock = !(ignflags & RTF_RNH_LOCKED);
-retry:
if (needlock)
RADIX_NODE_HEAD_RLOCK(rnh);
#ifdef INVARIANTS
@@ -295,103 +295,33 @@ retry:
#endif
rn = rnh->rnh_matchaddr(dst, rnh);
if (rn && ((rn->rn_flags & RNF_ROOT) == 0)) {
-
newrt = rt = RNTORT(rn);
- nflags = rt->rt_flags & ~ignflags;
- if (report && (nflags & RTF_CLONING)) {
- if (needlock && !RADIX_NODE_HEAD_LOCK_TRY_UPGRADE(rnh)) {
- RADIX_NODE_HEAD_RUNLOCK(rnh);
- RADIX_NODE_HEAD_LOCK(rnh);
- /*
- * lookup again to make sure it wasn't changed
- */
- rn = rnh->rnh_matchaddr(dst, rnh);
- if (!(rn && ((rn->rn_flags & RNF_ROOT) == 0))) {
- RADIX_NODE_HEAD_UNLOCK(rnh);
- needresolve = 0;
- log(LOG_INFO, "retrying route lookup ...\n");
- goto retry;
- }
- }
- needresolve = 1;
- } else {
- RT_LOCK(newrt);
- RT_ADDREF(newrt);
- if (needlock)
- RADIX_NODE_HEAD_RUNLOCK(rnh);
- goto done;
- }
- }
- /*
- * if needresolve is set then we have the exclusive lock
- * and we need to keep it held for the benefit of rtrequest_fib
- */
- if (!needresolve && needlock)
+ RT_LOCK(newrt);
+ RT_ADDREF(newrt);
+ if (needlock)
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+ goto done;
+
+ } else if (needlock)
RADIX_NODE_HEAD_RUNLOCK(rnh);
- if (needresolve) {
- RADIX_NODE_HEAD_WLOCK_ASSERT(rnh);
+ /*
+ * Either we hit the root or couldn't find any match,
+ * Which basically means
+ * "caint get there frm here"
+ */
+ V_rtstat.rts_unreach++;
+miss:
+ if (report) {
/*
- * We are apparently adding (report = 0 in delete).
- * If it requires that it be cloned, do so.
- * (This implies it wasn't a HOST route.)
+ * If required, report the failure to the supervising
+ * Authorities.
+ * For a delete, this is not an error. (report == 0)
*/
- err = rtrequest_fib(RTM_RESOLVE, dst, NULL,
- NULL, RTF_RNH_LOCKED, &newrt, fibnum);
- if (err) {
- /*
- * If the cloning didn't succeed, maybe
- * what we have will do. Return that.
- */
- newrt = rt; /* existing route */
- RT_LOCK(newrt);
- RT_ADDREF(newrt);
- goto miss;
- }
- KASSERT(newrt, ("no route and no error"));
- RT_LOCK(newrt);
- if (newrt->rt_flags & RTF_XRESOLVE) {
- /*
- * If the new route specifies it be
- * externally resolved, then go do that.
- */
- msgtype = RTM_RESOLVE;
- goto miss;
- }
- /* Inform listeners of the new route. */
bzero(&info, sizeof(info));
- info.rti_info[RTAX_DST] = rt_key(newrt);
- info.rti_info[RTAX_NETMASK] = rt_mask(newrt);
- info.rti_info[RTAX_GATEWAY] = newrt->rt_gateway;
- if (newrt->rt_ifp != NULL) {
- info.rti_info[RTAX_IFP] =
- newrt->rt_ifp->if_addr->ifa_addr;
- info.rti_info[RTAX_IFA] = newrt->rt_ifa->ifa_addr;
- }
- rt_missmsg(RTM_ADD, &info, newrt->rt_flags, 0);
- if (needlock)
- RADIX_NODE_HEAD_UNLOCK(rnh);
- } else {
- /*
- * Either we hit the root or couldn't find any match,
- * Which basically means
- * "caint get there frm here"
- */
- V_rtstat.rts_unreach++;
- miss:
- if (needlock && needresolve)
- RADIX_NODE_HEAD_UNLOCK(rnh);
- miss2: if (report) {
- /*
- * If required, report the failure to the supervising
- * Authorities.
- * For a delete, this is not an error. (report == 0)
- */
- bzero(&info, sizeof(info));
- info.rti_info[RTAX_DST] = dst;
- rt_missmsg(msgtype, &info, 0, err);
- }
- }
+ info.rti_info[RTAX_DST] = dst;
+ rt_missmsg(msgtype, &info, 0, err);
+ }
done:
if (newrt)
RT_LOCK_ASSERT(newrt);
@@ -420,7 +350,7 @@ rtfree(struct rtentry *rt)
*/
RT_REMREF(rt);
if (rt->rt_refcnt > 0) {
- printf("%s: %p has %lu refs\n", __func__, rt, rt->rt_refcnt);
+ log(LOG_DEBUG, "%s: %p has %d refs\t", __func__, rt, rt->rt_refcnt);
goto done;
}
@@ -461,8 +391,6 @@ rtfree(struct rtentry *rt)
*/
if (rt->rt_ifa)
IFAFREE(rt->rt_ifa);
- rt->rt_parent = NULL; /* NB: no refcnt on parent */
-
/*
* The key is separatly alloc'd so free it (see rt_setgate()).
* This also frees the gateway, as they are always malloc'd
@@ -715,14 +643,6 @@ ifa_ifwithroute_fib(int flags, struct sockaddr *dst, struct sockaddr *gateway,
return (ifa);
}
-static walktree_f_t rt_fixdelete;
-static walktree_f_t rt_fixchange;
-
-struct rtfc_arg {
- struct rtentry *rt0;
- struct radix_node_head *rnh;
-};
-
/*
* Do appropriate manipulations of a routing tree given
* all the bits of info needed
@@ -828,8 +748,13 @@ rtexpunge(struct rtentry *rt)
struct ifaddr *ifa;
int error = 0;
+ /*
+ * Find the correct routing tree to use for this Address Family
+ */
rnh = V_rt_tables[rt->rt_fibnum][rt_key(rt)->sa_family];
RT_LOCK_ASSERT(rt);
+ if (rnh == NULL)
+ return (EAFNOSUPPORT);
RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
#if 0
/*
@@ -840,13 +765,6 @@ rtexpunge(struct rtentry *rt)
KASSERT(rt->rt_refcnt <= 1, ("bogus refcnt %ld", rt->rt_refcnt));
#endif
/*
- * Find the correct routing tree to use for this Address Family
- */
- rnh = V_rt_tables[rt->rt_fibnum][rt_key(rt)->sa_family];
- if (rnh == NULL)
- return (EAFNOSUPPORT);
-
- /*
* Remove the item from the tree; it should be there,
* but when callers invoke us blindly it may not (sigh).
*/
@@ -863,24 +781,6 @@ rtexpunge(struct rtentry *rt)
rt->rt_flags &= ~RTF_UP;
/*
- * Now search what's left of the subtree for any cloned
- * routes which might have been formed from this node.
- */
- if ((rt->rt_flags & RTF_CLONING) && rt_mask(rt))
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixdelete, rt);
-
- /*
- * Remove any external references we may have.
- * This might result in another rtentry being freed if
- * we held its last reference.
- */
- if (rt->rt_gwroute) {
- RTFREE(rt->rt_gwroute);
- rt->rt_gwroute = NULL;
- }
-
- /*
* Give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest) {
@@ -904,12 +804,6 @@ bad:
}
int
-rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt)
-{
- return (rtrequest1_fib(req, info, ret_nrt, 0));
-}
-
-int
rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
u_int fibnum)
{
@@ -941,10 +835,9 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
* If we are adding a host route then we don't want to put
* a netmask in the tree, nor do we want to clone it.
*/
- if (flags & RTF_HOST) {
+ if (flags & RTF_HOST)
netmask = NULL;
- flags &= ~RTF_CLONING;
- }
+
switch (req) {
case RTM_DELETE:
#ifdef RADIX_MPATH
@@ -1023,26 +916,6 @@ normal_rtdel:
rt->rt_flags &= ~RTF_UP;
/*
- * Now search what's left of the subtree for any cloned
- * routes which might have been formed from this node.
- */
- if ((rt->rt_flags & RTF_CLONING) &&
- rt_mask(rt)) {
- rnh->rnh_walktree_from(rnh, dst, rt_mask(rt),
- rt_fixdelete, rt);
- }
-
- /*
- * Remove any external references we may have.
- * This might result in another rtentry being freed if
- * we held its last reference.
- */
- if (rt->rt_gwroute) {
- RTFREE(rt->rt_gwroute);
- rt->rt_gwroute = NULL;
- }
-
- /*
* give the protocol a chance to keep things in sync.
*/
if ((ifa = rt->rt_ifa) && ifa->ifa_rtrequest)
@@ -1069,20 +942,12 @@ deldone:
} else
RTFREE_LOCKED(rt);
break;
-
case RTM_RESOLVE:
- if (ret_nrt == NULL || (rt = *ret_nrt) == NULL)
- senderr(EINVAL);
- ifa = rt->rt_ifa;
- /* XXX locking? */
- flags = rt->rt_flags &
- ~(RTF_CLONING | RTF_STATIC);
- flags |= RTF_WASCLONED;
- gateway = rt->rt_gateway;
- if ((netmask = rt->rt_genmask) == NULL)
- flags |= RTF_HOST;
- goto makeroute;
-
+ /*
+ * resolve was only used for route cloning
+ * here for compat
+ */
+ break;
case RTM_ADD:
if ((flags & RTF_GATEWAY) && !gateway)
senderr(EINVAL);
@@ -1093,8 +958,6 @@ deldone:
if (info->rti_ifa == NULL && (error = rt_getifa_fib(info, fibnum)))
senderr(error);
ifa = info->rti_ifa;
-
- makeroute:
rt = uma_zalloc(rtzone, M_NOWAIT | M_ZERO);
if (rt == NULL)
senderr(ENOBUFS);
@@ -1103,7 +966,7 @@ deldone:
rt->rt_fibnum = fibnum;
/*
* Add the gateway. Possibly re-malloc-ing the storage for it
- * also add the rt_gwroute if possible.
+ *
*/
RT_LOCK(rt);
if ((error = rt_setgate(rt, dst, gateway)) != 0) {
@@ -1138,8 +1001,6 @@ deldone:
/* do not permit exactly the same dst/mask/gw pair */
if (rn_mpath_capable(rnh) &&
rt_mpath_conflict(rnh, rt, netmask)) {
- if (rt->rt_gwroute)
- RTFREE(rt->rt_gwroute);
if (rt->rt_ifa) {
IFAFREE(rt->rt_ifa);
}
@@ -1152,34 +1013,11 @@ deldone:
/* XXX mtu manipulation will be done in rnh_addaddr -- itojun */
rn = rnh->rnh_addaddr(ndst, netmask, rnh, rt->rt_nodes);
- if (rn == NULL) {
- struct rtentry *rt2;
- /*
- * Uh-oh, we already have one of these in the tree.
- * We do a special hack: if the route that's already
- * there was generated by the cloning mechanism
- * then we just blow it away and retry the insertion
- * of the new one.
- */
- rt2 = rtalloc1_fib(dst, 0, RTF_RNH_LOCKED, fibnum);
- if (rt2 && rt2->rt_parent) {
- rtexpunge(rt2);
- RT_UNLOCK(rt2);
- rn = rnh->rnh_addaddr(ndst, netmask,
- rnh, rt->rt_nodes);
- } else if (rt2) {
- /* undo the extra ref we got */
- RTFREE_LOCKED(rt2);
- }
- }
-
/*
* If it still failed to go into the tree,
* then un-make it (this should be a function)
*/
if (rn == NULL) {
- if (rt->rt_gwroute)
- RTFREE(rt->rt_gwroute);
if (rt->rt_ifa)
IFAFREE(rt->rt_ifa);
Free(rt_key(rt));
@@ -1188,33 +1026,6 @@ deldone:
senderr(EEXIST);
}
- rt->rt_parent = NULL;
-
- /*
- * If we got here from RESOLVE, then we are cloning
- * so clone the rest, and note that we
- * are a clone (and increment the parent's references)
- */
- if (req == RTM_RESOLVE) {
- KASSERT(ret_nrt && *ret_nrt,
- ("no route to clone from"));
- rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */
- rt->rt_rmx.rmx_pksent = 0; /* reset packet counter */
- if ((*ret_nrt)->rt_flags & RTF_CLONING) {
- /*
- * NB: We do not bump the refcnt on the parent
- * entry under the assumption that it will
- * remain so long as we do. This is
- * important when deleting the parent route
- * as this operation requires traversing
- * the tree to delete all clones and futzing
- * with refcnts requires us to double-lock
- * parent through this back reference.
- */
- rt->rt_parent = *ret_nrt;
- }
- }
-
/*
* If this protocol has something to add to this then
* allow it to do that as well.
@@ -1223,20 +1034,6 @@ deldone:
ifa->ifa_rtrequest(req, rt, info);
/*
- * We repeat the same procedure from rt_setgate() here because
- * it doesn't fire when we call it there because the node
- * hasn't been added to the tree yet.
- */
- if (req == RTM_ADD &&
- !(rt->rt_flags & RTF_HOST) && rt_mask(rt) != NULL) {
- struct rtfc_arg arg;
- arg.rnh = rnh;
- arg.rt0 = rt;
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixchange, &arg);
- }
-
- /*
* actually return a resultant rtentry and
* give the caller a single reference.
*/
@@ -1263,159 +1060,21 @@ bad:
#undef ifpaddr
#undef flags
-/*
- * Called from rtrequest(RTM_DELETE, ...) to fix up the route's ``family''
- * (i.e., the routes related to it by the operation of cloning). This
- * routine is iterated over all potential former-child-routes by way of
- * rnh->rnh_walktree_from() above, and those that actually are children of
- * the late parent (passed in as VP here) are themselves deleted.
- */
-static int
-rt_fixdelete(struct radix_node *rn, void *vp)
-{
- struct rtentry *rt = RNTORT(rn);
- struct rtentry *rt0 = vp;
-
- if (rt->rt_parent == rt0 &&
- !(rt->rt_flags & (RTF_PINNED | RTF_CLONING))) {
- return rtrequest_fib(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt),
- rt->rt_flags|RTF_RNH_LOCKED, NULL, rt->rt_fibnum);
- }
- return 0;
-}
-
-/*
- * This routine is called from rt_setgate() to do the analogous thing for
- * adds and changes. There is the added complication in this case of a
- * middle insert; i.e., insertion of a new network route between an older
- * network route and (cloned) host routes. For this reason, a simple check
- * of rt->rt_parent is insufficient; each candidate route must be tested
- * against the (mask, value) of the new route (passed as before in vp)
- * to see if the new route matches it.
- *
- * XXX - it may be possible to do fixdelete() for changes and reserve this
- * routine just for adds. I'm not sure why I thought it was necessary to do
- * changes this way.
- */
-
-static int
-rt_fixchange(struct radix_node *rn, void *vp)
-{
- struct rtentry *rt = RNTORT(rn);
- struct rtfc_arg *ap = vp;
- struct rtentry *rt0 = ap->rt0;
- struct radix_node_head *rnh = ap->rnh;
- u_char *xk1, *xm1, *xk2, *xmp;
- int i, len, mlen;
-
- /* make sure we have a parent, and route is not pinned or cloning */
- if (!rt->rt_parent ||
- (rt->rt_flags & (RTF_PINNED | RTF_CLONING)))
- return 0;
-
- if (rt->rt_parent == rt0) /* parent match */
- goto delete_rt;
- /*
- * There probably is a function somewhere which does this...
- * if not, there should be.
- */
- len = imin(rt_key(rt0)->sa_len, rt_key(rt)->sa_len);
-
- xk1 = (u_char *)rt_key(rt0);
- xm1 = (u_char *)rt_mask(rt0);
- xk2 = (u_char *)rt_key(rt);
-
- /* avoid applying a less specific route */
- xmp = (u_char *)rt_mask(rt->rt_parent);
- mlen = rt_key(rt->rt_parent)->sa_len;
- if (mlen > rt_key(rt0)->sa_len) /* less specific route */
- return 0;
- for (i = rnh->rnh_treetop->rn_offset; i < mlen; i++)
- if ((xmp[i] & ~(xmp[i] ^ xm1[i])) != xmp[i])
- return 0; /* less specific route */
-
- for (i = rnh->rnh_treetop->rn_offset; i < len; i++)
- if ((xk2[i] & xm1[i]) != xk1[i])
- return 0; /* no match */
-
- /*
- * OK, this node is a clone, and matches the node currently being
- * changed/added under the node's mask. So, get rid of it.
- */
-delete_rt:
- return rtrequest_fib(RTM_DELETE, rt_key(rt), NULL,
- rt_mask(rt), rt->rt_flags, NULL, rt->rt_fibnum);
-}
-
int
rt_setgate(struct rtentry *rt, struct sockaddr *dst, struct sockaddr *gate)
{
INIT_VNET_NET(curvnet);
/* XXX dst may be overwritten, can we move this to below */
+ int dlen = SA_SIZE(dst), glen = SA_SIZE(gate);
+#ifdef INVARIANTS
struct radix_node_head *rnh =
V_rt_tables[rt->rt_fibnum][dst->sa_family];
- int dlen = SA_SIZE(dst), glen = SA_SIZE(gate);
+#endif
-again:
RT_LOCK_ASSERT(rt);
RADIX_NODE_HEAD_LOCK_ASSERT(rnh);
/*
- * A host route with the destination equal to the gateway
- * will interfere with keeping LLINFO in the routing
- * table, so disallow it.
- */
- if (((rt->rt_flags & (RTF_HOST|RTF_GATEWAY|RTF_LLINFO)) ==
- (RTF_HOST|RTF_GATEWAY)) &&
- dst->sa_len == gate->sa_len &&
- bcmp(dst, gate, dst->sa_len) == 0) {
- /*
- * The route might already exist if this is an RTM_CHANGE
- * or a routing redirect, so try to delete it.
- */
- if (rt_key(rt))
- rtexpunge(rt);
- return EADDRNOTAVAIL;
- }
-
- /*
- * Cloning loop avoidance in case of bad configuration.
- */
- if (rt->rt_flags & RTF_GATEWAY) {
- struct rtentry *gwrt;
-
- RT_UNLOCK(rt); /* XXX workaround LOR */
- gwrt = rtalloc1_fib(gate, 1, RTF_RNH_LOCKED, rt->rt_fibnum);
- if (gwrt == rt) {
- RT_REMREF(rt);
- return (EADDRINUSE); /* failure */
- }
- /*
- * Try to reacquire the lock on rt, and if it fails,
- * clean state and restart from scratch.
- */
- if (!RT_TRYLOCK(rt)) {
- RTFREE_LOCKED(gwrt);
- RT_LOCK(rt);
- goto again;
- }
- /*
- * If there is already a gwroute, then drop it. If we
- * are asked to replace route with itself, then do
- * not leak its refcounter.
- */
- if (rt->rt_gwroute != NULL) {
- if (rt->rt_gwroute == gwrt) {
- RT_REMREF(rt->rt_gwroute);
- } else
- RTFREE(rt->rt_gwroute);
- }
-
- if ((rt->rt_gwroute = gwrt) != NULL)
- RT_UNLOCK(rt->rt_gwroute);
- }
-
- /*
* Prepare to store the gateway in rt->rt_gateway.
* Both dst and gateway are stored one after the other in the same
* malloc'd chunk. If we have room, we can reuse the old buffer,
@@ -1446,21 +1105,7 @@ again:
*/
bcopy(gate, rt->rt_gateway, glen);
- /*
- * This isn't going to do anything useful for host routes, so
- * don't bother. Also make sure we have a reasonable mask
- * (we don't yet have one during adds).
- */
- if (!(rt->rt_flags & RTF_HOST) && rt_mask(rt) != 0) {
- struct rtfc_arg arg;
-
- arg.rnh = rnh;
- arg.rt0 = rt;
- rnh->rnh_walktree_from(rnh, rt_key(rt), rt_mask(rt),
- rt_fixchange, &arg);
- }
-
- return 0;
+ return (0);
}
static void
@@ -1500,6 +1145,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
char tempbuf[_SOCKADDR_TMPSIZE];
int didwork = 0;
int a_failure = 0;
+ static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
if (flags & RTF_HOST) {
dst = ifa->ifa_dstaddr;
@@ -1604,7 +1250,14 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
info.rti_ifa = ifa;
info.rti_flags = flags | ifa->ifa_flags;
info.rti_info[RTAX_DST] = dst;
- info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD)
+ info.rti_info[RTAX_GATEWAY] =
+ (struct sockaddr *)&null_sdl;
+ else
+ info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
info.rti_info[RTAX_NETMASK] = netmask;
error = rtrequest1_fib(cmd, &info, &rt, fibnum);
if (error == 0 && rt != NULL) {
@@ -1628,6 +1281,15 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
rt->rt_ifa = ifa;
}
#endif
+ /*
+ * doing this for compatibility reasons
+ */
+ if (cmd == RTM_ADD) {
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
+ rt->rt_ifp->if_type;
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
+ rt->rt_ifp->if_index;
+ }
rt_newaddrmsg(cmd, ifa, error, rt);
if (cmd == RTM_DELETE) {
/*
@@ -1696,147 +1358,5 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
return (rtinit1(ifa, cmd, flags, fib));
}
-/*
- * rt_check() is invoked on each layer 2 output path, prior to
- * encapsulating outbound packets.
- *
- * The function is mostly used to find a routing entry for the gateway,
- * which in some protocol families could also point to the link-level
- * address for the gateway itself (the side effect of revalidating the
- * route to the destination is rather pointless at this stage, we did it
- * already a moment before in the pr_output() routine to locate the ifp
- * and gateway to use).
- *
- * When we remove the layer-3 to layer-2 mapping tables from the
- * routing table, this function can be removed.
- *
- * === On input ===
- * *dst is the address of the NEXT HOP (which coincides with the
- * final destination if directly reachable);
- * *lrt0 points to the cached route to the final destination;
- * *lrt is not meaningful;
- * (*lrt0 has no ref held on it by us so REMREF is not needed.
- * Refs only account for major structural references and not usages,
- * which is actually a bit of a problem.)
- *
- * === Operation ===
- * If the route is marked down try to find a new route. If the route
- * to the gateway is gone, try to setup a new route. Otherwise,
- * if the route is marked for packets to be rejected, enforce that.
- * Note that rtalloc returns an rtentry with an extra REF that we may
- * need to lose.
- *
- * === On return ===
- * *dst is unchanged;
- * *lrt0 points to the (possibly new) route to the final destination
- * *lrt points to the route to the next hop [LOCKED]
- *
- * Their values are meaningful ONLY if no error is returned.
- *
- * To follow this you have to remember that:
- * RT_REMREF reduces the reference count by 1 but doesn't check it for 0 (!)
- * RTFREE_LOCKED includes an RT_REMREF (or an rtfree if refs == 1)
- * and an RT_UNLOCK
- * RTFREE does an RT_LOCK and an RTFREE_LOCKED
- * The gwroute pointer counts as a reference on the rtentry to which it points.
- * so when we add it we use the ref that rtalloc gives us and when we lose it
- * we need to remove the reference.
- * RT_TEMP_UNLOCK does an RT_ADDREF before freeing the lock, and
- * RT_RELOCK locks it (it can't have gone away due to the ref) and
- * drops the ref, possibly freeing it and zeroing the pointer if
- * the ref goes to 0 (unlocking in the process).
- */
-int
-rt_check(struct rtentry **lrt, struct rtentry **lrt0, struct sockaddr *dst)
-{
- struct rtentry *rt;
- struct rtentry *rt0;
- u_int fibnum;
-
- KASSERT(*lrt0 != NULL, ("rt_check"));
- rt0 = *lrt0;
- rt = NULL;
- fibnum = rt0->rt_fibnum;
-
- /* NB: the locking here is tortuous... */
- RT_LOCK(rt0);
-retry:
- if (rt0 && (rt0->rt_flags & RTF_UP) == 0) {
- /* Current rt0 is useless, try get a replacement. */
- RT_UNLOCK(rt0);
- rt0 = NULL;
- }
- if (rt0 == NULL) {
- rt0 = rtalloc1_fib(dst, 1, 0UL, fibnum);
- if (rt0 == NULL) {
- return (EHOSTUNREACH);
- }
- RT_REMREF(rt0); /* don't need the reference. */
- }
-
- if (rt0->rt_flags & RTF_GATEWAY) {
- if ((rt = rt0->rt_gwroute) != NULL) {
- RT_LOCK(rt); /* NB: gwroute */
- if ((rt->rt_flags & RTF_UP) == 0) {
- /* gw route is dud. ignore/lose it */
- RTFREE_LOCKED(rt); /* unref (&unlock) gwroute */
- rt = rt0->rt_gwroute = NULL;
- }
- }
-
- if (rt == NULL) { /* NOT AN ELSE CLAUSE */
- RT_TEMP_UNLOCK(rt0); /* MUST return to undo this */
- rt = rtalloc1_fib(rt0->rt_gateway, 1, 0UL, fibnum);
- if ((rt == rt0) || (rt == NULL)) {
- /* the best we can do is not good enough */
- if (rt) {
- RT_REMREF(rt); /* assumes ref > 0 */
- RT_UNLOCK(rt);
- }
- RTFREE(rt0); /* lock, unref, (unlock) */
- return (ENETUNREACH);
- }
- /*
- * Relock it and lose the added reference.
- * All sorts of things could have happenned while we
- * had no lock on it, so check for them.
- */
- RT_RELOCK(rt0);
- if (rt0 == NULL || ((rt0->rt_flags & RTF_UP) == 0))
- /* Ru-roh.. what we had is no longer any good */
- goto retry;
- /*
- * While we were away, someone replaced the gateway.
- * Since a reference count is involved we can't just
- * overwrite it.
- */
- if (rt0->rt_gwroute) {
- if (rt0->rt_gwroute != rt) {
- RTFREE_LOCKED(rt);
- goto retry;
- }
- } else {
- rt0->rt_gwroute = rt;
- }
- }
- RT_LOCK_ASSERT(rt);
- RT_UNLOCK(rt0);
- } else {
- /* think of rt as having the lock from now on.. */
- rt = rt0;
- }
- /* XXX why are we inspecting rmx_expire? */
- if ((rt->rt_flags & RTF_REJECT) &&
- (rt->rt_rmx.rmx_expire == 0 ||
- time_uptime < rt->rt_rmx.rmx_expire)) {
- RT_UNLOCK(rt);
- return (rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
- }
-
- *lrt = rt;
- *lrt0 = rt0;
- return (0);
-}
-
/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);
diff --git a/sys/net/route.h b/sys/net/route.h
index fb8df39..5062198 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -135,15 +135,11 @@ struct rtentry {
#define rt_key(r) (*((struct sockaddr **)(&(r)->rt_nodes->rn_key)))
#define rt_mask(r) (*((struct sockaddr **)(&(r)->rt_nodes->rn_mask)))
struct sockaddr *rt_gateway; /* value */
- u_long rt_flags; /* up/down?, host/net */
+ int rt_flags; /* up/down?, host/net */
+ int rt_refcnt; /* # held references */
struct ifnet *rt_ifp; /* the answer: interface to use */
struct ifaddr *rt_ifa; /* the answer: interface address to use */
struct rt_metrics_lite rt_rmx; /* metrics used by rx'ing protocols */
- long rt_refcnt; /* # held references */
- struct sockaddr *rt_genmask; /* for generation of cloned routes */
- caddr_t rt_llinfo; /* pointer to link level info cache */
- struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
- struct rtentry *rt_parent; /* cloning parent of this route */
u_int rt_fibnum; /* which FIB */
#ifdef _KERNEL
/* XXX ugly, user apps use this definition but don't have a mtx def */
@@ -175,9 +171,9 @@ struct ortentry {
#define RTF_MODIFIED 0x20 /* modified dynamically (by redirect) */
#define RTF_DONE 0x40 /* message confirmed */
/* 0x80 unused, was RTF_DELCLONE */
-#define RTF_CLONING 0x100 /* generate new routes on use */
+/* 0x100 unused, was RTF_CLONING */
#define RTF_XRESOLVE 0x200 /* external daemon resolves name */
-#define RTF_LLINFO 0x400 /* generated by link layer (e.g. ARP) */
+/* 0x400 unused, was RTF_LLINFO */
#define RTF_STATIC 0x800 /* manually added */
#define RTF_BLACKHOLE 0x1000 /* just discard pkts (during updates) */
#define RTF_PROTO2 0x4000 /* protocol specific routing flag */
@@ -188,7 +184,7 @@ struct ortentry {
#define RTF_PRCLONING 0x10000 /* unused, for compatibility */
#endif
-#define RTF_WASCLONED 0x20000 /* route generated through cloning */
+/* 0x20000 unused, was RTF_WASCLONED */
#define RTF_PROTO3 0x40000 /* protocol specific routing flag */
/* 0x80000 unused */
#define RTF_PINNED 0x100000 /* future use */
@@ -326,14 +322,14 @@ struct rt_addrinfo {
#define RT_ADDREF(_rt) do { \
RT_LOCK_ASSERT(_rt); \
KASSERT((_rt)->rt_refcnt >= 0, \
- ("negative refcnt %ld", (_rt)->rt_refcnt)); \
+ ("negative refcnt %d", (_rt)->rt_refcnt)); \
(_rt)->rt_refcnt++; \
} while (0)
#define RT_REMREF(_rt) do { \
RT_LOCK_ASSERT(_rt); \
KASSERT((_rt)->rt_refcnt > 0, \
- ("bogus refcnt %ld", (_rt)->rt_refcnt)); \
+ ("bogus refcnt %d", (_rt)->rt_refcnt)); \
(_rt)->rt_refcnt--; \
} while (0)
@@ -409,7 +405,6 @@ void rtredirect(struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *);
int rtrequest(int, struct sockaddr *,
struct sockaddr *, struct sockaddr *, int, struct rtentry **);
-int rtrequest1(int, struct rt_addrinfo *, struct rtentry **);
/* defaults to "all" FIBs */
int rtinit_fib(struct ifaddr *, int, int);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index e8cc021..30591c7 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -53,6 +53,7 @@
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_llatbl.h>
#include <net/netisr.h>
#include <net/raw_cb.h>
#include <net/route.h>
@@ -496,19 +497,6 @@ route_output(struct mbuf *m, struct socket *so)
(info.rti_info[RTAX_GATEWAY] != NULL &&
info.rti_info[RTAX_GATEWAY]->sa_family >= AF_MAX))
senderr(EINVAL);
- if (info.rti_info[RTAX_GENMASK]) {
- struct radix_node *t;
- t = rn_addmask((caddr_t) info.rti_info[RTAX_GENMASK], 0, 1);
- if (t != NULL &&
- bcmp((char *)(void *)info.rti_info[RTAX_GENMASK] + 1,
- (char *)(void *)t->rn_key + 1,
- ((struct sockaddr *)t->rn_key)->sa_len - 1) == 0)
- info.rti_info[RTAX_GENMASK] =
- (struct sockaddr *)t->rn_key;
- else
- senderr(ENOBUFS);
- }
-
/*
* Verify that the caller has the appropriate privilege; RTM_GET
* is the only operation the non-superuser is allowed.
@@ -526,6 +514,11 @@ route_output(struct mbuf *m, struct socket *so)
if (info.rti_info[RTAX_GATEWAY] == NULL)
senderr(EINVAL);
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1_fib(RTM_ADD, &info, &saved_nrt,
so->so_fibnum);
if (error == 0 && saved_nrt) {
@@ -534,13 +527,18 @@ route_output(struct mbuf *m, struct socket *so)
&rtm->rtm_rmx, &saved_nrt->rt_rmx);
rtm->rtm_index = saved_nrt->rt_ifp->if_index;
RT_REMREF(saved_nrt);
- saved_nrt->rt_genmask = info.rti_info[RTAX_GENMASK];
RT_UNLOCK(saved_nrt);
}
break;
case RTM_DELETE:
saved_nrt = NULL;
+ /* support for new ARP code */
+ if (info.rti_info[RTAX_GATEWAY] &&
+ (info.rti_info[RTAX_GATEWAY]->sa_family == AF_LINK)) {
+ error = lla_rt_output(rtm, &info);
+ break;
+ }
error = rtrequest1_fib(RTM_DELETE, &info, &saved_nrt,
so->so_fibnum);
if (error == 0) {
@@ -612,7 +610,7 @@ route_output(struct mbuf *m, struct socket *so)
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
+ info.rti_info[RTAX_GENMASK] = 0;
if (rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) {
ifp = rt->rt_ifp;
if (ifp) {
@@ -673,10 +671,10 @@ route_output(struct mbuf *m, struct socket *so)
rt->rt_ifa->ifa_addr))) {
RT_UNLOCK(rt);
RADIX_NODE_HEAD_LOCK(rnh);
- if ((error = rt_getifa_fib(&info,
- rt->rt_fibnum)) != 0)
- senderr(error);
+ error = rt_getifa_fib(&info, rt->rt_fibnum);
RADIX_NODE_HEAD_UNLOCK(rnh);
+ if (error != 0)
+ senderr(error);
RT_LOCK(rt);
}
if (info.rti_ifa != NULL &&
@@ -699,8 +697,7 @@ route_output(struct mbuf *m, struct socket *so)
RT_UNLOCK(rt);
senderr(error);
}
- if (!(rt->rt_flags & RTF_LLINFO))
- rt->rt_flags |= RTF_GATEWAY;
+ rt->rt_flags |= RTF_GATEWAY;
}
if (info.rti_ifa != NULL &&
info.rti_ifa != rt->rt_ifa) {
@@ -718,8 +715,6 @@ route_output(struct mbuf *m, struct socket *so)
rtm->rtm_index = rt->rt_ifp->if_index;
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
- if (info.rti_info[RTAX_GENMASK])
- rt->rt_genmask = info.rti_info[RTAX_GENMASK];
/* FALLTHROUGH */
case RTM_LOCK:
/* We don't support locks anymore */
@@ -1261,7 +1256,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
info.rti_info[RTAX_DST] = rt_key(rt);
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_mask(rt);
- info.rti_info[RTAX_GENMASK] = rt->rt_genmask;
+ info.rti_info[RTAX_GENMASK] = 0;
if (rt->rt_ifp) {
info.rti_info[RTAX_IFP] = rt->rt_ifp->if_addr->ifa_addr;
info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
@@ -1440,6 +1435,11 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS)
RADIX_NODE_HEAD_UNLOCK(rnh);
} else if (af != 0)
error = EAFNOSUPPORT;
+ /*
+ * take care of llinfo entries
+ */
+ if (w.w_op == NET_RT_FLAGS)
+ error = lltable_sysctl_dumparp(af, w.w_req);
break;
case NET_RT_IFLIST:
diff --git a/sys/net80211/_ieee80211.h b/sys/net80211/_ieee80211.h
index b735b5c..f5858fe 100644
--- a/sys/net80211/_ieee80211.h
+++ b/sys/net80211/_ieee80211.h
@@ -137,7 +137,7 @@ struct ieee80211_channel {
uint8_t ic_extieee; /* HT40 extension channel number */
};
-#define IEEE80211_CHAN_MAX 255
+#define IEEE80211_CHAN_MAX 256
#define IEEE80211_CHAN_BYTES 32 /* howmany(IEEE80211_CHAN_MAX, NBBY) */
#define IEEE80211_CHAN_ANY 0xffff /* token for ``any channel'' */
#define IEEE80211_CHAN_ANYC \
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index cce1312..e0a9432 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -118,7 +118,7 @@ ieee80211_chan_init(struct ieee80211com *ic)
struct ieee80211_channel *c;
int i;
- KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX,
+ KASSERT(0 < ic->ic_nchans && ic->ic_nchans <= IEEE80211_CHAN_MAX,
("invalid number of channels specified: %u", ic->ic_nchans));
memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail));
memset(ic->ic_modecaps, 0, sizeof(ic->ic_modecaps));
@@ -126,8 +126,6 @@ ieee80211_chan_init(struct ieee80211com *ic)
for (i = 0; i < ic->ic_nchans; i++) {
c = &ic->ic_channels[i];
KASSERT(c->ic_flags != 0, ("channel with no flags"));
- KASSERT(c->ic_ieee < IEEE80211_CHAN_MAX,
- ("channel with bogus ieee number %u", c->ic_ieee));
setbit(ic->ic_chan_avail, c->ic_ieee);
/*
* Identify mode capabilities.
diff --git a/sys/net80211/ieee80211_acl.c b/sys/net80211/ieee80211_acl.c
index 13407a4..cb20b87 100644
--- a/sys/net80211/ieee80211_acl.c
+++ b/sys/net80211/ieee80211_acl.c
@@ -99,7 +99,7 @@ acl_attach(struct ieee80211vap *vap)
{
struct aclstate *as;
- MALLOC(as, struct aclstate *, sizeof(struct aclstate),
+ as = (struct aclstate *) malloc(sizeof(struct aclstate),
M_80211_ACL, M_NOWAIT | M_ZERO);
if (as == NULL)
return 0;
@@ -123,7 +123,7 @@ acl_detach(struct ieee80211vap *vap)
acl_free_all(vap);
vap->iv_as = NULL;
ACL_LOCK_DESTROY(as);
- FREE(as, M_80211_ACL);
+ free(as, M_80211_ACL);
}
static __inline struct acl *
@@ -147,7 +147,7 @@ _acl_free(struct aclstate *as, struct acl *acl)
TAILQ_REMOVE(&as->as_list, acl, acl_list);
LIST_REMOVE(acl, acl_hash);
- FREE(acl, M_80211_ACL);
+ free(acl, M_80211_ACL);
as->as_nacls--;
}
@@ -175,7 +175,7 @@ acl_add(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
struct acl *acl, *new;
int hash;
- MALLOC(new, struct acl *, sizeof(struct acl), M_80211_ACL, M_NOWAIT | M_ZERO);
+ new = (struct acl *) malloc(sizeof(struct acl), M_80211_ACL, M_NOWAIT | M_ZERO);
if (new == NULL) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
"ACL: add %s failed, no memory\n", ether_sprintf(mac));
@@ -188,7 +188,7 @@ acl_add(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
LIST_FOREACH(acl, &as->as_hash[hash], acl_hash) {
if (IEEE80211_ADDR_EQ(acl->acl_macaddr, mac)) {
ACL_UNLOCK(as);
- FREE(new, M_80211_ACL);
+ free(new, M_80211_ACL);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ACL,
"ACL: add %s failed, already present\n",
ether_sprintf(mac));
@@ -301,7 +301,7 @@ acl_getioctl(struct ieee80211vap *vap, struct ieee80211req *ireq)
ireq->i_len = space; /* return required space */
return 0; /* NB: must not error */
}
- MALLOC(ap, struct ieee80211req_maclist *, space,
+ ap = (struct ieee80211req_maclist *) malloc(space,
M_TEMP, M_NOWAIT);
if (ap == NULL)
return ENOMEM;
@@ -317,7 +317,7 @@ acl_getioctl(struct ieee80211vap *vap, struct ieee80211req *ireq)
ireq->i_len = space;
} else
error = copyout(ap, ireq->i_data, ireq->i_len);
- FREE(ap, M_TEMP);
+ free(ap, M_TEMP);
return error;
}
return EINVAL;
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index 63a9583..40a6b03 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -218,7 +218,7 @@ static __inline void
ieee80211_crypto_resetkey(struct ieee80211vap *vap,
struct ieee80211_key *k, ieee80211_keyix ix)
{
- k->wk_cipher = &ieee80211_cipher_none;;
+ k->wk_cipher = &ieee80211_cipher_none;
k->wk_private = k->wk_cipher->ic_attach(vap, k);
k->wk_keyix = k->wk_rxkeyix = ix;
k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c
index bdaf7e3..c2e9486 100644
--- a/sys/net80211/ieee80211_crypto_ccmp.c
+++ b/sys/net80211/ieee80211_crypto_ccmp.c
@@ -96,7 +96,7 @@ ccmp_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct ccmp_ctx *ctx;
- MALLOC(ctx, struct ccmp_ctx *, sizeof(struct ccmp_ctx),
+ ctx = (struct ccmp_ctx *) malloc(sizeof(struct ccmp_ctx),
M_80211_CRYPTO, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
vap->iv_stats.is_crypto_nomem++;
@@ -113,7 +113,7 @@ ccmp_detach(struct ieee80211_key *k)
{
struct ccmp_ctx *ctx = k->wk_private;
- FREE(ctx, M_80211_CRYPTO);
+ free(ctx, M_80211_CRYPTO);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c
index f509856..b20946a 100644
--- a/sys/net80211/ieee80211_crypto_tkip.c
+++ b/sys/net80211/ieee80211_crypto_tkip.c
@@ -109,7 +109,7 @@ tkip_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct tkip_ctx *ctx;
- MALLOC(ctx, struct tkip_ctx *, sizeof(struct tkip_ctx),
+ ctx = (struct tkip_ctx *) malloc(sizeof(struct tkip_ctx),
M_80211_CRYPTO, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
vap->iv_stats.is_crypto_nomem++;
@@ -126,7 +126,7 @@ tkip_detach(struct ieee80211_key *k)
{
struct tkip_ctx *ctx = k->wk_private;
- FREE(ctx, M_80211_CRYPTO);
+ free(ctx, M_80211_CRYPTO);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
diff --git a/sys/net80211/ieee80211_crypto_wep.c b/sys/net80211/ieee80211_crypto_wep.c
index 7eade59..07c1797 100644
--- a/sys/net80211/ieee80211_crypto_wep.c
+++ b/sys/net80211/ieee80211_crypto_wep.c
@@ -87,7 +87,7 @@ wep_attach(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct wep_ctx *ctx;
- MALLOC(ctx, struct wep_ctx *, sizeof(struct wep_ctx),
+ ctx = (struct wep_ctx *) malloc(sizeof(struct wep_ctx),
M_80211_CRYPTO, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
vap->iv_stats.is_crypto_nomem++;
@@ -106,7 +106,7 @@ wep_detach(struct ieee80211_key *k)
{
struct wep_ctx *ctx = k->wk_private;
- FREE(ctx, M_80211_CRYPTO);
+ free(ctx, M_80211_CRYPTO);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index b3dd4d4..59c6a46 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -92,7 +92,8 @@ __FBSDID("$FreeBSD$");
#define IEEE80211_NODE_BITS \
"\20\1AUTH\2QOS\3ERP\5PWR_MGT\6AREF\7HT\10HTCOMPAT\11WPS\12TSN" \
- "\13AMPDU_RX\14AMPDU_TX\15MIMO_PS\16MIMO_RTS\17RIFS\20SGI20\21SGI40"
+ "\13AMPDU_RX\14AMPDU_TX\15MIMO_PS\16MIMO_RTS\17RIFS\20SGI20\21SGI40" \
+ "\22ASSOCID"
#define IEEE80211_ERP_BITS \
"\20\1NON_ERP_PRESENT\2USE_PROTECTION\3LONG_PREAMBLE"
@@ -541,7 +542,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showp
*/
db_printf("\tnchans %d", ic->ic_nchans);
#if 0
- struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
+ struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX];
uint8_t ic_chan_avail[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_active[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_scan[IEEE80211_CHAN_BYTES];
diff --git a/sys/net80211/ieee80211_dfs.h b/sys/net80211/ieee80211_dfs.h
index 36d14aa..9076077 100644
--- a/sys/net80211/ieee80211_dfs.h
+++ b/sys/net80211/ieee80211_dfs.h
@@ -32,7 +32,7 @@
*/
struct ieee80211_dfs_state {
- int nol_event[IEEE80211_CHAN_MAX+1];
+ int nol_event[IEEE80211_CHAN_MAX];
struct callout nol_timer; /* NOL list processing */
struct callout cac_timer; /* CAC timer */
struct timeval lastevent; /* time of last radar event */
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index 71174b7..60de0f4 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -234,7 +234,7 @@ ieee80211_sysctl_vattach(struct ieee80211vap *vap)
struct sysctl_oid *oid;
char num[14]; /* sufficient for 32 bits */
- MALLOC(ctx, struct sysctl_ctx_list *, sizeof(struct sysctl_ctx_list),
+ ctx = (struct sysctl_ctx_list *) malloc(sizeof(struct sysctl_ctx_list),
M_DEVBUF, M_NOWAIT | M_ZERO);
if (ctx == NULL) {
if_printf(ifp, "%s: cannot allocate sysctl context!\n",
@@ -310,7 +310,7 @@ ieee80211_sysctl_vdetach(struct ieee80211vap *vap)
if (vap->iv_sysctl != NULL) {
sysctl_ctx_free(vap->iv_sysctl);
- FREE(vap->iv_sysctl, M_DEVBUF);
+ free(vap->iv_sysctl, M_DEVBUF);
vap->iv_sysctl = NULL;
}
}
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 60cbe4b..c333954 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -902,7 +902,7 @@ hostap_auth_open(struct ieee80211_node *ni, struct ieee80211_frame *wh,
* open auth is attempted.
*/
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
/* XXX hack to workaround calling convention */
@@ -928,6 +928,11 @@ hostap_auth_open(struct ieee80211_node *ni, struct ieee80211_frame *wh,
* after the transaction completes.
*/
ni->ni_flags |= IEEE80211_NODE_AREF;
+ /*
+ * Mark the node as requiring a valid association id
+ * before outbound traffic is permitted.
+ */
+ ni->ni_flags |= IEEE80211_NODE_ASSOCID;
if (vap->iv_acl != NULL &&
vap->iv_acl->iac_getpolicy(vap) == IEEE80211_MACCMD_POLICY_RADIUS) {
@@ -1054,6 +1059,11 @@ hostap_auth_shared(struct ieee80211_node *ni, struct ieee80211_frame *wh,
* after the transaction completes.
*/
ni->ni_flags |= IEEE80211_NODE_AREF;
+ /*
+ * Mark the node as requiring a valid associatio id
+ * before outbound traffic is permitted.
+ */
+ ni->ni_flags |= IEEE80211_NODE_ASSOCID;
IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi);
ni->ni_noise = noise;
ni->ni_rstamp = rstamp;
@@ -1986,7 +1996,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
return;
/* discard challenge after association */
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
/* NB: 802.11 spec says to ignore station's privacy bit */
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index e72a2a2..e68bb6c 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -499,7 +499,7 @@ int
ieee80211_alloc_challenge(struct ieee80211_node *ni)
{
if (ni->ni_challenge == NULL)
- MALLOC(ni->ni_challenge, uint32_t*, IEEE80211_CHALLENGE_LEN,
+ ni->ni_challenge = (uint32_t *) malloc(IEEE80211_CHALLENGE_LEN,
M_80211_NODE, M_NOWAIT);
if (ni->ni_challenge == NULL) {
IEEE80211_NOTE(ni->ni_vap,
@@ -673,14 +673,6 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
}
IEEE80211_VERIFY_ELEMENT(scan->ssid, IEEE80211_NWID_LEN,
scan->status |= IEEE80211_BPARSE_SSID_INVALID);
-#if IEEE80211_CHAN_MAX < 255
- if (scan->chan > IEEE80211_CHAN_MAX) {
- IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,
- wh, NULL, "invalid channel %u", scan->chan);
- vap->iv_stats.is_rx_badchan++;
- scan->status |= IEEE80211_BPARSE_CHAN_INVALID;
- }
-#endif
if (scan->chan != scan->bchan && ic->ic_phytype != IEEE80211_T_FH) {
/*
* Frame was received on a channel different from the
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index ae39fd6..b967e47 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -320,14 +320,14 @@ ieee80211_ioctl_getscanresults(struct ieee80211vap *vap,
space = req.space;
/* XXX M_WAITOK after driver lock released */
- MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
+ p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
if (p == NULL)
return ENOMEM;
req.sr = p;
ieee80211_scan_iterate(vap, get_scan_result, &req);
ireq->i_len = space - req.space;
error = copyout(p, ireq->i_data, ireq->i_len);
- FREE(p, M_TEMP);
+ free(p, M_TEMP);
} else
ireq->i_len = 0;
@@ -467,7 +467,7 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
if (req.space > 0) {
space = req.space;
/* XXX M_WAITOK after driver lock released */
- MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
+ p = malloc(space, M_TEMP, M_NOWAIT | M_ZERO);
if (p == NULL) {
error = ENOMEM;
goto bad;
@@ -479,7 +479,7 @@ getstainfo_common(struct ieee80211vap *vap, struct ieee80211req *ireq,
get_sta_info(&req, ni);
ireq->i_len = space - req.space;
error = copyout(p, (uint8_t *) ireq->i_data+off, ireq->i_len);
- FREE(p, M_TEMP);
+ free(p, M_TEMP);
} else
ireq->i_len = 0;
bad:
@@ -696,7 +696,7 @@ ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
if (ireq->i_len != sizeof(struct ieee80211_devcaps_req))
return EINVAL;
- MALLOC(dc, struct ieee80211_devcaps_req *,
+ dc = (struct ieee80211_devcaps_req *) malloc(
sizeof(struct ieee80211_devcaps_req), M_TEMP, M_NOWAIT | M_ZERO);
if (dc == NULL)
return ENOMEM;
@@ -707,7 +707,7 @@ ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
ic->ic_getradiocaps(ic, &ci->ic_nchans, ci->ic_chans);
ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
error = copyout(dc, ireq->i_data, sizeof(*dc));
- FREE(dc, M_TEMP);
+ free(dc, M_TEMP);
return error;
}
@@ -1556,7 +1556,7 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211req_chanlist list;
u_char chanlist[IEEE80211_CHAN_BYTES];
- int i, j, nchan, error;
+ int i, nchan, error;
if (ireq->i_len != sizeof(list))
return EINVAL;
@@ -1564,22 +1564,16 @@ ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
if (error)
return error;
memset(chanlist, 0, sizeof(chanlist));
- /*
- * Since channel 0 is not available for DS, channel 1
- * is assigned to LSB on WaveLAN.
- */
- if (ic->ic_phytype == IEEE80211_T_DS)
- i = 1;
- else
- i = 0;
nchan = 0;
- for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) {
+ for (i = 0; i < ic->ic_nchans; i++) {
+ const struct ieee80211_channel *c = &ic->ic_channels[i];
/*
- * NB: silently discard unavailable channels so users
- * can specify 1-255 to get all available channels.
+ * Calculate the intersection of the user list and the
+ * available channels so users can do things like specify
+ * 1-255 to get all available channels.
*/
- if (isset(list.ic_channels, j) && isset(ic->ic_chan_avail, i)) {
- setbit(chanlist, i);
+ if (isset(list.ic_channels, c->ic_ieee)) {
+ setbit(chanlist, c->ic_ieee);
nchan++;
}
}
@@ -1890,8 +1884,6 @@ ieee80211_ioctl_setchannel(struct ieee80211vap *vap,
if (ireq->i_val == 0 ||
ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
c = IEEE80211_CHAN_ANYC;
- } else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
- return EINVAL;
} else {
struct ieee80211_channel *c2;
@@ -1993,14 +1985,14 @@ ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
if (ireq->i_len != sizeof(struct ieee80211_regdomain_req))
return EINVAL;
- MALLOC(reg, struct ieee80211_regdomain_req *,
+ reg = (struct ieee80211_regdomain_req *) malloc(
sizeof(struct ieee80211_regdomain_req), M_TEMP, M_NOWAIT);
if (reg == NULL)
return ENOMEM;
error = copyin(ireq->i_data, reg, sizeof(*reg));
if (error == 0)
error = ieee80211_setregdomain(vap, reg);
- FREE(reg, M_TEMP);
+ free(reg, M_TEMP);
return (error == 0 ? ENETRESET : error);
}
@@ -2139,7 +2131,7 @@ setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
if (ireq->i_len == 0) { /* delete any existing ie */
if (app != NULL) {
*aie = NULL; /* XXX racey */
- FREE(app, M_80211_NODE_IE);
+ free(app, M_80211_NODE_IE);
}
return 0;
}
@@ -2153,20 +2145,20 @@ setappie(struct ieee80211_appie **aie, const struct ieee80211req *ireq)
*
* XXX bad bad bad
*/
- MALLOC(napp, struct ieee80211_appie *,
+ napp = (struct ieee80211_appie *) malloc(
sizeof(struct ieee80211_appie) + ireq->i_len, M_80211_NODE_IE, M_NOWAIT);
if (napp == NULL)
return ENOMEM;
/* XXX holding ic lock */
error = copyin(ireq->i_data, napp->ie_data, ireq->i_len);
if (error) {
- FREE(napp, M_80211_NODE_IE);
+ free(napp, M_80211_NODE_IE);
return error;
}
napp->ie_len = ireq->i_len;
*aie = napp;
if (app != NULL)
- FREE(app, M_80211_NODE_IE);
+ free(app, M_80211_NODE_IE);
return 0;
}
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 8e9d91f..e3028d9 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -153,7 +153,7 @@ ieee80211_node_latevattach(struct ieee80211vap *vap)
"WARNING: max aid too small, changed to %d\n",
vap->iv_max_aid);
}
- MALLOC(vap->iv_aid_bitmap, uint32_t *,
+ vap->iv_aid_bitmap = (uint32_t *) malloc(
howmany(vap->iv_max_aid, 32) * sizeof(uint32_t),
M_80211_NODE, M_NOWAIT | M_ZERO);
if (vap->iv_aid_bitmap == NULL) {
@@ -180,7 +180,7 @@ ieee80211_node_vdetach(struct ieee80211vap *vap)
vap->iv_bss = NULL;
}
if (vap->iv_aid_bitmap != NULL) {
- FREE(vap->iv_aid_bitmap, M_80211_NODE);
+ free(vap->iv_aid_bitmap, M_80211_NODE);
vap->iv_aid_bitmap = NULL;
}
}
@@ -732,6 +732,7 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan,
ni->ni_erp = se->se_erp;
IEEE80211_RSSI_LPF(ni->ni_avgrssi, se->se_rssi);
ni->ni_noise = se->se_noise;
+ ni->ni_flags |= IEEE80211_NODE_ASSOCID;
if (ieee80211_ies_init(&ni->ni_ies, se->se_ies.data, se->se_ies.len)) {
ieee80211_ies_expand(&ni->ni_ies);
@@ -788,7 +789,7 @@ node_alloc(struct ieee80211vap *vap, const uint8_t macaddr[IEEE80211_ADDR_LEN])
{
struct ieee80211_node *ni;
- MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node),
+ ni = (struct ieee80211_node *) malloc(sizeof(struct ieee80211_node),
M_80211_NODE, M_NOWAIT | M_ZERO);
return ni;
}
@@ -806,11 +807,11 @@ ieee80211_ies_init(struct ieee80211_ies *ies, const uint8_t *data, int len)
memset(ies, 0, offsetof(struct ieee80211_ies, data));
if (ies->data != NULL && ies->len != len) {
/* data size changed */
- FREE(ies->data, M_80211_NODE_IE);
+ free(ies->data, M_80211_NODE_IE);
ies->data = NULL;
}
if (ies->data == NULL) {
- MALLOC(ies->data, uint8_t *, len, M_80211_NODE_IE, M_NOWAIT);
+ ies->data = (uint8_t *) malloc(len, M_80211_NODE_IE, M_NOWAIT);
if (ies->data == NULL) {
ies->len = 0;
/* NB: pointers have already been zero'd above */
@@ -829,7 +830,7 @@ void
ieee80211_ies_cleanup(struct ieee80211_ies *ies)
{
if (ies->data != NULL)
- FREE(ies->data, M_80211_NODE_IE);
+ free(ies->data, M_80211_NODE_IE);
}
/*
@@ -898,8 +899,10 @@ node_cleanup(struct ieee80211_node *ni)
* has happened. This is probably not needed as the node
* should always be removed from the table so not found but
* do it just in case.
+ * Likewise clear the ASSOCID flag as these flags are intended
+ * to be managed in tandem.
*/
- ni->ni_flags &= ~IEEE80211_NODE_AREF;
+ ni->ni_flags &= ~(IEEE80211_NODE_AREF | IEEE80211_NODE_ASSOCID);
/*
* Drain power save queue and, if needed, clear TIM.
@@ -909,7 +912,7 @@ node_cleanup(struct ieee80211_node *ni)
ni->ni_associd = 0;
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
/*
@@ -945,7 +948,7 @@ node_free(struct ieee80211_node *ni)
ieee80211_ies_cleanup(&ni->ni_ies);
ieee80211_psq_cleanup(&ni->ni_psq);
IEEE80211_NODE_WDSQ_DESTROY(ni);
- FREE(ni, M_80211_NODE);
+ free(ni, M_80211_NODE);
}
static void
@@ -1511,19 +1514,8 @@ ieee80211_find_txnode(struct ieee80211vap *vap,
vap->iv_opmode == IEEE80211_M_WDS ||
IEEE80211_IS_MULTICAST(macaddr))
ni = ieee80211_ref_node(vap->iv_bss);
- else {
+ else
ni = ieee80211_find_node_locked(nt, macaddr);
- if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
- (ni != NULL && ni->ni_associd == 0)) {
- /*
- * Station is not associated; don't permit the
- * data frame to be sent by returning NULL. This
- * is kinda a kludge but the least intrusive way
- * to add this check into all drivers.
- */
- ieee80211_unref_node(&ni); /* NB: null's ni */
- }
- }
IEEE80211_NODE_UNLOCK(nt);
if (ni == NULL) {
@@ -1651,7 +1643,7 @@ ieee80211_node_delucastkey(struct ieee80211_node *ni)
IEEE80211_NODE_LOCK(nt);
nikey = NULL;
status = 1; /* NB: success */
- if (!IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) {
+ if (ni->ni_ucastkey.wk_keyix != IEEE80211_KEYIX_NONE) {
keyix = ni->ni_ucastkey.wk_rxkeyix;
status = ieee80211_crypto_delkey(ni->ni_vap, &ni->ni_ucastkey);
if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax) {
@@ -1799,7 +1791,7 @@ ieee80211_node_table_init(struct ieee80211com *ic,
nt->nt_inact_init = inact;
nt->nt_keyixmax = keyixmax;
if (nt->nt_keyixmax > 0) {
- MALLOC(nt->nt_keyixmap, struct ieee80211_node **,
+ nt->nt_keyixmap = (struct ieee80211_node **) malloc(
keyixmax * sizeof(struct ieee80211_node *),
M_80211_NODE, M_NOWAIT | M_ZERO);
if (nt->nt_keyixmap == NULL)
@@ -1860,7 +1852,7 @@ ieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
printf("%s: %s[%u] still active\n", __func__,
nt->nt_name, i);
#endif
- FREE(nt->nt_keyixmap, M_80211_NODE);
+ free(nt->nt_keyixmap, M_80211_NODE);
nt->nt_keyixmap = NULL;
}
IEEE80211_NODE_ITERATE_LOCK_DESTROY(nt);
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index b8a30ad..bd304d5 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -117,6 +117,7 @@ struct ieee80211_node {
#define IEEE80211_NODE_RIFS 0x004000 /* RIFS enabled */
#define IEEE80211_NODE_SGI20 0x008000 /* Short GI in HT20 enabled */
#define IEEE80211_NODE_SGI40 0x010000 /* Short GI in HT40 enabled */
+#define IEEE80211_NODE_ASSOCID 0x020000 /* xmit requires associd */
uint16_t ni_associd; /* association ID */
uint16_t ni_vlan; /* vlan tag */
uint16_t ni_txpower; /* current transmit power */
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index e5c6889..050d892 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -203,10 +203,8 @@ ieee80211_start(struct ifnet *ifp)
continue;
}
/* XXX AUTH'd */
- /* XXX mark vap to identify if associd is required */
if (ni->ni_associd == 0 &&
- (vap->iv_opmode == IEEE80211_M_STA ||
- vap->iv_opmode == IEEE80211_M_HOSTAP || IS_DWDS(vap))) {
+ (ni->ni_flags & IEEE80211_NODE_ASSOCID)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_OUTPUT,
eh->ether_dhost, NULL,
"sta not associated (type 0x%04x)",
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index b2ace4a..aad82ba 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -80,7 +80,7 @@ ieee80211_power_latevattach(struct ieee80211vap *vap)
*/
if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
vap->iv_tim_len = howmany(vap->iv_max_aid,8) * sizeof(uint8_t);
- MALLOC(vap->iv_tim_bitmap, uint8_t *, vap->iv_tim_len,
+ vap->iv_tim_bitmap = (uint8_t *) malloc(vap->iv_tim_len,
M_80211_POWER, M_NOWAIT | M_ZERO);
if (vap->iv_tim_bitmap == NULL) {
printf("%s: no memory for TIM bitmap!\n", __func__);
@@ -94,7 +94,7 @@ void
ieee80211_power_vdetach(struct ieee80211vap *vap)
{
if (vap->iv_tim_bitmap != NULL) {
- FREE(vap->iv_tim_bitmap, M_80211_POWER);
+ free(vap->iv_tim_bitmap, M_80211_POWER);
vap->iv_tim_bitmap = NULL;
}
}
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 452bd3f..31b68fd 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -214,7 +214,7 @@ ieee80211_proto_vdetach(struct ieee80211vap *vap)
{
#define FREEAPPIE(ie) do { \
if (ie != NULL) \
- FREE(ie, M_80211_NODE_IE); \
+ free(ie, M_80211_NODE_IE); \
} while (0)
/*
* Detach operating mode module.
diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c
index 0e41355..724d00b 100644
--- a/sys/net80211/ieee80211_regdomain.c
+++ b/sys/net80211/ieee80211_regdomain.c
@@ -338,7 +338,7 @@ ieee80211_setregdomain(struct ieee80211vap *vap,
reg->rd.isocc[0], reg->rd.isocc[1]);
return EINVAL;
}
- if (reg->chaninfo.ic_nchans >= IEEE80211_CHAN_MAX) {
+ if (reg->chaninfo.ic_nchans > IEEE80211_CHAN_MAX) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
"%s: too many channels %u, max %u\n", __func__,
reg->chaninfo.ic_nchans, IEEE80211_CHAN_MAX);
diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c
index dabb404..f56617a0 100644
--- a/sys/net80211/ieee80211_scan.c
+++ b/sys/net80211/ieee80211_scan.c
@@ -96,7 +96,7 @@ ieee80211_scan_attach(struct ieee80211com *ic)
{
struct scan_state *ss;
- MALLOC(ss, struct scan_state *, sizeof(struct scan_state),
+ ss = (struct scan_state *) malloc(sizeof(struct scan_state),
M_80211_SCAN, M_NOWAIT | M_ZERO);
if (ss == NULL) {
ic->ic_scan = NULL;
@@ -122,7 +122,7 @@ ieee80211_scan_detach(struct ieee80211com *ic)
}
ic->ic_flags &= ~IEEE80211_F_SCAN;
ic->ic_scan = NULL;
- FREE(SCAN_PRIVATE(ss), M_80211_SCAN);
+ free(SCAN_PRIVATE(ss), M_80211_SCAN);
}
}
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index e3a4bda..15e4ff6 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -87,6 +87,9 @@ struct sta_entry {
#define STA_HASH(addr) \
(((const uint8_t *)(addr))[IEEE80211_ADDR_LEN - 1] % STA_HASHSIZE)
+#define MAX_IEEE_CHAN 256 /* max acceptable IEEE chan # */
+CTASSERT(MAX_IEEE_CHAN >= 256);
+
struct sta_table {
struct mtx st_lock; /* on scan table */
TAILQ_HEAD(, sta_entry) st_entry; /* all entries */
@@ -96,7 +99,7 @@ struct sta_table {
u_int st_scangen; /* scan generation # */
int st_newscan;
/* ap-related state */
- int st_maxrssi[IEEE80211_CHAN_MAX];
+ int st_maxrssi[MAX_IEEE_CHAN];
};
static void sta_flush_table(struct sta_table *);
@@ -137,7 +140,7 @@ sta_attach(struct ieee80211_scan_state *ss)
{
struct sta_table *st;
- MALLOC(st, struct sta_table *, sizeof(struct sta_table),
+ st = (struct sta_table *) malloc(sizeof(struct sta_table),
M_80211_SCAN, M_NOWAIT | M_ZERO);
if (st == NULL)
return 0;
@@ -161,7 +164,7 @@ sta_detach(struct ieee80211_scan_state *ss)
sta_flush_table(st);
mtx_destroy(&st->st_lock);
mtx_destroy(&st->st_scanlock);
- FREE(st, M_80211_SCAN);
+ free(st, M_80211_SCAN);
KASSERT(nrefs > 0, ("imbalanced attach/detach"));
nrefs--; /* NB: we assume caller locking */
}
@@ -195,7 +198,7 @@ sta_flush_table(struct sta_table *st)
TAILQ_REMOVE(&st->st_entry, se, se_list);
LIST_REMOVE(se, se_hash);
ieee80211_ies_cleanup(&se->base.se_ies);
- FREE(se, M_80211_SCAN);
+ free(se, M_80211_SCAN);
}
memset(st->st_maxrssi, 0, sizeof(st->st_maxrssi));
}
@@ -228,7 +231,7 @@ sta_add(struct ieee80211_scan_state *ss,
LIST_FOREACH(se, &st->st_hash[hash], se_hash)
if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr))
goto found;
- MALLOC(se, struct sta_entry *, sizeof(struct sta_entry),
+ se = (struct sta_entry *) malloc(sizeof(struct sta_entry),
M_80211_SCAN, M_NOWAIT | M_ZERO);
if (se == NULL) {
mtx_unlock(&st->st_lock);
@@ -343,6 +346,7 @@ found:
se->se_seen = 1;
se->se_notseen = 0;
+ KASSERT(sizeof(sp->bchan) == 1, ("bchan size"));
if (rssi > st->st_maxrssi[sp->bchan])
st->st_maxrssi[sp->bchan] = rssi;
@@ -1505,7 +1509,7 @@ adhoc_age(struct ieee80211_scan_state *ss)
TAILQ_REMOVE(&st->st_entry, se, se_list);
LIST_REMOVE(se, se_hash);
ieee80211_ies_cleanup(&se->base.se_ies);
- FREE(se, M_80211_SCAN);
+ free(se, M_80211_SCAN);
}
}
mtx_unlock(&st->st_lock);
@@ -1604,6 +1608,7 @@ ap_pick_channel(struct ieee80211_scan_state *ss, int flags)
/* check channel attributes for band compatibility */
if (flags != 0 && (chan->ic_flags & flags) != flags)
continue;
+ KASSERT(sizeof(chan->ic_ieee) == 1, ("ic_chan size"));
/* XXX channel have interference */
if (st->st_maxrssi[chan->ic_ieee] == 0) {
/* XXX use other considerations */
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 35fcead..54733c9 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -1018,7 +1018,7 @@ sta_auth_shared(struct ieee80211_node *ni, struct ieee80211_frame *wh,
switch (seq) {
case IEEE80211_AUTH_SHARED_PASS:
if (ni->ni_challenge != NULL) {
- FREE(ni->ni_challenge, M_80211_NODE);
+ free(ni->ni_challenge, M_80211_NODE);
ni->ni_challenge = NULL;
}
if (status != 0) {
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 3e90201..ccd95d0 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -156,7 +156,7 @@ struct ieee80211com {
* (e.g. for dynamic turbo)
*/
int ic_nchans; /* # entries in ic_channels */
- struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX+1];
+ struct ieee80211_channel ic_channels[IEEE80211_CHAN_MAX];
uint8_t ic_chan_avail[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_active[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_scan[IEEE80211_CHAN_BYTES];
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
index 5443629..411730a 100644
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -270,7 +270,7 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
sin.sin_family = AF_INET;
sin.sin_addr = fle->f.r.r_dst;
/* XXX MRT 0 as a default.. need the m here to get fib */
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, RTF_CLONING, 0);
+ rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, 0);
if (rt != NULL) {
fle->f.fle_o_ifx = rt->rt_ifp->if_index;
@@ -295,7 +295,7 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
sin.sin_family = AF_INET;
sin.sin_addr = fle->f.r.r_src;
/* XXX MRT 0 as a default revisit. need the mbuf for fib*/
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, RTF_CLONING, 0);
+ rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, 0);
if (rt != NULL) {
if (rt_mask(rt))
fle->f.src_mask = bitcount32(((struct sockaddr_in *)
diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h
index 4072f76..859af71 100644
--- a/sys/netgraph/netgraph.h
+++ b/sys/netgraph/netgraph.h
@@ -1130,7 +1130,6 @@ item_p ng_package_msg(struct ng_mesg *msg, int flags);
item_p ng_package_msg_self(node_p here, hook_p hook, struct ng_mesg *msg);
void ng_replace_retaddr(node_p here, item_p item, ng_ID_t retaddr);
int ng_rmhook_self(hook_p hook); /* if a node wants to kill a hook */
-int ng_rmnode_flags(node_p here, int flags);
int ng_rmnode_self(node_p here); /* if a node wants to suicide */
int ng_rmtype(struct ng_type *tp);
int ng_snd_item(item_p item, int queue);
diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c
index 0406da1..0e9f96c 100644
--- a/sys/netgraph/ng_base.c
+++ b/sys/netgraph/ng_base.c
@@ -62,6 +62,9 @@
#include <sys/refcount.h>
#include <sys/proc.h>
#include <sys/vimage.h>
+#include <sys/unistd.h>
+#include <sys/kthread.h>
+#include <sys/smp.h>
#include <machine/cpu.h>
#include <net/netisr.h>
@@ -211,7 +214,7 @@ static int ng_generic_msg(node_p here, item_p item, hook_p lasthook);
static ng_ID_t ng_decodeidname(const char *name);
static int ngb_mod_event(module_t mod, int event, void *data);
static void ng_worklist_add(node_p node);
-static void ngintr(void);
+static void ngthread(void *);
static int ng_apply_item(node_p node, item_p item, int rw);
static void ng_flush_input_queue(node_p node);
static node_p ng_ID2noderef(ng_ID_t ID);
@@ -259,6 +262,10 @@ MALLOC_DEFINE(M_NETGRAPH_MSG, "netgraph_msg", "netgraph name storage");
mtx_lock(&ng_worklist_mtx)
#define NG_WORKLIST_UNLOCK() \
mtx_unlock(&ng_worklist_mtx)
+#define NG_WORKLIST_SLEEP() \
+ mtx_sleep(&ng_worklist, &ng_worklist_mtx, PI_NET, "sleep", 0)
+#define NG_WORKLIST_WAKEUP() \
+ wakeup_one(&ng_worklist)
#ifdef NETGRAPH_DEBUG /*----------------------------------------------*/
/*
@@ -1521,7 +1528,7 @@ ng_mkpeer(node_p node, const char *name, const char *name2, char *type)
/* Shut this node down as soon as everyone is clear of it */
/* Should add arg "immediately" to jump the queue */
int
-ng_rmnode_flags(node_p node, int flags)
+ng_rmnode_self(node_p node)
{
int error;
@@ -1531,16 +1538,10 @@ ng_rmnode_flags(node_p node, int flags)
if (node->nd_flags & NGF_CLOSING)
return (0);
- error = ng_send_fn1(node, NULL, &ng_rmnode, NULL, 0, flags);
+ error = ng_send_fn(node, NULL, &ng_rmnode, NULL, 0);
return (error);
}
-int
-ng_rmnode_self(node_p node)
-{
- return (ng_rmnode_flags(node, NG_NOFLAGS));
-}
-
static void
ng_rmhook_part2(node_p node, hook_p hook, void *arg1, int arg2)
{
@@ -2874,9 +2875,13 @@ out:
uma_zone_t ng_qzone;
uma_zone_t ng_qdzone;
+static int numthreads = 0; /* number of queue threads */
static int maxalloc = 4096;/* limit the damage of a leak */
static int maxdata = 512; /* limit the damage of a DoS */
+TUNABLE_INT("net.graph.threads", &numthreads);
+SYSCTL_INT(_net_graph, OID_AUTO, threads, CTLFLAG_RDTUN, &numthreads,
+ 0, "Number of queue processing threads");
TUNABLE_INT("net.graph.maxalloc", &maxalloc);
SYSCTL_INT(_net_graph, OID_AUTO, maxalloc, CTLFLAG_RDTUN, &maxalloc,
0, "Maximum number of non-data queue items to allocate");
@@ -3070,7 +3075,9 @@ ng_mod_event(module_t mod, int event, void *data)
static int
ngb_mod_event(module_t mod, int event, void *data)
{
- int error = 0;
+ struct proc *p;
+ struct thread *td;
+ int i, error = 0;
switch (event) {
case MOD_LOAD:
@@ -3097,7 +3104,18 @@ ngb_mod_event(module_t mod, int event, void *data)
ng_qdzone = uma_zcreate("NetGraph data items", sizeof(struct ng_item),
NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
uma_zone_set_max(ng_qdzone, maxdata);
- netisr_register(NETISR_NETGRAPH, (netisr_t *)ngintr, NULL, 0);
+ /* Autoconfigure number of threads. */
+ if (numthreads <= 0)
+ numthreads = mp_ncpus;
+ /* Create threads. */
+ p = NULL; /* start with no process */
+ for (i = 0; i < numthreads; i++) {
+ if (kproc_kthread_add(ngthread, NULL, &p, &td,
+ RFHIGHPID, 0, "ng_queue", "ng_queue%d", i)) {
+ numthreads = i;
+ break;
+ }
+ }
break;
case MOD_UNLOAD:
/* You can't unload it because an interface may be using it. */
@@ -3252,25 +3270,20 @@ SYSCTL_PROC(_debug, OID_AUTO, ng_dump_items, CTLTYPE_INT | CTLFLAG_RW,
/***********************************************************************
* Worklist routines
**********************************************************************/
-/* NETISR thread enters here */
/*
* Pick a node off the list of nodes with work,
- * try get an item to process off it.
- * If there are no more, remove the node from the list.
+ * try get an item to process off it. Remove the node from the list.
*/
static void
-ngintr(void)
+ngthread(void *arg)
{
for (;;) {
node_p node;
/* Get node from the worklist. */
NG_WORKLIST_LOCK();
- node = STAILQ_FIRST(&ng_worklist);
- if (!node) {
- NG_WORKLIST_UNLOCK();
- break;
- }
+ while ((node = STAILQ_FIRST(&ng_worklist)) == NULL)
+ NG_WORKLIST_SLEEP();
STAILQ_REMOVE_HEAD(&ng_worklist, nd_input_queue.q_work);
NG_WORKLIST_UNLOCK();
CTR3(KTR_NET, "%20s: node [%x] (%p) taken off worklist",
@@ -3326,9 +3339,9 @@ ng_worklist_add(node_p node)
NG_WORKLIST_LOCK();
STAILQ_INSERT_TAIL(&ng_worklist, node, nd_input_queue.q_work);
NG_WORKLIST_UNLOCK();
- schednetisr(NETISR_NETGRAPH);
CTR3(KTR_NET, "%20s: node [%x] (%p) put on worklist", __func__,
node->nd_ID, node);
+ NG_WORKLIST_WAKEUP();
} else {
CTR3(KTR_NET, "%20s: node [%x] (%p) already on worklist",
__func__, node->nd_ID, node);
diff --git a/sys/netgraph/ng_mppc.c b/sys/netgraph/ng_mppc.c
index 472968f..5a6c302 100644
--- a/sys/netgraph/ng_mppc.c
+++ b/sys/netgraph/ng_mppc.c
@@ -824,21 +824,24 @@ ng_mppc_reset_req(node_p node)
static void
ng_mppc_getkey(const u_char *h, u_char *h2, int len)
{
- static const u_char pad1[10] =
- { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
- static const u_char pad2[10] =
- { 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, };
+ static const u_char pad1[40] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static const u_char pad2[40] =
+ { 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2 };
u_char hash[20];
SHA1_CTX c;
- int k;
SHA1Init(&c);
SHA1Update(&c, h, len);
- for (k = 0; k < 4; k++)
- SHA1Update(&c, pad1, sizeof(pad1));
+ SHA1Update(&c, pad1, sizeof(pad1));
SHA1Update(&c, h2, len);
- for (k = 0; k < 4; k++)
- SHA1Update(&c, pad2, sizeof(pad2));
+ SHA1Update(&c, pad2, sizeof(pad2));
SHA1Final(hash, &c);
bcopy(hash, h2, len);
}
diff --git a/sys/netgraph/ng_tty.c b/sys/netgraph/ng_tty.c
index c504b84..2fa33fc 100644
--- a/sys/netgraph/ng_tty.c
+++ b/sys/netgraph/ng_tty.c
@@ -114,7 +114,6 @@ static th_getc_poll_t ngt_getc_poll;
static th_rint_t ngt_rint;
static th_rint_bypass_t ngt_rint_bypass;
static th_rint_poll_t ngt_rint_poll;
-static th_close_t ngt_close;
static struct ttyhook ngt_hook = {
.th_getc_inject = ngt_getc_inject,
@@ -122,7 +121,6 @@ static struct ttyhook ngt_hook = {
.th_rint = ngt_rint,
.th_rint_bypass = ngt_rint_bypass,
.th_rint_poll = ngt_rint_poll,
- .th_close = ngt_close,
};
/* Netgraph node type descriptor */
@@ -252,7 +250,6 @@ static int
ngt_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct proc *p;
- struct thread *td;
const sc_p sc = NG_NODE_PRIVATE(node);
struct ng_mesg *msg, *resp = NULL;
int error = 0;
@@ -266,12 +263,13 @@ ngt_rcvmsg(node_p node, item_p item, hook_p lasthook)
return (EBUSY);
p = pfind(((int *)msg->data)[0]);
- if (p == NULL)
+ if (p == NULL || (p->p_flag & P_WEXIT))
return (ESRCH);
- td = FIRST_THREAD_IN_PROC(p);
- error = ttyhook_register(&sc->tp, td, ((int *)msg->data)[1],
- &ngt_hook, sc);
+ _PHOLD(p);
PROC_UNLOCK(p);
+ error = ttyhook_register(&sc->tp, p, ((int *)msg->data)[1],
+ &ngt_hook, sc);
+ PRELE(p);
if (error != 0)
return (error);
break;
@@ -515,12 +513,3 @@ ngt_rint_poll(struct tty *tp)
return (1);
}
-static void
-ngt_close(struct tty *tp)
-{
- sc_p sc = ttyhook_softc(tp);
-
- /* Must be queued to drop the tty lock */
- ng_rmnode_flags(sc->node, NG_QUEUE);
-}
-
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index 91b1658..fcdc9ce 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -707,8 +707,10 @@ do { \
} \
} while (/*CONSTCOND*/ 0)
+#ifdef VIMAGE_GLOBALS
extern int icmp6_rediraccept; /* accept/process redirects */
extern int icmp6_redirtimeout; /* cache time for redirect routes */
+#endif
#define ICMP6_NODEINFO_FQDNOK 0x1
#define ICMP6_NODEINFO_NODEADDROK 0x2
diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h
index dda84f2..cd9ee00 100644
--- a/sys/netinet/icmp_var.h
+++ b/sys/netinet/icmp_var.h
@@ -74,7 +74,9 @@ struct icmpstat {
#ifdef _KERNEL
SYSCTL_DECL(_net_inet_icmp);
+#ifdef VIMAGE_GLOBALS
extern struct icmpstat icmpstat; /* icmp statistics */
+#endif
extern int badport_bandlim(int);
#define BANDLIM_UNLIMITED -1
#define BANDLIM_ICMP_UNREACH 0
diff --git a/sys/netinet/if_atm.c b/sys/netinet/if_atm.c
index 065f0c4..d534a18 100644
--- a/sys/netinet/if_atm.c
+++ b/sys/netinet/if_atm.c
@@ -127,10 +127,6 @@ atm_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
break;
}
- if ((rt->rt_flags & RTF_CLONING) != 0) {
- printf("atm_rtrequest: cloning route detected?\n");
- break;
- }
if (gate->sa_family != AF_LINK ||
gate->sa_len < sizeof(null_sdl)) {
log(LOG_DEBUG, "atm_rtrequest: bad gateway value");
@@ -332,8 +328,6 @@ atmresolve(struct rtentry *rt, struct mbuf *m, struct sockaddr *dst,
goto bad; /* failed */
RT_REMREF(rt); /* don't keep LL references */
if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
- (rt->rt_flags & RTF_LLINFO) == 0 ||
- /* XXX: are we using LLINFO? */
rt->rt_gateway->sa_family != AF_LINK) {
RT_UNLOCK(rt);
goto bad;
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index da7946d..1b03fb3 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <net/if_llatbl.h>
#include <netinet/if_ether.h>
#include <netinet/vinet.h>
@@ -79,6 +80,7 @@ __FBSDID("$FreeBSD$");
#define SIN(s) ((struct sockaddr_in *)s)
#define SDL(s) ((struct sockaddr_dl *)s)
+#define LLTABLE(ifp) ((struct lltable *)(ifp)->if_afdata[AF_INET])
SYSCTL_DECL(_net_link_ether);
SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
@@ -87,23 +89,13 @@ SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, "");
#ifdef VIMAGE_GLOBALS
static int arpt_keep; /* once resolved, good for 20 more minutes */
static int arp_maxtries;
-static int useloopback; /* use loopback interface for local traffic */
+int useloopback; /* use loopback interface for local traffic */
static int arp_proxyall;
#endif
SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, max_age,
CTLFLAG_RW, arpt_keep, 0, "ARP entry lifetime in seconds");
-#define rt_expire rt_rmx.rmx_expire
-
-struct llinfo_arp {
- struct callout la_timer;
- struct rtentry *la_rt;
- struct mbuf *la_hold; /* last packet until resolved/timeout */
- u_short la_preempt; /* countdown for pre-expiry arps */
- u_short la_asked; /* # requests sent */
-};
-
static struct ifqueue arpintrq;
SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, maxtries,
@@ -117,196 +109,65 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, proxyall,
"Enable proxy ARP for all suitable requests");
static void arp_init(void);
-static void arp_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
-static void arprequest(struct ifnet *,
+void arprequest(struct ifnet *,
struct in_addr *, struct in_addr *, u_char *);
static void arpintr(struct mbuf *);
static void arptimer(void *);
-static struct rtentry
- *arplookup(u_long, int, int, int);
#ifdef INET
static void in_arpinput(struct mbuf *);
#endif
+#ifdef AF_INET
+void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
+
/*
- * Timeout routine.
+ * called by in_ifscrub to remove entry from the table when
+ * the interface goes away
*/
-static void
-arptimer(void *arg)
+void
+arp_ifscrub(struct ifnet *ifp, uint32_t addr)
{
- struct rtentry *rt = (struct rtentry *)arg;
-
- RT_LOCK_ASSERT(rt);
- /*
- * The lock is needed to close a theoretical race
- * between spontaneous expiry and intentional removal.
- * We still got an extra reference on rtentry, so can
- * safely pass pointers to its contents.
- */
- RT_UNLOCK(rt);
-
- in_rtrequest(RTM_DELETE, rt_key(rt), NULL, rt_mask(rt), 0, NULL,
- rt->rt_fibnum);
+ struct sockaddr_in addr4;
+
+ bzero((void *)&addr4, sizeof(addr4));
+ addr4.sin_len = sizeof(addr4);
+ addr4.sin_family = AF_INET;
+ addr4.sin_addr.s_addr = addr;
+ IF_AFDATA_LOCK(ifp);
+ lla_lookup(LLTABLE(ifp), (LLE_DELETE | LLE_IFADDR),
+ (struct sockaddr *)&addr4);
+ IF_AFDATA_UNLOCK(ifp);
}
+#endif
/*
- * Parallel to llc_rtrequest.
+ * Timeout routine. Age arp_tab entries periodically.
*/
static void
-arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
+arptimer(void *arg)
{
- INIT_VNET_NET(curvnet);
- INIT_VNET_INET(curvnet);
- struct sockaddr *gate;
- struct llinfo_arp *la;
- static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
- struct in_ifaddr *ia;
- struct ifaddr *ifa;
+ struct ifnet *ifp;
+ struct llentry *lle = (struct llentry *)arg;
- RT_LOCK_ASSERT(rt);
-
- if (rt->rt_flags & RTF_GATEWAY)
+ if (lle == NULL) {
+ panic("%s: NULL entry!\n", __func__);
return;
- gate = rt->rt_gateway;
- la = (struct llinfo_arp *)rt->rt_llinfo;
- switch (req) {
-
- case RTM_ADD:
- /*
- * XXX: If this is a manually added route to interface
- * such as older version of routed or gated might provide,
- * restore cloning bit.
- */
- if ((rt->rt_flags & RTF_HOST) == 0 &&
- rt_mask(rt) != NULL &&
- SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
- rt->rt_flags |= RTF_CLONING;
- if (rt->rt_flags & RTF_CLONING) {
- /*
- * Case 1: This route should come from a route to iface.
- */
- rt_setgate(rt, rt_key(rt),
- (struct sockaddr *)&null_sdl);
- gate = rt->rt_gateway;
- SDL(gate)->sdl_type = rt->rt_ifp->if_type;
- SDL(gate)->sdl_index = rt->rt_ifp->if_index;
- rt->rt_expire = time_uptime;
- break;
- }
- /* Announce a new entry if requested. */
- if (rt->rt_flags & RTF_ANNOUNCE)
- arprequest(rt->rt_ifp,
- &SIN(rt_key(rt))->sin_addr,
- &SIN(rt_key(rt))->sin_addr,
- (u_char *)LLADDR(SDL(gate)));
- /*FALLTHROUGH*/
- case RTM_RESOLVE:
- if (gate->sa_family != AF_LINK ||
- gate->sa_len < sizeof(null_sdl)) {
- log(LOG_DEBUG, "%s: bad gateway %s%s\n", __func__,
- inet_ntoa(SIN(rt_key(rt))->sin_addr),
- (gate->sa_family != AF_LINK) ?
- " (!AF_LINK)": "");
- break;
- }
- SDL(gate)->sdl_type = rt->rt_ifp->if_type;
- SDL(gate)->sdl_index = rt->rt_ifp->if_index;
- if (la != 0)
- break; /* This happens on a route change */
- /*
- * Case 2: This route may come from cloning, or a manual route
- * add with a LL address.
- */
- R_Zalloc(la, struct llinfo_arp *, sizeof(*la));
- rt->rt_llinfo = (caddr_t)la;
- if (la == 0) {
- log(LOG_DEBUG, "%s: malloc failed\n", __func__);
- break;
- }
- /*
- * We are storing a route entry outside of radix tree. So,
- * it can be found and accessed by other means than radix
- * lookup. The routing code assumes that any rtentry detached
- * from radix can be destroyed safely. To prevent this, we
- * add an additional reference.
- */
- RT_ADDREF(rt);
- la->la_rt = rt;
- rt->rt_flags |= RTF_LLINFO;
- callout_init_mtx(&la->la_timer, &rt->rt_mtx,
- CALLOUT_RETURNUNLOCKED);
-
-#ifdef INET
+ }
+ ifp = lle->lle_tbl->llt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ LLE_WLOCK(lle);
+ if ((lle->la_flags & LLE_DELETED) ||
+ (time_second >= lle->la_expire)) {
+ if (!callout_pending(&lle->la_timer) &&
+ callout_active(&lle->la_timer))
+ (void) llentry_free(lle);
+ } else {
/*
- * This keeps the multicast addresses from showing up
- * in `arp -a' listings as unresolved. It's not actually
- * functional. Then the same for broadcast.
+ * Still valid, just drop our reference
*/
- if (IN_MULTICAST(ntohl(SIN(rt_key(rt))->sin_addr.s_addr)) &&
- rt->rt_ifp->if_type != IFT_ARCNET) {
- ETHER_MAP_IP_MULTICAST(&SIN(rt_key(rt))->sin_addr,
- LLADDR(SDL(gate)));
- SDL(gate)->sdl_alen = 6;
- rt->rt_expire = 0;
- }
- if (in_broadcast(SIN(rt_key(rt))->sin_addr, rt->rt_ifp)) {
- memcpy(LLADDR(SDL(gate)), rt->rt_ifp->if_broadcastaddr,
- rt->rt_ifp->if_addrlen);
- SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen;
- rt->rt_expire = 0;
- }
-#endif
-
- TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
- if (ia->ia_ifp == rt->rt_ifp &&
- SIN(rt_key(rt))->sin_addr.s_addr ==
- (IA_SIN(ia))->sin_addr.s_addr)
- break;
- }
- if (ia) {
- /*
- * This test used to be
- * if (loif.if_flags & IFF_UP)
- * It allowed local traffic to be forced
- * through the hardware by configuring the loopback down.
- * However, it causes problems during network configuration
- * for boards that can't receive packets they send.
- * It is now necessary to clear "useloopback" and remove
- * the route to force traffic out to the hardware.
- */
- rt->rt_expire = 0;
- bcopy(IF_LLADDR(rt->rt_ifp), LLADDR(SDL(gate)),
- SDL(gate)->sdl_alen = rt->rt_ifp->if_addrlen);
- if (V_useloopback) {
- rt->rt_ifp = V_loif;
- rt->rt_rmx.rmx_mtu = V_loif->if_mtu;
- }
-
- /*
- * make sure to set rt->rt_ifa to the interface
- * address we are using, otherwise we will have trouble
- * with source address selection.
- */
- ifa = &ia->ia_ifa;
- if (ifa != rt->rt_ifa) {
- IFAFREE(rt->rt_ifa);
- IFAREF(ifa);
- rt->rt_ifa = ifa;
- }
- }
- break;
-
- case RTM_DELETE:
- if (la == NULL) /* XXX: at least CARP does this. */
- break;
- callout_stop(&la->la_timer);
- rt->rt_llinfo = NULL;
- rt->rt_flags &= ~RTF_LLINFO;
- RT_REMREF(rt);
- if (la->la_hold)
- m_freem(la->la_hold);
- Free((caddr_t)la);
+ LLE_FREE_LOCKED(lle);
}
+ IF_AFDATA_UNLOCK(ifp);
}
/*
@@ -315,14 +176,37 @@ arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
* - arp header target ip address
* - arp header source ethernet address
*/
-static void
-arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
+void
+arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
u_char *enaddr)
{
struct mbuf *m;
struct arphdr *ah;
struct sockaddr sa;
+ if (sip == NULL) {
+ /* XXX don't believe this can happen (or explain why) */
+ /*
+ * The caller did not supply a source address, try to find
+ * a compatible one among those assigned to this interface.
+ */
+ struct ifaddr *ifa;
+
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (!ifa->ifa_addr ||
+ ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+ sip = &SIN(ifa->ifa_addr)->sin_addr;
+ if (0 == ((sip->s_addr ^ tip->s_addr) &
+ SIN(ifa->ifa_netmask)->sin_addr.s_addr) )
+ break; /* found it. */
+ }
+ if (sip == NULL) {
+ printf("%s: cannot find matching address\n", __func__);
+ return;
+ }
+ }
+
if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL)
return;
m->m_len = sizeof(*ah) + 2*sizeof(struct in_addr) +
@@ -345,8 +229,6 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
sa.sa_len = 2;
m->m_flags |= M_BCAST;
(*ifp->if_output)(ifp, m, &sa, (struct rtentry *)0);
-
- return;
}
/*
@@ -365,16 +247,15 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip,
*/
int
arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
- struct sockaddr *dst, u_char *desten)
+ struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
INIT_VNET_INET(ifp->if_vnet);
- struct llinfo_arp *la = NULL;
- struct rtentry *rt = NULL;
- struct sockaddr_dl *sdl;
- int error;
- int fibnum = -1;
+ struct llentry *la = 0;
+ u_int flags = 0;
+ int error, renew;
- if (m) {
+ *lle = NULL;
+ if (m != NULL) {
if (m->m_flags & M_BCAST) {
/* broadcast */
(void)memcpy(desten,
@@ -386,110 +267,79 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten);
return (0);
}
- fibnum = M_GETFIB(m);
}
-
- if (rt0 != NULL) {
- /* Look for a cached arp (ll) entry. */
- if (m == NULL)
- fibnum = rt0->rt_fibnum;
- error = rt_check(&rt, &rt0, dst);
- if (error) {
- m_freem(m);
- return error;
- }
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL)
- RT_UNLOCK(rt);
- }
-
- /*
- * If we had no mbuf and no route, then hope the caller
- * has a fib in mind because we are running out of ideas.
- * I think this should not happen in current code.
- * (kmacy would know).
+ /* XXXXX
*/
- if (fibnum == -1)
- fibnum = curthread->td_proc->p_fibnum; /* last gasp */
-
+retry:
+ IF_AFDATA_RLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, dst);
+ IF_AFDATA_RUNLOCK(ifp);
+ if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0)
+ && ((ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) == 0)) {
+ flags |= (LLE_CREATE | LLE_EXCLUSIVE);
+ IF_AFDATA_WLOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, dst);
+ IF_AFDATA_WUNLOCK(ifp);
+ }
if (la == NULL) {
- /*
- * We enter this block if rt0 was NULL,
- * or if rt found by rt_check() didn't have llinfo.
- * we should get a cloned route, which since it should
- * come from the local interface should have a ll entry.
- * It may be incomplete but that's ok.
- */
- rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0, fibnum);
- if (rt == NULL) {
- log(LOG_DEBUG,
- "arpresolve: can't allocate route for %s\n",
- inet_ntoa(SIN(dst)->sin_addr));
- m_freem(m);
- return (EINVAL); /* XXX */
- }
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL) {
- RT_UNLOCK(rt);
+ if (flags & LLE_CREATE)
log(LOG_DEBUG,
"arpresolve: can't allocate llinfo for %s\n",
inet_ntoa(SIN(dst)->sin_addr));
- m_freem(m);
- return (EINVAL); /* XXX */
- }
- }
- sdl = SDL(rt->rt_gateway);
- /*
- * Check the address family and length is valid, the address
- * is resolved; otherwise, try to resolve.
- */
- if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) &&
- sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
-
- bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
+ m_freem(m);
+ return (EINVAL);
+ }
+ if ((la->la_flags & LLE_VALID) &&
+ ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) {
+ bcopy(&la->ll_addr, desten, ifp->if_addrlen);
/*
* If entry has an expiry time and it is approaching,
- * send an ARP request.
+ * see if we need to send an ARP request within this
+ * arpt_down interval.
*/
- if ((rt->rt_expire != 0) &&
- (time_uptime + la->la_preempt > rt->rt_expire)) {
- struct in_addr sin =
- SIN(rt->rt_ifa->ifa_addr)->sin_addr;
+ if (!(la->la_flags & LLE_STATIC) &&
+ time_uptime + la->la_preempt > la->la_expire) {
+ arprequest(ifp, NULL,
+ &SIN(dst)->sin_addr, IF_LLADDR(ifp));
la->la_preempt--;
- RT_UNLOCK(rt);
- arprequest(ifp, &sin, &SIN(dst)->sin_addr,
- IF_LLADDR(ifp));
- return (0);
- }
-
- RT_UNLOCK(rt);
- return (0);
- }
- /*
- * If ARP is disabled or static on this interface, stop.
- * XXX
- * Probably should not allocate empty llinfo struct if we are
- * not going to be sending out an arp request.
- */
- if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) {
- RT_UNLOCK(rt);
+ }
+
+ *lle = la;
+ error = 0;
+ goto done;
+ }
+
+ if (la->la_flags & LLE_STATIC) { /* should not happen! */
+ log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n",
+ inet_ntoa(SIN(dst)->sin_addr));
m_freem(m);
- return (EINVAL);
+ error = EINVAL;
+ goto done;
+ }
+
+ renew = (la->la_asked == 0 || la->la_expire != time_uptime);
+ if ((renew || m != NULL) && (flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ LLE_RUNLOCK(la);
+ goto retry;
}
/*
* There is an arptab entry, but no ethernet address
* response yet. Replace the held mbuf with this
* latest one.
*/
- if (m) {
- if (la->la_hold)
+ if (m != NULL) {
+ if (la->la_hold != NULL)
m_freem(la->la_hold);
la->la_hold = m;
+ if (renew == 0 && (flags & LLE_EXCLUSIVE)) {
+ flags &= ~LLE_EXCLUSIVE;
+ LLE_DOWNGRADE(la);
+ }
+
}
- KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry"));
-
/*
* Return EWOULDBLOCK if we have tried less than arp_maxtries. It
* will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH
@@ -499,22 +349,24 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
if (la->la_asked < V_arp_maxtries)
error = EWOULDBLOCK; /* First request. */
else
- error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH;
-
- if (la->la_asked == 0 || rt->rt_expire != time_uptime) {
- struct in_addr sin =
- SIN(rt->rt_ifa->ifa_addr)->sin_addr;
+ error =
+ (rt0->rt_flags & RTF_GATEWAY) ? EHOSTDOWN : EHOSTUNREACH;
- rt->rt_expire = time_uptime;
- callout_reset(&la->la_timer, hz, arptimer, rt);
+ if (renew) {
+ LLE_ADDREF(la);
+ la->la_expire = time_uptime;
+ callout_reset(&la->la_timer, hz, arptimer, la);
la->la_asked++;
- RT_UNLOCK(rt);
-
- arprequest(ifp, &sin, &SIN(dst)->sin_addr,
+ LLE_WUNLOCK(la);
+ arprequest(ifp, NULL, &SIN(dst)->sin_addr,
IF_LLADDR(ifp));
- } else
- RT_UNLOCK(rt);
-
+ return (error);
+ }
+done:
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(la);
+ else
+ LLE_RUNLOCK(la);
return (error);
}
@@ -598,21 +450,17 @@ in_arpinput(struct mbuf *m)
{
struct arphdr *ah;
struct ifnet *ifp = m->m_pkthdr.rcvif;
- struct llinfo_arp *la;
+ struct llentry *la = NULL;
struct rtentry *rt;
struct ifaddr *ifa;
struct in_ifaddr *ia;
- struct sockaddr_dl *sdl;
struct sockaddr sa;
struct in_addr isaddr, itaddr, myaddr;
- struct mbuf *hold;
u_int8_t *enaddr = NULL;
- int op, rif_len;
+ int op, flags;
+ struct mbuf *m0;
int req_len;
int bridged = 0, is_bridge = 0;
- u_int fibnum;
- u_int goodfib = 0;
- int firstpass = 1;
#ifdef DEV_CARP
int carp_match = 0;
#endif
@@ -649,7 +497,7 @@ in_arpinput(struct mbuf *m)
*/
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
- (ia->ia_ifp == ifp)) &&
+ ia->ia_ifp == ifp) &&
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
goto match;
#ifdef DEV_CARP
@@ -663,7 +511,7 @@ in_arpinput(struct mbuf *m)
}
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash)
if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
- (ia->ia_ifp == ifp)) &&
+ ia->ia_ifp == ifp) &&
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr)
goto match;
@@ -729,254 +577,151 @@ match:
}
if (ifp->if_flags & IFF_STATICARP)
goto reply;
- /*
- * We look for any FIB that has this address to find
- * the interface etc.
- * For sanity checks that are FIB independent we abort the loop.
- */
- for (fibnum = 0; fibnum < rt_numfibs; fibnum++) {
- rt = arplookup(isaddr.s_addr,
- itaddr.s_addr == myaddr.s_addr, 0, fibnum);
- if (rt == NULL)
- continue;
-
- sdl = SDL(rt->rt_gateway);
- /* Only call this once */
- if (firstpass) {
- sin.sin_addr.s_addr = isaddr.s_addr;
- EVENTHANDLER_INVOKE(route_arp_update_event, rt,
- ar_sha(ah), (struct sockaddr *)&sin);
- }
-
- la = (struct llinfo_arp *)rt->rt_llinfo;
- if (la == NULL) {
- RT_UNLOCK(rt);
- continue;
- }
- if (firstpass) {
- /* The following is not an error when doing bridging. */
- if (!bridged && rt->rt_ifp != ifp
+ bzero(&sin, sizeof(sin));
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr = isaddr;
+ flags = (itaddr.s_addr == myaddr.s_addr) ? LLE_CREATE : 0;
+ flags |= LLE_EXCLUSIVE;
+ IF_AFDATA_LOCK(ifp);
+ la = lla_lookup(LLTABLE(ifp), flags, (struct sockaddr *)&sin);
+ IF_AFDATA_UNLOCK(ifp);
+ if (la != NULL) {
+ /* the following is not an error when doing bridging */
+ if (!bridged && la->lle_tbl->llt_ifp != ifp
#ifdef DEV_CARP
- && (ifp->if_type != IFT_CARP || !carp_match)
+ && (ifp->if_type != IFT_CARP || !carp_match)
#endif
- ) {
- if (log_arp_wrong_iface)
- log(LOG_ERR, "arp: %s is on %s "
- "but got reply from %*D "
- "on %s\n",
- inet_ntoa(isaddr),
- rt->rt_ifp->if_xname,
- ifp->if_addrlen,
- (u_char *)ar_sha(ah), ":",
- ifp->if_xname);
- RT_UNLOCK(rt);
- break;
- }
- if (sdl->sdl_alen &&
- bcmp(ar_sha(ah), LLADDR(sdl), sdl->sdl_alen)) {
- if (rt->rt_expire) {
- if (log_arp_movements)
- log(LOG_INFO,
- "arp: %s moved from %*D to %*D "
- "on %s\n",
- inet_ntoa(isaddr),
- ifp->if_addrlen,
- (u_char *)LLADDR(sdl), ":",
- ifp->if_addrlen,
- (u_char *)ar_sha(ah), ":",
- ifp->if_xname);
- } else {
- RT_UNLOCK(rt);
- if (log_arp_permanent_modify)
- log(LOG_ERR,
- "arp: %*D attempts to "
- "modify permanent entry "
- "for %s on %s\n",
- ifp->if_addrlen,
- (u_char *)ar_sha(ah), ":",
- inet_ntoa(isaddr),
- ifp->if_xname);
- break;
- }
- }
- /*
- * sanity check for the address length.
- * XXX this does not work for protocols
- * with variable address length. -is
- */
- if (sdl->sdl_alen &&
- sdl->sdl_alen != ah->ar_hln) {
- log(LOG_WARNING,
- "arp from %*D: new addr len %d, was %d",
- ifp->if_addrlen, (u_char *) ar_sha(ah),
- ":", ah->ar_hln, sdl->sdl_alen);
+ ) {
+ if (log_arp_wrong_iface)
+ log(LOG_ERR, "arp: %s is on %s "
+ "but got reply from %*D on %s\n",
+ inet_ntoa(isaddr),
+ la->lle_tbl->llt_ifp->if_xname,
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ ifp->if_xname);
+ goto reply;
+ }
+ if ((la->la_flags & LLE_VALID) &&
+ bcmp(ar_sha(ah), &la->ll_addr, ifp->if_addrlen)) {
+ if (la->la_flags & LLE_STATIC) {
+ log(LOG_ERR,
+ "arp: %*D attempts to modify permanent "
+ "entry for %s on %s\n",
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ inet_ntoa(isaddr), ifp->if_xname);
+ goto reply;
}
- if (ifp->if_addrlen != ah->ar_hln) {
- log(LOG_WARNING,
- "arp from %*D: addr len: "
- "new %d, i/f %d (ignored)",
- ifp->if_addrlen, (u_char *) ar_sha(ah),
- ":", ah->ar_hln, ifp->if_addrlen);
- RT_UNLOCK(rt);
- break;
+ if (log_arp_movements) {
+ log(LOG_INFO, "arp: %s moved from %*D "
+ "to %*D on %s\n",
+ inet_ntoa(isaddr),
+ ifp->if_addrlen,
+ (u_char *)&la->ll_addr, ":",
+ ifp->if_addrlen, (u_char *)ar_sha(ah), ":",
+ ifp->if_xname);
}
- firstpass = 0;
- goodfib = fibnum;
}
-
- /* Copy in the information received. */
- (void)memcpy(LLADDR(sdl), ar_sha(ah),
- sdl->sdl_alen = ah->ar_hln);
- /*
- * If we receive an arp from a token-ring station over
- * a token-ring nic then try to save the source routing info.
- * XXXMRT Only minimal Token Ring support for MRT.
- * Only do this on the first pass as if modifies the mbuf.
- */
- if (ifp->if_type == IFT_ISO88025) {
- struct iso88025_header *th = NULL;
- struct iso88025_sockaddr_dl_data *trld;
-
- /* force the fib loop to end after this pass */
- fibnum = rt_numfibs - 1;
-
- th = (struct iso88025_header *)m->m_pkthdr.header;
- trld = SDL_ISO88025(sdl);
- rif_len = TR_RCF_RIFLEN(th->rcf);
- if ((th->iso88025_shost[0] & TR_RII) &&
- (rif_len > 2)) {
- trld->trld_rcf = th->rcf;
- trld->trld_rcf ^= htons(TR_RCF_DIR);
- memcpy(trld->trld_route, th->rd, rif_len - 2);
- trld->trld_rcf &= ~htons(TR_RCF_BCST_MASK);
- /*
- * Set up source routing information for
- * reply packet (XXX)
- */
- m->m_data -= rif_len;
- m->m_len += rif_len;
- m->m_pkthdr.len += rif_len;
- } else {
- th->iso88025_shost[0] &= ~TR_RII;
- trld->trld_rcf = 0;
- }
- m->m_data -= 8;
- m->m_len += 8;
- m->m_pkthdr.len += 8;
- th->rcf = trld->trld_rcf;
+
+ if (ifp->if_addrlen != ah->ar_hln) {
+ log(LOG_WARNING,
+ "arp from %*D: addr len: new %d, i/f %d (ignored)",
+ ifp->if_addrlen, (u_char *) ar_sha(ah), ":",
+ ah->ar_hln, ifp->if_addrlen);
+ goto reply;
}
+ (void)memcpy(&la->ll_addr, ar_sha(ah), ifp->if_addrlen);
+ la->la_flags |= LLE_VALID;
- if (rt->rt_expire) {
- rt->rt_expire = time_uptime + V_arpt_keep;
+ if (!(la->la_flags & LLE_STATIC)) {
+ la->la_expire = time_uptime + V_arpt_keep;
callout_reset(&la->la_timer, hz * V_arpt_keep,
- arptimer, rt);
+ arptimer, la);
}
la->la_asked = 0;
la->la_preempt = V_arp_maxtries;
- hold = la->la_hold;
- la->la_hold = NULL;
- RT_UNLOCK(rt);
- if (hold != NULL)
- (*ifp->if_output)(ifp, hold, rt_key(rt), rt);
- } /* end of FIB loop */
+ if (la->la_hold != NULL) {
+ m0 = la->la_hold;
+ la->la_hold = 0;
+ memcpy(&sa, L3_ADDR(la), sizeof(sa));
+ LLE_WUNLOCK(la);
+
+ (*ifp->if_output)(ifp, m0, &sa, NULL);
+ return;
+ }
+ }
reply:
-
- /*
- * Decide if we have to respond to something.
- */
if (op != ARPOP_REQUEST)
goto drop;
+
if (itaddr.s_addr == myaddr.s_addr) {
/* Shortcut.. the receiving interface is the target. */
(void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
(void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
} else {
- /* It's not asking for our address. But it still may
- * be something we should answer.
- *
- * XXX MRT
- * We assume that link level info is independent of
- * the table used and so we use whichever we can and don't
- * have a better option.
+ struct llentry *lle = NULL;
+
+ if (!V_arp_proxyall)
+ goto drop;
+
+ sin.sin_addr = itaddr;
+ /* XXX MRT use table 0 for arp reply */
+ rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
+ if (!rt)
+ goto drop;
+
+ /*
+ * Don't send proxies for nodes on the same interface
+ * as this one came out of, or we'll get into a fight
+ * over who claims what Ether address.
*/
- /* Have we been asked to proxy for the target. */
- rt = arplookup(itaddr.s_addr, 0, SIN_PROXY, goodfib);
- if (rt == NULL) {
- /* Nope, only intersted now if proxying everything. */
- struct sockaddr_in sin;
-
- if (!V_arp_proxyall)
- goto drop;
-
- bzero(&sin, sizeof sin);
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof sin;
- sin.sin_addr = itaddr;
-
- /* XXX MRT use table 0 for arp reply */
- rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
- if (!rt)
- goto drop;
- /*
- * Don't send proxies for nodes on the same interface
- * as this one came out of, or we'll get into a fight
- * over who claims what Ether address.
- */
- if (rt->rt_ifp == ifp) {
- RTFREE_LOCKED(rt);
- goto drop;
- }
- (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
- (void)memcpy(ar_sha(ah), enaddr, ah->ar_hln);
+ if (!rt->rt_ifp || rt->rt_ifp == ifp) {
RTFREE_LOCKED(rt);
+ goto drop;
+ }
+ IF_AFDATA_LOCK(rt->rt_ifp);
+ lle = lla_lookup(LLTABLE(rt->rt_ifp), 0, (struct sockaddr *)&sin);
+ IF_AFDATA_UNLOCK(rt->rt_ifp);
+ RTFREE_LOCKED(rt);
- /*
- * Also check that the node which sent the ARP packet
- * is on the the interface we expect it to be on. This
- * avoids ARP chaos if an interface is connected to the
- * wrong network.
- */
- sin.sin_addr = isaddr;
-
- /* XXX MRT use table 0 for arp checks */
- rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
- if (!rt)
- goto drop;
- if (rt->rt_ifp != ifp) {
- log(LOG_INFO, "arp_proxy: ignoring request"
- " from %s via %s, expecting %s\n",
- inet_ntoa(isaddr), ifp->if_xname,
- rt->rt_ifp->if_xname);
- RTFREE_LOCKED(rt);
- goto drop;
- }
+ if (lle != NULL) {
+ (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
+ (void)memcpy(ar_sha(ah), &lle->ll_addr, ah->ar_hln);
+ LLE_RUNLOCK(lle);
+ } else
+ goto drop;
+
+ /*
+ * Also check that the node which sent the ARP packet
+ * is on the the interface we expect it to be on. This
+ * avoids ARP chaos if an interface is connected to the
+ * wrong network.
+ */
+ sin.sin_addr = isaddr;
+
+ /* XXX MRT use table 0 for arp checks */
+ rt = in_rtalloc1((struct sockaddr *)&sin, 0, 0UL, 0);
+ if (!rt)
+ goto drop;
+ if (rt->rt_ifp != ifp) {
+ log(LOG_INFO, "arp_proxy: ignoring request"
+ " from %s via %s, expecting %s\n",
+ inet_ntoa(isaddr), ifp->if_xname,
+ rt->rt_ifp->if_xname);
RTFREE_LOCKED(rt);
+ goto drop;
+ }
+ RTFREE_LOCKED(rt);
#ifdef DEBUG_PROXY
- printf("arp: proxying for %s\n",
- inet_ntoa(itaddr));
+ printf("arp: proxying for %s\n",
+ inet_ntoa(itaddr));
#endif
- } else {
- /*
- * Return proxied ARP replies only on the interface
- * or bridge cluster where this network resides.
- * Otherwise we may conflict with the host we are
- * proxying for.
- */
- if (rt->rt_ifp != ifp &&
- (rt->rt_ifp->if_bridge != ifp->if_bridge ||
- ifp->if_bridge == NULL)) {
- RT_UNLOCK(rt);
- goto drop;
- }
- sdl = SDL(rt->rt_gateway);
- (void)memcpy(ar_tha(ah), ar_sha(ah), ah->ar_hln);
- (void)memcpy(ar_sha(ah), LLADDR(sdl), ah->ar_hln);
- RT_UNLOCK(rt);
- }
}
+ if (la != NULL)
+ LLE_WUNLOCK(la);
if (itaddr.s_addr == myaddr.s_addr &&
IN_LINKLOCAL(ntohl(itaddr.s_addr))) {
/* RFC 3927 link-local IPv4; always reply by broadcast. */
@@ -1002,68 +747,35 @@ reply:
return;
drop:
+ if (la != NULL)
+ LLE_WUNLOCK(la);
m_freem(m);
}
#endif
-/*
- * Lookup or enter a new address in arptab.
- */
-static struct rtentry *
-arplookup(u_long addr, int create, int proxy, int fibnum)
-{
- struct rtentry *rt;
- struct sockaddr_inarp sin;
- const char *why = 0;
-
- bzero(&sin, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = addr;
- if (proxy)
- sin.sin_other = SIN_PROXY;
- rt = in_rtalloc1((struct sockaddr *)&sin, create, 0UL, fibnum);
- if (rt == 0)
- return (0);
-
- if (rt->rt_flags & RTF_GATEWAY)
- why = "host is not on local network";
- else if ((rt->rt_flags & RTF_LLINFO) == 0)
- why = "could not allocate llinfo";
- else if (rt->rt_gateway->sa_family != AF_LINK)
- why = "gateway route is not ours";
-
- if (why) {
-#define ISDYNCLONE(_rt) \
- (((_rt)->rt_flags & (RTF_STATIC | RTF_WASCLONED)) == RTF_WASCLONED)
- if (create)
- log(LOG_DEBUG, "arplookup %s failed: %s\n",
- inet_ntoa(sin.sin_addr), why);
- /*
- * If there are no references to this Layer 2 route,
- * and it is a cloned route, and not static, and
- * arplookup() is creating the route, then purge
- * it from the routing table as it is probably bogus.
- */
- if (rt->rt_refcnt == 1 && ISDYNCLONE(rt))
- rtexpunge(rt);
- RTFREE_LOCKED(rt);
- return (0);
-#undef ISDYNCLONE
- } else {
- RT_REMREF(rt);
- return (rt);
- }
-}
-
void
arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa)
{
+ struct llentry *lle;
+
if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
arprequest(ifp, &IA_SIN(ifa)->sin_addr,
&IA_SIN(ifa)->sin_addr, IF_LLADDR(ifp));
- ifa->ifa_rtrequest = arp_rtrequest;
- ifa->ifa_flags |= RTF_CLONING;
+ /*
+ * interface address is considered static entry
+ * because the output of the arp utility shows
+ * that L2 entry as permanent
+ */
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(LLTABLE(ifp), (LLE_CREATE | LLE_IFADDR | LLE_STATIC),
+ (struct sockaddr *)IA_SIN(ifa));
+ IF_AFDATA_UNLOCK(ifp);
+ if (lle == NULL)
+ log(LOG_INFO, "arp_ifinit: cannot create arp "
+ "entry for interface address\n");
+ else
+ LLE_RUNLOCK(lle);
+ ifa->ifa_rtrequest = NULL;
}
void
@@ -1072,8 +784,7 @@ arp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr)
if (ntohl(IA_SIN(ifa)->sin_addr.s_addr) != INADDR_ANY)
arprequest(ifp, &IA_SIN(ifa)->sin_addr,
&IA_SIN(ifa)->sin_addr, enaddr);
- ifa->ifa_rtrequest = arp_rtrequest;
- ifa->ifa_flags |= RTF_CLONING;
+ ifa->ifa_rtrequest = NULL;
}
static void
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index 14df15f..ba4e2f6 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -109,8 +109,11 @@ struct sockaddr_inarp {
extern u_char ether_ipmulticast_min[ETHER_ADDR_LEN];
extern u_char ether_ipmulticast_max[ETHER_ADDR_LEN];
+struct llentry;
+
int arpresolve(struct ifnet *ifp, struct rtentry *rt,
- struct mbuf *m, struct sockaddr *dst, u_char *desten);
+ struct mbuf *m, struct sockaddr *dst, u_char *desten,
+ struct llentry **lle);
void arp_ifinit(struct ifnet *, struct ifaddr *);
void arp_ifinit2(struct ifnet *, struct ifaddr *, u_char *);
#endif
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 9b6dd48..94535b1 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/vimage.h>
#include <net/if.h>
+#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
@@ -871,6 +872,8 @@ in_addprefix(struct in_ifaddr *target, int flags)
return (error);
}
+extern void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
+
/*
* If there is no other address in the system that can serve a route to the
* same prefix, remove the route. Hand over the route to the new address
@@ -893,6 +896,8 @@ in_scrubprefix(struct in_ifaddr *target)
prefix = target->ia_addr.sin_addr;
mask = target->ia_sockmask.sin_addr;
prefix.s_addr &= mask.s_addr;
+ /* remove arp cache */
+ arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
}
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
@@ -1015,3 +1020,240 @@ in_ifdetach(struct ifnet *ifp)
in_pcbpurgeif0(&V_udbinfo, ifp);
in_purgemaddrs(ifp);
}
+
+#include <sys/syslog.h>
+#include <net/if_dl.h>
+#include <netinet/if_ether.h>
+
+struct in_llentry {
+ struct llentry base;
+ struct sockaddr_in l3_addr4;
+};
+
+static struct llentry *
+in_lltable_new(const struct sockaddr *l3addr, u_int flags)
+{
+ struct in_llentry *lle;
+
+ lle = malloc(sizeof(struct in_llentry), M_LLTABLE, M_DONTWAIT | M_ZERO);
+ if (lle == NULL) /* NB: caller generates msg */
+ return NULL;
+
+ callout_init(&lle->base.la_timer, CALLOUT_MPSAFE);
+ /*
+ * For IPv4 this will trigger "arpresolve" to generate
+ * an ARP request.
+ */
+ lle->base.la_expire = time_second; /* mark expired */
+ lle->l3_addr4 = *(const struct sockaddr_in *)l3addr;
+ lle->base.lle_refcnt = 1;
+ LLE_LOCK_INIT(&lle->base);
+ return &lle->base;
+}
+
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+static void
+in_lltable_free(struct lltable *llt, struct llentry *lle)
+{
+ LLE_WUNLOCK(lle);
+ LLE_LOCK_DESTROY(lle);
+ free(lle, M_LLTABLE);
+}
+
+static int
+in_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
+{
+ struct rtentry *rt;
+
+ KASSERT(l3addr->sa_family == AF_INET,
+ ("sin_family %d", l3addr->sa_family));
+
+ /* XXX rtalloc1 should take a const param */
+ rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
+ if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
+ log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
+ inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
+ if (rt != NULL)
+ RTFREE_LOCKED(rt);
+ return (EINVAL);
+ }
+ RTFREE_LOCKED(rt);
+ return 0;
+}
+
+/*
+ * Return NULL if not found or marked for deletion.
+ * If found return lle read locked.
+ */
+static struct llentry *
+in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3addr)
+{
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)l3addr;
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ struct llentries *lleh;
+ u_int hashkey;
+
+ IF_AFDATA_LOCK_ASSERT(ifp);
+ KASSERT(l3addr->sa_family == AF_INET,
+ ("sin_family %d", l3addr->sa_family));
+
+ hashkey = sin->sin_addr.s_addr;
+ lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
+ LIST_FOREACH(lle, lleh, lle_next) {
+ if (lle->la_flags & LLE_DELETED)
+ continue;
+ if (bcmp(L3_ADDR(lle), l3addr, sizeof(struct sockaddr_in)) == 0)
+ break;
+ }
+ if (lle == NULL) {
+#ifdef DIAGNOSTICS
+ if (flags & LLE_DELETE)
+ log(LOG_INFO, "interface address is missing from cache = %p in delete\n", lle);
+#endif
+ if (!(flags & LLE_CREATE))
+ return (NULL);
+ /*
+ * A route that covers the given address must have
+ * been installed 1st because we are doing a resolution,
+ * verify this.
+ */
+ if (!(flags & LLE_IFADDR) &&
+ in_lltable_rtcheck(ifp, l3addr) != 0)
+ goto done;
+
+ lle = in_lltable_new(l3addr, flags);
+ if (lle == NULL) {
+ log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
+ goto done;
+ }
+ lle->la_flags = flags & ~LLE_CREATE;
+ if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
+ bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
+ lle->la_flags |= (LLE_VALID | LLE_STATIC);
+ }
+
+ lle->lle_tbl = llt;
+ lle->lle_head = lleh;
+ LIST_INSERT_HEAD(lleh, lle, lle_next);
+ } else if (flags & LLE_DELETE) {
+ if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) {
+ LLE_WLOCK(lle);
+ lle->la_flags = LLE_DELETED;
+ LLE_WUNLOCK(lle);
+#ifdef DIAGNOSTICS
+ log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
+#endif
+ }
+ lle = (void *)-1;
+
+ }
+ if (lle != NULL && lle != (void *)-1) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WLOCK(lle);
+ else
+ LLE_RLOCK(lle);
+ }
+done:
+ return (lle);
+}
+
+static int
+in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
+{
+#define SIN(lle) ((struct sockaddr_in *) L3_ADDR(lle))
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ /* XXX stack use */
+ struct {
+ struct rt_msghdr rtm;
+ struct sockaddr_inarp sin;
+ struct sockaddr_dl sdl;
+ } arpc;
+ int error, i;
+
+ /* XXXXX
+ * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
+ * so it is okay to use this ASSERT, change it when
+ * IFNET lock is finalized
+ */
+ IFNET_WLOCK_ASSERT();
+
+ error = 0;
+ for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
+ struct sockaddr_dl *sdl;
+
+ /* skip deleted entries */
+ if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
+ continue;
+ /*
+ * produce a msg made of:
+ * struct rt_msghdr;
+ * struct sockaddr_inarp; (IPv4)
+ * struct sockaddr_dl;
+ */
+ bzero(&arpc, sizeof(arpc));
+ arpc.rtm.rtm_msglen = sizeof(arpc);
+ arpc.sin.sin_family = AF_INET;
+ arpc.sin.sin_len = sizeof(arpc.sin);
+ arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
+
+ /* publish */
+ if (lle->la_flags & LLE_PUB) {
+ arpc.rtm.rtm_flags |= RTF_ANNOUNCE;
+ /* proxy only */
+ if (lle->la_flags & LLE_PROXY)
+ arpc.sin.sin_other = SIN_PROXY;
+ }
+
+ sdl = &arpc.sdl;
+ sdl->sdl_family = AF_LINK;
+ sdl->sdl_len = sizeof(*sdl);
+ sdl->sdl_alen = ifp->if_addrlen;
+ sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = ifp->if_type;
+ bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+
+ arpc.rtm.rtm_rmx.rmx_expire =
+ lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
+ arpc.rtm.rtm_flags |= RTF_HOST;
+ if (lle->la_flags & LLE_STATIC)
+ arpc.rtm.rtm_flags |= RTF_STATIC;
+ arpc.rtm.rtm_index = ifp->if_index;
+ error = SYSCTL_OUT(wr, &arpc, sizeof(arpc));
+ if (error)
+ break;
+ }
+ }
+ return error;
+#undef SIN
+}
+
+void *
+in_domifattach(struct ifnet *ifp)
+{
+ struct lltable *llt = lltable_init(ifp, AF_INET);
+
+ if (llt != NULL) {
+ llt->llt_new = in_lltable_new;
+ llt->llt_free = in_lltable_free;
+ llt->llt_rtcheck = in_lltable_rtcheck;
+ llt->llt_lookup = in_lltable_lookup;
+ llt->llt_dump = in_lltable_dump;
+ }
+ return (llt);
+}
+
+void
+in_domifdetach(struct ifnet *ifp __unused, void *aux)
+{
+ struct lltable *llt = (struct lltable *)aux;
+
+ lltable_free(llt);
+}
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index e7916dd..6f5dfe1 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -1036,7 +1036,7 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
ro.ro_rt = NULL;
*(struct sockaddr_in *)&ro.ro_dst = gsa->sin;
- in_rtalloc_ign(&ro, RTF_CLONING,
+ in_rtalloc_ign(&ro, 0,
inp->inp_inc.inc_fibnum);
if (ro.ro_rt != NULL) {
ifp = ro.ro_rt->rt_ifp;
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 70f217a..6d1c2aa 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -570,7 +570,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
* Find out route to destination.
*/
if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0)
- in_rtalloc_ign(&sro, RTF_CLONING, inp->inp_inc.inc_fibnum);
+ in_rtalloc_ign(&sro, 0, inp->inp_inc.inc_fibnum);
/*
* If we found a route, use the address corresponding to
@@ -695,6 +695,10 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
ia = ifatoia(ifa_ifwithnet(sintosa(&sain)));
if (cred == NULL || !jailed(cred)) {
+#if __FreeBSD_version < 800000
+ if (ia == NULL)
+ ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa;
+#endif
if (ia == NULL) {
error = ENETUNREACH;
goto done;
@@ -1696,7 +1700,7 @@ db_print_inconninfo(struct in_conninfo *inc, const char *name, int indent)
indent += 2;
#ifdef INET6
- if (inc->inc_flags == 1) {
+ if (inc->inc_flags & INC_ISIPV6) {
/* IPv6. */
ip6_sprintf(laddr_str, &inc->inc6_laddr);
ip6_sprintf(faddr_str, &inc->inc6_faddr);
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index f0275bd..01636fe 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -106,6 +106,12 @@ struct in_conninfo {
/* protocol dependent part */
struct in_endpoints inc_ie;
};
+
+/*
+ * Flags for inc_flags.
+ */
+#define INC_ISIPV6 0x01
+
#define inc_isipv6 inc_flags /* temp compatability */
#define inc_fport inc_ie.ie_fport
#define inc_lport inc_ie.ie_lport
@@ -435,7 +441,7 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define IN6P_RECVIF INP_RECVIF
#define IN6P_MTUDISC INP_MTUDISC
#define IN6P_FAITH INP_FAITH
-#define IN6P_CONTROLOPTS INP_CONTROLOPTS
+#define IN6P_CONTROLOPTS INP_CONTROLOPTS
/*
* socket AF version is {newer than,or include}
* actual datagram AF version
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index a93f1f2..f3fbe0c 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
@@ -364,7 +365,9 @@ struct domain inetdomain = {
.dom_rtattach = in_inithead,
#endif
.dom_rtoffset = 32,
- .dom_maxrtkey = sizeof(struct sockaddr_in)
+ .dom_maxrtkey = sizeof(struct sockaddr_in),
+ .dom_ifattach = in_domifattach,
+ .dom_ifdetach = in_domifdetach
};
DOMAIN_SET(inet);
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c
index aa4ca0d..f9e9d98 100644
--- a/sys/netinet/in_rmx.c
+++ b/sys/netinet/in_rmx.c
@@ -75,8 +75,8 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
{
struct rtentry *rt = (struct rtentry *)treenodes;
struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt);
- struct radix_node *ret;
+ RADIX_NODE_HEAD_WLOCK_ASSERT(head);
/*
* A little bit of help for both IP output and input:
* For host routes, we make sure that RTF_BROADCAST
@@ -106,31 +106,7 @@ in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
if (!rt->rt_rmx.rmx_mtu && rt->rt_ifp)
rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
- ret = rn_addroute(v_arg, n_arg, head, treenodes);
- if (ret == NULL && rt->rt_flags & RTF_HOST) {
- struct rtentry *rt2;
- /*
- * We are trying to add a host route, but can't.
- * Find out if it is because of an
- * ARP entry and delete it if so.
- */
- rt2 = in_rtalloc1((struct sockaddr *)sin, 0,
- RTF_CLONING, rt->rt_fibnum);
- if (rt2) {
- if (rt2->rt_flags & RTF_LLINFO &&
- rt2->rt_flags & RTF_HOST &&
- rt2->rt_gateway &&
- rt2->rt_gateway->sa_family == AF_LINK) {
- rtexpunge(rt2);
- RTFREE_LOCKED(rt2);
- ret = rn_addroute(v_arg, n_arg, head,
- treenodes);
- } else
- RTFREE_LOCKED(rt2);
- }
- }
-
- return ret;
+ return (rn_addroute(v_arg, n_arg, head, treenodes));
}
/*
@@ -187,13 +163,10 @@ in_clsroute(struct radix_node *rn, struct radix_node_head *head)
if (!(rt->rt_flags & RTF_UP))
return; /* prophylactic measures */
- if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
- return;
-
if (rt->rt_flags & RTPRF_OURS)
return;
- if (!(rt->rt_flags & (RTF_WASCLONED | RTF_DYNAMIC)))
+ if (!(rt->rt_flags & RTF_DYNAMIC))
return;
/*
@@ -434,7 +407,6 @@ in_ifadownkill(struct radix_node *rn, void *xap)
* the routes that rtrequest() would have in any case,
* so that behavior is not needed there.
*/
- rt->rt_flags &= ~RTF_CLONING;
rtexpunge(rt);
}
RT_UNLOCK(rt);
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index 1190826..73868ad 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -84,9 +84,13 @@ extern u_char inetctlerrmap[];
/*
* Hash table for IP addresses.
*/
-extern LIST_HEAD(in_ifaddrhashhead, in_ifaddr) *in_ifaddrhashtbl;
-extern TAILQ_HEAD(in_ifaddrhead, in_ifaddr) in_ifaddrhead;
+TAILQ_HEAD(in_ifaddrhead, in_ifaddr);
+LIST_HEAD(in_ifaddrhashhead, in_ifaddr);
+#ifdef VIMAGE_GLOBALS
+extern struct in_ifaddrhashhead *in_ifaddrhashtbl;
+extern struct in_ifaddrhead in_ifaddrhead;
extern u_long in_ifaddrhmask; /* mask for hash table */
+#endif
#define INADDR_NHASH_LOG2 9
#define INADDR_NHASH (1 << INADDR_NHASH_LOG2)
@@ -227,7 +231,10 @@ SYSCTL_DECL(_net_inet_ip);
SYSCTL_DECL(_net_inet_raw);
#endif
-extern LIST_HEAD(in_multihead, in_multi) in_multihead;
+LIST_HEAD(in_multihead, in_multi);
+#ifdef VIMAGE_GLOBALS
+extern struct in_multihead in_multihead;
+#endif
/*
* Lock macros for IPv4 layer multicast address lists. IPv4 lock goes
@@ -314,6 +321,9 @@ void ip_input(struct mbuf *);
int in_ifadown(struct ifaddr *ifa, int);
void in_ifscrub(struct ifnet *, struct in_ifaddr *);
struct mbuf *ip_fastforward(struct mbuf *);
+void *in_domifattach(struct ifnet *);
+void in_domifdetach(struct ifnet *, void *);
+
/* XXX */
void in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum);
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 9f6bc31..6d96163 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -371,14 +371,6 @@ carp_setroute(struct carp_softc *sc, int cmd)
(cmd == RTM_DELETE && count == 0))
rtinit(ifa, cmd, RTF_UP | RTF_HOST);
}
-#ifdef INET6
- if (ifa->ifa_addr->sa_family == AF_INET6) {
- if (cmd == RTM_ADD)
- in6_ifaddloop(ifa);
- else
- in6_ifremloop(ifa);
- }
-#endif /* INET6 */
}
splx(s);
}
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index 407b08c..ea106df 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -128,7 +128,7 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr.s_addr = dest.s_addr;
- in_rtalloc_ign(ro, RTF_CLONING, M_GETFIB(m));
+ in_rtalloc_ign(ro, 0, M_GETFIB(m));
/*
* Route there and interface still up?
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 6e7db99..831686d 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -637,7 +637,7 @@ void ipfw_nat_destroy(void);
typedef int ip_fw_ctl_t(struct sockopt *);
extern ip_fw_ctl_t *ip_fw_ctl_ptr;
-#ifndef VIMAGE
+#ifdef VIMAGE_GLOBALS
extern int fw_one_pass;
extern int fw_enable;
#ifdef INET6
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c
index 5c3ac59..1f2e67d 100644
--- a/sys/netinet/ip_fw2.c
+++ b/sys/netinet/ip_fw2.c
@@ -128,8 +128,8 @@ struct vnet_ipfw vnet_ipfw_0;
static u_int32_t set_disable;
static int fw_verbose;
static struct callout ipfw_timeout;
-#endif
static int verbose_limit;
+#endif
static uma_zone_t ipfw_dyn_rule_zone;
@@ -190,8 +190,9 @@ SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW,
SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose,
CTLFLAG_RW | CTLFLAG_SECURE3,
fw_verbose, 0, "Log matches to ipfw rules");
-SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW,
- &verbose_limit, 0, "Set upper limit of matches of ipfw rules logged");
+SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, verbose_limit,
+ CTLFLAG_RW, verbose_limit, 0,
+ "Set upper limit of matches of ipfw rules logged");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
NULL, IPFW_DEFAULT_RULE, "The default/max possible rule number.");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
@@ -527,7 +528,7 @@ verify_path(struct in_addr src, struct ifnet *ifp, u_int fib)
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = src;
- in_rtalloc_ign(&ro, RTF_CLONING, fib);
+ in_rtalloc_ign(&ro, 0, fib);
if (ro.ro_rt == NULL)
return 0;
@@ -619,7 +620,7 @@ verify_path6(struct in6_addr *src, struct ifnet *ifp)
dst->sin6_len = sizeof(*dst);
dst->sin6_addr = *src;
/* XXX MRT 0 for ipv6 at this time */
- rtalloc_ign((struct route *)&ro, RTF_CLONING);
+ rtalloc_ign((struct route *)&ro, 0);
if (ro.ro_rt == NULL)
return 0;
@@ -1813,6 +1814,7 @@ add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
INIT_VNET_IPFW(curvnet);
struct radix_node_head *rnh;
struct table_entry *ent;
+ struct radix_node *rn;
if (tbl >= IPFW_TABLES_MAX)
return (EINVAL);
@@ -1825,8 +1827,8 @@ add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
ent->mask.sin_addr.s_addr = htonl(mlen ? ~((1 << (32 - mlen)) - 1) : 0);
ent->addr.sin_addr.s_addr = addr & ent->mask.sin_addr.s_addr;
IPFW_WLOCK(ch);
- if (rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent) ==
- NULL) {
+ rn = rnh->rnh_addaddr(&ent->addr, &ent->mask, rnh, (void *)ent);
+ if (rn == NULL) {
IPFW_WUNLOCK(ch);
free(ent, M_IPFW_TBL);
return (EEXIST);
diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c
index 952574d..694f8ab 100644
--- a/sys/netinet/ip_fw_pfil.c
+++ b/sys/netinet/ip_fw_pfil.c
@@ -435,8 +435,10 @@ ipfw_hook(void)
if (pfh_inet == NULL)
return ENOENT;
- pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
- pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+ (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
return 0;
}
@@ -450,8 +452,10 @@ ipfw_unhook(void)
if (pfh_inet == NULL)
return ENOENT;
- pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
- pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+ (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
return 0;
}
@@ -466,8 +470,10 @@ ipfw6_hook(void)
if (pfh_inet6 == NULL)
return ENOENT;
- pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
- pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
+ (void)pfil_add_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet6);
+ (void)pfil_add_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet6);
return 0;
}
@@ -481,8 +487,10 @@ ipfw6_unhook(void)
if (pfh_inet6 == NULL)
return ENOENT;
- pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
- pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
+ (void)pfil_remove_hook(ipfw_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet6);
+ (void)pfil_remove_hook(ipfw_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet6);
return 0;
}
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index c99c53e..4a169ff 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1286,7 +1286,7 @@ ip_rtaddr(struct in_addr dst, u_int fibnum)
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
sin->sin_addr = dst;
- in_rtalloc_ign(&sro, RTF_CLONING, fibnum);
+ in_rtalloc_ign(&sro, 0, fibnum);
if (sro.ro_rt == NULL)
return (NULL);
@@ -1412,7 +1412,7 @@ ip_forward(struct mbuf *m, int srcrt)
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
sin->sin_addr = ip->ip_dst;
- in_rtalloc_ign(&ro, RTF_CLONING, M_GETFIB(m));
+ in_rtalloc_ign(&ro, 0, M_GETFIB(m));
rt = ro.ro_rt;
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 03cf56f..6cda8aa 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -567,7 +567,6 @@ passout:
* to avoid confusing lower layers.
*/
m->m_flags &= ~(M_PROTOFLAGS);
-
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst, ro->ro_rt);
goto done;
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 9b5a3f3..9fe0eca 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -280,7 +280,7 @@ rip_input(struct mbuf *m, int off)
if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
continue;
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n;
n = m_copy(m, 0, (int)M_COPYALL);
@@ -310,7 +310,7 @@ rip_input(struct mbuf *m, int off)
if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
continue;
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n;
n = m_copy(m, 0, (int)M_COPYALL);
@@ -964,6 +964,7 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
INP_RLOCK(inp);
if (inp->inp_gencnt <= gencnt) {
struct xinpcb xi;
+
bzero(&xi, sizeof(xi));
xi.xi_len = sizeof xi;
/* XXX should avoid extra copy */
diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index 7c76160..c9b5b8c 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -249,7 +249,7 @@ tcp_hc_lookup(struct in_conninfo *inc)
/*
* Hash the foreign ip address.
*/
- if (inc->inc_isipv6)
+ if (inc->inc_flags & INC_ISIPV6)
hash = HOSTCACHE_HASH6(&inc->inc6_faddr);
else
hash = HOSTCACHE_HASH(&inc->inc_faddr);
@@ -267,7 +267,7 @@ tcp_hc_lookup(struct in_conninfo *inc)
* Iterate through entries in bucket row looking for a match.
*/
TAILQ_FOREACH(hc_entry, &hc_head->hch_bucket, rmx_q) {
- if (inc->inc_isipv6) {
+ if (inc->inc_flags & INC_ISIPV6) {
if (memcmp(&inc->inc6_faddr, &hc_entry->ip6,
sizeof(inc->inc6_faddr)) == 0)
return hc_entry;
@@ -305,7 +305,7 @@ tcp_hc_insert(struct in_conninfo *inc)
/*
* Hash the foreign ip address.
*/
- if (inc->inc_isipv6)
+ if (inc->inc_flags & INC_ISIPV6)
hash = HOSTCACHE_HASH6(&inc->inc6_faddr);
else
hash = HOSTCACHE_HASH(&inc->inc_faddr);
@@ -360,7 +360,7 @@ tcp_hc_insert(struct in_conninfo *inc)
* Initialize basic information of hostcache entry.
*/
bzero(hc_entry, sizeof(*hc_entry));
- if (inc->inc_isipv6)
+ if (inc->inc_flags & INC_ISIPV6)
bcopy(&inc->inc6_faddr, &hc_entry->ip6, sizeof(hc_entry->ip6));
else
hc_entry->ip4 = inc->inc_faddr;
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index dfb2aff..30b3fde 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -737,9 +737,9 @@ findpcb:
"tp not listening", __func__));
bzero(&inc, sizeof(inc));
- inc.inc_isipv6 = isipv6;
#ifdef INET6
if (isipv6) {
+ inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = ip6->ip6_src;
inc.inc6_laddr = ip6->ip6_dst;
} else
@@ -3338,14 +3338,11 @@ tcp_mssopt(struct in_conninfo *inc)
u_long maxmtu = 0;
u_long thcmtu = 0;
size_t min_protoh;
-#ifdef INET6
- int isipv6 = inc->inc_isipv6 ? 1 : 0;
-#endif
KASSERT(inc != NULL, ("tcp_mssopt with NULL in_conninfo pointer"));
#ifdef INET6
- if (isipv6) {
+ if (inc->inc_flags & INC_ISIPV6) {
mss = V_tcp_v6mssdflt;
maxmtu = tcp_maxmtu6(inc, NULL);
thcmtu = tcp_hc_getmtu(inc); /* IPv4 and IPv6 */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 207d37a..9cb941a 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -434,7 +434,7 @@ tcpip_fillheaders(struct inpcb *inp, void *ip_ptr, void *tcp_ptr)
ip6 = (struct ip6_hdr *)ip_ptr;
ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
- (inp->in6p_flowinfo & IPV6_FLOWINFO_MASK);
+ (inp->inp_flow & IPV6_FLOWINFO_MASK);
ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
(IPV6_VERSION & IPV6_VERSION_MASK);
ip6->ip6_nxt = IPPROTO_TCP;
@@ -1306,7 +1306,6 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
* value (if given) and then notify.
*/
bzero(&inc, sizeof(inc));
- inc.inc_flags = 0; /* IPv4 */
inc.inc_faddr = faddr;
inc.inc_fibnum =
inp->inp_inc.inc_fibnum;
@@ -1343,13 +1342,11 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
if (inp != NULL)
INP_WUNLOCK(inp);
} else {
+ bzero(&inc, sizeof(inc));
inc.inc_fport = th->th_dport;
inc.inc_lport = th->th_sport;
inc.inc_faddr = faddr;
inc.inc_laddr = ip->ip_src;
-#ifdef INET6
- inc.inc_isipv6 = 0;
-#endif
syncache_unreach(&inc, th);
}
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -1419,11 +1416,12 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
(struct sockaddr *)ip6cp->ip6c_src,
th.th_sport, cmd, NULL, notify);
+ bzero(&inc, sizeof(inc));
inc.inc_fport = th.th_dport;
inc.inc_lport = th.th_sport;
inc.inc6_faddr = ((struct sockaddr_in6 *)sa)->sin6_addr;
inc.inc6_laddr = ip6cp->ip6c_src->sin6_addr;
- inc.inc_isipv6 = 1;
+ inc.inc_flags |= INC_ISIPV6;
INP_INFO_WLOCK(&V_tcbinfo);
syncache_unreach(&inc, &th);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -1486,13 +1484,13 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
static u_char isn_secret[32];
static int isn_last_reseed;
static u_int32_t isn_offset, isn_offset_old;
-static MD5_CTX isn_ctx;
#endif
tcp_seq
tcp_new_isn(struct tcpcb *tp)
{
INIT_VNET_INET(tp->t_vnet);
+ MD5_CTX isn_ctx;
u_int32_t md5_buffer[4];
tcp_seq new_isn;
@@ -1508,25 +1506,25 @@ tcp_new_isn(struct tcpcb *tp)
}
/* Compute the md5 hash and return the ISN. */
- MD5Init(&V_isn_ctx);
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short));
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short));
+ MD5Init(&isn_ctx);
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short));
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short));
#ifdef INET6
if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) {
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr,
sizeof(struct in6_addr));
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr,
sizeof(struct in6_addr));
} else
#endif
{
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr,
sizeof(struct in_addr));
- MD5Update(&V_isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr,
+ MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr,
sizeof(struct in_addr));
}
- MD5Update(&V_isn_ctx, (u_char *) &V_isn_secret, sizeof(V_isn_secret));
- MD5Final((u_char *) &md5_buffer, &V_isn_ctx);
+ MD5Update(&isn_ctx, (u_char *) &V_isn_secret, sizeof(V_isn_secret));
+ MD5Final((u_char *) &md5_buffer, &isn_ctx);
new_isn = (tcp_seq) md5_buffer[0];
V_isn_offset += ISN_STATIC_INCREMENT +
(arc4random() & ISN_RANDOM_INCREMENT);
@@ -1659,7 +1657,7 @@ tcp_maxmtu(struct in_conninfo *inc, int *flags)
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = inc->inc_faddr;
- in_rtalloc_ign(&sro, RTF_CLONING, inc->inc_fibnum);
+ in_rtalloc_ign(&sro, 0, inc->inc_fibnum);
}
if (sro.ro_rt != NULL) {
ifp = sro.ro_rt->rt_ifp;
@@ -1694,7 +1692,7 @@ tcp_maxmtu6(struct in_conninfo *inc, int *flags)
sro6.ro_dst.sin6_family = AF_INET6;
sro6.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
sro6.ro_dst.sin6_addr = inc->inc6_faddr;
- rtalloc_ign((struct route *)&sro6, RTF_CLONING);
+ rtalloc_ign((struct route *)&sro6, 0);
}
if (sro6.ro_rt != NULL) {
ifp = sro6.ro_rt->rt_ifp;
@@ -2263,7 +2261,7 @@ tcp_log_addrs(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr,
strcat(s, "TCP: [");
sp = s + strlen(s);
- if (inc && inc->inc_isipv6 == 0) {
+ if (inc && ((inc->inc_flags & INC_ISIPV6) == 0)) {
inet_ntoa_r(inc->inc_faddr, sp);
sp = s + strlen(s);
sprintf(sp, "]:%i to [", ntohs(inc->inc_fport));
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 838fd52..18fab28 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -430,7 +430,7 @@ syncache_lookup(struct in_conninfo *inc, struct syncache_head **schp)
struct syncache_head *sch;
#ifdef INET6
- if (inc->inc_isipv6) {
+ if (inc->inc_flags & INC_ISIPV6) {
sch = &V_tcp_syncache.hashbase[
SYNCACHE_HASH6(inc, V_tcp_syncache.hashmask)];
*schp = sch;
@@ -454,7 +454,7 @@ syncache_lookup(struct in_conninfo *inc, struct syncache_head **schp)
/* Circle through bucket row to find matching entry. */
TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) {
#ifdef INET6
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
continue;
#endif
if (ENDPTS_EQ(&inc->inc_ie, &sc->sc_inc.inc_ie))
@@ -643,9 +643,9 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
INP_WLOCK(inp);
/* Insert new socket into PCB hash list. */
- inp->inp_inc.inc_isipv6 = sc->sc_inc.inc_isipv6;
+ inp->inp_inc.inc_flags = sc->sc_inc.inc_flags;
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
inp->in6p_laddr = sc->sc_inc.inc6_laddr;
} else {
inp->inp_vflag &= ~INP_IPV6;
@@ -662,7 +662,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
* put the PCB on the hash lists.
*/
#ifdef INET6
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
inp->in6p_laddr = in6addr_any;
else
#endif
@@ -676,7 +676,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
printf("syncache_socket: could not copy policy\n");
#endif
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
struct inpcb *oinp = sotoinpcb(lso);
struct in6_addr laddr6;
struct sockaddr_in6 sin6;
@@ -708,8 +708,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
goto abort;
}
/* Override flowlabel from in6_pcbconnect. */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
- inp->in6p_flowinfo |= sc->sc_flowlabel;
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
+ inp->inp_flow |= sc->sc_flowlabel;
} else
#endif
{
@@ -993,8 +993,8 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
cred = crhold(so->so_cred);
#ifdef INET6
- if (inc->inc_isipv6 &&
- (inp->in6p_flags & IN6P_AUTOFLOWLABEL))
+ if ((inc->inc_flags & INC_ISIPV6) &&
+ (inp->inp_flags & IN6P_AUTOFLOWLABEL))
autoflowlabel = 1;
#endif
ip_ttl = inp->inp_ip_ttl;
@@ -1022,7 +1022,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* Remember the IP options, if any.
*/
#ifdef INET6
- if (!inc->inc_isipv6)
+ if (!(inc->inc_flags & INC_ISIPV6))
#endif
ipopts = (m) ? ip_srcroute(m) : NULL;
@@ -1123,10 +1123,11 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
sc->sc_cred = cred;
cred = NULL;
sc->sc_ipopts = ipopts;
+ /* XXX-BZ this fib assignment is just useless. */
sc->sc_inc.inc_fibnum = inp->inp_inc.inc_fibnum;
bcopy(inc, &sc->sc_inc, sizeof(struct in_conninfo));
#ifdef INET6
- if (!inc->inc_isipv6)
+ if (!(inc->inc_flags & INC_ISIPV6))
#endif
{
sc->sc_ip_tos = ip_tos;
@@ -1272,7 +1273,7 @@ syncache_respond(struct syncache *sc)
hlen =
#ifdef INET6
- (sc->sc_inc.inc_isipv6) ? sizeof(struct ip6_hdr) :
+ (sc->sc_inc.inc_flags & INC_ISIPV6) ? sizeof(struct ip6_hdr) :
#endif
sizeof(struct ip);
tlen = hlen + sizeof(struct tcphdr);
@@ -1299,7 +1300,7 @@ syncache_respond(struct syncache *sc)
m->m_pkthdr.rcvif = NULL;
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_vfc = IPV6_VERSION;
ip6->ip6_nxt = IPPROTO_TCP;
@@ -1390,7 +1391,7 @@ syncache_respond(struct syncache *sc)
to.to_signature, IPSEC_DIR_OUTBOUND);
#endif
#ifdef INET6
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) + optlen);
else
#endif
@@ -1399,7 +1400,7 @@ syncache_respond(struct syncache *sc)
optlen = 0;
#ifdef INET6
- if (sc->sc_inc.inc_isipv6) {
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
th->th_sum = 0;
th->th_sum = in6_cksum(m, IPPROTO_TCP, hlen,
tlen + optlen - hlen);
@@ -1653,8 +1654,8 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
sc->sc_iss = ack;
#ifdef INET6
- if (inc->inc_isipv6) {
- if (sotoinpcb(so)->in6p_flags & IN6P_AUTOFLOWLABEL)
+ if (inc->inc_flags & INC_ISIPV6) {
+ if (sotoinpcb(so)->inp_flags & IN6P_AUTOFLOWLABEL)
sc->sc_flowlabel = md5_buffer[1] & IPV6_FLOWLABEL_MASK;
} else
#endif
@@ -1743,7 +1744,7 @@ syncache_pcblist(struct sysctl_req *req, int max_pcbs, int *pcbs_exported)
continue;
bzero(&xt, sizeof(xt));
xt.xt_len = sizeof(xt);
- if (sc->sc_inc.inc_isipv6)
+ if (sc->sc_inc.inc_flags & INC_ISIPV6)
xt.xt_inp.inp_vflag = INP_IPV6;
else
xt.xt_inp.inp_vflag = INP_IPV4;
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 37fafa0..3138547 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -538,7 +538,7 @@ tcp_twrespond(struct tcptw *tw, int flags)
struct tcpopt to;
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
- int isipv6 = inp->inp_inc.inc_isipv6;
+ int isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6;
#endif
INP_WLOCK_ASSERT(inp);
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 2011dff..f6dcae1 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -519,7 +519,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
}
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
- inp->inp_inc.inc_isipv6 = 1;
+ inp->inp_inc.inc_flags |= INC_ISIPV6;
if (prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr) != 0) {
error = EINVAL;
goto out;
@@ -1167,9 +1167,9 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
inp->in6p_faddr = sin6->sin6_addr;
inp->inp_fport = sin6->sin6_port;
/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
- if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
- inp->in6p_flowinfo |=
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
+ if (inp->inp_flags & IN6P_AUTOFLOWLABEL)
+ inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
in_pcbrehash(inp);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index ed872b9..a4392cb 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -38,7 +38,9 @@
/*
* Kernel variables for tcp.
*/
+#ifdef VIMAGE_GLOBALS
extern int tcp_do_rfc1323;
+#endif
/* TCP segment queue entry */
struct tseg_qent {
@@ -48,7 +50,9 @@ struct tseg_qent {
struct mbuf *tqe_m; /* mbuf contains packet */
};
LIST_HEAD(tsegqe_head, tseg_qent);
+#ifdef VIMAGE_GLOBALS
extern int tcp_reass_qsize;
+#endif
extern struct uma_zone *tcp_reass_zone;
struct sackblk {
diff --git a/sys/netinet/vinet.h b/sys/netinet/vinet.h
index 65ccfa4..449334e 100644
--- a/sys/netinet/vinet.h
+++ b/sys/netinet/vinet.h
@@ -142,7 +142,6 @@ struct vnet_inet {
int _isn_last_reseed;
u_int32_t _isn_offset;
u_int32_t _isn_offset_old;
- MD5_CTX _isn_ctx;
struct inpcbhead _udb;
struct inpcbinfo _udbinfo;
@@ -265,7 +264,6 @@ extern struct vnet_inet vnet_inet_0;
#define V_ipsendredirects VNET_INET(ipsendredirects)
#define V_ipstat VNET_INET(ipstat)
#define V_ipstealth VNET_INET(ipstealth)
-#define V_isn_ctx VNET_INET(isn_ctx)
#define V_isn_last_reseed VNET_INET(isn_last_reseed)
#define V_isn_offset VNET_INET(isn_offset)
#define V_isn_offset_old VNET_INET(isn_offset_old)
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 59bc95a..7bdd8a8 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/if_dl.h>
+#include <net/if_llatbl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <net/vnet.h>
@@ -1147,7 +1148,7 @@ icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated)
mtu = IPV6_MMTU - 8;
bzero(&inc, sizeof(inc));
- inc.inc_flags = 1; /* IPv6 */
+ inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = *dst;
if (in6_setscope(&inc.inc6_faddr, m->m_pkthdr.rcvif, NULL))
return;
@@ -1898,8 +1899,8 @@ icmp6_rip6_input(struct mbuf **mp, int off)
INIT_VNET_INET6(curvnet);
struct mbuf *m = *mp;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- struct in6pcb *in6p;
- struct in6pcb *last = NULL;
+ struct inpcb *in6p;
+ struct inpcb *last = NULL;
struct sockaddr_in6 fromsa;
struct icmp6_hdr *icmp6;
struct mbuf *opts = NULL;
@@ -1932,7 +1933,7 @@ icmp6_rip6_input(struct mbuf **mp, int off)
LIST_FOREACH(in6p, &V_ripcb, inp_list) {
if ((in6p->inp_vflag & INP_IPV6) == 0)
continue;
- if (in6p->in6p_ip6_nxt != IPPROTO_ICMPV6)
+ if (in6p->inp_ip_p != IPPROTO_ICMPV6)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
@@ -1946,7 +1947,7 @@ icmp6_rip6_input(struct mbuf **mp, int off)
INP_RUNLOCK(in6p);
continue;
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n = NULL;
/*
@@ -1982,13 +1983,13 @@ icmp6_rip6_input(struct mbuf **mp, int off)
}
if (n != NULL ||
(n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
- if (last->in6p_flags & IN6P_CONTROLOPTS)
+ if (last->inp_flags & INP_CONTROLOPTS)
ip6_savecontrol(last, n, &opts);
/* strip intermediate headers */
m_adj(n, off);
- SOCKBUF_LOCK(&last->in6p_socket->so_rcv);
+ SOCKBUF_LOCK(&last->inp_socket->so_rcv);
if (sbappendaddr_locked(
- &last->in6p_socket->so_rcv,
+ &last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, n, opts)
== 0) {
/* should notify about lost packet */
@@ -1997,9 +1998,9 @@ icmp6_rip6_input(struct mbuf **mp, int off)
m_freem(opts);
}
SOCKBUF_UNLOCK(
- &last->in6p_socket->so_rcv);
+ &last->inp_socket->so_rcv);
} else
- sorwakeup_locked(last->in6p_socket);
+ sorwakeup_locked(last->inp_socket);
opts = NULL;
}
INP_RUNLOCK(last);
@@ -2007,8 +2008,8 @@ icmp6_rip6_input(struct mbuf **mp, int off)
last = in6p;
}
INP_INFO_RUNLOCK(&V_ripcbinfo);
- if (last) {
- if (last->in6p_flags & IN6P_CONTROLOPTS)
+ if (last != NULL) {
+ if (last->inp_flags & INP_CONTROLOPTS)
ip6_savecontrol(last, m, &opts);
/* strip intermediate headers */
m_adj(m, off);
@@ -2032,15 +2033,15 @@ icmp6_rip6_input(struct mbuf **mp, int off)
}
}
}
- SOCKBUF_LOCK(&last->in6p_socket->so_rcv);
- if (sbappendaddr_locked(&last->in6p_socket->so_rcv,
+ SOCKBUF_LOCK(&last->inp_socket->so_rcv);
+ if (sbappendaddr_locked(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
- SOCKBUF_UNLOCK(&last->in6p_socket->so_rcv);
+ SOCKBUF_UNLOCK(&last->inp_socket->so_rcv);
} else
- sorwakeup_locked(last->in6p_socket);
+ sorwakeup_locked(last->inp_socket);
INP_RUNLOCK(last);
} else {
m_freem(m);
@@ -2452,6 +2453,7 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
struct mbuf *m = NULL; /* newly allocated one */
struct ip6_hdr *ip6; /* m as struct ip6_hdr */
struct nd_redirect *nd_rd;
+ struct llentry *ln = NULL;
size_t maxlen;
u_char *p;
struct ifnet *outif = NULL;
@@ -2573,35 +2575,35 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt)
{
/* target lladdr option */
- struct rtentry *rt_router = NULL;
int len;
- struct sockaddr_dl *sdl;
struct nd_opt_hdr *nd_opt;
char *lladdr;
- rt_router = nd6_lookup(router_ll6, 0, ifp);
- if (!rt_router)
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(router_ll6, 0, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln == NULL)
goto nolladdropt;
+
len = sizeof(*nd_opt) + ifp->if_addrlen;
len = (len + 7) & ~7; /* round by 8 */
/* safety check */
- if (len + (p - (u_char *)ip6) > maxlen)
+ if (len + (p - (u_char *)ip6) > maxlen)
goto nolladdropt;
- if (!(rt_router->rt_flags & RTF_GATEWAY) &&
- (rt_router->rt_flags & RTF_LLINFO) &&
- (rt_router->rt_gateway->sa_family == AF_LINK) &&
- (sdl = (struct sockaddr_dl *)rt_router->rt_gateway) &&
- sdl->sdl_alen) {
+
+ if (ln->la_flags & LLE_VALID) {
nd_opt = (struct nd_opt_hdr *)p;
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
nd_opt->nd_opt_len = len >> 3;
lladdr = (char *)(nd_opt + 1);
- bcopy(LLADDR(sdl), lladdr, ifp->if_addrlen);
+ bcopy(&ln->ll_addr, lladdr, ifp->if_addrlen);
p += len;
}
}
-nolladdropt:;
-
+nolladdropt:
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
+
m->m_pkthdr.len = m->m_len = p - (u_char *)ip6;
/* just to be safe */
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index c784845..6ba852c 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -88,6 +88,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <net/if_llatbl.h>
#include <netinet/if_ether.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -135,152 +136,7 @@ static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *);
struct in6_multihead in6_multihead; /* XXX BSS initialization */
int (*faithprefix_p)(struct in6_addr *);
-/*
- * Subroutine for in6_ifaddloop() and in6_ifremloop().
- * This routine does actual work.
- */
-static void
-in6_ifloop_request(int cmd, struct ifaddr *ifa)
-{
- struct sockaddr_in6 all1_sa;
- struct rtentry *nrt = NULL;
- int e;
- char ip6buf[INET6_ADDRSTRLEN];
-
- bzero(&all1_sa, sizeof(all1_sa));
- all1_sa.sin6_family = AF_INET6;
- all1_sa.sin6_len = sizeof(struct sockaddr_in6);
- all1_sa.sin6_addr = in6mask128;
-
- /*
- * We specify the address itself as the gateway, and set the
- * RTF_LLINFO flag, so that the corresponding host route would have
- * the flag, and thus applications that assume traditional behavior
- * would be happy. Note that we assume the caller of the function
- * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest,
- * which changes the outgoing interface to the loopback interface.
- */
- e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr,
- (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt);
- if (e != 0) {
- /* XXX need more descriptive message */
-
- log(LOG_ERR, "in6_ifloop_request: "
- "%s operation failed for %s (errno=%d)\n",
- cmd == RTM_ADD ? "ADD" : "DELETE",
- ip6_sprintf(ip6buf,
- &((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr), e);
- }
-
- /*
- * Report the addition/removal of the address to the routing socket.
- * XXX: since we called rtinit for a p2p interface with a destination,
- * we end up reporting twice in such a case. Should we rather
- * omit the second report?
- */
- if (nrt) {
- RT_LOCK(nrt);
- /*
- * Make sure rt_ifa be equal to IFA, the second argument of
- * the function. We need this because when we refer to
- * rt_ifa->ia6_flags in ip6_input, we assume that the rt_ifa
- * points to the address instead of the loopback address.
- */
- if (cmd == RTM_ADD && ifa != nrt->rt_ifa) {
- IFAFREE(nrt->rt_ifa);
- IFAREF(ifa);
- nrt->rt_ifa = ifa;
- }
-
- rt_newaddrmsg(cmd, ifa, e, nrt);
- if (cmd == RTM_DELETE)
- RTFREE_LOCKED(nrt);
- else {
- /* the cmd must be RTM_ADD here */
- RT_REMREF(nrt);
- RT_UNLOCK(nrt);
- }
- }
-}
-
-/*
- * Add ownaddr as loopback rtentry. We previously add the route only if
- * necessary (ex. on a p2p link). However, since we now manage addresses
- * separately from prefixes, we should always add the route. We can't
- * rely on the cloning mechanism from the corresponding interface route
- * any more.
- */
-void
-in6_ifaddloop(struct ifaddr *ifa)
-{
- struct rtentry *rt;
- int need_loop;
-
- /* If there is no loopback entry, allocate one. */
- rt = rtalloc1(ifa->ifa_addr, 0, 0);
- need_loop = (rt == NULL || (rt->rt_flags & RTF_HOST) == 0 ||
- (rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0);
- if (rt)
- RTFREE_LOCKED(rt);
- if (need_loop)
- in6_ifloop_request(RTM_ADD, ifa);
-}
-
-/*
- * Remove loopback rtentry of ownaddr generated by in6_ifaddloop(),
- * if it exists.
- */
-void
-in6_ifremloop(struct ifaddr *ifa)
-{
- INIT_VNET_INET6(curvnet);
- struct in6_ifaddr *ia;
- struct rtentry *rt;
- int ia_count = 0;
-
- /*
- * Some of BSD variants do not remove cloned routes
- * from an interface direct route, when removing the direct route
- * (see comments in net/net_osdep.h). Even for variants that do remove
- * cloned routes, they could fail to remove the cloned routes when
- * we handle multple addresses that share a common prefix.
- * So, we should remove the route corresponding to the deleted address.
- */
- /*
- * Delete the entry only if exact one ifa exists. More than one ifa
- * can exist if we assign a same single address to multiple
- * (probably p2p) interfaces.
- * XXX: we should avoid such a configuration in IPv6...
- */
- for (ia = V_in6_ifaddr; ia; ia = ia->ia_next) {
- if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
- ia_count++;
- if (ia_count > 1)
- break;
- }
- }
-
- if (ia_count == 1) {
- /*
- * Before deleting, check if a corresponding loopbacked host
- * route surely exists. With this check, we can avoid to
- * delete an interface direct route whose destination is same
- * as the address being removed. This can happen when removing
- * a subnet-router anycast address on an interface attahced
- * to a shared medium.
- */
- rt = rtalloc1(ifa->ifa_addr, 0, 0);
- if (rt != NULL) {
- if ((rt->rt_flags & RTF_HOST) != 0 &&
- (rt->rt_ifp->if_flags & IFF_LOOPBACK) != 0) {
- RTFREE_LOCKED(rt);
- in6_ifloop_request(RTM_DELETE, ifa);
- } else
- RT_UNLOCK(rt);
- }
- }
-}
int
in6_mask2len(struct in6_addr *mask, u_char *lim0)
@@ -1131,10 +987,9 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
}
}
if (!rt) {
- /* XXX: we need RTF_CLONING to fake nd6_rtrequest */
error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
(struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
+ (struct sockaddr *)&mltmask, RTF_UP,
(struct rtentry **)0);
if (error)
goto cleanup;
@@ -1208,7 +1063,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra,
if (!rt) {
error = rtrequest(RTM_ADD, (struct sockaddr *)&mltaddr,
(struct sockaddr *)&ia->ia_addr,
- (struct sockaddr *)&mltmask, RTF_UP | RTF_CLONING,
+ (struct sockaddr *)&mltmask, RTF_UP,
(struct rtentry **)0);
if (error)
goto cleanup;
@@ -1287,34 +1142,16 @@ in6_purgeaddr(struct ifaddr *ifa)
{
struct ifnet *ifp = ifa->ifa_ifp;
struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
- char ip6buf[INET6_ADDRSTRLEN];
struct in6_multi_mship *imm;
/* stop DAD processing */
nd6_dad_stop(ifa);
- /*
- * delete route to the destination of the address being purged.
- * The interface must be p2p or loopback in this case.
- */
- if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) {
- int e;
-
- if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST))
- != 0) {
- log(LOG_ERR, "in6_purgeaddr: failed to remove "
- "a route to the p2p destination: %s on %s, "
- "errno=%d\n",
- ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr),
- if_name(ifp), e);
- /* proceed anyway... */
- } else
- ia->ia_flags &= ~IFA_ROUTE;
- }
-
- /* Remove ownaddr's loopback rtentry, if it exists. */
- in6_ifremloop(&(ia->ia_ifa));
-
+ IF_AFDATA_LOCK(ifp);
+ lla_lookup(LLTABLE6(ifp), (LLE_DELETE | LLE_IFADDR),
+ (struct sockaddr *)&ia->ia_addr);
+ IF_AFDATA_UNLOCK(ifp);
+
/*
* leave from multicast groups we have joined for the interface
*/
@@ -1688,26 +1525,15 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
/* we could do in(6)_socktrim here, but just omit it at this moment. */
- if (newhost) {
- /*
- * set the rtrequest function to create llinfo. It also
- * adjust outgoing interface of the route for the local
- * address when called via in6_ifaddloop() below.
- */
- ia->ia_ifa.ifa_rtrequest = nd6_rtrequest;
- }
-
/*
* Special case:
* If a new destination address is specified for a point-to-point
* interface, install a route to the destination as an interface
- * direct route. In addition, if the link is expected to have neighbor
- * cache entries, specify RTF_LLINFO so that a cache entry for the
- * destination address will be created.
- * created
+ * direct route.
* XXX: the logic below rejects assigning multiple addresses on a p2p
* interface that share the same destination.
*/
+#if 0 /* QL - verify */
plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
ia->ia_dstaddr.sin6_family == AF_INET6) {
@@ -1715,7 +1541,6 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
struct rtentry *rt = NULL, **rtp = NULL;
if (nd6_need_cache(ifp) != 0) {
- rtflags |= RTF_LLINFO;
rtp = &rt;
}
@@ -1744,16 +1569,36 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
}
ia->ia_flags |= IFA_ROUTE;
}
- if (plen < 128) {
- /*
- * The RTF_CLONING flag is necessary for in6_is_ifloop_auto().
- */
- ia->ia_ifa.ifa_flags |= RTF_CLONING;
+#else
+ plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */
+ if (!(ia->ia_flags & IFA_ROUTE) && plen == 128 &&
+ ia->ia_dstaddr.sin6_family == AF_INET6) {
+ if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD,
+ RTF_UP | RTF_HOST)) != 0)
+ return (error);
+ ia->ia_flags |= IFA_ROUTE;
}
+#endif
/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
- if (newhost)
- in6_ifaddloop(&(ia->ia_ifa));
+ if (newhost) {
+ struct llentry *ln;
+
+ IF_AFDATA_LOCK(ifp);
+ ia->ia_ifa.ifa_rtrequest = NULL;
+
+ /* XXX QL
+ * we need to report rt_newaddrmsg
+ */
+ ln = lla_lookup(LLTABLE6(ifp), (LLE_CREATE | LLE_IFADDR | LLE_EXCLUSIVE),
+ (struct sockaddr *)&ia->ia_addr);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln != NULL) {
+ ln->la_expire = 0; /* for IPv6 this means permanent */
+ ln->ln_state = ND6_LLINFO_REACHABLE;
+ LLE_WUNLOCK(ln);
+ }
+ }
return (error);
}
@@ -2237,6 +2082,216 @@ in6_if2idlen(struct ifnet *ifp)
}
}
+#include <sys/sysctl.h>
+
+struct in6_llentry {
+ struct llentry base;
+ struct sockaddr_in6 l3_addr6;
+};
+
+static struct llentry *
+in6_lltable_new(const struct sockaddr *l3addr, u_int flags)
+{
+ struct in6_llentry *lle;
+
+ lle = malloc(sizeof(struct in6_llentry), M_LLTABLE,
+ M_DONTWAIT | M_ZERO);
+ if (lle == NULL) /* NB: caller generates msg */
+ return NULL;
+
+ callout_init(&lle->base.ln_timer_ch, CALLOUT_MPSAFE);
+ lle->l3_addr6 = *(const struct sockaddr_in6 *)l3addr;
+ lle->base.lle_refcnt = 1;
+ LLE_LOCK_INIT(&lle->base);
+ return &lle->base;
+}
+
+/*
+ * Deletes an address from the address table.
+ * This function is called by the timer functions
+ * such as arptimer() and nd6_llinfo_timer(), and
+ * the caller does the locking.
+ */
+static void
+in6_lltable_free(struct lltable *llt, struct llentry *lle)
+{
+ LLE_WUNLOCK(lle);
+ LLE_LOCK_DESTROY(lle);
+ free(lle, M_LLTABLE);
+}
+
+static int
+in6_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
+{
+ struct rtentry *rt;
+ char ip6buf[INET6_ADDRSTRLEN];
+
+ KASSERT(l3addr->sa_family == AF_INET6,
+ ("sin_family %d", l3addr->sa_family));
+
+ /* XXX rtalloc1 should take a const param */
+ rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
+ if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
+ struct ifaddr *ifa;
+ /*
+ * Create an ND6 cache for an IPv6 neighbor
+ * that is not covered by our own prefix.
+ */
+ /* XXX ifaof_ifpforaddr should take a const param */
+ ifa = ifaof_ifpforaddr(__DECONST(struct sockaddr *, l3addr), ifp);
+ if (ifa != NULL) {
+ if (rt != NULL)
+ rtfree(rt);
+ return 0;
+ }
+ log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n",
+ ip6_sprintf(ip6buf, &((const struct sockaddr_in6 *)l3addr)->sin6_addr));
+ if (rt != NULL)
+ rtfree(rt);
+ return EINVAL;
+ }
+ rtfree(rt);
+ return 0;
+}
+
+static struct llentry *
+in6_lltable_lookup(struct lltable *llt, u_int flags,
+ const struct sockaddr *l3addr)
+{
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr;
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ struct llentries *lleh;
+ u_int hashkey;
+
+ IF_AFDATA_LOCK_ASSERT(ifp);
+ KASSERT(l3addr->sa_family == AF_INET6,
+ ("sin_family %d", l3addr->sa_family));
+
+ hashkey = sin6->sin6_addr.s6_addr32[3];
+ lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
+ LIST_FOREACH(lle, lleh, lle_next) {
+ if (lle->la_flags & LLE_DELETED)
+ continue;
+ if (bcmp(L3_ADDR(lle), l3addr, l3addr->sa_len) == 0)
+ break;
+ }
+
+ if (lle == NULL) {
+ if (!(flags & LLE_CREATE))
+ return (NULL);
+ /*
+ * A route that covers the given address must have
+ * been installed 1st because we are doing a resolution,
+ * verify this.
+ */
+ if (!(flags & LLE_IFADDR) &&
+ in6_lltable_rtcheck(ifp, l3addr) != 0)
+ return NULL;
+
+ lle = in6_lltable_new(l3addr, flags);
+ if (lle == NULL) {
+ log(LOG_INFO, "lla_lookup: new lle malloc failed\n");
+ return NULL;
+ }
+ lle->la_flags = flags & ~LLE_CREATE;
+ if ((flags & (LLE_CREATE | LLE_IFADDR)) == (LLE_CREATE | LLE_IFADDR)) {
+ bcopy(IF_LLADDR(ifp), &lle->ll_addr, ifp->if_addrlen);
+ lle->la_flags |= (LLE_VALID | LLE_STATIC);
+ }
+
+ lle->lle_tbl = llt;
+ lle->lle_head = lleh;
+ LIST_INSERT_HEAD(lleh, lle, lle_next);
+ } else if (flags & LLE_DELETE) {
+ LLE_WLOCK(lle);
+ lle->la_flags = LLE_DELETED;
+ LLE_WUNLOCK(lle);
+#ifdef DIAGNOSTICS
+ log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle);
+#endif
+ lle = (void *)-1;
+ }
+ if (LLE_IS_VALID(lle)) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WLOCK(lle);
+ else
+ LLE_RLOCK(lle);
+ }
+ return (lle);
+}
+
+static int
+in6_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
+{
+ struct ifnet *ifp = llt->llt_ifp;
+ struct llentry *lle;
+ /* XXX stack use */
+ struct {
+ struct rt_msghdr rtm;
+ struct sockaddr_in6 sin6;
+ /*
+ * ndp.c assumes that sdl is word aligned
+ */
+#ifdef __LP64__
+ uint32_t pad;
+#endif
+ struct sockaddr_dl sdl;
+ } ndpc;
+ int i, error;
+
+ /* XXXXX
+ * current IFNET_RLOCK() is mapped to IFNET_WLOCK()
+ * so it is okay to use this ASSERT, change it when
+ * IFNET lock is finalized
+ */
+ IFNET_WLOCK_ASSERT();
+
+ error = 0;
+ for (i = 0; i < LLTBL_HASHTBL_SIZE; i++) {
+ LIST_FOREACH(lle, &llt->lle_head[i], lle_next) {
+ struct sockaddr_dl *sdl;
+
+ /* skip deleted or invalid entries */
+ if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
+ continue;
+ /*
+ * produce a msg made of:
+ * struct rt_msghdr;
+ * struct sockaddr_in6 (IPv6)
+ * struct sockaddr_dl;
+ */
+ bzero(&ndpc, sizeof(ndpc));
+ ndpc.rtm.rtm_msglen = sizeof(ndpc);
+ ndpc.sin6.sin6_family = AF_INET6;
+ ndpc.sin6.sin6_len = sizeof(ndpc.sin6);
+ bcopy(L3_ADDR(lle), &ndpc.sin6, L3_ADDR_LEN(lle));
+
+ /* publish */
+ if (lle->la_flags & LLE_PUB)
+ ndpc.rtm.rtm_flags |= RTF_ANNOUNCE;
+
+ sdl = &ndpc.sdl;
+ sdl->sdl_family = AF_LINK;
+ sdl->sdl_len = sizeof(*sdl);
+ sdl->sdl_alen = ifp->if_addrlen;
+ sdl->sdl_index = ifp->if_index;
+ sdl->sdl_type = ifp->if_type;
+ bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+ ndpc.rtm.rtm_rmx.rmx_expire =
+ lle->la_flags & LLE_STATIC ? 0 : lle->la_expire;
+ ndpc.rtm.rtm_flags |= RTF_HOST;
+ if (lle->la_flags & LLE_STATIC)
+ ndpc.rtm.rtm_flags |= RTF_STATIC;
+ ndpc.rtm.rtm_index = ifp->if_index;
+ error = SYSCTL_OUT(wr, &ndpc, sizeof(ndpc));
+ if (error)
+ break;
+ }
+ }
+ return error;
+}
+
void *
in6_domifattach(struct ifnet *ifp)
{
@@ -2256,6 +2311,14 @@ in6_domifattach(struct ifnet *ifp)
ext->nd_ifinfo = nd6_ifattach(ifp);
ext->scope6_id = scope6_ifattach(ifp);
+ ext->lltable = lltable_init(ifp, AF_INET6);
+ if (ext->lltable != NULL) {
+ ext->lltable->llt_new = in6_lltable_new;
+ ext->lltable->llt_free = in6_lltable_free;
+ ext->lltable->llt_rtcheck = in6_lltable_rtcheck;
+ ext->lltable->llt_lookup = in6_lltable_lookup;
+ ext->lltable->llt_dump = in6_lltable_dump;
+ }
return ext;
}
@@ -2266,6 +2329,7 @@ in6_domifdetach(struct ifnet *ifp, void *aux)
scope6_ifdetach(ext->scope6_id);
nd6_ifdetach(ext->nd_ifinfo);
+ lltable_free(ext->lltable);
free(ext->in6_ifstat, M_IFADDR);
free(ext->icmp6_ifstat, M_IFADDR);
free(ext, M_IFADDR);
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index ad19bee..753f45d 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -394,9 +394,9 @@ in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
inp->in6p_faddr = sin6->sin6_addr;
inp->inp_fport = sin6->sin6_port;
/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
- if (inp->in6p_flags & IN6P_AUTOFLOWLABEL)
- inp->in6p_flowinfo |=
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
+ if (inp->inp_flags & IN6P_AUTOFLOWLABEL)
+ inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
in_pcbrehash(inp);
@@ -414,7 +414,7 @@ in6_pcbdisconnect(struct inpcb *inp)
bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
inp->inp_fport = 0;
/* clear flowinfo - draft-itojun-ipv6-flowlabel-api-00 */
- inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
+ inp->inp_flow &= ~IPV6_FLOWLABEL_MASK;
in_pcbrehash(inp);
}
@@ -617,7 +617,7 @@ in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
*/
if (lport == 0 && fport == 0 && flowinfo &&
inp->inp_socket != NULL &&
- flowinfo == (inp->in6p_flowinfo & IPV6_FLOWLABEL_MASK) &&
+ flowinfo == (inp->inp_flow & IPV6_FLOWLABEL_MASK) &&
IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, &sa6_src.sin6_addr))
goto do_notify;
else if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
@@ -736,7 +736,7 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
void
in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
{
- struct in6pcb *in6p;
+ struct inpcb *in6p;
struct ip6_moptions *im6o;
struct in6_multi_mship *imm, *nimm;
diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c
index 7e1a262..ade7649 100644
--- a/sys/netinet6/in6_rmx.c
+++ b/sys/netinet6/in6_rmx.c
@@ -124,6 +124,7 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rt_key(rt);
struct radix_node *ret;
+ RADIX_NODE_HEAD_WLOCK_ASSERT(head);
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
rt->rt_flags |= RTF_MULTICAST;
@@ -153,27 +154,7 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
rt->rt_rmx.rmx_mtu = IN6_LINKMTU(rt->rt_ifp);
ret = rn_addroute(v_arg, n_arg, head, treenodes);
- if (ret == NULL && rt->rt_flags & RTF_HOST) {
- struct rtentry *rt2;
- /*
- * We are trying to add a host route, but can't.
- * Find out if it is because of an
- * ARP entry and delete it if so.
- */
- rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_CLONING);
- if (rt2) {
- if (rt2->rt_flags & RTF_LLINFO &&
- rt2->rt_flags & RTF_HOST &&
- rt2->rt_gateway &&
- rt2->rt_gateway->sa_family == AF_LINK) {
- rtexpunge(rt2);
- RTFREE_LOCKED(rt2);
- ret = rn_addroute(v_arg, n_arg, head,
- treenodes);
- } else
- RTFREE_LOCKED(rt2);
- }
- } else if (ret == NULL && rt->rt_flags & RTF_CLONING) {
+ if (ret == NULL) {
struct rtentry *rt2;
/*
* We are trying to add a net route, but can't.
@@ -187,10 +168,9 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
* net route entry, 3ffe:0501:: -> if0.
* This case should not raise an error.
*/
- rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_CLONING);
+ rt2 = rtalloc1((struct sockaddr *)sin6, 0, RTF_RNH_LOCKED);
if (rt2) {
- if ((rt2->rt_flags & (RTF_CLONING|RTF_HOST|RTF_GATEWAY))
- == RTF_CLONING
+ if (((rt2->rt_flags & (RTF_HOST|RTF_GATEWAY)) == 0)
&& rt2->rt_gateway
&& rt2->rt_gateway->sa_family == AF_LINK
&& rt2->rt_ifp == rt->rt_ifp) {
@@ -199,7 +179,7 @@ in6_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
RTFREE_LOCKED(rt2);
}
}
- return ret;
+ return (ret);
}
/*
@@ -240,39 +220,6 @@ SYSCTL_V_INT(V_NET, vnet_inet6, _net_inet6_ip6, IPV6CTL_RTMAXCACHE,
rtmaxcache, CTLFLAG_RW, rtq_toomany6 , 0, "");
-/*
- * On last reference drop, mark the route as belong to us so that it can be
- * timed out.
- */
-static void
-in6_clsroute(struct radix_node *rn, struct radix_node_head *head)
-{
- INIT_VNET_INET6(curvnet);
- struct rtentry *rt = (struct rtentry *)rn;
-
- RT_LOCK_ASSERT(rt);
-
- if (!(rt->rt_flags & RTF_UP))
- return; /* prophylactic measures */
-
- if ((rt->rt_flags & (RTF_LLINFO | RTF_HOST)) != RTF_HOST)
- return;
-
- if ((rt->rt_flags & (RTF_WASCLONED | RTPRF_OURS)) != RTF_WASCLONED)
- return;
-
- /*
- * As requested by David Greenman:
- * If rtq_reallyold6 is 0, just delete the route without
- * waiting for a timeout cycle to kill it.
- */
- if (V_rtq_reallyold6 != 0) {
- rt->rt_flags |= RTPRF_OURS;
- rt->rt_rmx.rmx_expire = time_uptime + V_rtq_reallyold6;
- } else {
- rtexpunge(rt);
- }
-}
struct rtqk_arg {
struct radix_node_head *rnh;
@@ -307,7 +254,7 @@ in6_rtqkill(struct radix_node *rn, void *rock)
err = rtrequest(RTM_DELETE,
(struct sockaddr *)rt_key(rt),
rt->rt_gateway, rt_mask(rt),
- rt->rt_flags, 0);
+ rt->rt_flags|RTF_RNH_LOCKED, 0);
if (err) {
log(LOG_WARNING, "in6_rtqkill: error %d", err);
} else {
@@ -495,7 +442,6 @@ in6_inithead(void **head, int off)
rnh = *head;
rnh->rnh_addaddr = in6_addroute;
rnh->rnh_matchaddr = in6_matroute;
- rnh->rnh_close = in6_clsroute;
callout_init(&V_rtq_timer6, CALLOUT_MPSAFE);
in6_rtqtimo(rnh); /* kick off timeout first time */
callout_init(&V_rtq_mtutimer, CALLOUT_MPSAFE);
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 4d7723a..ca65bc9 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/route.h>
+#include <net/if_llatbl.h>
#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
#endif
@@ -131,7 +132,7 @@ int ip6_prefer_tempaddr;
static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int, int));
+ struct rtentry **, int));
static int in6_selectif __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *ro, struct ifnet **));
@@ -479,8 +480,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
static int
selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int clone,
- int norouteok)
+ struct ifnet **retifp, struct rtentry **retrt, int norouteok)
{
INIT_VNET_INET6(curvnet);
int error = 0;
@@ -536,9 +536,10 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*/
if (opts && opts->ip6po_nexthop) {
struct route_in6 *ron;
-
+ struct llentry *la;
+
sin6_next = satosin6(opts->ip6po_nexthop);
-
+
/* at this moment, we only support AF_INET6 next hops */
if (sin6_next->sin6_family != AF_INET6) {
error = EAFNOSUPPORT; /* or should we proceed? */
@@ -550,6 +551,36 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
* by that address must be a neighbor of the sending host.
*/
ron = &opts->ip6po_nextroute;
+ /*
+ * XXX what do we do here?
+ * PLZ to be fixing
+ */
+
+
+ if (ron->ro_rt == NULL) {
+ rtalloc((struct route *)ron); /* multi path case? */
+ if (ron->ro_rt == NULL) {
+ if (ron->ro_rt) {
+ RTFREE(ron->ro_rt);
+ ron->ro_rt = NULL;
+ }
+ error = EHOSTUNREACH;
+ goto done;
+ }
+ }
+
+ rt = ron->ro_rt;
+ ifp = rt->rt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6_next->sin6_addr);
+ IF_AFDATA_UNLOCK(ifp);
+ if (la != NULL)
+ LLE_RUNLOCK(la);
+ else {
+ error = EHOSTUNREACH;
+ goto done;
+ }
+#if 0
if ((ron->ro_rt &&
(ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) !=
(RTF_UP | RTF_LLINFO)) ||
@@ -573,16 +604,14 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
goto done;
}
}
- rt = ron->ro_rt;
- ifp = rt->rt_ifp;
+#endif
/*
* When cloning is required, try to allocate a route to the
* destination so that the caller can store path MTU
* information.
*/
- if (!clone)
- goto done;
+ goto done;
}
/*
@@ -608,21 +637,17 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*sa6 = *dstsock;
sa6->sin6_scope_id = 0;
- if (clone) {
#ifdef RADIX_MPATH
rtalloc_mpath((struct route *)ro,
ntohl(sa6->sin6_addr.s6_addr32[3]));
-#else
- rtalloc((struct route *)ro);
-#endif
- } else {
+#else
ro->ro_rt = rtalloc1(&((struct route *)ro)
- ->ro_dst, 0, 0UL);
+ ->ro_dst, 0, 0UL);
if (ro->ro_rt)
RT_UNLOCK(ro->ro_rt);
- }
+#endif
}
-
+
/*
* do not care about the result if we have the nexthop
* explicitly specified.
@@ -693,7 +718,7 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
}
if ((error = selectroute(dstsock, opts, mopts, ro, retifp,
- &rt, 0, 1)) != 0) {
+ &rt, 1)) != 0) {
if (ro == &sro && rt && rt == sro.ro_rt)
RTFREE(rt);
return (error);
@@ -745,11 +770,11 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
int
in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int clone)
+ struct ifnet **retifp, struct rtentry **retrt)
{
return (selectroute(dstsock, opts, mopts, ro, retifp,
- retrt, clone, 0));
+ retrt, 0));
}
/*
@@ -760,7 +785,7 @@ in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
* 3. The system default hoplimit.
*/
int
-in6_selecthlim(struct in6pcb *in6p, struct ifnet *ifp)
+in6_selecthlim(struct inpcb *in6p, struct ifnet *ifp)
{
INIT_VNET_INET6(curvnet);
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index e906d7c..b5dba5e 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -88,13 +88,17 @@ struct in6_addrlifetime {
struct nd_ifinfo;
struct scope6_id;
+struct lltable;
struct in6_ifextra {
struct in6_ifstat *in6_ifstat;
struct icmp6_ifstat *icmp6_ifstat;
struct nd_ifinfo *nd_ifinfo;
struct scope6_id *scope6_id;
+ struct lltable *lltable;
};
+#define LLTABLE6(ifp) (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->lltable)
+
struct in6_ifaddr {
struct ifaddr ia_ifa; /* protocol-independent info */
#define ia_ifp ia_ifa.ifa_ifp
@@ -474,6 +478,8 @@ struct in6_rrenumreq {
extern struct in6_ifaddr *in6_ifaddr;
extern struct icmp6stat icmp6stat;
+
+extern unsigned long in6_maxmtu;
#endif /* VIMAGE_GLOBALS */
#define in6_ifstat_inc(ifp, tag) \
do { \
@@ -483,7 +489,6 @@ do { \
extern struct in6_addr zeroin6_addr;
extern u_char inet6ctlerrmap[];
-extern unsigned long in6_maxmtu;
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_IP6MADDR);
#endif /* MALLOC_DECLARE */
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 7edcaa3..228777b 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_systm.h>
+#include <net/if_llatbl.h>
#ifdef INET
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
@@ -130,7 +131,6 @@ struct vnet_inet6 vnet_inet6_0;
static int ip6qmaxlen;
struct in6_ifaddr *in6_ifaddr;
struct ip6stat ip6stat;
-#endif
extern struct callout in6_tmpaddrtimer_ch;
@@ -144,7 +144,8 @@ extern int icmp6_nodeinfo;
extern int udp6_sendspace;
extern int udp6_recvspace;
-#ifdef VIMAGE_GLOBALS
+extern struct route_in6 ip6_forward_rt;
+
int ip6_forward_srcrt; /* XXX */
int ip6_sourcecheck; /* XXX */
int ip6_sourcecheck_interval; /* XXX */
@@ -301,8 +302,6 @@ ip6_init2(void *dummy)
/* This must be after route_init(), which is now SI_ORDER_THIRD */
SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
-extern struct route_in6 ip6_forward_rt;
-
void
ip6_input(struct mbuf *m)
{
@@ -313,9 +312,11 @@ ip6_input(struct mbuf *m)
u_int32_t plen;
u_int32_t rtalert = ~0;
int nxt, ours = 0;
- struct ifnet *deliverifp = NULL;
+ struct ifnet *deliverifp = NULL, *ifp = NULL;
struct in6_addr odst;
int srcrt = 0;
+ struct llentry *lle = NULL;
+ struct sockaddr_in6 dst6;
#ifdef IPSEC
/*
@@ -550,6 +551,25 @@ passin:
/*
* Unicast check
*/
+
+ bzero(&dst6, sizeof(dst6));
+ dst6.sin6_family = AF_INET6;
+ dst6.sin6_len = sizeof(struct sockaddr_in6);
+ dst6.sin6_addr = ip6->ip6_dst;
+ ifp = m->m_pkthdr.rcvif;
+ IF_AFDATA_LOCK(ifp);
+ lle = lla_lookup(LLTABLE6(ifp), 0,
+ (struct sockaddr *)&dst6);
+ IF_AFDATA_UNLOCK(ifp);
+ if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) {
+ ours = 1;
+ deliverifp = ifp;
+ LLE_RUNLOCK(lle);
+ goto hbhcheck;
+ }
+ if (lle != NULL)
+ LLE_RUNLOCK(lle);
+
if (V_ip6_forward_rt.ro_rt != NULL &&
(V_ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 &&
IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
@@ -1206,7 +1226,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
if (v4only)
return;
- if ((in6p->in6p_flags & IN6P_TCLASS) != 0) {
+ if ((in6p->inp_flags & IN6P_TCLASS) != 0) {
u_int32_t flowinfo;
int tclass;
@@ -1227,7 +1247,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
* returned to normal user.
* See also RFC 2292 section 6 (or RFC 3542 section 8).
*/
- if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) {
+ if ((in6p->inp_flags & IN6P_HOPOPTS) != 0) {
/*
* Check if a hop-by-hop options header is contatined in the
* received packet, and if so, store the options as ancillary
@@ -1279,7 +1299,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
}
}
- if ((in6p->in6p_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
+ if ((in6p->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) {
int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
/*
@@ -1340,7 +1360,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
switch (nxt) {
case IPPROTO_DSTOPTS:
- if (!(in6p->in6p_flags & IN6P_DSTOPTS))
+ if (!(in6p->inp_flags & IN6P_DSTOPTS))
break;
*mp = sbcreatecontrol((caddr_t)ip6e, elen,
@@ -1351,7 +1371,7 @@ ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp)
mp = &(*mp)->m_next;
break;
case IPPROTO_ROUTING:
- if (!in6p->in6p_flags & IN6P_RTHDR)
+ if (!in6p->inp_flags & IN6P_RTHDR)
break;
*mp = sbcreatecontrol((caddr_t)ip6e, elen,
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 6e5d0d0..ba40b68 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -615,7 +615,7 @@ again:
dst_sa.sin6_len = sizeof(dst_sa);
dst_sa.sin6_addr = ip6->ip6_dst;
if ((error = in6_selectroute(&dst_sa, opt, im6o, ro,
- &ifp, &rt, 0)) != 0) {
+ &ifp, &rt)) != 0) {
switch (error) {
case EHOSTUNREACH:
V_ip6stat.ip6s_noroute++;
@@ -1320,7 +1320,7 @@ ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
struct in_conninfo inc;
bzero(&inc, sizeof(inc));
- inc.inc_flags = 1; /* IPv6 */
+ inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = *dst;
if (ifp == NULL)
@@ -1464,7 +1464,7 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
else {
/* -1 = kernel default */
in6p->in6p_hops = optval;
- if ((in6p->in6p_vflag &
+ if ((in6p->inp_vflag &
INP_IPV4) != 0)
in6p->inp_ip_ttl = optval;
}
@@ -1472,19 +1472,19 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt)
#define OPTSET(bit) \
do { \
if (optval) \
- in6p->in6p_flags |= (bit); \
+ in6p->inp_flags |= (bit); \
else \
- in6p->in6p_flags &= ~(bit); \
+ in6p->inp_flags &= ~(bit); \
} while (/*CONSTCOND*/ 0)
#define OPTSET2292(bit) \
do { \
- in6p->in6p_flags |= IN6P_RFC2292; \
+ in6p->inp_flags |= IN6P_RFC2292; \
if (optval) \
- in6p->in6p_flags |= (bit); \
+ in6p->inp_flags |= (bit); \
else \
- in6p->in6p_flags &= ~(bit); \
+ in6p->inp_flags &= ~(bit); \
} while (/*CONSTCOND*/ 0)
-#define OPTBIT(bit) (in6p->in6p_flags & (bit) ? 1 : 0)
+#define OPTBIT(bit) (in6p->inp_flags & (bit) ? 1 : 0)
case IPV6_RECVPKTINFO:
/* cannot mix with RFC2292 */
@@ -1558,7 +1558,7 @@ do { \
break;
case IPV6_FAITH:
- OPTSET(IN6P_FAITH);
+ OPTSET(INP_FAITH);
break;
case IPV6_RECVPATHMTU:
@@ -1578,16 +1578,16 @@ do { \
* available only prior to bind(2).
* see ipng mailing list, Jun 22 2001.
*/
- if (in6p->in6p_lport ||
+ if (in6p->inp_lport ||
!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
error = EINVAL;
break;
}
OPTSET(IN6P_IPV6_V6ONLY);
if (optval)
- in6p->in6p_vflag &= ~INP_IPV4;
+ in6p->inp_vflag &= ~INP_IPV4;
else
- in6p->in6p_vflag |= INP_IPV4;
+ in6p->inp_vflag |= INP_IPV4;
break;
case IPV6_RECVTCLASS:
/* cannot mix with RFC2292 XXX */
@@ -1768,18 +1768,18 @@ do { \
switch (optval) {
case IPV6_PORTRANGE_DEFAULT:
- in6p->in6p_flags &= ~(IN6P_LOWPORT);
- in6p->in6p_flags &= ~(IN6P_HIGHPORT);
+ in6p->inp_flags &= ~(INP_LOWPORT);
+ in6p->inp_flags &= ~(INP_HIGHPORT);
break;
case IPV6_PORTRANGE_HIGH:
- in6p->in6p_flags &= ~(IN6P_LOWPORT);
- in6p->in6p_flags |= IN6P_HIGHPORT;
+ in6p->inp_flags &= ~(INP_LOWPORT);
+ in6p->inp_flags |= INP_HIGHPORT;
break;
case IPV6_PORTRANGE_LOW:
- in6p->in6p_flags &= ~(IN6P_HIGHPORT);
- in6p->in6p_flags |= IN6P_LOWPORT;
+ in6p->inp_flags &= ~(INP_HIGHPORT);
+ in6p->inp_flags |= INP_LOWPORT;
break;
default:
@@ -1881,7 +1881,7 @@ do { \
break;
case IPV6_FAITH:
- optval = OPTBIT(IN6P_FAITH);
+ optval = OPTBIT(INP_FAITH);
break;
case IPV6_V6ONLY:
@@ -1891,10 +1891,10 @@ do { \
case IPV6_PORTRANGE:
{
int flags;
- flags = in6p->in6p_flags;
- if (flags & IN6P_HIGHPORT)
+ flags = in6p->inp_flags;
+ if (flags & INP_HIGHPORT)
optval = IPV6_PORTRANGE_HIGH;
- else if (flags & IN6P_LOWPORT)
+ else if (flags & INP_LOWPORT)
optval = IPV6_PORTRANGE_LOW;
else
optval = 0;
@@ -2050,7 +2050,7 @@ ip6_raw_ctloutput(struct socket *so, struct sockopt *sopt)
{
int error = 0, optval, optlen;
const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
- struct in6pcb *in6p = sotoin6pcb(so);
+ struct inpcb *in6p = sotoinpcb(so);
int level, op, optname;
level = sopt->sopt_level;
@@ -3326,7 +3326,7 @@ ip6_splithdr(struct mbuf *m, struct ip6_exthdrs *exthdrs)
* Compute IPv6 extension header length.
*/
int
-ip6_optlen(struct in6pcb *in6p)
+ip6_optlen(struct inpcb *in6p)
{
int len;
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index e384da1..55bc5db 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -313,15 +313,16 @@ extern int ip6_auto_linklocal;
extern int ip6_use_tempaddr; /* whether to use temporary addresses. */
extern int ip6_prefer_tempaddr; /* whether to prefer temporary addresses
in the source address selection */
-#endif /* VIMAGE_GLOBALS */
+
+#ifdef IPSTEALTH
+extern int ip6stealth;
+#endif
extern int ip6_use_defzone; /* whether to use the default scope zone
when unspecified */
+#endif /* VIMAGE_GLOBALS */
extern struct pfil_head inet6_pfil_hook; /* packet filter hooks */
-#ifdef IPSTEALTH
-extern int ip6stealth;
-#endif
extern struct pr_usrreqs rip6_usrreqs;
struct sockopt;
@@ -397,7 +398,7 @@ struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ifnet **, int *));
int in6_selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int));
+ struct rtentry **));
u_int32_t ip6_randomid __P((void));
u_int32_t ip6_randomflowlabel __P((void));
#endif /* _KERNEL */
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 18e81c3..e2ca9eb 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
#include <sys/protosw.h>
#include <sys/errno.h>
#include <sys/syslog.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
@@ -61,6 +63,8 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <net/if_llatbl.h>
+#define L3_ADDR_SIN6(le) ((struct sockaddr_in6 *) L3_ADDR(le))
#include <netinet/if_ether.h>
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
@@ -98,8 +102,9 @@ int nd6_maxqueuelen;
int nd6_debug;
/* for debugging? */
+#if 0
static int nd6_inuse, nd6_allocated;
-struct llinfo_nd6 llinfo_nd6;
+#endif
struct nd_drhead nd_defrouter;
struct nd_prhead nd_prefix;
@@ -114,9 +119,9 @@ static int nd6_is_new_addr_neighbor __P((struct sockaddr_in6 *,
static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
static void nd6_slowtimo(void *);
static int regen_tmpaddr(struct in6_ifaddr *);
-static struct llinfo_nd6 *nd6_free(struct rtentry *, int);
+static struct llentry *nd6_free(struct llentry *, int);
static void nd6_llinfo_timer(void *);
-static void clear_llinfo_pqueue(struct llinfo_nd6 *);
+static void clear_llinfo_pqueue(struct llentry *);
#ifdef VIMAGE_GLOBALS
struct callout nd6_slowtimo_ch;
@@ -162,8 +167,13 @@ nd6_init(void)
V_dad_ignore_ns = 0; /* ignore NS in DAD - specwise incorrect*/
V_dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */
+ /*
+ * XXX just to get this to compile KMM
+ */
+#ifdef notyet
V_llinfo_nd6.ln_next = &V_llinfo_nd6;
V_llinfo_nd6.ln_prev = &V_llinfo_nd6;
+#endif
LIST_INIT(&V_nd_prefix);
V_ip6_use_tempaddr = 0;
@@ -424,14 +434,23 @@ skip1:
* ND6 timer routine to handle ND6 entries
*/
void
-nd6_llinfo_settimer(struct llinfo_nd6 *ln, long tick)
+nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
{
if (tick < 0) {
- ln->ln_expire = 0;
+ ln->la_expire = 0;
ln->ln_ntick = 0;
callout_stop(&ln->ln_timer_ch);
+ /*
+ * XXX - do we know that there is
+ * callout installed? i.e. are we
+ * guaranteed that we're not dropping
+ * a reference that we did not add?
+ * KMM
+ */
+ LLE_REMREF(ln);
} else {
- ln->ln_expire = time_second + tick / hz;
+ ln->la_expire = time_second + tick / hz;
+ LLE_ADDREF(ln);
if (tick > INT_MAX) {
ln->ln_ntick = tick - INT_MAX;
callout_reset(&ln->ln_timer_ch, INT_MAX,
@@ -444,16 +463,34 @@ nd6_llinfo_settimer(struct llinfo_nd6 *ln, long tick)
}
}
+void
+nd6_llinfo_settimer(struct llentry *ln, long tick)
+{
+
+ LLE_WLOCK(ln);
+ nd6_llinfo_settimer_locked(ln, tick);
+ LLE_WUNLOCK(ln);
+}
+
static void
nd6_llinfo_timer(void *arg)
{
- struct llinfo_nd6 *ln;
- struct rtentry *rt;
+ struct llentry *ln;
struct in6_addr *dst;
struct ifnet *ifp;
struct nd_ifinfo *ndi = NULL;
- ln = (struct llinfo_nd6 *)arg;
+ ln = (struct llentry *)arg;
+ if (ln == NULL) {
+ panic("%s: NULL entry!\n", __func__);
+ return;
+ }
+
+ if ((ifp = ((ln->lle_tbl != NULL) ? ln->lle_tbl->llt_ifp : NULL)) == NULL)
+ panic("ln ifp == NULL");
+
+ CURVNET_SET(ifp->if_vnet);
+ INIT_VNET_INET6(curvnet);
if (ln->ln_ntick > 0) {
if (ln->ln_ntick > INT_MAX) {
@@ -463,52 +500,44 @@ nd6_llinfo_timer(void *arg)
ln->ln_ntick = 0;
nd6_llinfo_settimer(ln, ln->ln_ntick);
}
- return;
+ goto done;
}
- if ((rt = ln->ln_rt) == NULL)
- panic("ln->ln_rt == NULL");
- if ((ifp = rt->rt_ifp) == NULL)
- panic("ln->ln_rt->rt_ifp == NULL");
ndi = ND_IFINFO(ifp);
+ dst = &L3_ADDR_SIN6(ln)->sin6_addr;
+ if ((ln->la_flags & LLE_STATIC) || (ln->la_expire > time_second)) {
+ goto done;
+ }
- CURVNET_SET(ifp->if_vnet);
- INIT_VNET_INET6(curvnet);
-
- /* sanity check */
- if (rt->rt_llinfo && (struct llinfo_nd6 *)rt->rt_llinfo != ln)
- panic("rt_llinfo(%p) is not equal to ln(%p)",
- rt->rt_llinfo, ln);
- if (rt_key(rt) == NULL)
- panic("rt key is NULL in nd6_timer(ln=%p)", ln);
-
- dst = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
+ if (ln->la_flags & LLE_DELETED) {
+ (void)nd6_free(ln, 0);
+ goto done;
+ }
switch (ln->ln_state) {
case ND6_LLINFO_INCOMPLETE:
- if (ln->ln_asked < V_nd6_mmaxtries) {
- ln->ln_asked++;
+ if (ln->la_asked < V_nd6_mmaxtries) {
+ ln->la_asked++;
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_ns_output(ifp, NULL, dst, ln, 0);
} else {
- struct mbuf *m = ln->ln_hold;
+ struct mbuf *m = ln->la_hold;
if (m) {
struct mbuf *m0;
/*
- * assuming every packet in ln_hold has the
+ * assuming every packet in la_hold has the
* same IP header
*/
m0 = m->m_nextpkt;
m->m_nextpkt = NULL;
icmp6_error2(m, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_ADDR, 0, rt->rt_ifp);
+ ICMP6_DST_UNREACH_ADDR, 0, ifp);
- ln->ln_hold = m0;
+ ln->la_hold = m0;
clear_llinfo_pqueue(ln);
}
- if (rt && rt->rt_llinfo)
- (void)nd6_free(rt, 0);
+ (void)nd6_free(ln, 0);
ln = NULL;
}
break;
@@ -522,8 +551,7 @@ nd6_llinfo_timer(void *arg)
case ND6_LLINFO_STALE:
/* Garbage Collection(RFC 2461 5.3) */
if (!ND6_LLINFO_PERMANENT(ln)) {
- if (rt && rt->rt_llinfo)
- (void)nd6_free(rt, 1);
+ (void)nd6_free(ln, 1);
ln = NULL;
}
break;
@@ -531,7 +559,7 @@ nd6_llinfo_timer(void *arg)
case ND6_LLINFO_DELAY:
if (ndi && (ndi->flags & ND6_IFF_PERFORMNUD) != 0) {
/* We need NUD */
- ln->ln_asked = 1;
+ ln->la_asked = 1;
ln->ln_state = ND6_LLINFO_PROBE;
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_ns_output(ifp, dst, dst, ln, 0);
@@ -541,31 +569,20 @@ nd6_llinfo_timer(void *arg)
}
break;
case ND6_LLINFO_PROBE:
- if (ln->ln_asked < V_nd6_umaxtries) {
- ln->ln_asked++;
+ if (ln->la_asked < V_nd6_umaxtries) {
+ ln->la_asked++;
nd6_llinfo_settimer(ln, (long)ndi->retrans * hz / 1000);
nd6_ns_output(ifp, dst, dst, ln, 0);
- } else if (rt->rt_ifa != NULL &&
- rt->rt_ifa->ifa_addr->sa_family == AF_INET6 &&
- (((struct in6_ifaddr *)rt->rt_ifa)->ia_flags & IFA_ROUTE)) {
- /*
- * This is an unreachable neighbor whose address is
- * specified as the destination of a p2p interface
- * (see in6_ifinit()). We should not free the entry
- * since this is sort of a "static" entry generated
- * via interface address configuration.
- */
- ln->ln_asked = 0;
- ln->ln_expire = 0; /* make it permanent */
- ln->ln_state = ND6_LLINFO_STALE;
} else {
- if (rt && rt->rt_llinfo)
- (void)nd6_free(rt, 0);
+ (void)nd6_free(ln, 0);
ln = NULL;
}
break;
}
CURVNET_RESTORE();
+done:
+ if (ln != NULL)
+ LLE_FREE(ln);
}
@@ -772,7 +789,6 @@ void
nd6_purge(struct ifnet *ifp)
{
INIT_VNET_INET6(ifp->if_vnet);
- struct llinfo_nd6 *ln, *nln;
struct nd_defrouter *dr, *ndr;
struct nd_prefix *pr, *npr;
@@ -829,132 +845,54 @@ nd6_purge(struct ifnet *ifp)
nd6_setdefaultiface(0);
if (!V_ip6_forwarding && V_ip6_accept_rtadv) { /* XXX: too restrictive? */
- /* refresh default router list */
+ /* refresh default router list
+ *
+ *
+ */
defrouter_select();
+
}
- /*
- * Nuke neighbor cache entries for the ifp.
- * Note that rt->rt_ifp may not be the same as ifp,
- * due to KAME goto ours hack. See RTM_RESOLVE case in
- * nd6_rtrequest(), and ip6_input().
+ /* XXXXX
+ * We do not nuke the neighbor cache entries here any more
+ * because the neighbor cache is kept in if_afdata[AF_INET6].
+ * nd6_purge() is invoked by in6_ifdetach() which is called
+ * from if_detach() where everything gets purged. So let
+ * in6_domifdetach() do the actual L2 table purging work.
*/
- ln = V_llinfo_nd6.ln_next;
- while (ln && ln != &V_llinfo_nd6) {
- struct rtentry *rt;
- struct sockaddr_dl *sdl;
-
- nln = ln->ln_next;
- rt = ln->ln_rt;
- if (rt && rt->rt_gateway &&
- rt->rt_gateway->sa_family == AF_LINK) {
- sdl = (struct sockaddr_dl *)rt->rt_gateway;
- if (sdl->sdl_index == ifp->if_index)
- nln = nd6_free(rt, 0);
- }
- ln = nln;
- }
}
-struct rtentry *
-nd6_lookup(struct in6_addr *addr6, int create, struct ifnet *ifp)
+/*
+ * the caller acquires and releases the lock on the lltbls
+ * Returns the llentry locked
+ */
+struct llentry *
+nd6_lookup(struct in6_addr *addr6, int flags, struct ifnet *ifp)
{
INIT_VNET_INET6(curvnet);
- struct rtentry *rt;
struct sockaddr_in6 sin6;
- char ip6buf[INET6_ADDRSTRLEN];
-
+ struct llentry *ln;
+ int llflags = 0;
+
bzero(&sin6, sizeof(sin6));
sin6.sin6_len = sizeof(struct sockaddr_in6);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = *addr6;
- rt = rtalloc1((struct sockaddr *)&sin6, create, 0UL);
- if (rt) {
- if ((rt->rt_flags & RTF_LLINFO) == 0 && create) {
- /*
- * This is the case for the default route.
- * If we want to create a neighbor cache for the
- * address, we should free the route for the
- * destination and allocate an interface route.
- */
- RTFREE_LOCKED(rt);
- rt = NULL;
- }
- }
- if (rt == NULL) {
- if (create && ifp) {
- int e;
- /*
- * If no route is available and create is set,
- * we allocate a host route for the destination
- * and treat it like an interface route.
- * This hack is necessary for a neighbor which can't
- * be covered by our own prefix.
- */
- struct ifaddr *ifa =
- ifaof_ifpforaddr((struct sockaddr *)&sin6, ifp);
- if (ifa == NULL)
- return (NULL);
+ IF_AFDATA_LOCK_ASSERT(ifp);
- /*
- * Create a new route. RTF_LLINFO is necessary
- * to create a Neighbor Cache entry for the
- * destination in nd6_rtrequest which will be
- * called in rtrequest via ifa->ifa_rtrequest.
- */
- if ((e = rtrequest(RTM_ADD, (struct sockaddr *)&sin6,
- ifa->ifa_addr, (struct sockaddr *)&all1_sa,
- (ifa->ifa_flags | RTF_HOST | RTF_LLINFO) &
- ~RTF_CLONING, &rt)) != 0) {
- log(LOG_ERR,
- "nd6_lookup: failed to add route for a "
- "neighbor(%s), errno=%d\n",
- ip6_sprintf(ip6buf, addr6), e);
- }
- if (rt == NULL)
- return (NULL);
- RT_LOCK(rt);
- if (rt->rt_llinfo) {
- struct llinfo_nd6 *ln =
- (struct llinfo_nd6 *)rt->rt_llinfo;
- ln->ln_state = ND6_LLINFO_NOSTATE;
- }
- } else
- return (NULL);
- }
- RT_LOCK_ASSERT(rt);
- RT_REMREF(rt);
- /*
- * Validation for the entry.
- * Note that the check for rt_llinfo is necessary because a cloned
- * route from a parent route that has the L flag (e.g. the default
- * route to a p2p interface) may have the flag, too, while the
- * destination is not actually a neighbor.
- * XXX: we can't use rt->rt_ifp to check for the interface, since
- * it might be the loopback interface if the entry is for our
- * own address on a non-loopback interface. Instead, we should
- * use rt->rt_ifa->ifa_ifp, which would specify the REAL
- * interface.
- * Note also that ifa_ifp and ifp may differ when we connect two
- * interfaces to a same link, install a link prefix to an interface,
- * and try to install a neighbor cache on an interface that does not
- * have a route to the prefix.
- */
- if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
- rt->rt_gateway->sa_family != AF_LINK || rt->rt_llinfo == NULL ||
- (ifp && rt->rt_ifa->ifa_ifp != ifp)) {
- if (create) {
- nd6log((LOG_DEBUG,
- "nd6_lookup: failed to lookup %s (if = %s)\n",
- ip6_sprintf(ip6buf, addr6),
- ifp ? if_name(ifp) : "unspec"));
- }
- RT_UNLOCK(rt);
- return (NULL);
+ if (flags & ND6_CREATE)
+ llflags |= LLE_CREATE;
+ if (flags & ND6_EXCLUSIVE)
+ llflags |= LLE_EXCLUSIVE;
+
+ ln = lla_lookup(LLTABLE6(ifp), llflags, (struct sockaddr *)&sin6);
+ if ((ln != NULL) && (flags & LLE_CREATE)) {
+ ln->ln_state = ND6_LLINFO_NOSTATE;
+ callout_init(&ln->ln_timer_ch, 0);
}
- RT_UNLOCK(rt); /* XXX not ready to return rt locked */
- return (rt);
+
+ return (ln);
}
/*
@@ -1040,7 +978,10 @@ nd6_is_new_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
int
nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
{
+ struct llentry *lle;
+ int rc = 0;
+ IF_AFDATA_UNLOCK_ASSERT(ifp);
if (nd6_is_new_addr_neighbor(addr, ifp))
return (1);
@@ -1048,10 +989,13 @@ nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
* Even if the address matches none of our addresses, it might be
* in the neighbor cache.
*/
- if (nd6_lookup(&addr->sin6_addr, 0, ifp) != NULL)
- return (1);
-
- return (0);
+ IF_AFDATA_LOCK(ifp);
+ if ((lle = nd6_lookup(&addr->sin6_addr, 0, ifp)) != NULL) {
+ LLE_RUNLOCK(lle);
+ rc = 1;
+ }
+ IF_AFDATA_UNLOCK(ifp);
+ return (rc);
}
/*
@@ -1060,13 +1004,13 @@ nd6_is_addr_neighbor(struct sockaddr_in6 *addr, struct ifnet *ifp)
* make it global, unless you have a strong reason for the change, and are sure
* that the change is safe.
*/
-static struct llinfo_nd6 *
-nd6_free(struct rtentry *rt, int gc)
+static struct llentry *
+nd6_free(struct llentry *ln, int gc)
{
INIT_VNET_INET6(curvnet);
- struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo, *next;
- struct in6_addr in6 = ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
+ struct llentry *next;
struct nd_defrouter *dr;
+ struct ifnet *ifp=NULL;
/*
* we used to have pfctlinput(PRC_HOSTDEAD) here.
@@ -1079,8 +1023,7 @@ nd6_free(struct rtentry *rt, int gc)
if (!V_ip6_forwarding) {
int s;
s = splnet();
- dr = defrouter_lookup(&((struct sockaddr_in6 *)rt_key(rt))->sin6_addr,
- rt->rt_ifp);
+ dr = defrouter_lookup(&L3_ADDR_SIN6(ln)->sin6_addr, ln->lle_tbl->llt_ifp);
if (dr != NULL && dr->expire &&
ln->ln_state == ND6_LLINFO_STALE && gc) {
@@ -1102,7 +1045,7 @@ nd6_free(struct rtentry *rt, int gc)
else
nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
splx(s);
- return (ln->ln_next);
+ return (LIST_NEXT(ln, lle_next));
}
if (ln->ln_router || dr) {
@@ -1111,7 +1054,7 @@ nd6_free(struct rtentry *rt, int gc)
* is in the Default Router List.
* See a corresponding comment in nd6_na_input().
*/
- rt6_flush(&in6, rt->rt_ifp);
+ rt6_flush(&L3_ADDR_SIN6(ln)->sin6_addr, ln->lle_tbl->llt_ifp);
}
if (dr) {
@@ -1152,15 +1095,13 @@ nd6_free(struct rtentry *rt, int gc)
* might have freed other entries (particularly the old next entry) as
* a side effect (XXX).
*/
- next = ln->ln_next;
+ next = LIST_NEXT(ln, lle_next);
- /*
- * Detach the route from the routing tree and the list of neighbor
- * caches, and disable the route entry not to be used in already
- * cached routes.
- */
- rtrequest(RTM_DELETE, rt_key(rt), (struct sockaddr *)0,
- rt_mask(rt), 0, (struct rtentry **)0);
+ ifp = ln->lle_tbl->llt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ LLE_WLOCK(ln);
+ llentry_free(ln);
+ IF_AFDATA_UNLOCK(ifp);
return (next);
}
@@ -1174,297 +1115,42 @@ void
nd6_nud_hint(struct rtentry *rt, struct in6_addr *dst6, int force)
{
INIT_VNET_INET6(curvnet);
- struct llinfo_nd6 *ln;
+ struct llentry *ln;
+ struct ifnet *ifp;
- /*
- * If the caller specified "rt", use that. Otherwise, resolve the
- * routing table by supplied "dst6".
- */
- if (rt == NULL) {
- if (dst6 == NULL)
- return;
- if ((rt = nd6_lookup(dst6, 0, NULL)) == NULL)
- return;
- }
-
- if ((rt->rt_flags & RTF_GATEWAY) != 0 ||
- (rt->rt_flags & RTF_LLINFO) == 0 ||
- rt->rt_llinfo == NULL || rt->rt_gateway == NULL ||
- rt->rt_gateway->sa_family != AF_LINK) {
- /* This is not a host route. */
+ if ((dst6 == NULL) || (rt == NULL))
return;
- }
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- if (ln->ln_state < ND6_LLINFO_REACHABLE)
+ ifp = rt->rt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(dst6, ND6_EXCLUSIVE, NULL);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln == NULL)
return;
+ if (ln->ln_state < ND6_LLINFO_REACHABLE)
+ goto done;
+
/*
* if we get upper-layer reachability confirmation many times,
* it is possible we have false information.
*/
if (!force) {
ln->ln_byhint++;
- if (ln->ln_byhint > V_nd6_maxnudhint)
- return;
+ if (ln->ln_byhint > V_nd6_maxnudhint) {
+ goto done;
+ }
}
- ln->ln_state = ND6_LLINFO_REACHABLE;
+ ln->ln_state = ND6_LLINFO_REACHABLE;
if (!ND6_LLINFO_PERMANENT(ln)) {
nd6_llinfo_settimer(ln,
(long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
}
+done:
+ LLE_WUNLOCK(ln);
}
-/*
- * info - XXX unused
- */
-void
-nd6_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
-{
- struct sockaddr *gate = rt->rt_gateway;
- struct llinfo_nd6 *ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
- struct ifnet *ifp = rt->rt_ifp;
- struct ifaddr *ifa;
- INIT_VNET_NET(ifp->if_vnet);
- INIT_VNET_INET6(ifp->if_vnet);
-
- RT_LOCK_ASSERT(rt);
-
- if ((rt->rt_flags & RTF_GATEWAY) != 0)
- return;
-
- if (nd6_need_cache(ifp) == 0 && (rt->rt_flags & RTF_HOST) == 0) {
- /*
- * This is probably an interface direct route for a link
- * which does not need neighbor caches (e.g. fe80::%lo0/64).
- * We do not need special treatment below for such a route.
- * Moreover, the RTF_LLINFO flag which would be set below
- * would annoy the ndp(8) command.
- */
- return;
- }
-
- if (req == RTM_RESOLVE &&
- (nd6_need_cache(ifp) == 0 || /* stf case */
- !nd6_is_new_addr_neighbor((struct sockaddr_in6 *)rt_key(rt),
- ifp))) {
- /*
- * FreeBSD and BSD/OS often make a cloned host route based
- * on a less-specific route (e.g. the default route).
- * If the less specific route does not have a "gateway"
- * (this is the case when the route just goes to a p2p or an
- * stf interface), we'll mistakenly make a neighbor cache for
- * the host route, and will see strange neighbor solicitation
- * for the corresponding destination. In order to avoid the
- * confusion, we check if the destination of the route is
- * a neighbor in terms of neighbor discovery, and stop the
- * process if not. Additionally, we remove the LLINFO flag
- * so that ndp(8) will not try to get the neighbor information
- * of the destination.
- */
- rt->rt_flags &= ~RTF_LLINFO;
- return;
- }
-
- switch (req) {
- case RTM_ADD:
- /*
- * There is no backward compatibility :)
- *
- * if ((rt->rt_flags & RTF_HOST) == 0 &&
- * SIN(rt_mask(rt))->sin_addr.s_addr != 0xffffffff)
- * rt->rt_flags |= RTF_CLONING;
- */
- if ((rt->rt_flags & RTF_CLONING) ||
- ((rt->rt_flags & RTF_LLINFO) && ln == NULL)) {
- /*
- * Case 1: This route should come from a route to
- * interface (RTF_CLONING case) or the route should be
- * treated as on-link but is currently not
- * (RTF_LLINFO && ln == NULL case).
- */
- rt_setgate(rt, rt_key(rt),
- (struct sockaddr *)&null_sdl);
- gate = rt->rt_gateway;
- SDL(gate)->sdl_type = ifp->if_type;
- SDL(gate)->sdl_index = ifp->if_index;
- if (ln)
- nd6_llinfo_settimer(ln, 0);
- if ((rt->rt_flags & RTF_CLONING) != 0)
- break;
- }
- /*
- * In IPv4 code, we try to annonuce new RTF_ANNOUNCE entry here.
- * We don't do that here since llinfo is not ready yet.
- *
- * There are also couple of other things to be discussed:
- * - unsolicited NA code needs improvement beforehand
- * - RFC2461 says we MAY send multicast unsolicited NA
- * (7.2.6 paragraph 4), however, it also says that we
- * SHOULD provide a mechanism to prevent multicast NA storm.
- * we don't have anything like it right now.
- * note that the mechanism needs a mutual agreement
- * between proxies, which means that we need to implement
- * a new protocol, or a new kludge.
- * - from RFC2461 6.2.4, host MUST NOT send an unsolicited NA.
- * we need to check ip6forwarding before sending it.
- * (or should we allow proxy ND configuration only for
- * routers? there's no mention about proxy ND from hosts)
- */
- /* FALLTHROUGH */
- case RTM_RESOLVE:
- if ((ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
- /*
- * Address resolution isn't necessary for a point to
- * point link, so we can skip this test for a p2p link.
- */
- if (gate->sa_family != AF_LINK ||
- gate->sa_len < sizeof(null_sdl)) {
- log(LOG_DEBUG,
- "nd6_rtrequest: bad gateway value: %s\n",
- if_name(ifp));
- break;
- }
- SDL(gate)->sdl_type = ifp->if_type;
- SDL(gate)->sdl_index = ifp->if_index;
- }
- if (ln != NULL)
- break; /* This happens on a route change */
- /*
- * Case 2: This route may come from cloning, or a manual route
- * add with a LL address.
- */
- R_Malloc(ln, struct llinfo_nd6 *, sizeof(*ln));
- rt->rt_llinfo = (caddr_t)ln;
- if (ln == NULL) {
- log(LOG_DEBUG, "nd6_rtrequest: malloc failed\n");
- break;
- }
- V_nd6_inuse++;
- V_nd6_allocated++;
- bzero(ln, sizeof(*ln));
- RT_ADDREF(rt);
- ln->ln_rt = rt;
- callout_init(&ln->ln_timer_ch, 0);
-
- /* this is required for "ndp" command. - shin */
- if (req == RTM_ADD) {
- /*
- * gate should have some valid AF_LINK entry,
- * and ln->ln_expire should have some lifetime
- * which is specified by ndp command.
- */
- ln->ln_state = ND6_LLINFO_REACHABLE;
- ln->ln_byhint = 0;
- } else {
- /*
- * When req == RTM_RESOLVE, rt is created and
- * initialized in rtrequest(), so rt_expire is 0.
- */
- ln->ln_state = ND6_LLINFO_NOSTATE;
- nd6_llinfo_settimer(ln, 0);
- }
- rt->rt_flags |= RTF_LLINFO;
- ln->ln_next = V_llinfo_nd6.ln_next;
- V_llinfo_nd6.ln_next = ln;
- ln->ln_prev = &V_llinfo_nd6;
- ln->ln_next->ln_prev = ln;
-
- /*
- * check if rt_key(rt) is one of my address assigned
- * to the interface.
- */
- ifa = (struct ifaddr *)in6ifa_ifpwithaddr(rt->rt_ifp,
- &SIN6(rt_key(rt))->sin6_addr);
- if (ifa) {
- caddr_t macp = nd6_ifptomac(ifp);
- nd6_llinfo_settimer(ln, -1);
- ln->ln_state = ND6_LLINFO_REACHABLE;
- ln->ln_byhint = 0;
- if (macp) {
- bcopy(macp, LLADDR(SDL(gate)), ifp->if_addrlen);
- SDL(gate)->sdl_alen = ifp->if_addrlen;
- }
- if (V_nd6_useloopback) {
- rt->rt_ifp = &V_loif[0]; /* XXX */
- /*
- * Make sure rt_ifa be equal to the ifaddr
- * corresponding to the address.
- * We need this because when we refer
- * rt_ifa->ia6_flags in ip6_input, we assume
- * that the rt_ifa points to the address instead
- * of the loopback address.
- */
- if (ifa != rt->rt_ifa) {
- IFAFREE(rt->rt_ifa);
- IFAREF(ifa);
- rt->rt_ifa = ifa;
- }
- }
- } else if (rt->rt_flags & RTF_ANNOUNCE) {
- nd6_llinfo_settimer(ln, -1);
- ln->ln_state = ND6_LLINFO_REACHABLE;
- ln->ln_byhint = 0;
-
- /* join solicited node multicast for proxy ND */
- if (ifp->if_flags & IFF_MULTICAST) {
- struct in6_addr llsol;
- int error;
-
- llsol = SIN6(rt_key(rt))->sin6_addr;
- llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
- llsol.s6_addr32[1] = 0;
- llsol.s6_addr32[2] = htonl(1);
- llsol.s6_addr8[12] = 0xff;
- if (in6_setscope(&llsol, ifp, NULL))
- break;
- if (in6_addmulti(&llsol, ifp,
- &error, 0) == NULL) {
- char ip6buf[INET6_ADDRSTRLEN];
- nd6log((LOG_ERR, "%s: failed to join "
- "%s (errno=%d)\n", if_name(ifp),
- ip6_sprintf(ip6buf, &llsol),
- error));
- }
- }
- }
- break;
-
- case RTM_DELETE:
- if (ln == NULL)
- break;
- /* leave from solicited node multicast for proxy ND */
- if ((rt->rt_flags & RTF_ANNOUNCE) != 0 &&
- (ifp->if_flags & IFF_MULTICAST) != 0) {
- struct in6_addr llsol;
- struct in6_multi *in6m;
-
- llsol = SIN6(rt_key(rt))->sin6_addr;
- llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
- llsol.s6_addr32[1] = 0;
- llsol.s6_addr32[2] = htonl(1);
- llsol.s6_addr8[12] = 0xff;
- if (in6_setscope(&llsol, ifp, NULL) == 0) {
- IN6_LOOKUP_MULTI(llsol, ifp, in6m);
- if (in6m)
- in6_delmulti(in6m);
- } else
- ; /* XXX: should not happen. bark here? */
- }
- V_nd6_inuse--;
- ln->ln_next->ln_prev = ln->ln_prev;
- ln->ln_prev->ln_next = ln->ln_next;
- ln->ln_prev = NULL;
- nd6_llinfo_settimer(ln, -1);
- RT_REMREF(rt);
- rt->rt_llinfo = 0;
- rt->rt_flags &= ~RTF_LLINFO;
- clear_llinfo_pqueue(ln);
- Free((caddr_t)ln);
- }
-}
int
nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
@@ -1477,7 +1163,6 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
struct in6_ndifreq *ndif = (struct in6_ndifreq *)data;
struct nd_defrouter *dr;
struct nd_prefix *pr;
- struct rtentry *rt;
int i = 0, error = 0;
int s;
@@ -1667,25 +1352,25 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
}
case SIOCGNBRINFO_IN6:
{
- struct llinfo_nd6 *ln;
+ struct llentry *ln;
struct in6_addr nb_addr = nbi->addr; /* make local for safety */
if ((error = in6_setscope(&nb_addr, ifp, NULL)) != 0)
return (error);
- s = splnet();
- if ((rt = nd6_lookup(&nb_addr, 0, ifp)) == NULL) {
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(&nb_addr, 0, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+
+ if (ln == NULL) {
error = EINVAL;
- splx(s);
break;
}
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
nbi->state = ln->ln_state;
- nbi->asked = ln->ln_asked;
+ nbi->asked = ln->la_asked;
nbi->isrouter = ln->ln_router;
- nbi->expire = ln->ln_expire;
- splx(s);
-
+ nbi->expire = ln->la_expire;
+ LLE_RUNLOCK(ln);
break;
}
case SIOCGDEFIFACE_IN6: /* XXX: should be implemented as a sysctl? */
@@ -1703,20 +1388,29 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
*
* type - ICMP6 type
* code - type dependent information
+ *
+ * XXXXX
+ * The caller of this function already acquired the ndp
+ * cache table lock because the cache entry is returned.
*/
-struct rtentry *
+struct llentry *
nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
int lladdrlen, int type, int code)
{
INIT_VNET_INET6(curvnet);
- struct rtentry *rt = NULL;
- struct llinfo_nd6 *ln = NULL;
+ struct llentry *ln = NULL;
int is_newentry;
- struct sockaddr_dl *sdl = NULL;
int do_update;
int olladdr;
int llchange;
+ int flags = 0;
int newstate = 0;
+ uint16_t router = 0;
+ struct sockaddr_in6 sin6;
+ struct mbuf *chain = NULL;
+ int static_route = 0;
+
+ IF_AFDATA_UNLOCK_ASSERT(ifp);
if (ifp == NULL)
panic("ifp == NULL in nd6_cache_lladdr");
@@ -1736,40 +1430,31 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
* Spec says nothing in sections for RA, RS and NA. There's small
* description on it in NS section (RFC 2461 7.2.3).
*/
-
- rt = nd6_lookup(from, 0, ifp);
- if (rt == NULL) {
- rt = nd6_lookup(from, 1, ifp);
+ flags |= lladdr ? ND6_EXCLUSIVE : 0;
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(from, flags, ifp);
+
+ if (ln == NULL) {
+ flags |= LLE_EXCLUSIVE;
+ ln = nd6_lookup(from, flags |ND6_CREATE, ifp);
+ IF_AFDATA_UNLOCK(ifp);
is_newentry = 1;
} else {
+ IF_AFDATA_UNLOCK(ifp);
/* do nothing if static ndp is set */
- if (rt->rt_flags & RTF_STATIC)
- return NULL;
+ if (ln->la_flags & LLE_STATIC) {
+ static_route = 1;
+ goto done;
+ }
is_newentry = 0;
}
-
- if (rt == NULL)
- return NULL;
- if ((rt->rt_flags & (RTF_GATEWAY | RTF_LLINFO)) != RTF_LLINFO) {
-fail:
- (void)nd6_free(rt, 0);
- return NULL;
- }
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
if (ln == NULL)
- goto fail;
- if (rt->rt_gateway == NULL)
- goto fail;
- if (rt->rt_gateway->sa_family != AF_LINK)
- goto fail;
- sdl = SDL(rt->rt_gateway);
-
- olladdr = (sdl->sdl_alen) ? 1 : 0;
+ return (NULL);
+
+ olladdr = (ln->la_flags & LLE_VALID) ? 1 : 0;
if (olladdr && lladdr) {
- if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
- llchange = 1;
- else
- llchange = 0;
+ llchange = bcmp(lladdr, &ln->ll_addr,
+ ifp->if_addrlen);
} else
llchange = 0;
@@ -1789,8 +1474,8 @@ fail:
* Record source link-layer address
* XXX is it dependent to ifp->if_type?
*/
- sdl->sdl_alen = ifp->if_addrlen;
- bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
+ bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
+ ln->la_flags |= LLE_VALID;
}
if (!is_newentry) {
@@ -1821,17 +1506,17 @@ fail:
* we must set the timer now, although it is actually
* meaningless.
*/
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
- if (ln->ln_hold) {
+ if (ln->la_hold) {
struct mbuf *m_hold, *m_hold_next;
/*
- * reset the ln_hold in advance, to explicitly
- * prevent a ln_hold lookup in nd6_output()
+ * reset the la_hold in advance, to explicitly
+ * prevent a la_hold lookup in nd6_output()
* (wouldn't happen, though...)
*/
- for (m_hold = ln->ln_hold, ln->ln_hold = NULL;
+ for (m_hold = ln->la_hold, ln->la_hold = NULL;
m_hold; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;
m_hold->m_nextpkt = NULL;
@@ -1841,14 +1526,19 @@ fail:
* just set the 2nd argument as the
* 1st one.
*/
- nd6_output(ifp, ifp, m_hold,
- (struct sockaddr_in6 *)rt_key(rt),
- rt);
+ nd6_output_lle(ifp, ifp, m_hold, L3_ADDR_SIN6(ln), NULL, ln, &chain);
}
+ /*
+ * If we have mbufs in the chain we need to do
+ * deferred transmit. Copy the address from the
+ * llentry before dropping the lock down below.
+ */
+ if (chain != NULL)
+ memcpy(&sin6, L3_ADDR_SIN6(ln), sizeof(sin6));
}
} else if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
/* probe right away */
- nd6_llinfo_settimer((void *)ln, 0);
+ nd6_llinfo_settimer_locked((void *)ln, 0);
}
}
@@ -1917,6 +1607,20 @@ fail:
break;
}
+ if (ln != NULL) {
+ static_route = (ln->la_flags & LLE_STATIC);
+ router = ln->ln_router;
+
+ if (flags & ND6_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ if (static_route)
+ ln = NULL;
+ }
+ if (chain)
+ nd6_output_flush(ifp, ifp, chain, &sin6, NULL);
+
/*
* When the link-layer address of a router changes, select the
* best router again. In particular, when the neighbor entry is newly
@@ -1932,10 +1636,24 @@ fail:
* for those are not autoconfigured hosts, we explicitly avoid such
* cases for safety.
*/
- if (do_update && ln->ln_router && !V_ip6_forwarding && V_ip6_accept_rtadv)
+ if (do_update && router && !V_ip6_forwarding && V_ip6_accept_rtadv) {
+ /*
+ * guaranteed recursion
+ */
defrouter_select();
-
- return rt;
+ }
+
+ return (ln);
+done:
+ if (ln != NULL) {
+ if (flags & ND6_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ if (static_route)
+ ln = NULL;
+ }
+ return (ln);
}
static void
@@ -1969,18 +1687,44 @@ nd6_slowtimo(void *arg)
CURVNET_RESTORE();
}
-#define senderr(e) { error = (e); goto bad;}
int
nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
struct sockaddr_in6 *dst, struct rtentry *rt0)
{
+
+ return (nd6_output_lle(ifp, origifp, m0, dst, rt0, NULL, NULL));
+}
+
+
+/*
+ * Note that I'm not enforcing any global serialization
+ * lle state or asked changes here as the logic is too
+ * complicated to avoid having to always acquire an exclusive
+ * lock
+ * KMM
+ *
+ */
+#define senderr(e) { error = (e); goto bad;}
+
+int
+nd6_output_lle(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
+ struct sockaddr_in6 *dst, struct rtentry *rt0, struct llentry *lle,
+ struct mbuf **chain)
+{
INIT_VNET_INET6(curvnet);
struct mbuf *m = m0;
- struct rtentry *rt = rt0;
- struct sockaddr_in6 *gw6 = NULL;
- struct llinfo_nd6 *ln = NULL;
+ struct llentry *ln = lle;
int error = 0;
+ int flags = 0;
+#ifdef INVARIANTS
+ if (lle != NULL) {
+
+ LLE_WLOCK_ASSERT(lle);
+
+ KASSERT(chain != NULL, (" lle locked but no mbuf chain pointer passed"));
+ }
+#endif
if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr))
goto sendpkt;
@@ -1990,81 +1734,6 @@ nd6_output(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *m0,
/*
* next hop determination. This routine is derived from ether_output.
*/
- /* NB: the locking here is tortuous... */
- if (rt != NULL)
- RT_LOCK(rt);
-again:
- if (rt != NULL) {
- if ((rt->rt_flags & RTF_UP) == 0) {
- RT_UNLOCK(rt);
- rt0 = rt = rtalloc1((struct sockaddr *)dst, 1, 0UL);
- if (rt != NULL) {
- RT_REMREF(rt);
- if (rt->rt_ifp != ifp)
- /*
- * XXX maybe we should update ifp too,
- * but the original code didn't and I
- * don't know what is correct here.
- */
- goto again;
- } else
- senderr(EHOSTUNREACH);
- }
-
- if (rt->rt_flags & RTF_GATEWAY) {
- gw6 = (struct sockaddr_in6 *)rt->rt_gateway;
-
- /*
- * We skip link-layer address resolution and NUD
- * if the gateway is not a neighbor from ND point
- * of view, regardless of the value of nd_ifinfo.flags.
- * The second condition is a bit tricky; we skip
- * if the gateway is our own address, which is
- * sometimes used to install a route to a p2p link.
- */
- if (!nd6_is_addr_neighbor(gw6, ifp) ||
- in6ifa_ifpwithaddr(ifp, &gw6->sin6_addr)) {
- RT_UNLOCK(rt);
- /*
- * We allow this kind of tricky route only
- * when the outgoing interface is p2p.
- * XXX: we may need a more generic rule here.
- */
- if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
- senderr(EHOSTUNREACH);
-
- goto sendpkt;
- }
-
- if (rt->rt_gwroute == NULL)
- goto lookup;
- rt = rt->rt_gwroute;
- RT_LOCK(rt); /* NB: gwroute */
- if ((rt->rt_flags & RTF_UP) == 0) {
- RTFREE_LOCKED(rt); /* unlock gwroute */
- rt = rt0;
- rt0->rt_gwroute = NULL;
- lookup:
- RT_UNLOCK(rt0);
- rt = rtalloc1(rt->rt_gateway, 1, 0UL);
- if (rt == rt0) {
- RT_REMREF(rt0);
- RT_UNLOCK(rt0);
- senderr(EHOSTUNREACH);
- }
- RT_LOCK(rt0);
- if (rt0->rt_gwroute != NULL)
- RTFREE(rt0->rt_gwroute);
- rt0->rt_gwroute = rt;
- if (rt == NULL) {
- RT_UNLOCK(rt0);
- senderr(EHOSTUNREACH);
- }
- }
- RT_UNLOCK(rt0);
- }
- RT_UNLOCK(rt);
- }
/*
* Address resolution or Neighbor Unreachability Detection
@@ -2073,38 +1742,46 @@ again:
* or an anycast address(i.e. not a multicast).
*/
- /* Look up the neighbor cache for the nexthop */
- if (rt && (rt->rt_flags & RTF_LLINFO) != 0)
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- else {
- /*
- * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
- * the condition below is not very efficient. But we believe
- * it is tolerable, because this should be a rare case.
- */
- if (nd6_is_addr_neighbor(dst, ifp) &&
- (rt = nd6_lookup(&dst->sin6_addr, 1, ifp)) != NULL)
- ln = (struct llinfo_nd6 *)rt->rt_llinfo;
- }
- if (ln == NULL || rt == NULL) {
+ flags = ((m != NULL) || (lle != NULL)) ? LLE_EXCLUSIVE : 0;
+ if (ln == NULL) {
+ retry:
+ IF_AFDATA_LOCK(ifp);
+ ln = lla_lookup(LLTABLE6(ifp), flags, (struct sockaddr *)dst);
+ IF_AFDATA_UNLOCK(ifp);
+ if ((ln == NULL) && nd6_is_addr_neighbor(dst, ifp)) {
+ /*
+ * Since nd6_is_addr_neighbor() internally calls nd6_lookup(),
+ * the condition below is not very efficient. But we believe
+ * it is tolerable, because this should be a rare case.
+ */
+ flags = ND6_CREATE | (m ? ND6_EXCLUSIVE : 0);
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(&dst->sin6_addr, flags, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ }
+ }
+ if (ln == NULL) {
if ((ifp->if_flags & IFF_POINTOPOINT) == 0 &&
!(ND_IFINFO(ifp)->flags & ND6_IFF_PERFORMNUD)) {
char ip6buf[INET6_ADDRSTRLEN];
log(LOG_DEBUG,
"nd6_output: can't allocate llinfo for %s "
- "(ln=%p, rt=%p)\n",
- ip6_sprintf(ip6buf, &dst->sin6_addr), ln, rt);
+ "(ln=%p)\n",
+ ip6_sprintf(ip6buf, &dst->sin6_addr), ln);
senderr(EIO); /* XXX: good error? */
}
-
goto sendpkt; /* send anyway */
}
/* We don't have to do link-layer address resolution on a p2p link. */
if ((ifp->if_flags & IFF_POINTOPOINT) != 0 &&
ln->ln_state < ND6_LLINFO_REACHABLE) {
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ goto retry;
+ }
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
}
/*
@@ -2115,9 +1792,14 @@ again:
* (RFC 2461 7.3.3)
*/
if (ln->ln_state == ND6_LLINFO_STALE) {
- ln->ln_asked = 0;
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ LLE_RUNLOCK(ln);
+ goto retry;
+ }
+ ln->la_asked = 0;
ln->ln_state = ND6_LLINFO_DELAY;
- nd6_llinfo_settimer(ln, (long)V_nd6_delay * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_delay * hz);
}
/*
@@ -2137,12 +1819,18 @@ again:
*/
if (ln->ln_state == ND6_LLINFO_NOSTATE)
ln->ln_state = ND6_LLINFO_INCOMPLETE;
- if (ln->ln_hold) {
+
+ if ((flags & LLE_EXCLUSIVE) == 0) {
+ flags |= LLE_EXCLUSIVE;
+ LLE_RUNLOCK(ln);
+ goto retry;
+ }
+ if (ln->la_hold) {
struct mbuf *m_hold;
int i;
-
+
i = 0;
- for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold->m_nextpkt) {
+ for (m_hold = ln->la_hold; m_hold; m_hold = m_hold->m_nextpkt) {
i++;
if (m_hold->m_nextpkt == NULL) {
m_hold->m_nextpkt = m;
@@ -2150,21 +1838,32 @@ again:
}
}
while (i >= V_nd6_maxqueuelen) {
- m_hold = ln->ln_hold;
- ln->ln_hold = ln->ln_hold->m_nextpkt;
+ m_hold = ln->la_hold;
+ ln->la_hold = ln->la_hold->m_nextpkt;
m_freem(m_hold);
i--;
}
} else {
- ln->ln_hold = m;
+ ln->la_hold = m;
}
-
+ /*
+ * We did the lookup (no lle arg) so we
+ * need to do the unlock here
+ */
+ if (lle == NULL) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ }
+
/*
* If there has been no NS for the neighbor after entering the
* INCOMPLETE state, send the first solicitation.
*/
- if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) {
- ln->ln_asked++;
+ if (!ND6_LLINFO_PERMANENT(ln) && ln->la_asked == 0) {
+ ln->la_asked++;
+
nd6_llinfo_settimer(ln,
(long)ND_IFINFO(ifp)->retrans * hz / 1000);
nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0);
@@ -2177,23 +1876,97 @@ again:
error = ENETDOWN; /* better error? */
goto bad;
}
+ /*
+ * ln is valid and the caller did not pass in
+ * an llentry
+ */
+ if ((ln != NULL) && (lle == NULL)) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ }
#ifdef MAC
mac_netinet6_nd6_send(ifp, m);
#endif
+ /*
+ * We were passed in a pointer to an lle with the lock held
+ * this means that we can't call if_output as we will
+ * recurse on the lle lock - so what we do is we create
+ * a list of mbufs to send and transmit them in the caller
+ * after the lock is dropped
+ */
+ if (lle != NULL) {
+ if (*chain == NULL)
+ *chain = m;
+ else {
+ struct mbuf *m = *chain;
+
+ /*
+ * append mbuf to end of deferred chain
+ */
+ while (m->m_nextpkt != NULL)
+ m = m->m_nextpkt;
+ m->m_nextpkt = m;
+ }
+ return (error);
+ }
if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
return ((*ifp->if_output)(origifp, m, (struct sockaddr *)dst,
- rt));
+ NULL));
}
- return ((*ifp->if_output)(ifp, m, (struct sockaddr *)dst, rt));
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, NULL);
+ return (error);
bad:
+ /*
+ * ln is valid and the caller did not pass in
+ * an llentry
+ */
+ if ((ln != NULL) && (lle == NULL)) {
+ if (flags & LLE_EXCLUSIVE)
+ LLE_WUNLOCK(ln);
+ else
+ LLE_RUNLOCK(ln);
+ }
if (m)
m_freem(m);
return (error);
}
#undef senderr
+
+int
+nd6_output_flush(struct ifnet *ifp, struct ifnet *origifp, struct mbuf *chain,
+ struct sockaddr_in6 *dst, struct rtentry *rt)
+{
+ struct mbuf *m, *m_head;
+ struct ifnet *outifp;
+ int error = 0;
+
+ m_head = chain;
+ if ((ifp->if_flags & IFF_LOOPBACK) != 0)
+ outifp = origifp;
+ else
+ outifp = ifp;
+
+ while (m_head) {
+ m = m_head;
+ m_head = m_head->m_nextpkt;
+ error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, rt);
+ }
+
+ /*
+ * XXX
+ * note that intermediate errors are blindly ignored - but this is
+ * the same convention as used with nd6_output when called by
+ * nd6_cache_lladdr
+ */
+ return (error);
+}
+
+
int
nd6_need_cache(struct ifnet *ifp)
{
@@ -2229,14 +2002,18 @@ nd6_need_cache(struct ifnet *ifp)
}
}
+/*
+ * the callers of this function need to be re-worked to drop
+ * the lle lock, drop here for now
+ */
int
-nd6_storelladdr(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
- struct sockaddr *dst, u_char *desten)
+nd6_storelladdr(struct ifnet *ifp, struct mbuf *m,
+ struct sockaddr *dst, u_char *desten, struct llentry **lle)
{
- struct sockaddr_dl *sdl;
- struct rtentry *rt;
- int error;
+ struct llentry *ln;
+ *lle = NULL;
+ IF_AFDATA_UNLOCK_ASSERT(ifp);
if (m->m_flags & M_MCAST) {
int i;
@@ -2271,48 +2048,42 @@ nd6_storelladdr(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
}
}
- if (rt0 == NULL) {
- /* this could happen, if we could not allocate memory */
- m_freem(m);
- return (ENOMEM);
- }
-
- error = rt_check(&rt, &rt0, dst);
- if (error) {
- m_freem(m);
- return (error);
- }
- RT_UNLOCK(rt);
- if (rt->rt_gateway->sa_family != AF_LINK) {
- printf("nd6_storelladdr: something odd happens\n");
- m_freem(m);
- return (EINVAL);
- }
- sdl = SDL(rt->rt_gateway);
- if (sdl->sdl_alen == 0) {
- /* this should be impossible, but we bark here for debugging */
- printf("nd6_storelladdr: sdl_alen == 0\n");
+ /*
+ * the entry should have been created in nd6_store_lladdr
+ */
+ IF_AFDATA_LOCK(ifp);
+ ln = lla_lookup(LLTABLE6(ifp), 0, dst);
+ IF_AFDATA_UNLOCK(ifp);
+ if ((ln == NULL) || !(ln->la_flags & LLE_VALID)) {
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
+ /* this could happen, if we could not allocate memory */
m_freem(m);
- return (EINVAL);
+ return (1);
}
- bcopy(LLADDR(sdl), desten, sdl->sdl_alen);
+ bcopy(&ln->ll_addr, desten, ifp->if_addrlen);
+ *lle = ln;
+ LLE_RUNLOCK(ln);
+ /*
+ * A *small* use after free race exists here
+ */
return (0);
}
-static void
-clear_llinfo_pqueue(struct llinfo_nd6 *ln)
+static void
+clear_llinfo_pqueue(struct llentry *ln)
{
struct mbuf *m_hold, *m_hold_next;
- for (m_hold = ln->ln_hold; m_hold; m_hold = m_hold_next) {
+ for (m_hold = ln->la_hold; m_hold; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;
m_hold->m_nextpkt = NULL;
m_freem(m_hold);
}
- ln->ln_hold = NULL;
+ ln->la_hold = NULL;
return;
}
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 4d3c06b..e2007f7 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -41,20 +41,7 @@
#include <sys/queue.h>
#include <sys/callout.h>
-struct llinfo_nd6 {
- struct llinfo_nd6 *ln_next;
- struct llinfo_nd6 *ln_prev;
- struct rtentry *ln_rt;
- struct mbuf *ln_hold; /* last packet until resolved/timeout */
- long ln_asked; /* number of queries already sent for this addr */
- u_long ln_expire; /* lifetime for NDP state transition */
- short ln_state; /* reachability state */
- short ln_router; /* 2^0: ND6 router bit */
- int ln_byhint; /* # of times we made it reachable by UL hint */
-
- long ln_ntick;
- struct callout ln_timer_ch;
-};
+struct llentry;
#define ND6_LLINFO_NOSTATE -2
/*
@@ -72,7 +59,7 @@ struct llinfo_nd6 {
#define ND6_LLINFO_PROBE 4
#define ND6_IS_LLINFO_PROBREACH(n) ((n)->ln_state > ND6_LLINFO_INCOMPLETE)
-#define ND6_LLINFO_PERMANENT(n) (((n)->ln_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))
+#define ND6_LLINFO_PERMANENT(n) (((n)->la_expire == 0) && ((n)->ln_state > ND6_LLINFO_INCOMPLETE))
struct nd_ifinfo {
u_int32_t linkmtu; /* LinkMTU */
@@ -98,6 +85,9 @@ struct nd_ifinfo {
*/
#define ND6_IFF_DONT_SET_IFROUTE 0x10
+#define ND6_CREATE LLE_CREATE
+#define ND6_EXCLUSIVE LLE_EXCLUSIVE
+
#ifdef _KERNEL
#define ND_IFINFO(ifp) \
(((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->nd_ifinfo)
@@ -336,7 +326,6 @@ extern int nd6_mmaxtries;
extern int nd6_useloopback;
extern int nd6_maxnudhint;
extern int nd6_gctimer;
-extern struct llinfo_nd6 llinfo_nd6;
extern struct nd_drhead nd_defrouter;
extern struct nd_prhead nd_prefix;
extern int nd6_debug;
@@ -388,23 +377,28 @@ int nd6_is_addr_neighbor __P((struct sockaddr_in6 *, struct ifnet *));
void nd6_option_init __P((void *, int, union nd_opts *));
struct nd_opt_hdr *nd6_option __P((union nd_opts *));
int nd6_options __P((union nd_opts *));
-struct rtentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
+struct llentry *nd6_lookup __P((struct in6_addr *, int, struct ifnet *));
void nd6_setmtu __P((struct ifnet *));
-void nd6_llinfo_settimer __P((struct llinfo_nd6 *, long));
+void nd6_llinfo_settimer __P((struct llentry *, long));
+void nd6_llinfo_settimer_locked __P((struct llentry *, long));
void nd6_timer __P((void *));
void nd6_purge __P((struct ifnet *));
void nd6_nud_hint __P((struct rtentry *, struct in6_addr *, int));
int nd6_resolve __P((struct ifnet *, struct rtentry *, struct mbuf *,
struct sockaddr *, u_char *));
-void nd6_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
int nd6_ioctl __P((u_long, caddr_t, struct ifnet *));
-struct rtentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
+struct llentry *nd6_cache_lladdr __P((struct ifnet *, struct in6_addr *,
char *, int, int, int));
int nd6_output __P((struct ifnet *, struct ifnet *, struct mbuf *,
struct sockaddr_in6 *, struct rtentry *));
+int nd6_output_lle __P((struct ifnet *, struct ifnet *, struct mbuf *,
+ struct sockaddr_in6 *, struct rtentry *, struct llentry *,
+ struct mbuf **));
+int nd6_output_flush __P((struct ifnet *, struct ifnet *, struct mbuf *,
+ struct sockaddr_in6 *, struct rtentry *));
int nd6_need_cache __P((struct ifnet *));
-int nd6_storelladdr __P((struct ifnet *, struct rtentry *, struct mbuf *,
- struct sockaddr *, u_char *));
+int nd6_storelladdr __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, u_char *, struct llentry **));
/* nd6_nbr.c */
void nd6_na_input __P((struct mbuf *, int, int));
@@ -412,7 +406,7 @@ void nd6_na_output __P((struct ifnet *, const struct in6_addr *,
const struct in6_addr *, u_long, int, struct sockaddr *));
void nd6_ns_input __P((struct mbuf *, int, int));
void nd6_ns_output __P((struct ifnet *, const struct in6_addr *,
- const struct in6_addr *, struct llinfo_nd6 *, int));
+ const struct in6_addr *, struct llentry *, int));
caddr_t nd6_ifptomac __P((struct ifnet *));
void nd6_dad_start __P((struct ifaddr *, int));
void nd6_dad_stop __P((struct ifaddr *));
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index ecfad0e..c1cb423 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/rwlock.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -63,6 +65,8 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <net/if_llatbl.h>
+#define L3_ADDR_SIN6(le) ((struct sockaddr_in6 *) L3_ADDR(le))
#include <netinet6/in6_var.h>
#include <netinet6/in6_ifattach.h>
#include <netinet/ip6.h>
@@ -167,7 +171,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
src_sa6.sin6_family = AF_INET6;
src_sa6.sin6_len = sizeof(src_sa6);
src_sa6.sin6_addr = saddr6;
- if (!nd6_is_addr_neighbor(&src_sa6, ifp)) {
+ if (nd6_is_addr_neighbor(&src_sa6, ifp) == 0) {
nd6log((LOG_INFO, "nd6_ns_input: "
"NS packet from non-neighbor\n"));
goto bad;
@@ -378,8 +382,8 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
* dad - duplicate address detection
*/
void
-nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
- const struct in6_addr *taddr6, struct llinfo_nd6 *ln, int dad)
+nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
+ const struct in6_addr *taddr6, struct llentry *ln, int dad)
{
INIT_VNET_INET6(ifp->if_vnet);
struct mbuf *m;
@@ -470,14 +474,14 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
struct ip6_hdr *hip6; /* hold ip6 */
struct in6_addr *hsrc = NULL;
- if (ln && ln->ln_hold) {
+ if ((ln != NULL) && ln->la_hold) {
/*
- * assuming every packet in ln_hold has the same IP
+ * assuming every packet in la_hold has the same IP
* header
*/
- hip6 = mtod(ln->ln_hold, struct ip6_hdr *);
+ hip6 = mtod(ln->la_hold, struct ip6_hdr *);
/* XXX pullup? */
- if (sizeof(*hip6) < ln->ln_hold->m_len)
+ if (sizeof(*hip6) < ln->la_hold->m_len)
hsrc = &hip6->ip6_src;
else
hsrc = NULL;
@@ -600,10 +604,10 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
char *lladdr = NULL;
int lladdrlen = 0;
struct ifaddr *ifa;
- struct llinfo_nd6 *ln;
- struct rtentry *rt;
- struct sockaddr_dl *sdl;
+ struct llentry *ln = NULL;
union nd_opts ndopts;
+ struct mbuf *chain = NULL;
+ struct sockaddr_in6 sin6;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
if (ip6->ip6_hlim != 255) {
@@ -697,35 +701,37 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* If no neighbor cache entry is found, NA SHOULD silently be
* discarded.
*/
- rt = nd6_lookup(&taddr6, 0, ifp);
- if ((rt == NULL) ||
- ((ln = (struct llinfo_nd6 *)rt->rt_llinfo) == NULL) ||
- ((sdl = SDL(rt->rt_gateway)) == NULL))
+ IF_AFDATA_LOCK(ifp);
+ ln = nd6_lookup(&taddr6, LLE_EXCLUSIVE, ifp);
+ IF_AFDATA_UNLOCK(ifp);
+ if (ln == NULL) {
goto freeit;
+ }
if (ln->ln_state == ND6_LLINFO_INCOMPLETE) {
/*
* If the link-layer has address, and no lladdr option came,
* discard the packet.
*/
- if (ifp->if_addrlen && lladdr == NULL)
+ if (ifp->if_addrlen && lladdr == NULL) {
goto freeit;
+ }
/*
* Record link-layer address, and update the state.
*/
- sdl->sdl_alen = ifp->if_addrlen;
- bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
+ bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
+ ln->la_flags |= LLE_VALID;
if (is_solicited) {
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
if (!ND6_LLINFO_PERMANENT(ln)) {
- nd6_llinfo_settimer(ln,
- (long)ND_IFINFO(rt->rt_ifp)->reachable * hz);
+ nd6_llinfo_settimer_locked(ln,
+ (long)ND_IFINFO(ln->lle_tbl->llt_ifp)->reachable * hz);
}
} else {
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
}
if ((ln->ln_router = is_router) != 0) {
/*
@@ -744,8 +750,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
if (lladdr == NULL)
llchange = 0;
else {
- if (sdl->sdl_alen) {
- if (bcmp(lladdr, LLADDR(sdl), ifp->if_addrlen))
+ if (ln->la_flags & LLE_VALID) {
+ if (bcmp(lladdr, &ln->ll_addr, ifp->if_addrlen))
llchange = 1;
else
llchange = 0;
@@ -779,7 +785,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
if (ln->ln_state == ND6_LLINFO_REACHABLE) {
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln, (long)V_nd6_gctimer * hz);
+ nd6_llinfo_settimer_locked(ln, (long)V_nd6_gctimer * hz);
}
goto freeit;
} else if (is_override /* (2a) */
@@ -789,8 +795,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* Update link-local address, if any.
*/
if (lladdr != NULL) {
- sdl->sdl_alen = ifp->if_addrlen;
- bcopy(lladdr, LLADDR(sdl), ifp->if_addrlen);
+ bcopy(lladdr, &ln->ll_addr, ifp->if_addrlen);
+ ln->la_flags |= LLE_VALID;
}
/*
@@ -802,13 +808,13 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
if (!ND6_LLINFO_PERMANENT(ln)) {
- nd6_llinfo_settimer(ln,
+ nd6_llinfo_settimer_locked(ln,
(long)ND_IFINFO(ifp)->reachable * hz);
}
} else {
if (lladdr != NULL && llchange) {
ln->ln_state = ND6_LLINFO_STALE;
- nd6_llinfo_settimer(ln,
+ nd6_llinfo_settimer_locked(ln,
(long)V_nd6_gctimer * hz);
}
}
@@ -822,9 +828,8 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
struct nd_defrouter *dr;
struct in6_addr *in6;
- int s;
- in6 = &((struct sockaddr_in6 *)rt_key(rt))->sin6_addr;
+ in6 = &L3_ADDR_SIN6(ln)->sin6_addr;
/*
* Lock to protect the default router list.
@@ -832,8 +837,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* is only called under the network software interrupt
* context. However, we keep it just for safety.
*/
- s = splnet();
- dr = defrouter_lookup(in6, ifp);
+ dr = defrouter_lookup(in6, ln->lle_tbl->llt_ifp);
if (dr)
defrtrlist_del(dr);
else if (!V_ip6_forwarding) {
@@ -846,21 +850,23 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
*/
rt6_flush(&ip6->ip6_src, ifp);
}
- splx(s);
}
ln->ln_router = is_router;
}
- rt->rt_flags &= ~RTF_REJECT;
- ln->ln_asked = 0;
- if (ln->ln_hold) {
+ /* XXX - QL
+ * Does this matter?
+ * rt->rt_flags &= ~RTF_REJECT;
+ */
+ ln->la_asked = 0;
+ if (ln->la_hold) {
struct mbuf *m_hold, *m_hold_next;
/*
- * reset the ln_hold in advance, to explicitly
- * prevent a ln_hold lookup in nd6_output()
+ * reset the la_hold in advance, to explicitly
+ * prevent a la_hold lookup in nd6_output()
* (wouldn't happen, though...)
*/
- for (m_hold = ln->ln_hold;
+ for (m_hold = ln->la_hold, ln->la_hold = NULL;
m_hold; m_hold = m_hold_next) {
m_hold_next = m_hold->m_nextpkt;
m_hold->m_nextpkt = NULL;
@@ -868,17 +874,25 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* we assume ifp is not a loopback here, so just set
* the 2nd argument as the 1st one.
*/
- nd6_output(ifp, ifp, m_hold,
- (struct sockaddr_in6 *)rt_key(rt), rt);
+ nd6_output_lle(ifp, ifp, m_hold, L3_ADDR_SIN6(ln), NULL, ln, &chain);
}
- ln->ln_hold = NULL;
}
-
freeit:
+ if (ln != NULL) {
+ if (chain)
+ memcpy(&sin6, L3_ADDR_SIN6(ln), sizeof(sin6));
+ LLE_WUNLOCK(ln);
+
+ if (chain)
+ nd6_output_flush(ifp, ifp, chain, &sin6, NULL);
+ }
m_freem(m);
return;
bad:
+ if (ln != NULL)
+ LLE_WUNLOCK(ln);
+
V_icmp6stat.icp6s_badna++;
m_freem(m);
}
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index c9ed36d..7df364e 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <net/if_llatbl.h>
#include <netinet6/in6_var.h>
#include <netinet6/in6_ifattach.h>
#include <netinet/ip6.h>
@@ -471,10 +472,8 @@ defrouter_addreq(struct nd_defrouter *new)
(struct sockaddr *)&gate, (struct sockaddr *)&mask,
RTF_GATEWAY, &newrt);
if (newrt) {
- RT_LOCK(newrt);
nd6_rtmsg(RTM_ADD, newrt); /* tell user process */
- RT_REMREF(newrt);
- RT_UNLOCK(newrt);
+ RTFREE(newrt);
}
if (error == 0)
new->installed = 1;
@@ -615,8 +614,7 @@ defrouter_select(void)
INIT_VNET_INET6(curvnet);
int s = splnet();
struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
- struct rtentry *rt = NULL;
- struct llinfo_nd6 *ln = NULL;
+ struct llentry *ln = NULL;
/*
* This function should be called only when acting as an autoconfigured
@@ -648,12 +646,15 @@ defrouter_select(void)
*/
for (dr = TAILQ_FIRST(&V_nd_defrouter); dr;
dr = TAILQ_NEXT(dr, dr_entry)) {
+ IF_AFDATA_LOCK(dr->ifp);
if (selected_dr == NULL &&
- (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
- (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
+ (ln = nd6_lookup(&dr->rtaddr, 0, dr->ifp)) &&
ND6_IS_LLINFO_PROBREACH(ln)) {
selected_dr = dr;
}
+ IF_AFDATA_UNLOCK(dr->ifp);
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
if (dr->installed && installed_dr == NULL)
installed_dr = dr;
@@ -676,12 +677,16 @@ defrouter_select(void)
selected_dr = TAILQ_FIRST(&V_nd_defrouter);
else
selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
- } else if (installed_dr &&
- (rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
- (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
- ND6_IS_LLINFO_PROBREACH(ln) &&
- rtpref(selected_dr) <= rtpref(installed_dr)) {
- selected_dr = installed_dr;
+ } else if (installed_dr) {
+ IF_AFDATA_LOCK(installed_dr->ifp);
+ if ((ln = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp)) &&
+ ND6_IS_LLINFO_PROBREACH(ln) &&
+ rtpref(selected_dr) <= rtpref(installed_dr)) {
+ selected_dr = installed_dr;
+ }
+ IF_AFDATA_UNLOCK(installed_dr->ifp);
+ if (ln != NULL)
+ LLE_RUNLOCK(ln);
}
/*
@@ -1323,18 +1328,21 @@ static struct nd_pfxrouter *
find_pfxlist_reachable_router(struct nd_prefix *pr)
{
struct nd_pfxrouter *pfxrtr;
- struct rtentry *rt;
- struct llinfo_nd6 *ln;
+ struct llentry *ln;
+ int canreach;
- for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr;
+ for (pfxrtr = LIST_FIRST(&pr->ndpr_advrtrs); pfxrtr != NULL;
pfxrtr = LIST_NEXT(pfxrtr, pfr_entry)) {
- if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
- pfxrtr->router->ifp)) &&
- (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
- ND6_IS_LLINFO_PROBREACH(ln))
- break; /* found */
+ IF_AFDATA_LOCK(pfxrtr->router->ifp);
+ ln = nd6_lookup(&pfxrtr->router->rtaddr, 0, pfxrtr->router->ifp);
+ IF_AFDATA_UNLOCK(pfxrtr->router->ifp);
+ if (ln == NULL)
+ continue;
+ canreach = ND6_IS_LLINFO_PROBREACH(ln);
+ LLE_RUNLOCK(ln);
+ if (canreach)
+ break;
}
-
return (pfxrtr);
}
@@ -1541,8 +1549,10 @@ nd6_prefix_onlink(struct nd_prefix *pr)
struct nd_prefix *opr;
u_long rtflags;
int error = 0;
+ struct radix_node_head *rnh;
struct rtentry *rt = NULL;
char ip6buf[INET6_ADDRSTRLEN];
+ struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
/* sanity check */
if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
@@ -1609,21 +1619,24 @@ nd6_prefix_onlink(struct nd_prefix *pr)
bzero(&mask6, sizeof(mask6));
mask6.sin6_len = sizeof(mask6);
mask6.sin6_addr = pr->ndpr_mask;
- rtflags = ifa->ifa_flags | RTF_CLONING | RTF_UP;
- if (nd6_need_cache(ifp)) {
- /* explicitly set in case ifa_flags does not set the flag. */
- rtflags |= RTF_CLONING;
- } else {
- /*
- * explicitly clear the cloning bit in case ifa_flags sets it.
- */
- rtflags &= ~RTF_CLONING;
- }
+ rtflags = ifa->ifa_flags | RTF_UP;
error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
if (error == 0) {
- if (rt != NULL) /* this should be non NULL, though */
+ if (rt != NULL) /* this should be non NULL, though */ {
+ rnh = V_rt_tables[rt->rt_fibnum][AF_INET6];
+ RADIX_NODE_HEAD_LOCK(rnh);
+ RT_LOCK(rt);
+ if (!rt_setgate(rt, rt_key(rt), (struct sockaddr *)&null_sdl)) {
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_type =
+ rt->rt_ifp->if_type;
+ ((struct sockaddr_dl *)rt->rt_gateway)->sdl_index =
+ rt->rt_ifp->if_index;
+ }
+ RADIX_NODE_HEAD_UNLOCK(rnh);
nd6_rtmsg(RTM_ADD, rt);
+ RT_UNLOCK(rt);
+ }
pr->ndpr_stateflags |= NDPRF_ONLINK;
} else {
char ip6bufg[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index b132751..d342bc8 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -168,10 +168,10 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
INP_INFO_RLOCK(&V_ripcbinfo);
LIST_FOREACH(in6p, &V_ripcb, inp_list) {
/* XXX inp locking */
- if ((in6p->in6p_vflag & INP_IPV6) == 0)
+ if ((in6p->inp_vflag & INP_IPV6) == 0)
continue;
- if (in6p->in6p_ip6_nxt &&
- in6p->in6p_ip6_nxt != proto)
+ if (in6p->inp_ip_p &&
+ in6p->inp_ip_p != proto)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
@@ -193,7 +193,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
continue;
}
}
- if (last) {
+ if (last != NULL) {
struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
#ifdef IPSEC
@@ -207,12 +207,12 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
} else
#endif /* IPSEC */
if (n) {
- if (last->in6p_flags & IN6P_CONTROLOPTS ||
- last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, n, &opts);
/* strip intermediate headers */
m_adj(n, *offp);
- if (sbappendaddr(&last->in6p_socket->so_rcv,
+ if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa,
n, opts) == 0) {
m_freem(n);
@@ -220,7 +220,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
m_freem(opts);
V_rip6stat.rip6s_fullsock++;
} else
- sorwakeup(last->in6p_socket);
+ sorwakeup(last->inp_socket);
opts = NULL;
}
INP_RUNLOCK(last);
@@ -232,7 +232,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
/*
* Check AH/ESP integrity.
*/
- if (last && ipsec6_in_reject(m, last)) {
+ if ((last != NULL) && ipsec6_in_reject(m, last)) {
m_freem(m);
V_ipsec6stat.in_polvio++;
V_ip6stat.ip6s_delivered--;
@@ -240,20 +240,20 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
INP_RUNLOCK(last);
} else
#endif /* IPSEC */
- if (last) {
- if (last->in6p_flags & IN6P_CONTROLOPTS ||
- last->in6p_socket->so_options & SO_TIMESTAMP)
+ if (last != NULL) {
+ if (last->inp_flags & INP_CONTROLOPTS ||
+ last->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(last, m, &opts);
/* Strip intermediate headers. */
m_adj(m, *offp);
- if (sbappendaddr(&last->in6p_socket->so_rcv,
+ if (sbappendaddr(&last->inp_socket->so_rcv,
(struct sockaddr *)&fromsa, m, opts) == 0) {
m_freem(m);
if (opts)
m_freem(opts);
V_rip6stat.rip6s_fullsock++;
} else
- sorwakeup(last->in6p_socket);
+ sorwakeup(last->inp_socket);
INP_RUNLOCK(last);
} else {
V_rip6stat.rip6s_nosock++;
@@ -353,11 +353,11 @@ rip6_output(m, va_alist)
control = va_arg(ap, struct mbuf *);
va_end(ap);
- in6p = sotoin6pcb(so);
+ in6p = sotoinpcb(so);
INP_WLOCK(in6p);
dst = &dstsock->sin6_addr;
- if (control) {
+ if (control != NULL) {
if ((error = ip6_setpktopts(control, &opt,
in6p->in6p_outputopts, so->so_cred,
so->so_proto->pr_protocol)) != 0) {
@@ -437,14 +437,14 @@ rip6_output(m, va_alist)
* Fill in the rest of the IPv6 header fields.
*/
ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
- (in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK);
+ (in6p->inp_flow & IPV6_FLOWINFO_MASK);
ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
(IPV6_VERSION & IPV6_VERSION_MASK);
/*
* ip6_plen will be filled in ip6_output, so not fill it here.
*/
- ip6->ip6_nxt = in6p->in6p_ip6_nxt;
+ ip6->ip6_nxt = in6p->inp_ip_p;
ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
@@ -491,7 +491,7 @@ rip6_output(m, va_alist)
m_freem(m);
freectl:
- if (control) {
+ if (control != NULL) {
ip6_clearpktopts(&opt, -1);
m_freem(control);
}
@@ -595,7 +595,7 @@ rip6_attach(struct socket *so, int proto, struct thread *td)
inp = (struct inpcb *)so->so_pcb;
INP_INFO_WUNLOCK(&V_ripcbinfo);
inp->inp_vflag |= INP_IPV6;
- inp->in6p_ip6_nxt = (long)proto;
+ inp->inp_ip_p = (long)proto;
inp->in6p_hops = -1; /* use kernel default */
inp->in6p_cksum = -1;
inp->in6p_icmp6filt = filter;
diff --git a/sys/netinet6/raw_ip6.h b/sys/netinet6/raw_ip6.h
index 9ebd823..a57253e 100644
--- a/sys/netinet6/raw_ip6.h
+++ b/sys/netinet6/raw_ip6.h
@@ -48,7 +48,9 @@ struct rip6stat {
};
#ifdef _KERNEL
+#ifdef VIMAGE_GLOBALS
extern struct rip6stat rip6stat;
#endif
+#endif
#endif
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index cfb0ad6..f1634cb 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -153,7 +153,7 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off,
}
#endif
opts = NULL;
- if (inp->in6p_flags & IN6P_CONTROLOPTS ||
+ if (inp->inp_flags & INP_CONTROLOPTS ||
inp->inp_socket->so_options & SO_TIMESTAMP)
ip6_savecontrol(inp, n, &opts);
m_adj(n, off + sizeof(struct udphdr));
@@ -259,7 +259,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
LIST_FOREACH(inp, &V_udb, inp_list) {
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
- if (inp->in6p_lport != uh->uh_dport)
+ if (inp->inp_lport != uh->uh_dport)
continue;
/*
* XXX: Do not check source port of incoming datagram
@@ -278,7 +278,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr,
&ip6->ip6_src) ||
- inp->in6p_fport != uh->uh_sport)
+ inp->inp_fport != uh->uh_sport)
continue;
}
@@ -562,7 +562,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
fport = sin6->sin6_port; /* allow 0 port */
if (IN6_IS_ADDR_V4MAPPED(faddr)) {
- if ((inp->in6p_flags & IN6P_IPV6_V6ONLY)) {
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
/*
* I believe we should explicitly discard the
* packet when mapped addresses are disabled,
@@ -606,7 +606,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
error = EADDRNOTAVAIL;
goto release;
}
- if (inp->in6p_lport == 0 &&
+ if (inp->inp_lport == 0 &&
(error = in6_pcbsetport(laddr, inp, td->td_ucred)) != 0)
goto release;
} else {
@@ -615,7 +615,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
goto release;
}
if (IN6_IS_ADDR_V4MAPPED(&inp->in6p_faddr)) {
- if ((inp->in6p_flags & IN6P_IPV6_V6ONLY)) {
+ if ((inp->inp_flags & IN6P_IPV6_V6ONLY)) {
/*
* XXX: this case would happen when the
* application sets the V6ONLY flag after
@@ -632,7 +632,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
}
laddr = &inp->in6p_laddr;
faddr = &inp->in6p_faddr;
- fport = inp->in6p_fport;
+ fport = inp->inp_fport;
}
if (af == AF_INET)
@@ -652,7 +652,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
* Stuff checksum and output datagram.
*/
udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
- udp6->uh_sport = inp->in6p_lport; /* lport is always set in the PCB */
+ udp6->uh_sport = inp->inp_lport; /* lport is always set in the PCB */
udp6->uh_dport = fport;
if (plen <= 0xffff)
udp6->uh_ulen = htons((u_short)plen);
@@ -663,7 +663,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
switch (af) {
case AF_INET6:
ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_flow = inp->in6p_flowinfo & IPV6_FLOWINFO_MASK;
+ ip6->ip6_flow = inp->inp_flow & IPV6_FLOWINFO_MASK;
ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
ip6->ip6_vfc |= IPV6_VERSION;
#if 0 /* ip6_plen will be filled in ip6_output. */
diff --git a/sys/netinet6/vinet6.h b/sys/netinet6/vinet6.h
index d6c3f33..e271d4f 100644
--- a/sys/netinet6/vinet6.h
+++ b/sys/netinet6/vinet6.h
@@ -78,7 +78,6 @@ struct vnet_inet6 {
int _nd6_inuse;
int _nd6_allocated;
int _nd6_onlink_ns_rfc4861;
- struct llinfo_nd6 _llinfo_nd6;
struct nd_drhead _nd_defrouter;
struct nd_prhead _nd_prefix;
struct ifnet * _nd6_defifp;
diff --git a/sys/netipsec/ipip_var.h b/sys/netipsec/ipip_var.h
index 7fbc643..3d4ee15 100644
--- a/sys/netipsec/ipip_var.h
+++ b/sys/netipsec/ipip_var.h
@@ -60,6 +60,8 @@ struct ipipstat
#ifdef _KERNEL
extern int ipip_allow;
+#ifdef VIMAGE_GLOBALS
extern struct ipipstat ipipstat;
+#endif
#endif /* _KERNEL */
#endif /* _NETINET_IPIP_H_ */
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index 541e42e..108614f 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -230,7 +230,7 @@ SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet6_ipsec6, IPSECCTL_STATS,
static int ipsec4_setspidx_inpcb __P((struct mbuf *, struct inpcb *pcb));
#ifdef INET6
-static int ipsec6_setspidx_in6pcb __P((struct mbuf *, struct in6pcb *pcb));
+static int ipsec6_setspidx_in6pcb __P((struct mbuf *, struct inpcb *pcb));
#endif
static int ipsec_setspidx __P((struct mbuf *, struct secpolicyindex *, int));
static void ipsec4_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
@@ -376,7 +376,7 @@ ipsec_getpolicybysock(m, dir, inp, error)
if (inp->inp_vflag & INP_IPV6PROTO) {
#ifdef INET6
*error = ipsec6_setspidx_in6pcb(m, inp);
- pcbsp = inp->in6p_sp;
+ pcbsp = inp->inp_sp;
#else
*error = EINVAL; /* should not happen */
#endif
@@ -578,27 +578,27 @@ ipsec4_setspidx_inpcb(m, pcb)
static int
ipsec6_setspidx_in6pcb(m, pcb)
struct mbuf *m;
- struct in6pcb *pcb;
+ struct inpcb *pcb;
{
//INIT_VNET_IPSEC(curvnet);
struct secpolicyindex *spidx;
int error;
IPSEC_ASSERT(pcb != NULL, ("null pcb"));
- IPSEC_ASSERT(pcb->in6p_sp != NULL, ("null inp_sp"));
- IPSEC_ASSERT(pcb->in6p_sp->sp_out != NULL && pcb->in6p_sp->sp_in != NULL,
+ IPSEC_ASSERT(pcb->inp_sp != NULL, ("null inp_sp"));
+ IPSEC_ASSERT(pcb->inp_sp->sp_out != NULL && pcb->inp_sp->sp_in != NULL,
("null sp_in || sp_out"));
- bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
- bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
- spidx = &pcb->in6p_sp->sp_in->spidx;
+ spidx = &pcb->inp_sp->sp_in->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
spidx->dir = IPSEC_DIR_INBOUND;
- spidx = &pcb->in6p_sp->sp_out->spidx;
+ spidx = &pcb->inp_sp->sp_out->spidx;
error = ipsec_setspidx(m, spidx, 1);
if (error)
goto bad;
@@ -607,8 +607,8 @@ ipsec6_setspidx_in6pcb(m, pcb)
return 0;
bad:
- bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
- bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx));
+ bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx));
return error;
}
#endif
@@ -1245,7 +1245,7 @@ ipsec_delete_pcbpolicy(inp)
#ifdef INET6
int
ipsec6_set_policy(in6p, optname, request, len, cred)
- struct in6pcb *in6p;
+ struct inpcb *in6p;
int optname;
caddr_t request;
size_t len;
@@ -1265,10 +1265,10 @@ ipsec6_set_policy(in6p, optname, request, len, cred)
/* select direction */
switch (xpl->sadb_x_policy_dir) {
case IPSEC_DIR_INBOUND:
- pcb_sp = &in6p->in6p_sp->sp_in;
+ pcb_sp = &in6p->inp_sp->sp_in;
break;
case IPSEC_DIR_OUTBOUND:
- pcb_sp = &in6p->in6p_sp->sp_out;
+ pcb_sp = &in6p->inp_sp->sp_out;
break;
default:
ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
@@ -1281,7 +1281,7 @@ ipsec6_set_policy(in6p, optname, request, len, cred)
int
ipsec6_get_policy(in6p, request, len, mp)
- struct in6pcb *in6p;
+ struct inpcb *in6p;
caddr_t request;
size_t len;
struct mbuf **mp;
@@ -1293,7 +1293,7 @@ ipsec6_get_policy(in6p, request, len, mp)
/* sanity check. */
if (in6p == NULL || request == NULL || mp == NULL)
return EINVAL;
- IPSEC_ASSERT(in6p->in6p_sp != NULL, ("null in6p_sp"));
+ IPSEC_ASSERT(in6p->inp_sp != NULL, ("null inp_sp"));
if (len < sizeof(*xpl))
return EINVAL;
xpl = (struct sadb_x_policy *)request;
@@ -1301,10 +1301,10 @@ ipsec6_get_policy(in6p, request, len, mp)
/* select direction */
switch (xpl->sadb_x_policy_dir) {
case IPSEC_DIR_INBOUND:
- pcb_sp = in6p->in6p_sp->sp_in;
+ pcb_sp = in6p->inp_sp->sp_in;
break;
case IPSEC_DIR_OUTBOUND:
- pcb_sp = in6p->in6p_sp->sp_out;
+ pcb_sp = in6p->inp_sp->sp_out;
break;
default:
ipseclog((LOG_ERR, "%s: invalid direction=%u\n", __func__,
@@ -1684,7 +1684,7 @@ size_t
ipsec6_hdrsiz(m, dir, in6p)
struct mbuf *m;
u_int dir;
- struct in6pcb *in6p;
+ struct inpcb *in6p;
{
INIT_VNET_IPSEC(curvnet);
struct secpolicy *sp;
@@ -1692,7 +1692,7 @@ ipsec6_hdrsiz(m, dir, in6p)
size_t size;
IPSEC_ASSERT(m != NULL, ("null mbuf"));
- IPSEC_ASSERT(in6p == NULL || in6p->in6p_socket != NULL,
+ IPSEC_ASSERT(in6p == NULL || in6p->inp_socket != NULL,
("socket w/o inpcb"));
/* get SP for this packet */
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index f65d1f1..4906999 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -1160,42 +1160,24 @@ key_freeso(struct socket *so)
IPSEC_ASSERT(so != NULL, ("null so"));
switch (so->so_proto->pr_domain->dom_family) {
+#if defined(INET) || defined(INET6)
#ifdef INET
case PF_INET:
- {
- struct inpcb *pcb = sotoinpcb(so);
-
- /* Does it have a PCB ? */
- if (pcb == NULL)
- return;
- key_freesp_so(&pcb->inp_sp->sp_in);
- key_freesp_so(&pcb->inp_sp->sp_out);
- }
- break;
#endif
#ifdef INET6
case PF_INET6:
+#endif
{
-#ifdef HAVE_NRL_INPCB
- struct inpcb *pcb = sotoinpcb(so);
+ struct inpcb *pcb = sotoinpcb(so);
/* Does it have a PCB ? */
if (pcb == NULL)
return;
key_freesp_so(&pcb->inp_sp->sp_in);
key_freesp_so(&pcb->inp_sp->sp_out);
-#else
- struct in6pcb *pcb = sotoin6pcb(so);
-
- /* Does it have a PCB ? */
- if (pcb == NULL)
- return;
- key_freesp_so(&pcb->in6p_sp->sp_in);
- key_freesp_so(&pcb->in6p_sp->sp_out);
-#endif
}
break;
-#endif /* INET6 */
+#endif /* INET || INET6 */
default:
ipseclog((LOG_DEBUG, "%s: unknown address family=%d.\n",
__func__, so->so_proto->pr_domain->dom_family));
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 3b860ac..ab09421 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -3615,9 +3615,12 @@ again:
* Probe one of the directory entries to see if the filesystem
* supports VGET.
*/
- if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
- EOPNOTSUPP) {
- error = NFSERR_NOTSUPP;
+ error = VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp);
+ if (error) {
+ if (error == EOPNOTSUPP)
+ error = NFSERR_NOTSUPP;
+ else
+ error = NFSERR_SERVERFAULT;
vrele(vp);
vp = NULL;
free((caddr_t)cookies, M_TEMP);
diff --git a/sys/pc98/conf/DEFAULTS b/sys/pc98/conf/DEFAULTS
index 962c099..c16a29b 100644
--- a/sys/pc98/conf/DEFAULTS
+++ b/sys/pc98/conf/DEFAULTS
@@ -22,5 +22,5 @@ device uart_ns8250
#device uart_i8251
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_PC98
+options GEOM_PART_BSD
+options GEOM_PART_PC98
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 71866ce..d11d5d9 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -901,9 +901,15 @@ rl_attach(device_t dev)
}
if (sc->rl_type == 0) {
- device_printf(dev, "unknown device ID: %x\n", rl_did);
- error = ENXIO;
- goto fail;
+ device_printf(dev, "unknown device ID: %x assuming 8139\n",
+ rl_did);
+ sc->rl_type = RL_8139;
+ /*
+ * Read RL_IDR register to get ethernet address as accessing
+ * EEPROM may not extract correct address.
+ */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ eaddr[i] = CSR_READ_1(sc, RL_IDR0 + i);
}
if ((error = rl_dma_alloc(sc)) != 0)
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index d9df78c..b3569e8 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -131,6 +131,8 @@
#define RL_TBI_ANAR 0x0068
#define RL_TBI_LPAR 0x006A
#define RL_GMEDIASTAT 0x006C /* 8 bits */
+#define RL_MACDBG 0x006D /* 8 bits, 8168C SPIN2 only */
+#define RL_GPIO 0x006E /* 8 bits, 8168C SPIN2 only */
#define RL_MAXRXPKTLEN 0x00DA /* 16 bits, chip multiplies by 8 */
#define RL_GTXSTART 0x0038 /* 8 bits */
@@ -888,6 +890,8 @@ struct rl_softc {
#define RL_FLAG_PHY8169 0x0400
#define RL_FLAG_PHY8110S 0x0800
#define RL_FLAG_WOLRXENB 0x1000
+#define RL_FLAG_MACSLEEP 0x2000
+#define RL_FLAG_PCIE 0x4000
#define RL_FLAG_LINK 0x8000
};
diff --git a/sys/powerpc/aim/locore.S b/sys/powerpc/aim/locore.S
index cfe75d9..60e5e9d 100644
--- a/sys/powerpc/aim/locore.S
+++ b/sys/powerpc/aim/locore.S
@@ -129,14 +129,6 @@ kernel_text:
.text
.globl __start
__start:
-#ifdef FIRMWORKSBUGS
- mfmsr 0
- andi. 0,0,PSL_IR|PSL_DR
- beq 1f
-
- bl ofwr_init
-1:
-#endif
li 8,0
li 9,0x100
mtctr 9
@@ -154,7 +146,6 @@ __start:
lis 8,openfirmware_entry@ha
stw 5,openfirmware_entry@l(8) /* save client interface handler */
- mr 3,5
lis 1,(tmpstk+TMPSTKSZ-16)@ha
addi 1,1,(tmpstk+TMPSTKSZ-16)@l
@@ -172,7 +163,7 @@ __start:
mfsprg3 0
stw 0,16(9) /* ofmsr[4] = sprg3 */
- bl OF_init
+ bl OF_initial_setup
lis 4,end@ha
addi 4,4,end@l
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 13fc2a7..2199cb1 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -291,9 +291,19 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
__asm __volatile("mtsprg 0, %0" :: "r"(pc));
+ /*
+ * Init mutexes, which we use heavily in PMAP
+ */
+
mutex_init();
/*
+ * Install the OF client interface
+ */
+
+ OF_bootstrap();
+
+ /*
* Initialize the console before printing anything.
*/
cninit();
@@ -307,8 +317,6 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
kdb_init();
- kobj_machdep_init();
-
/*
* XXX: Initialize the interrupt tables.
* Disable translation in case the vector area
diff --git a/sys/powerpc/aim/ofw_machdep.c b/sys/powerpc/aim/ofw_machdep.c
index 2755819..0d5f03b 100644
--- a/sys/powerpc/aim/ofw_machdep.c
+++ b/sys/powerpc/aim/ofw_machdep.c
@@ -65,6 +65,10 @@ static struct mem_region OFfree[OFMEM_REGIONS + 3];
extern register_t ofmsr[5];
extern struct pmap ofw_pmap;
static int (*ofwcall)(void *);
+static void *fdt;
+int ofw_real_mode;
+
+static int openfirmware(void *args);
/*
* Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
@@ -192,13 +196,45 @@ mem_regions(struct mem_region **memp, int *memsz,
}
void
-set_openfirm_callback(int (*openfirm)(void *))
+OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
{
+ if (ofmsr[0] & PSL_DR)
+ ofw_real_mode = 0;
+ else
+ ofw_real_mode = 1;
ofwcall = openfirm;
+ fdt = fdt_ptr;
}
-int
+boolean_t
+OF_bootstrap()
+{
+ boolean_t status = FALSE;
+
+ if (ofwcall != NULL) {
+ if (ofw_real_mode)
+ status = OF_install(OFW_STD_REAL, 0);
+ else
+ status = OF_install(OFW_STD_DIRECT, 0);
+
+ if (status != TRUE)
+ return status;
+
+ OF_init(openfirmware);
+ } else {
+ status = OF_install(OFW_FDT, 0);
+
+ if (status != TRUE)
+ return status;
+
+ OF_init(fdt);
+ }
+
+ return (status);
+}
+
+static int
openfirmware(void *args)
{
long oldmsr;
@@ -206,6 +242,9 @@ openfirmware(void *args)
u_int srsave[16];
u_int i;
+ if (pmap_bootstrapped && ofw_real_mode)
+ args = (void *)pmap_kextract((vm_offset_t)args);
+
__asm __volatile( "\t"
"sync\n\t"
"mfmsr %0\n\t"
@@ -217,7 +256,7 @@ openfirmware(void *args)
ofw_sprg_prepare();
- if (pmap_bootstrapped) {
+ if (pmap_bootstrapped && !ofw_real_mode) {
/*
* Swap the kernel's address space with Open Firmware's
*/
@@ -236,7 +275,7 @@ openfirmware(void *args)
result = ofwcall(args);
- if (pmap_bootstrapped) {
+ if (pmap_bootstrapped && !ofw_real_mode) {
/*
* Restore the kernel's addr space. The isync() doesn;t
* work outside the loop unless mtsrin() is open-coded
diff --git a/sys/powerpc/booke/interrupt.c b/sys/powerpc/booke/interrupt.c
index 1d20772..01ee3d9 100644
--- a/sys/powerpc/booke/interrupt.c
+++ b/sys/powerpc/booke/interrupt.c
@@ -93,7 +93,6 @@ dump_frame(struct trapframe *frame)
printf("\n");
}
-
void powerpc_crit_interrupt(struct trapframe *framep)
{
diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S
index a6335e6..e4df6af 100644
--- a/sys/powerpc/booke/locore.S
+++ b/sys/powerpc/booke/locore.S
@@ -1,4 +1,5 @@
/*-
+ * Copyright (C) 2007-2008 Semihalf, Rafal Jaworowski <raj@semihalf.com>
* Copyright (C) 2006 Semihalf, Marian Balakowicz <m8@semihalf.com>
* All rights reserved.
*
@@ -10,8 +11,6 @@
* 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -29,8 +28,8 @@
#include "assym.s"
-#include <machine/param.h>
#include <machine/asm.h>
+#include <machine/param.h>
#include <machine/spr.h>
#include <machine/psl.h>
#include <machine/pte.h>
@@ -60,207 +59,140 @@ kernel_text:
__start:
/*
- * Assumption on a boot loader:
+ * Assumptions on the boot loader:
* - system memory starts from physical address 0
- * - kernel is loaded at 16MB boundary
* - it's mapped by a single TBL1 entry
* - TLB1 mapping is 1:1 pa to va
+ * - kernel is loaded at 16MB boundary
* - all PID registers are set to the same value
+ * - CPU is running in AS=0
*
- * Loader register use:
+ * Registers contents provided by the loader(8):
* r1 : stack pointer
* r3 : metadata pointer
*
* We rearrange the TLB1 layout as follows:
- * - find AS and entry kernel started in
+ * - find TLB1 entry we started in
* - make sure it's protected, ivalidate other entries
- * - create temp entry in the second AS (make sure it's not TLB[15])
+ * - create temp entry in the second AS (make sure it's not TLB[1])
* - switch to temp mapping
- * - map 16MB of RAM in TLB1[15]
+ * - map 16MB of RAM in TLB1[1]
* - use AS=1, set EPN to KERNBASE and RPN to kernel load address
- * - switch to to TLB1[15] mapping
+ * - switch to to TLB1[1] mapping
* - invalidate temp mapping
*
- * locore register use:
+ * locore registers use:
* r1 : stack pointer
- * r2 : unused
- * r3 : kernel_text
- * r4 : _end
- * r5 : metadata pointer
- * r6-r9 : unused
- * r10 : entry we started in
- * r11 : temp entry
- * r12 : AS we started in
- * r13-r31 : auxiliary registers
+ * r2 : trace pointer (AP only, for early diagnostics)
+ * r3-r27 : scratch registers
+ * r28 : kernload
+ * r29 : temp TLB1 entry
+ * r30 : initial TLB1 entry we started in
+ * r31 : metadata pointer
*/
/*
- * Move metadata ptr to r5
+ * Keep metadata ptr in r31 for later use.
*/
- mr %r5, %r3
+ mr %r31, %r3
/*
* Initial cleanup
*/
- li %r16, 0x200 /* Keep debug exceptions for CodeWarrior. */
- mtmsr %r16
- isync
-#if 0
- mtspr SPR_HID0, %r16
- isync
- msync
- mtspr SPR_HID1, %r16
+ li %r3, PSL_DE /* Keep debug exceptions for CodeWarrior. */
+ mtmsr %r3
isync
-#endif
- /* Issue INV_ALL Invalidate on TLB0 */
- li %r16, 0x04
- tlbivax 0, %r16
- isync
- msync
+ /* Invalidate all entries in TLB0 */
+ li %r3, 0
+ bl tlb_inval_all
/*
- * Use tblsx to locate the TLB1 entry that maps kernel code
+ * Locate the TLB1 entry that maps this code
*/
- bl 1f /* Current address */
-1: mflr %r15
-
- /* Find entry that maps current address */
- mfspr %r17, SPR_PID0
- slwi %r17, %r17, MAS6_SPID0_SHIFT
- mtspr SPR_MAS6, %r17
- isync
- tlbsx 0, %r15
-
- /* Copy entry number to r10 */
- mfspr %r17, SPR_MAS0
- rlwinm %r10, %r17, 16, 28, 31
-
- /* Invalidate TLB1, skipping our entry. */
- mfspr %r17, SPR_TLB1CFG /* Get number of entries */
- andi. %r17, %r17, TLBCFG_NENTRY_MASK@l
- li %r16, 0 /* Start from Entry 0 */
-
-2: lis %r15, MAS0_TLBSEL1@h /* Select TLB1 */
- rlwimi %r15, %r16, 16, 12, 15
- mtspr SPR_MAS0, %r15
- isync
- tlbre
- mfspr %r15, SPR_MAS1
- cmpw %r16, %r10
- beq 3f
- /* Clear VALID and IPROT bits for other entries */
- rlwinm %r15, %r15, 0, 2, 31
- mtspr SPR_MAS1, %r15
- isync
- tlbwe
- isync
- msync
-3: addi %r16, %r16, 1
- cmpw %r16, %r17 /* Check if this is the last entry */
- bne 2b
+ bl 1f
+1: mflr %r3
+ bl tlb1_find_current /* the entry number found is returned in r30 */
+ bl tlb1_inval_all_but_current
/*
- * Create temporary mapping in the other Address Space
+ * Create temporary mapping in AS=1 and switch to it
*/
- lis %r17, MAS0_TLBSEL1@h /* Select TLB1 */
- rlwimi %r17, %r10, 16, 12, 15 /* Select our entry */
- mtspr SPR_MAS0, %r17
- isync
- tlbre /* Read it in */
-
- /* Prepare and write temp entry */
- lis %r17, MAS0_TLBSEL1@h /* Select TLB1 */
- addi %r11, %r10, 0x1 /* Use next entry. */
- rlwimi %r17, %r11, 16, 12, 15 /* Select temp entry */
- mtspr SPR_MAS0, %r17
- isync
-
- mfspr %r16, SPR_MAS1
- li %r15, 1 /* AS 1 */
- rlwimi %r16, %r15, 12, 19, 19
- mtspr SPR_MAS1, %r16
- li %r17, 0
- rlwimi %r16, %r17, 0, 8, 15 /* Global mapping, TID=0 */
- isync
-
- tlbwe
- isync
- msync
-
- mfmsr %r16
- ori %r16, %r16, 0x30 /* Switch to AS 1. */
-
- bl 4f /* Find current execution address */
-4: mflr %r15
- addi %r15, %r15, 20 /* Increment to instruction after rfi */
- mtspr SPR_SRR0, %r15
- mtspr SPR_SRR1, %r16
+ bl tlb1_temp_mapping_as1
+
+ mfmsr %r3
+ ori %r3, %r3, (PSL_IS | PSL_DS)
+ bl 2f
+2: mflr %r4
+ addi %r4, %r4, 20
+ mtspr SPR_SRR0, %r4
+ mtspr SPR_SRR1, %r3
rfi /* Switch context */
/*
* Invalidate initial entry
*/
- mr %r22, %r10
+ mr %r3, %r30
bl tlb1_inval_entry
/*
* Setup final mapping in TLB1[1] and switch to it
*/
/* Final kernel mapping, map in 16 MB of RAM */
- lis %r16, MAS0_TLBSEL1@h /* Select TLB1 */
- li %r17, 1 /* Entry 1 */
- rlwimi %r16, %r17, 16, 12, 15
- mtspr SPR_MAS0, %r16
+ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */
+ li %r4, 1 /* Entry 1 */
+ rlwimi %r3, %r4, 16, 12, 15
+ mtspr SPR_MAS0, %r3
isync
- li %r16, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l
- oris %r16, %r16, (MAS1_VALID | MAS1_IPROT)@h
- mtspr SPR_MAS1, %r16
+ li %r3, (TLB_SIZE_16M << MAS1_TSIZE_SHIFT)@l
+ oris %r3, %r3, (MAS1_VALID | MAS1_IPROT)@h
+ mtspr SPR_MAS1, %r3 /* note TS was not filled, so it's TS=0 */
isync
- lis %r19, KERNBASE@h
- ori %r19, %r19, KERNBASE@l
- mtspr SPR_MAS2, %r19 /* Set final EPN, clear WIMG */
+ lis %r3, KERNBASE@h
+ ori %r3, %r3, KERNBASE@l /* EPN = KERNBASE */
+ mtspr SPR_MAS2, %r3
isync
- bl 5f
-5: mflr %r16 /* Use current address */
- lis %r18, 0xff00 /* 16MB alignment mask */
- and %r16, %r16, %r18
- mr %r25, %r16 /* Copy kernel load address */
- ori %r16, %r16, (MAS3_SX | MAS3_SW | MAS3_SR)@l
- mtspr SPR_MAS3, %r16 /* Set RPN and protection */
+ /* Discover phys load address */
+ bl 3f
+3: mflr %r4 /* Use current address */
+ rlwinm %r4, %r4, 0, 0, 7 /* 16MB alignment mask */
+ mr %r28, %r4 /* Keep kernel load address */
+ ori %r4, %r4, (MAS3_SX | MAS3_SW | MAS3_SR)@l
+ mtspr SPR_MAS3, %r4 /* Set RPN and protection */
isync
tlbwe
isync
msync
/* Switch to the above TLB1[1] mapping */
- lis %r18, 0x00ff /* 16MB offset mask */
- ori %r18, %r18, 0xffff
- bl 6f
-6: mflr %r20 /* Use current address */
- and %r20, %r20, %r18 /* Offset from kernel load address */
- add %r20, %r20, %r19 /* Move to kernel virtual address */
- addi %r20, %r20, 32 /* Increment to instr. after rfi */
- li %r21, 0x200
- mtspr SPR_SRR0, %r20
- mtspr SPR_SRR1, %r21
+ bl 4f
+4: mflr %r4
+ rlwinm %r4, %r4, 0, 8, 31 /* Current offset from kernel load address */
+ rlwinm %r3, %r3, 0, 0, 19
+ add %r4, %r4, %r3 /* Convert to kernel virtual address */
+ addi %r4, %r4, 36
+ li %r3, PSL_DE /* Note AS=0 */
+ mtspr SPR_SRR0, %r4
+ mtspr SPR_SRR1, %r3
rfi
- /* Save kernel load address for later use */
- lis %r24, kernload@ha
- addi %r24, %r24, kernload@l
- stw %r25, 0(%r24)
-
/*
* Invalidate temp mapping
*/
- mr %r22, %r11
+ mr %r3, %r29
bl tlb1_inval_entry
/*
+ * Save kernel load address for later use.
+ */
+ lis %r3, kernload@ha
+ addi %r3, %r3, kernload@l
+ stw %r28, 0(%r3)
+
+/*
* Setup a temporary stack
*/
lis %r1, tmpstack@ha
@@ -268,119 +200,203 @@ __start:
addi %r1, %r1, (TMPSTACKSZ - 8)
/*
- * Intialise exception vector offsets
+ * Initialise exception vector offsets
*/
bl ivor_setup
/*
- * Jump to system initialization code
- *
- * Setup first two arguments for e500_init, metadata (r5) is already in place.
+ * Set up arguments and jump to system initialization code
*/
lis %r3, kernel_text@ha
addi %r3, %r3, kernel_text@l
lis %r4, _end@ha
addi %r4, %r4, _end@l
+ mr %r5, %r31 /* metadata ptr */
+ /* Prepare e500 core */
bl e500_init
- /* Switch to thread0.td_kstack */
+ /* Switch to thread0.td_kstack now */
mr %r1, %r3
li %r3, 0
stw %r3, 0(%r1)
- bl mi_startup /* Machine independet part, does not return */
+ /* Machine independet part, does not return */
+ bl mi_startup
+ /* NOT REACHED */
+5: b 5b
-/************************************************************************/
-/* locore subroutines */
-/************************************************************************/
+/*
+ * Invalidate all entries in the given TLB.
+ *
+ * r3 TLBSEL
+ */
+tlb_inval_all:
+ rlwinm %r3, %r3, 3, 0x18 /* TLBSEL */
+ ori %r3, %r3, 0x4 /* INVALL */
+ tlbivax 0, %r3
+ isync
+ msync
-tlb1_inval_entry:
- lis %r17, MAS0_TLBSEL1@h /* Select TLB1 */
- rlwimi %r17, %r22, 16, 12, 15 /* Select our entry */
- mtspr SPR_MAS0, %r17
+ tlbsync
+ msync
+ blr
+
+/*
+ * expects address to look up in r3, returns entry number in r30
+ *
+ * FIXME: the hidden assumption is we are now running in AS=0, but we should
+ * retrieve actual AS from MSR[IS|DS] and put it in MAS6[SAS]
+ */
+tlb1_find_current:
+ mfspr %r17, SPR_PID0
+ slwi %r17, %r17, MAS6_SPID0_SHIFT
+ mtspr SPR_MAS6, %r17
isync
- tlbre /* Read it in */
+ tlbsx 0, %r3
+ mfspr %r17, SPR_MAS0
+ rlwinm %r30, %r17, 16, 20, 31 /* MAS0[ESEL] -> r30 */
- li %r16, 0
- mtspr SPR_MAS1, %r16
+ /* Make sure we have IPROT set on the entry */
+ mfspr %r17, SPR_MAS1
+ oris %r17, %r17, MAS1_IPROT@h
+ mtspr SPR_MAS1, %r17
isync
tlbwe
isync
msync
blr
-ivor_setup:
- /* Set base address of interrupt handler routines */
- lis %r21, interrupt_vector_base@h
- mtspr SPR_IVPR, %r21
-
- /* Assign interrupt handler routines offsets */
- li %r21, int_critical_input@l
- mtspr SPR_IVOR0, %r21
- li %r21, int_machine_check@l
- mtspr SPR_IVOR1, %r21
- li %r21, int_data_storage@l
- mtspr SPR_IVOR2, %r21
- li %r21, int_instr_storage@l
- mtspr SPR_IVOR3, %r21
- li %r21, int_external_input@l
- mtspr SPR_IVOR4, %r21
- li %r21, int_alignment@l
- mtspr SPR_IVOR5, %r21
- li %r21, int_program@l
- mtspr SPR_IVOR6, %r21
- li %r21, int_syscall@l
- mtspr SPR_IVOR8, %r21
- li %r21, int_decrementer@l
- mtspr SPR_IVOR10, %r21
- li %r21, int_fixed_interval_timer@l
- mtspr SPR_IVOR11, %r21
- li %r21, int_watchdog@l
- mtspr SPR_IVOR12, %r21
- li %r21, int_data_tlb_error@l
- mtspr SPR_IVOR13, %r21
- li %r21, int_inst_tlb_error@l
- mtspr SPR_IVOR14, %r21
- li %r21, int_debug@l
- mtspr SPR_IVOR15, %r21
- blr
-
/*
- * void tlb1_inval_va(vm_offset_t va)
+ * Invalidates a single entry in TLB1.
*
- * r3 - va to invalidate
+ * r3 ESEL
+ * r4-r5 scratched
*/
-ENTRY(tlb1_inval_va)
- /* EA mask */
- lis %r6, 0xffff
- ori %r6, %r6, 0xf000
- and %r3, %r3, %r6
+tlb1_inval_entry:
+ lis %r4, MAS0_TLBSEL1@h /* Select TLB1 */
+ rlwimi %r4, %r3, 16, 12, 15 /* Select our entry */
+ mtspr SPR_MAS0, %r4
+ isync
+ tlbre
+ li %r5, 0 /* MAS1[V] = 0 */
+ mtspr SPR_MAS1, %r5
+ isync
+ tlbwe
+ isync
+ msync
+ blr
- /* Select TLB1 */
- ori %r3, %r3, 0x08
+/*
+ * r30 current entry number
+ * r29 returned temp entry
+ * r3-r5 scratched
+ */
+tlb1_temp_mapping_as1:
+ /* Read our current translation */
+ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */
+ rlwimi %r3, %r30, 16, 12, 15 /* Select our current entry */
+ mtspr SPR_MAS0, %r3
+ isync
+ tlbre
+ /*
+ * Prepare and write temp entry
+ *
+ * FIXME this is not robust against overflow i.e. when the current
+ * entry is the last in TLB1
+ */
+ lis %r3, MAS0_TLBSEL1@h /* Select TLB1 */
+ addi %r29, %r30, 1 /* Use next entry. */
+ li %r4, 1
+ cmpw %r4, %r29
+ bne 1f
+ addi %r29, %r29, 1
+1: rlwimi %r3, %r29, 16, 12, 15 /* Select temp entry */
+ mtspr SPR_MAS0, %r3
+ isync
+ mfspr %r5, SPR_MAS1
+ li %r4, 1 /* AS=1 */
+ rlwimi %r5, %r4, 12, 19, 19
+ li %r4, 0 /* Global mapping, TID=0 */
+ rlwimi %r5, %r4, 16, 8, 15
+ oris %r5, %r5, (MAS1_VALID | MAS1_IPROT)@h
+ mtspr SPR_MAS1, %r5
isync
- tlbivax 0, %r3
+ tlbwe
isync
msync
blr
/*
- * void tlb0_inval_va(vm_offset_t va)
+ * Loops over TLB1, invalidates all entries skipping the one which currently
+ * maps this code.
*
- * r3 - va to invalidate
+ * r30 current entry
+ * r3-r5 scratched
*/
-ENTRY(tlb0_inval_va)
- /* EA mask, this also clears TLBSEL, selecting TLB0 */
- lis %r6, 0xffff
- ori %r6, %r6, 0xf000
- and %r3, %r3, %r6
-
+tlb1_inval_all_but_current:
+ mr %r6, %r3
+ mfspr %r3, SPR_TLB1CFG /* Get number of entries */
+ andi. %r3, %r3, TLBCFG_NENTRY_MASK@l
+ li %r4, 0 /* Start from Entry 0 */
+1: lis %r5, MAS0_TLBSEL1@h
+ rlwimi %r5, %r4, 16, 12, 15
+ mtspr SPR_MAS0, %r5
isync
- tlbivax 0, %r3
+ tlbre
+ mfspr %r5, SPR_MAS1
+ cmpw %r4, %r30 /* our current entry? */
+ beq 2f
+ rlwinm %r5, %r5, 0, 2, 31 /* clear VALID and IPROT bits */
+ mtspr SPR_MAS1, %r5
+ isync
+ tlbwe
isync
msync
+2: addi %r4, %r4, 1
+ cmpw %r4, %r3 /* Check if this is the last entry */
+ bne 1b
+ blr
+
+/************************************************************************/
+/* locore subroutines */
+/************************************************************************/
+
+ivor_setup:
+ /* Set base address of interrupt handler routines */
+ lis %r3, interrupt_vector_base@h
+ mtspr SPR_IVPR, %r3
+
+ /* Assign interrupt handler routines offsets */
+ li %r3, int_critical_input@l
+ mtspr SPR_IVOR0, %r3
+ li %r3, int_machine_check@l
+ mtspr SPR_IVOR1, %r3
+ li %r3, int_data_storage@l
+ mtspr SPR_IVOR2, %r3
+ li %r3, int_instr_storage@l
+ mtspr SPR_IVOR3, %r3
+ li %r3, int_external_input@l
+ mtspr SPR_IVOR4, %r3
+ li %r3, int_alignment@l
+ mtspr SPR_IVOR5, %r3
+ li %r3, int_program@l
+ mtspr SPR_IVOR6, %r3
+ li %r3, int_syscall@l
+ mtspr SPR_IVOR8, %r3
+ li %r3, int_decrementer@l
+ mtspr SPR_IVOR10, %r3
+ li %r3, int_fixed_interval_timer@l
+ mtspr SPR_IVOR11, %r3
+ li %r3, int_watchdog@l
+ mtspr SPR_IVOR12, %r3
+ li %r3, int_data_tlb_error@l
+ mtspr SPR_IVOR13, %r3
+ li %r3, int_inst_tlb_error@l
+ mtspr SPR_IVOR14, %r3
+ li %r3, int_debug@l
+ mtspr SPR_IVOR15, %r3
blr
/*
@@ -395,6 +411,9 @@ ENTRY(dcache_inval)
isync
mtspr SPR_L1CSR0, %r3
isync
+1: mfspr %r3, SPR_L1CSR0
+ andi. %r3, %r3, L1CSR0_DCFI
+ bne 1b
blr
ENTRY(dcache_disable)
@@ -427,6 +446,9 @@ ENTRY(icache_inval)
isync
mtspr SPR_L1CSR1, %r3
isync
+1: mfspr %r3, SPR_L1CSR1
+ andi. %r3, %r3, L1CSR1_ICFI
+ bne 1b
blr
ENTRY(icache_disable)
@@ -495,7 +517,7 @@ tmpstack:
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
GLOBAL(kernload)
- .long
+ .long 0
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
GLOBAL(eintrnames)
diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c
index 218127d..a48ece1 100644
--- a/sys/powerpc/booke/machdep.c
+++ b/sys/powerpc/booke/machdep.c
@@ -10,8 +10,6 @@
* 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. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
@@ -88,7 +86,6 @@ __FBSDID("$FreeBSD$");
#include <sys/cdefs.h>
#include <sys/types.h>
-
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
@@ -137,6 +134,9 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/reboot.h>
+#include <powerpc/mpc85xx/ocpbus.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
+
#ifdef DEBUG
#define debugf(fmt, args...) printf(fmt, ##args)
#else
@@ -180,8 +180,8 @@ static void cpu_e500_startup(void *);
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_e500_startup, NULL);
void print_kernel_section_addr(void);
-void dump_bootinfo(void);
-void dump_kenv(void);
+void print_bootinfo(void);
+void print_kenv(void);
u_int e500_init(u_int32_t, u_int32_t, void *);
static void
@@ -204,16 +204,17 @@ cpu_e500_startup(void *dummy)
printf("Physical memory chunk(s):\n");
for (indx = 0; phys_avail[indx + 1] != 0; indx += 2) {
size = phys_avail[indx + 1] - phys_avail[indx];
+
printf("0x%08x - 0x%08x, %d bytes (%d pages)\n",
- phys_avail[indx], phys_avail[indx + 1] - 1, size,
- size / PAGE_SIZE);
+ phys_avail[indx], phys_avail[indx + 1] - 1,
+ size, size / PAGE_SIZE);
}
}
vm_ksubmap_init(&kmi);
printf("avail memory = %ld (%ld MB)\n", ptoa(cnt.v_free_count),
- ptoa(cnt.v_free_count) / 1048576);
+ ptoa(cnt.v_free_count) / 1048576);
/* Set up buffers, so they can be used to read disk labels. */
bufinit();
@@ -235,7 +236,7 @@ kenv_next(char *cp)
}
void
-dump_kenv(void)
+print_kenv(void)
{
int len;
char *cp;
@@ -253,7 +254,7 @@ dump_kenv(void)
}
void
-dump_bootinfo(void)
+print_bootinfo(void)
{
struct bi_mem_region *mr;
struct bi_eth_addr *eth;
@@ -291,20 +292,20 @@ print_kernel_section_addr(void)
{
debugf("kernel image addresses:\n");
- debugf(" kernel_text = 0x%08x\n", (u_int32_t)kernel_text);
- debugf(" _etext (sdata) = 0x%08x\n", (u_int32_t)_etext);
- debugf(" _edata = 0x%08x\n", (u_int32_t)_edata);
- debugf(" __sbss_start = 0x%08x\n", (u_int32_t)__sbss_start);
- debugf(" __sbss_end = 0x%08x\n", (u_int32_t)__sbss_end);
- debugf(" __sbss_start = 0x%08x\n", (u_int32_t)__bss_start);
- debugf(" _end = 0x%08x\n", (u_int32_t)_end);
+ debugf(" kernel_text = 0x%08x\n", (uint32_t)kernel_text);
+ debugf(" _etext (sdata) = 0x%08x\n", (uint32_t)_etext);
+ debugf(" _edata = 0x%08x\n", (uint32_t)_edata);
+ debugf(" __sbss_start = 0x%08x\n", (uint32_t)__sbss_start);
+ debugf(" __sbss_end = 0x%08x\n", (uint32_t)__sbss_end);
+ debugf(" __sbss_start = 0x%08x\n", (uint32_t)__bss_start);
+ debugf(" _end = 0x%08x\n", (uint32_t)_end);
}
struct bi_mem_region *
bootinfo_mr(void)
{
- return((struct bi_mem_region *)bootinfo->bi_data);
+ return ((struct bi_mem_region *)bootinfo->bi_data);
}
struct bi_eth_addr *
@@ -346,7 +347,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
kmdp = preload_search_by_type("elf kernel");
if (kmdp != NULL) {
bootinfo = (struct bootinfo *)preload_search_info(kmdp,
- MODINFO_METADATA|MODINFOMD_BOOTINFO);
+ MODINFO_METADATA | MODINFOMD_BOOTINFO);
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
@@ -384,7 +385,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
* Time Base and Decrementer are updated every 8 CCB bus clocks.
* HID0[SEL_TBCLK] = 0
*/
- decr_config(bootinfo->bi_bus_clk/8);
+ decr_config(bootinfo->bi_bus_clk / 8);
/* Init params/tunables that can be overridden by the loader. */
init_param1();
@@ -397,7 +398,6 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
pc = &__pcpu[0];
pcpu_init(pc, 0, sizeof(struct pcpu));
pc->pc_curthread = &thread0;
- pc->pc_cpuid = 0;
__asm __volatile("mtsprg 0, %0" :: "r"(pc));
/* Initialize system mutexes. */
@@ -410,14 +410,17 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
debugf("e500_init: console initialized\n");
debugf(" arg1 startkernel = 0x%08x\n", startkernel);
debugf(" arg2 endkernel = 0x%08x\n", endkernel);
- debugf(" arg3 midp = 0x%08x\n", (u_int32_t)mdp);
+ debugf(" arg3 mdp = 0x%08x\n", (u_int32_t)mdp);
debugf(" end = 0x%08x\n", (u_int32_t)end);
debugf(" boothowto = 0x%08x\n", boothowto);
debugf(" kernel ccsrbar = 0x%08x\n", CCSRBAR_VA);
debugf(" MSR = 0x%08x\n", mfmsr());
- dump_bootinfo();
+ debugf(" HID0 = 0x%08x\n", mfspr(SPR_HID0));
+ debugf(" HID1 = 0x%08x\n", mfspr(SPR_HID1));
+
+ print_bootinfo();
print_kernel_section_addr();
- dump_kenv();
+ print_kenv();
//tlb1_print_entries();
//tlb1_print_tlbentries();
@@ -427,7 +430,6 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
if (boothowto & RB_KDB)
kdb_enter(KDB_WHY_BOOTFLAGS, "Boot flags requested debugger");
#endif
- kobj_machdep_init();
/* Initialise virtual memory. */
pmap_mmu_install(MMU_TYPE_BOOKE, 0);
@@ -459,6 +461,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
dcache_inval();
dcache_enable();
}
+
csr = mfspr(SPR_L1CSR0);
if ((boothowto & RB_VERBOSE) != 0 || (csr & L1CSR0_DCE) == 0)
printf("L1 D-cache %sabled\n",
@@ -470,6 +473,7 @@ e500_init(u_int32_t startkernel, u_int32_t endkernel, void *mdp)
icache_inval();
icache_enable();
}
+
csr = mfspr(SPR_L1CSR1);
if ((boothowto & RB_VERBOSE) != 0 || (csr & L1CSR1_ICE) == 0)
printf("L1 I-cache %sabled\n",
diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h
index d2b8e12..422a86a 100644
--- a/sys/powerpc/include/elf.h
+++ b/sys/powerpc/include/elf.h
@@ -80,9 +80,6 @@ __ElfType(Auxinfo);
#define AT_COUNT 13 /* Count of defined aux entry types. */
-/* Used in John Polstra's testbed stuff. */
-#define AT_DEBUG 14 /* Debugging level. */
-
/*
* Relocation types.
*/
diff --git a/sys/powerpc/include/ofw_machdep.h b/sys/powerpc/include/ofw_machdep.h
index a4b601e..1dd2027 100644
--- a/sys/powerpc/include/ofw_machdep.h
+++ b/sys/powerpc/include/ofw_machdep.h
@@ -28,9 +28,18 @@
#ifndef _MACHINE_OFW_MACHDEP_H_
#define _MACHINE_OFW_MACHDEP_H_
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/rman.h>
#include <sys/bus.h>
+#include <dev/ofw/openfirm.h>
+
+typedef uint32_t cell_t;
int OF_decode_addr(phandle_t, int, bus_space_tag_t *, bus_space_handle_t *);
void OF_getetheraddr(device_t dev, u_char *addr);
+void OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *));
+boolean_t OF_bootstrap(void);
+
#endif /* _MACHINE_OFW_MACHDEP_H_ */
diff --git a/sys/powerpc/include/param.h b/sys/powerpc/include/param.h
index 1b58db9..1a910ba 100644
--- a/sys/powerpc/include/param.h
+++ b/sys/powerpc/include/param.h
@@ -56,6 +56,9 @@
#ifndef _NO_NAMESPACE_POLLUTION
+/* Needed to display interrupts on OFW PCI */
+#define __PCI_REROUTE_INTERRUPT
+
#ifndef _MACHINE_PARAM_H_
#define _MACHINE_PARAM_H_
diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h
index 1662add..70a0012 100644
--- a/sys/powerpc/include/spr.h
+++ b/sys/powerpc/include/spr.h
@@ -560,14 +560,15 @@
#define SPR_MCSRR1 0x23b /* ..8 571 Machine check SRR1 */
#define SPR_SVR 0x3ff /* ..8 1023 System Version Register */
-#define SVR_MPC8533 0x803c0010
-#define SVR_MPC8533E 0x80340010
-#define SVR_MPC8541 0x80720011
-#define SVR_MPC8541E 0x807a0011
-#define SVR_MPC8555 0x80710011
-#define SVR_MPC8555E 0x80790011
-#define SVR_MPC8572 0x80e00010
-#define SVR_MPC8572E 0x80e80010
+#define SVR_MPC8533 0x803c
+#define SVR_MPC8533E 0x8034
+#define SVR_MPC8541 0x8072
+#define SVR_MPC8541E 0x807a
+#define SVR_MPC8555 0x8071
+#define SVR_MPC8555E 0x8079
+#define SVR_MPC8572 0x80e0
+#define SVR_MPC8572E 0x80e8
+#define SVR_VER(svr) (((svr) >> 16) & 0xffff)
#define SPR_PID0 0x030 /* ..8 Process ID Register 0 */
#define SPR_PID1 0x279 /* ..8 Process ID Register 1 */
@@ -623,5 +624,4 @@
#endif /* #elif defined(E500) */
-
#endif /* !_POWERPC_SPR_H_ */
diff --git a/sys/powerpc/mpc85xx/lbc.c b/sys/powerpc/mpc85xx/lbc.c
index 4b168b8..2267245 100644
--- a/sys/powerpc/mpc85xx/lbc.c
+++ b/sys/powerpc/mpc85xx/lbc.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2006-2008, Juniper Networks, Inc.
+ * Copyright (c) 2008 Semihalf, Rafal Czubak
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -44,6 +45,8 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <powerpc/mpc85xx/lbc.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
+#include <powerpc/mpc85xx/ocpbus.h>
struct lbc_softc {
device_t sc_dev;
@@ -54,16 +57,41 @@ struct lbc_softc {
int sc_rid;
struct rman sc_rman;
- uintptr_t sc_kva;
+ vm_offset_t sc_kva[LBC_DEV_MAX];
};
struct lbc_devinfo {
int lbc_devtype;
- int lbc_memtype;
- /* Also the BAR number */
+ /* LBC child unit. It also represents resource table entry number */
int lbc_unit;
};
+/* Resources for MPC8555CDS system */
+const struct lbc_resource mpc85xx_lbc_resources[] = {
+ /* Boot flash bank */
+ {
+ LBC_DEVTYPE_CFI, 0, 0xff800000, 0x00800000, 16,
+ LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
+ LBCRES_ATOM_DISABLED, 0
+ },
+
+ /* Second flash bank */
+ {
+ LBC_DEVTYPE_CFI, 1, 0xff000000, 0x00800000, 16,
+ LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
+ LBCRES_ATOM_DISABLED, 0
+ },
+
+ /* DS1553 RTC/NVRAM */
+ {
+ LBC_DEVTYPE_RTC, 2, 0xf8000000, 0x8000, 8,
+ LBCRES_MSEL_GPCM, LBCRES_DECC_DISABLED,
+ LBCRES_ATOM_DISABLED, 0
+ },
+
+ {0}
+};
+
static int lbc_probe(device_t);
static int lbc_attach(device_t);
static int lbc_shutdown(device_t);
@@ -108,26 +136,170 @@ static driver_t lbc_driver = {
devclass_t lbc_devclass;
DRIVER_MODULE(lbc, ocpbus, lbc_driver, lbc_devclass, 0, 0);
+static __inline void
+lbc_write_reg(struct lbc_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
+}
+
+static __inline uint32_t
+lbc_read_reg(struct lbc_softc *sc, bus_size_t off)
+{
+
+ return (bus_space_read_4(sc->sc_bst, sc->sc_bsh, off));
+}
+
+/*
+ * Calculate address mask used by OR(n) registers. Use memory region size to
+ * determine mask value. The size must be a power of two and within the range
+ * of 32KB - 4GB. Otherwise error code is returned. Value representing
+ * 4GB size can be passed as 0xffffffff.
+ */
+static uint32_t
+lbc_address_mask(uint32_t size)
+{
+ int n = 15;
+
+ if (size == ~0UL)
+ return (0);
+
+ while (n < 32) {
+ if (size == (1UL << n))
+ break;
+ n++;
+ }
+
+ if (n == 32)
+ return (EINVAL);
+
+ return (0xffff8000 << (n - 15));
+}
+
static device_t
-lbc_mk_child(device_t dev, int type, int mtype, int unit)
+lbc_mk_child(device_t dev, const struct lbc_resource *lbcres)
{
struct lbc_devinfo *dinfo;
device_t child;
+ if (lbcres->lbr_unit > LBC_DEV_MAX - 1)
+ return (NULL);
+
child = device_add_child(dev, NULL, -1);
if (child == NULL) {
- device_printf(dev, "could not add child device\n");
+ device_printf(dev, "could not add LBC child device\n");
return (NULL);
}
dinfo = malloc(sizeof(struct lbc_devinfo), M_DEVBUF, M_WAITOK | M_ZERO);
- dinfo->lbc_devtype = type;
- dinfo->lbc_memtype = mtype;
- dinfo->lbc_unit = unit;
+ dinfo->lbc_devtype = lbcres->lbr_devtype;
+ dinfo->lbc_unit = lbcres->lbr_unit;
device_set_ivars(child, dinfo);
return (child);
}
static int
+lbc_init_child(device_t dev, device_t child)
+{
+ struct lbc_softc *sc;
+ struct lbc_devinfo *dinfo;
+ const struct lbc_resource *res;
+ u_long start, size;
+ uint32_t regbuff;
+ int error, unit;
+
+ sc = device_get_softc(dev);
+ dinfo = device_get_ivars(child);
+
+ res = mpc85xx_lbc_resources;
+
+ regbuff = 0;
+ unit = -1;
+ for (; res->lbr_devtype; res++) {
+ if (res->lbr_unit != dinfo->lbc_unit)
+ continue;
+
+ start = res->lbr_base_addr;
+ size = res->lbr_size;
+ unit = res->lbr_unit;
+
+ /*
+ * Configure LAW for this LBC device and map its physical
+ * memory region into KVA
+ */
+ error = law_enable(OCP85XX_TGTIF_LBC, start, size);
+ if (error)
+ return (error);
+
+ sc->sc_kva[unit] = (vm_offset_t)pmap_mapdev(start, size);
+ if (sc->sc_kva[unit] == 0) {
+ law_disable(OCP85XX_TGTIF_LBC, start, size);
+ return (ENOSPC);
+ }
+
+ /*
+ * Compute and program BR value
+ */
+ regbuff |= start;
+
+ switch (res->lbr_port_size) {
+ case 8:
+ regbuff |= (1 << 11);
+ break;
+ case 16:
+ regbuff |= (2 << 11);
+ break;
+ case 32:
+ regbuff |= (3 << 11);
+ break;
+ default:
+ error = EINVAL;
+ goto fail;
+ }
+ regbuff |= (res->lbr_decc << 9);
+ regbuff |= (res->lbr_wp << 8);
+ regbuff |= (res->lbr_msel << 5);
+ regbuff |= (res->lbr_atom << 2);
+ regbuff |= 1;
+
+ lbc_write_reg(sc, LBC85XX_BR(unit), regbuff);
+
+ /*
+ * Compute and program OR value
+ */
+ regbuff = 0;
+ regbuff |= lbc_address_mask(size);
+
+ switch (res->lbr_msel) {
+ case LBCRES_MSEL_GPCM:
+ /* TODO Add flag support for option registers */
+ regbuff |= 0x00000ff7;
+ break;
+ case LBCRES_MSEL_FCM:
+ printf("FCM mode not supported yet!");
+ error = ENOSYS;
+ goto fail;
+ case LBCRES_MSEL_UPMA:
+ case LBCRES_MSEL_UPMB:
+ case LBCRES_MSEL_UPMC:
+ printf("UPM mode not supported yet!");
+ error = ENOSYS;
+ goto fail;
+ }
+
+ lbc_write_reg(sc, LBC85XX_OR(unit), regbuff);
+
+ return (0);
+ }
+fail:
+ if (unit != -1) {
+ law_disable(OCP85XX_TGTIF_LBC, start, size);
+ pmap_unmapdev(sc->sc_kva[unit], size);
+ return (error);
+ } else
+ return (ENOENT);
+}
+
+static int
lbc_probe(device_t dev)
{
device_t parent;
@@ -150,7 +322,7 @@ lbc_attach(device_t dev)
{
struct lbc_softc *sc;
struct rman *rm;
- u_long start, size;
+ const struct lbc_resource *lbcres;
int error;
sc = device_get_softc(dev);
@@ -165,15 +337,11 @@ lbc_attach(device_t dev)
sc->sc_bst = rman_get_bustag(sc->sc_res);
sc->sc_bsh = rman_get_bushandle(sc->sc_res);
- error = bus_get_resource(dev, SYS_RES_MEMORY, 1, &start, &size);
- if (error)
- goto fail;
-
rm = &sc->sc_rman;
rm->rm_type = RMAN_ARRAY;
rm->rm_descr = "MPC85XX Local Bus Space";
- rm->rm_start = start;
- rm->rm_end = start + size - 1;
+ rm->rm_start = 0UL;
+ rm->rm_end = ~0UL;
error = rman_init(rm);
if (error)
goto fail;
@@ -184,13 +352,35 @@ lbc_attach(device_t dev)
goto fail;
}
- sc->sc_kva = (uintptr_t)pmap_mapdev(start, size);
-
- lbc_mk_child(dev, LBC_DEVTYPE_CFI, 0, 0);
+ /*
+ * Initialize configuration register:
+ * - enable Local Bus
+ * - set data buffer control signal function
+ * - disable parity byte select
+ * - set ECC parity type
+ * - set bus monitor timing and timer prescale
+ */
+ lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000);
+
+ /*
+ * Initialize clock ratio register:
+ * - disable PLL bypass mode
+ * - configure LCLK delay cycles for the assertion of LALE
+ * - set system clock divider
+ */
+ lbc_write_reg(sc, LBC85XX_LCRR, 0x00030008);
+
+ lbcres = mpc85xx_lbc_resources;
+
+ for (; lbcres->lbr_devtype; lbcres++)
+ if (!lbc_mk_child(dev, lbcres)) {
+ error = ENXIO;
+ goto fail;
+ }
return (bus_generic_attach(dev));
- fail:
+fail:
bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
return (error);
}
@@ -208,11 +398,13 @@ lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags)
{
struct lbc_softc *sc;
+ struct lbc_devinfo *dinfo;
struct resource *rv;
struct rman *rm;
int error;
sc = device_get_softc(dev);
+ dinfo = device_get_ivars(child);
if (type != SYS_RES_MEMORY && type != SYS_RES_IRQ)
return (NULL);
@@ -225,6 +417,12 @@ lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (bus_alloc_resource(dev, type, rid, start, end, count,
flags));
+ if (!sc->sc_kva[dinfo->lbc_unit]) {
+ error = lbc_init_child(dev, child);
+ if (error)
+ return (NULL);
+ }
+
error = lbc_get_resource(dev, child, type, *rid, &start, &count);
if (error)
return (NULL);
@@ -234,8 +432,7 @@ lbc_alloc_resource(device_t dev, device_t child, int type, int *rid,
rv = rman_reserve_resource(rm, start, end, count, flags, child);
if (rv != NULL) {
rman_set_bustag(rv, &bs_be_tag);
- rman_set_bushandle(rv, sc->sc_kva + rman_get_start(rv) -
- rm->rm_start);
+ rman_set_bushandle(rv, rman_get_start(rv));
}
return (rv);
}
@@ -279,12 +476,6 @@ lbc_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
case LBC_IVAR_DEVTYPE:
*result = dinfo->lbc_devtype;
return (0);
- case LBC_IVAR_CLOCK:
- *result = 1843200;
- return (0);
- case LBC_IVAR_REGSHIFT:
- *result = 0;
- return (0);
default:
break;
}
@@ -305,24 +496,35 @@ lbc_get_resource(device_t dev, device_t child, int type, int rid,
{
struct lbc_softc *sc;
struct lbc_devinfo *dinfo;
+ const struct lbc_resource *lbcres;
if (type != SYS_RES_MEMORY)
return (ENOENT);
- /* Currently all devices have a single RID per type. */
+ /* Currently all LBC devices have a single RID per type. */
if (rid != 0)
return (ENOENT);
sc = device_get_softc(dev);
dinfo = device_get_ivars(child);
+ if ((dinfo->lbc_unit < 0) || (dinfo->lbc_unit > (LBC_DEV_MAX - 1)))
+ return (EINVAL);
+
+ lbcres = mpc85xx_lbc_resources;
+
switch (dinfo->lbc_devtype) {
case LBC_DEVTYPE_CFI:
- *startp = sc->sc_rman.rm_start;
- *countp = sc->sc_rman.rm_end - sc->sc_rman.rm_start + 1;
- break;
+ case LBC_DEVTYPE_RTC:
+ for (; lbcres->lbr_devtype; lbcres++) {
+ if (dinfo->lbc_unit == lbcres->lbr_unit) {
+ *startp = sc->sc_kva[lbcres->lbr_unit];
+ *countp = lbcres->lbr_size;
+ return (0);
+ }
+ }
default:
- return(EDOOFUS);
+ return (EDOOFUS);
}
- return(0);
+ return (0);
}
diff --git a/sys/powerpc/mpc85xx/lbc.h b/sys/powerpc/mpc85xx/lbc.h
index 8bc7843..24e741a 100644
--- a/sys/powerpc/mpc85xx/lbc.h
+++ b/sys/powerpc/mpc85xx/lbc.h
@@ -30,11 +30,49 @@
#define _MACHINE_LBC_H_
#define LBC_IVAR_DEVTYPE 1
-#define LBC_IVAR_CLOCK 2
-#define LBC_IVAR_REGSHIFT 3
+
+/* Maximum number of devices on Local Bus */
+#define LBC_DEV_MAX 8
/* Device types. */
#define LBC_DEVTYPE_CFI 1
-#define LBC_DEVTYPE_UART 2
+#define LBC_DEVTYPE_RTC 2
+
+/* Local access registers */
+#define LBC85XX_BR(n) (OCP85XX_LBC_OFF + (8 * n))
+#define LBC85XX_OR(n) (OCP85XX_LBC_OFF + 4 + (8 * n))
+#define LBC85XX_LBCR (OCP85XX_LBC_OFF + 0xd0)
+#define LBC85XX_LCRR (OCP85XX_LBC_OFF + 0xd4)
+
+/* LBC machine select */
+#define LBCRES_MSEL_GPCM 0
+#define LBCRES_MSEL_FCM 1
+#define LBCRES_MSEL_UPMA 8
+#define LBCRES_MSEL_UPMB 9
+#define LBCRES_MSEL_UPMC 10
+
+/* LBC data error checking modes */
+#define LBCRES_DECC_DISABLED 0
+#define LBCRES_DECC_NORMAL 1
+#define LBCRES_DECC_RMW 2
+
+/* LBC atomic operation modes */
+#define LBCRES_ATOM_DISABLED 0
+#define LBCRES_ATOM_RAWA 1
+#define LBCRES_ATOM_WARA 2
+
+struct lbc_resource {
+ int lbr_devtype; /* LBC device type */
+ int lbr_unit; /* Resource table entry number */
+ vm_paddr_t lbr_base_addr; /* Device mem region base address */
+ size_t lbr_size; /* Device mem region size */
+ int lbr_port_size; /* Data bus width */
+ uint8_t lbr_msel; /* LBC machine select */
+ uint8_t lbr_decc; /* Data error checking mode */
+ uint8_t lbr_atom; /* Atomic operation mode */
+ uint8_t lbr_wp; /* Write protect */
+};
+
+extern const struct lbc_resource mpc85xx_lbc_resources[];
#endif /* _MACHINE_LBC_H_ */
diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c
index 62a47a6..de9c771 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.c
+++ b/sys/powerpc/mpc85xx/mpc85xx.c
@@ -10,9 +10,6 @@
* 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. Neither the name of the author nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -38,33 +35,117 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/cpufunc.h>
-#include <machine/pio.h>
#include <machine/spr.h>
#include <powerpc/mpc85xx/ocpbus.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
/*
* MPC85xx system specific routines
*/
+uint32_t
+ccsr_read4(uintptr_t addr)
+{
+ volatile uint32_t *ptr = (void *)addr;
+
+ return (*ptr);
+}
+
+void
+ccsr_write4(uintptr_t addr, uint32_t val)
+{
+ volatile uint32_t *ptr = (void *)addr;
+
+ *ptr = val;
+ __asm __volatile("eieio; sync");
+}
+
+static __inline int
+law_getmax(void)
+{
+ uint32_t ver;
+
+ ver = SVR_VER(mfspr(SPR_SVR));
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
+ return (12);
+ else
+ return (8);
+}
+
+#define _LAW_SR(trgt,size) (0x80000000 | (trgt << 20) | (ffsl(size) - 2))
+#define _LAW_BAR(addr) (addr >> 12)
+
+int
+law_enable(int trgt, u_long addr, u_long size)
+{
+ uint32_t bar, sr;
+ int i, law_max;
+
+ law_max = law_getmax();
+ bar = _LAW_BAR(addr);
+ sr = _LAW_SR(trgt, size);
+
+ /* Bail if already programmed. */
+ for (i = 0; i < law_max; i++)
+ if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+ bar == ccsr_read4(OCP85XX_LAWBAR(i)))
+ return (0);
+
+ /* Find an unused access window. */
+ for (i = 0; i < law_max; i++)
+ if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
+ break;
+
+ if (i == law_max)
+ return (ENOSPC);
+
+ ccsr_write4(OCP85XX_LAWBAR(i), bar);
+ ccsr_write4(OCP85XX_LAWSR(i), sr);
+ return (0);
+}
+
+int
+law_disable(int trgt, u_long addr, u_long size)
+{
+ uint32_t bar, sr;
+ int i, law_max;
+
+ law_max = law_getmax();
+ bar = _LAW_BAR(addr);
+ sr = _LAW_SR(trgt, size);
+
+ /* Find and disable requested LAW. */
+ for (i = 0; i < law_max; i++)
+ if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
+ bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
+ ccsr_write4(OCP85XX_LAWBAR(i), 0);
+ ccsr_write4(OCP85XX_LAWSR(i), 0);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
void
-cpu_reset()
+cpu_reset(void)
{
- uint32_t svr = mfspr(SPR_SVR);
+ uint32_t ver = SVR_VER(mfspr(SPR_SVR));
- if (svr == SVR_MPC8572E || svr == SVR_MPC8572)
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
/* Systems with dedicated reset register */
- out32(OCP85XX_RSTCR, 2);
+ ccsr_write4(OCP85XX_RSTCR, 2);
else {
/* Clear DBCR0, disables debug interrupts and events. */
mtspr(SPR_DBCR0, 0);
- __asm volatile("isync");
+ __asm __volatile("isync");
/* Enable Debug Interrupts in MSR. */
mtmsr(mfmsr() | PSL_DE);
/* Enable debug interrupts and issue reset. */
- mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM);
+ mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM |
+ DBCR0_RST_SYSTEM);
}
printf("Reset failed...\n");
diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h
new file mode 100644
index 0000000..4d31b58
--- /dev/null
+++ b/sys/powerpc/mpc85xx/mpc85xx.h
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (C) 2008 Semihalf, Rafal Jaworowski
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MPC85XX_H_
+#define _MPC85XX_H_
+
+uint32_t ccsr_read4(uintptr_t addr);
+void ccsr_write4(uintptr_t addr, uint32_t val);
+int law_enable(int trgt, u_long addr, u_long size);
+int law_disable(int trgt, u_long addr, u_long size);
+
+#endif /* _MPC85XX_H_ */
diff --git a/sys/powerpc/mpc85xx/nexus.c b/sys/powerpc/mpc85xx/nexus.c
index 01e0425..fa07247 100644
--- a/sys/powerpc/mpc85xx/nexus.c
+++ b/sys/powerpc/mpc85xx/nexus.c
@@ -70,13 +70,9 @@ __FBSDID("$FreeBSD$");
*/
static int nexus_probe(device_t);
static int nexus_activate_resource(device_t, device_t, int, int,
- struct resource *);
+ struct resource *);
static int nexus_deactivate_resource(device_t, device_t, int, int,
- struct resource *);
-
-/*
- * Local routines
- */
+ struct resource *);
static device_method_t nexus_methods[] = {
/* Device interface */
diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c
index a741849..ae56fb0 100644
--- a/sys/powerpc/mpc85xx/ocpbus.c
+++ b/sys/powerpc/mpc85xx/ocpbus.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bootinfo.h>
#include <powerpc/mpc85xx/ocpbus.h>
+#include <powerpc/mpc85xx/mpc85xx.h>
#include "pic_if.h"
@@ -115,23 +116,6 @@ DRIVER_MODULE(ocpbus, nexus, ocpbus_driver, ocpbus_devclass, 0, 0);
static int law_max = 0;
-static __inline uint32_t
-ccsr_read4(uintptr_t addr)
-{
- volatile uint32_t *ptr = (void *)addr;
-
- return (*ptr);
-}
-
-static __inline void
-ccsr_write4(uintptr_t addr, uint32_t val)
-{
- volatile uint32_t *ptr = (void *)addr;
-
- *ptr = val;
- __asm __volatile("eieio; sync");
-}
-
static device_t
ocpbus_mk_child(device_t dev, int type, int unit)
{
@@ -154,8 +138,6 @@ static int
ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
{
u_long addr, size;
- int i;
- uint32_t bar, sr;
switch (type) {
case SYS_RES_MEMORY:
@@ -172,10 +154,6 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
addr = 0xA0000000;
size = 0x10000000;
break;
- case OCP85XX_TGTIF_LBC:
- addr = 0xff800000;
- size = 0x00800000;
- break;
default:
return (EINVAL);
}
@@ -205,40 +183,19 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
*startp = addr;
*countp = size;
- /* Program the LAWs for this memory range. */
- bar = addr >> 12;
- sr = 0x80000000 | (trgt << 20) | (ffsl(size) - 2);
-
- /* Check if already programmed. */
- for (i = 0; i < law_max; i++) {
- if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
- bar == ccsr_read4(OCP85XX_LAWBAR(i)))
- return (0);
- }
-
- /* Find an unused access window .*/
- for (i = 0; i < law_max; i++) {
- if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
- break;
- }
- if (i == law_max)
- return (ENOSPC);
-
- ccsr_write4(OCP85XX_LAWBAR(i), bar);
- ccsr_write4(OCP85XX_LAWSR(i), sr);
- return (0);
+ return (law_enable(trgt, *startp, *countp));
}
static int
-ocpbus_probe (device_t dev)
+ocpbus_probe(device_t dev)
{
struct ocpbus_softc *sc;
- uint32_t svr;
+ uint32_t ver;
sc = device_get_softc(dev);
- svr = mfspr(SPR_SVR);
- if (svr == SVR_MPC8572E || svr == SVR_MPC8572)
+ ver = SVR_VER(mfspr(SPR_SVR));
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
law_max = 12;
else
law_max = 8;
@@ -248,7 +205,7 @@ ocpbus_probe (device_t dev)
}
static int
-ocpbus_attach (device_t dev)
+ocpbus_attach(device_t dev)
{
struct ocpbus_softc *sc;
int error, i, tgt;
@@ -393,7 +350,6 @@ const struct ocp_resource mpc8555_resources[] = {
{OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 0, OCP85XX_LBC_OFF,
OCP85XX_LBC_SIZE},
- {OCPBUS_DEVTYPE_LBC, 0, SYS_RES_MEMORY, 1, 0, OCP85XX_TGTIF_LBC},
{OCPBUS_DEVTYPE_I2C, 0, SYS_RES_MEMORY, 0, OCP85XX_I2C0_OFF,
OCP85XX_I2C_SIZE},
diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c
index 5d6fba6..0b6e0ca 100644
--- a/sys/powerpc/ofw/ofw_pcib_pci.c
+++ b/sys/powerpc/ofw/ofw_pcib_pci.c
@@ -36,6 +36,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -46,6 +47,8 @@
static int ofw_pcib_pci_probe(device_t bus);
static int ofw_pcib_pci_attach(device_t bus);
static phandle_t ofw_pcib_pci_get_node(device_t bus, device_t dev);
+static int ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev,
+ int intpin);
static device_method_t ofw_pcib_pci_methods[] = {
/* Device interface */
@@ -70,7 +73,7 @@ static device_method_t ofw_pcib_pci_methods[] = {
DEVMETHOD(pcib_maxslots, pcib_maxslots),
DEVMETHOD(pcib_read_config, pcib_read_config),
DEVMETHOD(pcib_write_config, pcib_write_config),
- DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt),
+ DEVMETHOD(pcib_route_interrupt, ofw_pcib_pci_route_interrupt),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, ofw_pcib_pci_get_node),
@@ -80,8 +83,20 @@ static device_method_t ofw_pcib_pci_methods[] = {
static devclass_t pcib_devclass;
+struct ofw_pcib_softc {
+ /*
+ * This is here so that we can use pci bridge methods, too - the
+ * generic routines only need the dev, secbus and subbus members
+ * filled.
+ */
+ struct pcib_softc ops_pcib_sc;
+ phandle_t ops_node;
+ struct ofw_bus_iinfo ops_iinfo;
+};
+
+
DEFINE_CLASS_0(pcib, ofw_pcib_pci_driver, ofw_pcib_pci_methods,
- sizeof(struct pcib_softc));
+ sizeof(struct ofw_pcib_softc));
DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_pci_driver, pcib_devclass, 0, 0);
static int
@@ -103,6 +118,15 @@ ofw_pcib_pci_probe(device_t dev)
static int
ofw_pcib_pci_attach(device_t dev)
{
+ struct ofw_pcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->ops_pcib_sc.dev = dev;
+ sc->ops_node = ofw_bus_get_node(dev);
+
+ ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
+ sizeof(cell_t));
+
pcib_attach_common(dev);
device_add_child(dev, "pci", -1);
@@ -110,7 +134,7 @@ ofw_pcib_pci_attach(device_t dev)
return (bus_generic_attach(dev));
}
-phandle_t
+static phandle_t
ofw_pcib_pci_get_node(device_t bridge, device_t dev)
{
/* We have only one child, the PCI bus, so pass it our node */
@@ -118,3 +142,37 @@ ofw_pcib_pci_get_node(device_t bridge, device_t dev)
return (ofw_bus_get_node(bridge));
}
+static int
+ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin)
+{
+ struct ofw_pcib_softc *sc;
+ struct ofw_bus_iinfo *ii;
+ struct ofw_pci_register reg;
+ cell_t pintr, mintr;
+ uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
+
+ sc = device_get_softc(bridge);
+ ii = &sc->ops_iinfo;
+ if (ii->opi_imapsz > 0) {
+ pintr = intpin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), ii, &reg,
+ sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr),
+ maskbuf)) {
+ /*
+ * If we've found a mapping, return it and don't map
+ * it again on higher levels - that causes problems
+ * in some cases, and never seems to be required.
+ */
+ return (mintr);
+ }
+ } else if (intpin >= 1 && intpin <= 4) {
+ /*
+ * When an interrupt map is missing, we need to do the
+ * standard PCI swizzle and continue mapping at the parent.
+ */
+ return (pcib_route_interrupt(bridge, dev, intpin));
+ }
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(device_get_parent(
+ bridge)), bridge, intpin));
+}
+
diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c
index 916d98b..6ec2da6 100644
--- a/sys/powerpc/ofw/ofw_pcibus.c
+++ b/sys/powerpc/ofw/ofw_pcibus.c
@@ -1,6 +1,4 @@
/*-
- * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
- * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
* Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
* Copyright (c) 2000, BSDi
@@ -54,22 +52,27 @@ __FBSDID("$FreeBSD$");
#include "pcib_if.h"
#include "pci_if.h"
-/* Helper functions */
-static int find_node_intr(phandle_t, u_int32_t *, u_int32_t *);
-static int ofw_pci_find_intline(phandle_t node, uint32_t *irqs);
-static void ofw_pci_fixup_node(device_t dev, phandle_t node);
+typedef uint32_t ofw_pci_intr_t;
/* Methods */
static device_probe_t ofw_pcibus_probe;
static device_attach_t ofw_pcibus_attach;
static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo;
+static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child,
+ char *buf, size_t buflen);
+
+static void ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno);
+static void ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno);
static device_method_t ofw_pcibus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ofw_pcibus_probe),
DEVMETHOD(device_attach, ofw_pcibus_attach),
+ /* Bus interface */
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method),
+
/* PCI interface */
DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
@@ -100,6 +103,7 @@ MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1);
static int
ofw_pcibus_probe(device_t dev)
{
+
if (ofw_bus_get_node(dev) == 0)
return (ENXIO);
device_set_desc(dev, "OFW PCI bus");
@@ -110,18 +114,43 @@ ofw_pcibus_probe(device_t dev)
static int
ofw_pcibus_attach(device_t dev)
{
- device_t pcib;
- struct ofw_pci_register pcir;
- struct ofw_pcibus_devinfo *dinfo;
- phandle_t node, child;
- u_int busno, domain, func, slot;
+ u_int busno, domain;
- pcib = device_get_parent(dev);
domain = pcib_get_domain(dev);
busno = pcib_get_bus(dev);
if (bootverbose)
device_printf(dev, "domain=%d, physical bus=%d\n",
domain, busno);
+
+ /*
+ * Attach those children represented in the device tree.
+ */
+
+ ofw_pcibus_enum_devtree(dev, domain, busno);
+
+ /*
+ * We now attach any laggard devices. FDT, for instance, allows
+ * the device tree to enumerate only some PCI devices. Apple's
+ * OF device tree on some Grackle-based hardware can also miss
+ * functions on multi-function cards.
+ */
+
+ ofw_pcibus_enum_bus(dev, domain, busno);
+
+ return (bus_generic_attach(dev));
+}
+
+static void
+ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno)
+{
+ device_t pcib;
+ struct ofw_pci_register pcir;
+ struct ofw_pcibus_devinfo *dinfo;
+ phandle_t node, child;
+ u_int func, slot;
+ int intline;
+
+ pcib = device_get_parent(dev);
node = ofw_bus_get_node(dev);
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
@@ -134,226 +163,178 @@ ofw_pcibus_attach(device_t dev)
if (pci_find_dbsf(domain, busno, slot, func) != NULL)
continue;
- ofw_pci_fixup_node(pcib, child);
+ /*
+ * The preset in the intline register is usually bogus. Reset
+ * it such that the PCI code will reroute the interrupt if
+ * needed.
+ */
+
+ intline = PCI_INVALID_IRQ;
+ if (OF_getproplen(child, "interrupts") > 0)
+ intline = 0;
+ PCIB_WRITE_CONFIG(pcib, busno, slot, func, PCIR_INTLINE,
+ intline, 1);
+
+ /*
+ * Now set up the PCI and OFW bus layer devinfo and add it
+ * to the PCI bus.
+ */
dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
domain, busno, slot, func, sizeof(*dinfo));
-
if (dinfo == NULL)
continue;
-
- /* Set up OFW devinfo */
if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
0) {
pci_freecfg((struct pci_devinfo *)dinfo);
continue;
}
-
pci_add_child(dev, (struct pci_devinfo *)dinfo);
/*
- * Some devices don't have an intpin set, but do have
- * interrupts. Add them to the appropriate resource list.
- */
- if (dinfo->opd_dinfo.cfg.intpin == 0) {
- uint32_t irqs[4];
-
- if (ofw_pci_find_intline(child, irqs) > 0)
- resource_list_add(&dinfo->opd_dinfo.resources,
- SYS_RES_IRQ, 0, irqs[0], irqs[0], 1);
- }
+ * Some devices don't have an intpin set, but do have
+ * interrupts. These are fully specified, and set in the
+ * interrupts property, so add that value to the device's
+ * resource list.
+ */
+ if (dinfo->opd_dinfo.cfg.intpin == 0) {
+ ofw_pci_intr_t intr;
+
+ if (OF_getprop(child, "interrupts", &intr,
+ sizeof(intr)) > 0) {
+ resource_list_add(&dinfo->opd_dinfo.resources,
+ SYS_RES_IRQ, 0, intr, intr, 1);
+ }
+ }
}
-
- return (bus_generic_attach(dev));
}
-static int
-ofw_pcibus_assign_interrupt(device_t dev, device_t child)
-{
- uint32_t irqs[4];
-
- device_printf(child,"Assigning interrupt\n");
-
- if (ofw_pci_find_intline(ofw_bus_get_node(child), irqs) < 0)
- return PCI_INVALID_IRQ;
-
- device_printf(child,"IRQ %d\n",irqs[0]);
-
- return irqs[0];
-
-// return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
-}
-
-static const struct ofw_bus_devinfo *
-ofw_pcibus_get_devinfo(device_t bus, device_t dev)
-{
- struct ofw_pcibus_devinfo *dinfo;
-
- dinfo = device_get_ivars(dev);
- return (&dinfo->opd_obdinfo);
-}
+/*
+ * The following is an almost exact clone of pci_add_children(), with the
+ * addition that it (a) will not add children that have already been added,
+ * and (b) will set up the OFW devinfo to point to invalid values. This is
+ * to handle non-enumerated PCI children as exist in FDT and on the second
+ * function of the Rage 128 in my Blue & White G3.
+ */
static void
-ofw_pci_fixup_node(device_t dev, phandle_t node)
+ofw_pcibus_enum_bus(device_t dev, u_int domain, u_int busno)
{
- uint32_t csr, intr, irqs[4];
- struct ofw_pci_register addr[8];
- int len, i;
+ device_t pcib;
+ struct ofw_pcibus_devinfo *dinfo;
+ int maxslots;
+ int s, f, pcifunchigh;
+ uint8_t hdrtype;
- len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
- if (len < (int)sizeof(struct ofw_pci_register)) {
- return;
- }
+ pcib = device_get_parent(dev);
- csr = PCIB_READ_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, 4);
- csr &= ~(PCIM_CMD_PORTEN | PCIM_CMD_MEMEN);
-
- for (i = 0; i < len / sizeof(struct ofw_pci_register); i++) {
- switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
- case OFW_PCI_PHYS_HI_SPACE_IO:
- csr |= PCIM_CMD_PORTEN;
- break;
- case OFW_PCI_PHYS_HI_SPACE_MEM32:
- csr |= PCIM_CMD_MEMEN;
- break;
+ maxslots = PCIB_MAXSLOTS(pcib);
+ for (s = 0; s <= maxslots; s++) {
+ pcifunchigh = 0;
+ f = 0;
+ DELAY(1);
+ hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
+ if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
+ continue;
+ if (hdrtype & PCIM_MFDEV)
+ pcifunchigh = PCI_FUNCMAX;
+ for (f = 0; f <= pcifunchigh; f++) {
+ /* Filter devices we have already added */
+ if (pci_find_dbsf(domain, busno, s, f) != NULL)
+ continue;
+
+ dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(
+ pcib, domain, busno, s, f, sizeof(*dinfo));
+ if (dinfo != NULL) {
+ dinfo->opd_obdinfo.obd_node = -1;
+
+ dinfo->opd_obdinfo.obd_name = NULL;
+ dinfo->opd_obdinfo.obd_compat = NULL;
+ dinfo->opd_obdinfo.obd_type = NULL;
+ dinfo->opd_obdinfo.obd_model = NULL;
+ pci_add_child(dev, (struct pci_devinfo *)dinfo);
+ }
}
}
-
- PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_COMMAND, csr, 4);
-
- if (ofw_pci_find_intline(node, irqs) != -1) {
- intr = PCIB_READ_CONFIG(dev,
- OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE, 2);
- intr &= ~(0xff);
- intr |= irqs[0] & 0xff;
- PCIB_WRITE_CONFIG(dev,
- OFW_PCI_PHYS_HI_BUS(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_DEVICE(addr[0].phys_hi),
- OFW_PCI_PHYS_HI_FUNCTION(addr[0].phys_hi), PCIR_INTLINE,
- intr, 2);
- }
}
static int
-ofw_pci_find_intline(phandle_t node, uint32_t *irqs)
+ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
+ size_t buflen)
{
- uint32_t npintr, paddr[4];
- struct ofw_pci_register addr[8];
- int len;
+ pci_child_pnpinfo_str_method(cbdev, child, buf, buflen);
- len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
- if (len < (int)sizeof(struct ofw_pci_register))
- return -1;
- /*
- * Create PCI interrupt-map array element. pci-mid/pci-lo
- * aren't required, but the 'interrupts' property needs
- * to be appended
- */
- npintr = 0;
- OF_getprop(node, "interrupts", &npintr, 4);
- paddr[0] = addr[0].phys_hi;
- paddr[1] = 0;
- paddr[2] = 0;
- paddr[3] = npintr;
-
- return find_node_intr(node, paddr, irqs);
-}
+ if (ofw_bus_get_node(child) != -1) {
+ strlcat(buf, " ", buflen); /* Separate info */
+ ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen);
+ }
+ return (0);
+}
+
static int
-find_node_intr(phandle_t node, u_int32_t *addr, u_int32_t *intr)
+ofw_pcibus_assign_interrupt(device_t dev, device_t child)
{
- phandle_t parent, iparent;
- int len, mlen, match, i;
- u_int32_t map[160], *mp, imask[8], maskedaddr[8], icells;
- char name[32];
-
- len = OF_getprop(node, "AAPL,interrupts", intr, 4);
- if (len == 4) {
- return (len);
- }
-
- parent = OF_parent(node);
- len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
- mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
+ ofw_pci_intr_t intr;
+ phandle_t node;
+ int isz;
- if (len == -1 || mlen == -1)
- goto nomap;
-
- memcpy(maskedaddr, addr, mlen);
- for (i = 0; i < mlen/4; i++)
- maskedaddr[i] &= imask[i];
-
- mp = map;
- while (len > mlen) {
- match = bcmp(maskedaddr, mp, mlen);
- mp += mlen / 4;
- len -= mlen;
+ node = ofw_bus_get_node(child);
+ if (node == -1) {
+ /* Non-firmware enumerated child, use standard routing */
+
/*
- * We must read "#interrupt-cells" for each time because
- * interrupt-parent may be different.
+ * XXX: Right now we don't have anything sensible to do here,
+ * since the ofw_imap stuff relies on nodes have a reg
+ * property. There exists ways around this, so the ePAPR
+ * spec will need to be studied.
*/
- iparent = *mp++;
- len -= 4;
- if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
- goto nomap;
-
- /* Found. */
- if (match == 0) {
- bcopy(mp, intr, icells * 4);
- return (icells * 4);
- }
- mp += icells;
- len -= icells * 4;
- }
+ return (0);
-nomap:
+#ifdef NOTYET
+ intr = pci_get_intpin(child);
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child,
+ intr));
+#endif
+ }
+
/*
- * Check for local properties indicating interrupts
+ * Any AAPL,interrupts property gets priority and is
+ * fully specified (i.e. does not need routing)
*/
- len = OF_getprop(node, "interrupts", intr, 16);
- if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) ==
- sizeof(iparent)) {
- OF_getprop(iparent, "#interrupt-cells", &icells, sizeof(icells));
- for (i = 0; i < len/icells/4; i++)
- intr[i] = intr[i*icells];
+ isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr));
+ if (isz == sizeof(intr)) {
+ return (intr);
+ }
- return (len);
+ isz = OF_getprop(node, "interrupts", &intr, sizeof(intr));
+ if (isz != sizeof(intr)) {
+ /* No property; our best guess is the intpin. */
+ intr = pci_get_intpin(child);
}
-
/*
- * If the node has no interrupt property and the parent is a PCI
- * bridge, use the parent's interrupt. This occurs on a PCI slot.
+ * If we got intr from a property, it may or may not be an intpin.
+ * For on-board devices, it frequently is not, and is completely out
+ * of the valid intpin range. For PCI slots, it hopefully is,
+ * otherwise we will have trouble interfacing with non-OFW buses
+ * such as cardbus.
+ * Since we cannot tell which it is without violating layering, we
+ * will always use the route_interrupt method, and treat exceptions
+ * on the level they become apparent.
*/
- bzero(name, sizeof(name));
- OF_getprop(parent, "name", name, sizeof(name));
- if (strcmp(name, "pci-bridge") == 0) {
- len = OF_getprop(parent, "AAPL,interrupts", intr, 4);
- if (len == 4) {
- return (len);
- }
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
+}
- /*
- * XXX I don't know what is the correct local address.
- * XXX Use the first entry for now.
- */
- len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
- if (len >= 36) {
- addr = &map[5];
- /* XXX Use 0 for 'interrupts' for compat */
- return (find_node_intr(parent, addr, intr));
- }
- }
+static const struct ofw_bus_devinfo *
+ofw_pcibus_get_devinfo(device_t bus, device_t dev)
+{
+ struct ofw_pcibus_devinfo *dinfo;
- return (-1);
+ dinfo = device_get_ivars(dev);
+ return (&dinfo->opd_obdinfo);
}
diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c
index 373ba11..1080dad 100644
--- a/sys/powerpc/ofw/ofw_syscons.c
+++ b/sys/powerpc/ofw/ofw_syscons.c
@@ -137,10 +137,12 @@ static video_switch_t ofwfbvidsw = {
*/
static vi_blank_display_t ofwfb_blank_display8;
static vi_putc_t ofwfb_putc8;
+static vi_putm_t ofwfb_putm8;
static vi_set_border_t ofwfb_set_border8;
static vi_blank_display_t ofwfb_blank_display32;
static vi_putc_t ofwfb_putc32;
+static vi_putm_t ofwfb_putm32;
static vi_set_border_t ofwfb_set_border32;
VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure);
@@ -250,10 +252,12 @@ ofwfb_configure(int flags)
if (depth == 8) {
sc->sc_blank = ofwfb_blank_display8;
sc->sc_putc = ofwfb_putc8;
+ sc->sc_putm = ofwfb_putm8;
sc->sc_set_border = ofwfb_set_border8;
} else if (depth == 32) {
sc->sc_blank = ofwfb_blank_display32;
sc->sc_putc = ofwfb_putc32;
+ sc->sc_putm = ofwfb_putm32;
sc->sc_set_border = ofwfb_set_border32;
} else
return (0);
@@ -304,36 +308,14 @@ ofwfb_init(int unit, video_adapter_t *adp, int flags)
{
struct ofwfb_softc *sc;
video_info_t *vi;
- char name[64];
- ihandle_t ih;
- int i;
int cborder;
int font_height;
- int retval;
sc = (struct ofwfb_softc *)adp;
vi = &adp->va_info;
vid_init_struct(adp, "ofwfb", -1, unit);
- if (sc->sc_depth == 8) {
- /*
- * Install the ISO6429 colormap - older OFW systems
- * don't do this by default
- */
- memset(name, 0, sizeof(name));
- OF_package_to_path(sc->sc_node, name, sizeof(name));
- ih = OF_open(name);
- for (i = 0; i < 16; i++) {
- OF_call_method("color!", ih, 4, 1,
- ofwfb_cmap[i].red,
- ofwfb_cmap[i].green,
- ofwfb_cmap[i].blue,
- i,
- &retval);
- }
- }
-
/* The default font size can be overridden by loader */
font_height = 16;
TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height);
@@ -375,10 +357,13 @@ ofwfb_init(int unit, video_adapter_t *adp, int flags)
*/
adp->va_window = (vm_offset_t) ofwfb_static_window;
- /* Enable future font-loading and flag color support */
- adp->va_flags |= V_ADP_FONT | V_ADP_COLOR;
-
- ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
+ /*
+ * Enable future font-loading and flag color support, as well as
+ * adding V_ADP_MODECHANGE so that we ofwfb_set_mode() gets called
+ * when the X server shuts down. This enables us to get the console
+ * back when X disappears.
+ */
+ adp->va_flags |= V_ADP_FONT | V_ADP_COLOR | V_ADP_MODECHANGE;
ofwfb_set_mode(&sc->sc_va, 0);
@@ -404,6 +389,37 @@ ofwfb_query_mode(video_adapter_t *adp, video_info_t *info)
static int
ofwfb_set_mode(video_adapter_t *adp, int mode)
{
+ struct ofwfb_softc *sc;
+ char name[64];
+ ihandle_t ih;
+ int i, retval;
+
+ sc = (struct ofwfb_softc *)adp;
+
+ /*
+ * Open the display device, which will initialize it.
+ */
+
+ memset(name, 0, sizeof(name));
+ OF_package_to_path(sc->sc_node, name, sizeof(name));
+ ih = OF_open(name);
+
+ if (sc->sc_depth == 8) {
+ /*
+ * Install the ISO6429 colormap - older OFW systems
+ * don't do this by default
+ */
+ for (i = 0; i < 16; i++) {
+ OF_call_method("color!", ih, 4, 1,
+ ofwfb_cmap[i].red,
+ ofwfb_cmap[i].green,
+ ofwfb_cmap[i].blue,
+ i,
+ &retval);
+ }
+ }
+
+ ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
return (0);
}
@@ -823,7 +839,86 @@ ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
sc = (struct ofwfb_softc *)adp;
- /* put mouse */
+ return ((*sc->sc_putm)(adp, x, y, pixel_image, pixel_mask, size,
+ width));
+}
+
+static int
+ofwfb_putm8(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+ struct ofwfb_softc *sc;
+ int i, j, k;
+ uint32_t *addr;
+ u_char fg, bg;
+ union {
+ uint32_t l[2];
+ uint8_t c[8];
+ } ch;
+
+
+ sc = (struct ofwfb_softc *)adp;
+ addr = (u_int32_t *)((int)sc->sc_addr
+ + (y + sc->sc_ymargin)*sc->sc_stride
+ + x + sc->sc_xmargin);
+
+ fg = ofwfb_foreground(SC_NORM_ATTR);
+ bg = ofwfb_background(SC_NORM_ATTR);
+
+ for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
+ /*
+ * Use the current values for the line
+ */
+ ch.l[0] = addr[0];
+ ch.l[1] = addr[1];
+
+ /*
+ * Calculate 2 x 4-chars at a time, and then
+ * write these out.
+ */
+ for (j = 0, k = width; j < 8; j++, k--) {
+ if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
+ continue;
+
+ if (pixel_image[i] & (1 << k))
+ ch.c[j] = (ch.c[j] == fg) ? bg : fg;
+ }
+
+ addr[0] = ch.l[0];
+ addr[1] = ch.l[1];
+ addr += (sc->sc_stride / sizeof(u_int32_t));
+ }
+
+ return (0);
+}
+
+static int
+ofwfb_putm32(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
+ uint32_t pixel_mask, int size, int width)
+{
+ struct ofwfb_softc *sc;
+ int i, j, k;
+ uint32_t fg, bg;
+ uint32_t *addr;
+
+ sc = (struct ofwfb_softc *)adp;
+ addr = (uint32_t *)sc->sc_addr
+ + (y + sc->sc_ymargin)*(sc->sc_stride/4)
+ + x + sc->sc_xmargin;
+
+ fg = ofwfb_pix32(ofwfb_foreground(SC_NORM_ATTR));
+ bg = ofwfb_pix32(ofwfb_background(SC_NORM_ATTR));
+
+ for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
+ for (j = 0, k = width; j < 8; j++, k--) {
+ if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
+ continue;
+
+ if (pixel_image[i] & (1 << k))
+ *(addr + j) = (*(addr + j) == fg) ? bg : fg;
+ }
+ addr += (sc->sc_stride/4);
+ }
return (0);
}
diff --git a/sys/powerpc/ofw/ofw_syscons.h b/sys/powerpc/ofw/ofw_syscons.h
index af33c52..01b9727 100644
--- a/sys/powerpc/ofw/ofw_syscons.h
+++ b/sys/powerpc/ofw/ofw_syscons.h
@@ -51,6 +51,7 @@ struct ofwfb_softc {
vi_blank_display_t *sc_blank;
vi_putc_t *sc_putc;
+ vi_putm_t *sc_putm;
vi_set_border_t *sc_set_border;
#define OFWSC_MAXADDR 8
diff --git a/sys/powerpc/powermac/cuda.c b/sys/powerpc/powermac/cuda.c
index 274bb98..e6c010c 100644
--- a/sys/powerpc/powermac/cuda.c
+++ b/sys/powerpc/powermac/cuda.c
@@ -104,8 +104,6 @@ static devclass_t cuda_devclass;
DRIVER_MODULE(cuda, macio, cuda_driver, cuda_devclass, 0, 0);
DRIVER_MODULE(adb, cuda, adb_driver, adb_devclass, 0, 0);
-MALLOC_DEFINE(M_CUDA, "cuda", "CUDA packet queue");
-
static void cuda_intr(void *arg);
static uint8_t cuda_read_reg(struct cuda_softc *sc, u_int offset);
static void cuda_write_reg(struct cuda_softc *sc, u_int offset, uint8_t value);
@@ -178,6 +176,10 @@ cuda_attach(device_t dev)
STAILQ_INIT(&sc->sc_inq);
STAILQ_INIT(&sc->sc_outq);
+ STAILQ_INIT(&sc->sc_freeq);
+
+ for (i = 0; i < CUDA_MAXPACKETS; i++)
+ STAILQ_INSERT_TAIL(&sc->sc_freeq, &sc->sc_pkts[i], pkt_q);
/* Init CUDA */
@@ -348,11 +350,17 @@ cuda_send(void *cookie, int poll, int length, uint8_t *msg)
mtx_lock(&sc->sc_mutex);
- pkt = malloc(sizeof(struct cuda_packet), M_CUDA, M_WAITOK);
+ pkt = STAILQ_FIRST(&sc->sc_freeq);
+ if (pkt == NULL) {
+ mtx_unlock(&sc->sc_mutex);
+ return (-1);
+ }
+
pkt->len = length - 1;
pkt->type = msg[0];
memcpy(pkt->data, &msg[1], pkt->len);
+ STAILQ_REMOVE_HEAD(&sc->sc_freeq, pkt_q);
STAILQ_INSERT_TAIL(&sc->sc_outq, pkt, pkt_q);
/*
@@ -389,8 +397,8 @@ cuda_send_outbound(struct cuda_softc *sc)
memcpy(sc->sc_out, &pkt->type, pkt->len + 1);
sc->sc_sent = 0;
- free(pkt, M_CUDA);
STAILQ_REMOVE_HEAD(&sc->sc_outq, pkt_q);
+ STAILQ_INSERT_TAIL(&sc->sc_freeq, pkt, pkt_q);
sc->sc_waiting = 1;
@@ -455,9 +463,9 @@ cuda_send_inbound(struct cuda_softc *sc)
break;
}
- free(pkt,M_CUDA);
-
mtx_lock(&sc->sc_mutex);
+
+ STAILQ_INSERT_TAIL(&sc->sc_freeq, pkt, pkt_q);
}
mtx_unlock(&sc->sc_mutex);
@@ -559,18 +567,22 @@ switch_start:
cuda_idle(sc);
/* Queue up the packet */
- pkt = malloc(sizeof(struct cuda_packet), M_CUDA,
- M_WAITOK);
+ pkt = STAILQ_FIRST(&sc->sc_freeq);
+ if (pkt != NULL) {
+ /* If we have a free packet, process it */
- pkt->len = sc->sc_received - 2;
- pkt->type = sc->sc_in[1];
- memcpy(pkt->data, &sc->sc_in[2], pkt->len);
+ pkt->len = sc->sc_received - 2;
+ pkt->type = sc->sc_in[1];
+ memcpy(pkt->data, &sc->sc_in[2], pkt->len);
- STAILQ_INSERT_TAIL(&sc->sc_inq, pkt, pkt_q);
+ STAILQ_REMOVE_HEAD(&sc->sc_freeq, pkt_q);
+ STAILQ_INSERT_TAIL(&sc->sc_inq, pkt, pkt_q);
+
+ process_inbound = 1;
+ }
sc->sc_state = CUDA_IDLE;
sc->sc_received = 0;
- process_inbound = 1;
/*
* If there is something waiting to be sent out,
diff --git a/sys/powerpc/powermac/cudavar.h b/sys/powerpc/powermac/cudavar.h
index b6f25fe..02791cb 100644
--- a/sys/powerpc/powermac/cudavar.h
+++ b/sys/powerpc/powermac/cudavar.h
@@ -35,6 +35,7 @@
#define _POWERPC_CUDAVAR_H_
#define CUDA_DEVSTR "Apple CUDA I/O Controller"
+#define CUDA_MAXPACKETS 10
/* Cuda addresses */
#define CUDA_ADB 0
@@ -99,8 +100,10 @@ struct cuda_softc {
int sc_out_length;
int sc_received;
+ struct cuda_packet sc_pkts[CUDA_MAXPACKETS];
struct cuda_pktq sc_inq;
struct cuda_pktq sc_outq;
+ struct cuda_pktq sc_freeq;
};
#endif /* _POWERPC_CUDAVAR_H_ */
diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c
index 08e14ac..9dd796d 100644
--- a/sys/powerpc/powermac/grackle.c
+++ b/sys/powerpc/powermac/grackle.c
@@ -37,6 +37,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -164,7 +165,7 @@ static int
grackle_attach(device_t dev)
{
struct grackle_softc *sc;
- phandle_t node;
+ phandle_t node, iparent;
u_int32_t busrange[2];
struct grackle_range *rp, *io, *mem[2];
int nmem, i, error;
@@ -251,6 +252,16 @@ grackle_attach(device_t dev)
}
}
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
+ /* We need the number of interrupt cells to read the imap */
+ if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) <= 0)
+ iparent = node;
+
+ if (OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells,
+ sizeof(sc->sc_icells)) <= 0)
+ sc->sc_icells = 1;
+
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -335,8 +346,25 @@ grackle_write_config(device_t dev, u_int bus, u_int slot, u_int func,
static int
grackle_route_interrupt(device_t bus, device_t dev, int pin)
{
+ struct grackle_softc *sc;
+ struct ofw_pci_register reg;
+ uint32_t pintr, mintr[2];
+ uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
- return (0);
+ sc = device_get_softc(bus);
+ pintr = pin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+ sizeof(reg), &pintr, sizeof(pintr), &mintr,
+ sizeof(mintr[0])*sc->sc_icells, maskbuf))
+ return (mintr[0]);
+
+ /* Maybe it's a real interrupt, not an intpin */
+ if (pin > 4)
+ return (pin);
+
+ device_printf(bus, "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (PCI_INVALID_IRQ);
}
static int
diff --git a/sys/powerpc/powermac/gracklevar.h b/sys/powerpc/powermac/gracklevar.h
index bb5b150..78461d8 100644
--- a/sys/powerpc/powermac/gracklevar.h
+++ b/sys/powerpc/powermac/gracklevar.h
@@ -52,6 +52,9 @@ struct grackle_softc {
struct rman sc_mem_rman;
bus_space_tag_t sc_memt;
bus_dma_tag_t sc_dmat;
+ int sc_icells;
+
+ struct ofw_bus_iinfo sc_pci_iinfo;
};
/*
diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c
index 9a4b3ac..71be113 100644
--- a/sys/powerpc/powermac/macio.c
+++ b/sys/powerpc/powermac/macio.c
@@ -107,6 +107,8 @@ static device_method_t macio_methods[] = {
DEVMETHOD(bus_deactivate_resource, macio_deactivate_resource),
DEVMETHOD(bus_get_resource_list, macio_get_resource_list),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, macio_get_devinfo),
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c
index 097532c..b0b55a4 100644
--- a/sys/powerpc/powermac/uninorth.c
+++ b/sys/powerpc/powermac/uninorth.c
@@ -35,6 +35,7 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -163,8 +164,7 @@ uninorth_attach(device_t dev)
{
struct uninorth_softc *sc;
const char *compatible;
- phandle_t node;
- phandle_t child;
+ phandle_t node, child, iparent;
u_int32_t reg[2], busrange[2];
struct uninorth_range *rp, *io, *mem[2];
int nmem, i, error;
@@ -294,6 +294,14 @@ uninorth_attach(device_t dev)
}
}
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
+ /* We need the number of interrupt cells to read the imap */
+ sc->sc_icells = 2;
+ if (OF_getprop(node, "interrupt-parent", &iparent,sizeof(iparent)) > 0)
+ OF_getprop(iparent,"#interrupt-cells",&sc->sc_icells,
+ sizeof(sc->sc_icells));
+
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -360,8 +368,25 @@ uninorth_write_config(device_t dev, u_int bus, u_int slot, u_int func,
static int
uninorth_route_interrupt(device_t bus, device_t dev, int pin)
{
+ struct uninorth_softc *sc;
+ struct ofw_pci_register reg;
+ uint32_t pintr, mintr[2];
+ uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
- return (0);
+ sc = device_get_softc(bus);
+ pintr = pin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+ sizeof(reg), &pintr, sizeof(pintr), mintr,
+ sizeof(mintr[0])*sc->sc_icells, maskbuf))
+ return (mintr[0]);
+
+ /* Maybe it's a real interrupt, not an intpin */
+ if (pin > 4)
+ return (pin);
+
+ device_printf(bus, "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (PCI_INVALID_IRQ);
}
static int
diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h
index ff789ac..6bb4024 100644
--- a/sys/powerpc/powermac/uninorthvar.h
+++ b/sys/powerpc/powermac/uninorthvar.h
@@ -61,8 +61,10 @@ struct uninorth_softc {
bus_space_tag_t sc_iot;
bus_space_tag_t sc_memt;
bus_dma_tag_t sc_dmat;
+ struct ofw_bus_iinfo sc_pci_iinfo;
int sc_u3;
+ int sc_icells;
};
struct unin_chip_softc {
diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c
index 55112bb..33e94d1 100644
--- a/sys/powerpc/powerpc/pmap_dispatch.c
+++ b/sys/powerpc/powerpc/pmap_dispatch.c
@@ -37,9 +37,8 @@ __FBSDID("$FreeBSD$");
* the highest priority call will be installed as the default
* MMU handler when pmap_bootstrap() is called.
*
- * It is required that kobj_machdep_init() be called before
- * pmap_bootstrap() to allow the kobj subsystem to initialise. This
- * in turn requires that mutex_init() has been called.
+ * It is required that mutex_init() be called before pmap_bootstrap(),
+ * as the PMAP layer makes extensive use of mutexes.
*/
#include <sys/param.h>
diff --git a/sys/sparc64/conf/DEFAULTS b/sys/sparc64/conf/DEFAULTS
index 910e61e..38b2408 100644
--- a/sys/sparc64/conf/DEFAULTS
+++ b/sys/sparc64/conf/DEFAULTS
@@ -14,8 +14,8 @@ device uart_sab82532
device uart_z8530
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_SUNLABEL
+options GEOM_PART_BSD
+options GEOM_PART_VTOC8
# Let sunkbd emulate an AT keyboard by default.
options SUNKBD_EMULATE_ATKBD
diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c
index bcc92a2..9baa7a8 100644
--- a/sys/sparc64/ebus/ebus.c
+++ b/sys/sparc64/ebus/ebus.c
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
@@ -118,6 +117,7 @@ static device_method_t ebus_methods[] = {
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_release_resource, ebus_release_resource),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, ebus_get_devinfo),
diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h
index 76e3a76..108ade1 100644
--- a/sys/sparc64/include/elf.h
+++ b/sys/sparc64/include/elf.h
@@ -78,18 +78,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define T_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/sparc64/include/ofw_bus.h b/sys/sparc64/include/ofw_bus.h
deleted file mode 100644
index 1e9004e..0000000
--- a/sys/sparc64/include/ofw_bus.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _MACHINE_OFW_BUS_H_
-#define _MACHINE_OFW_BUS_H_
-
-#define ORIP_NOINT -1
-#define ORIR_NOTFOUND 0xffffffff
-
-/*
- * Other than in Open Firmware calls, the size of a bus cell seems to be
- * always the same.
- */
-typedef u_int32_t pcell_t;
-
-struct ofw_bus_iinfo {
- u_int8_t *opi_imap;
- u_int8_t *opi_imapmsk;
- int opi_imapsz;
- pcell_t opi_addrc;
-};
-
-void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
-int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
- void *, int, void *, int, void *);
-int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
- void *, void *, int);
-
-#endif /* !_MACHINE_OFW_BUS_H_ */
diff --git a/sys/sparc64/include/ofw_machdep.h b/sys/sparc64/include/ofw_machdep.h
index ac1fcc1..625b131 100644
--- a/sys/sparc64/include/ofw_machdep.h
+++ b/sys/sparc64/include/ofw_machdep.h
@@ -29,10 +29,15 @@
#define _MACHINE_OFW_MACHDEP_H_
#include <sys/bus.h>
+#include <machine/bus.h>
+#include <dev/ofw/openfirm.h>
+
+typedef uint64_t cell_t;
int OF_decode_addr(phandle_t, int, int *, bus_addr_t *);
void OF_getetheraddr(device_t, u_char *);
void cpu_shutdown(void *);
-void openfirmware_exit(void *);
+int ofw_entry(void *);
+void ofw_exit(void *);
#endif /* _MACHINE_OFW_MACHDEP_H_ */
diff --git a/sys/sparc64/isa/ofw_isa.c b/sys/sparc64/isa/ofw_isa.c
index e1d7537..de90869 100644
--- a/sys/sparc64/isa/ofw_isa.c
+++ b/sys/sparc64/isa/ofw_isa.c
@@ -41,10 +41,10 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
#include <machine/resource.h>
-#include <machine/ofw_bus.h>
#include <sparc64/pci/ofw_pci.h>
#include <sparc64/isa/ofw_isa.h>
diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c
index d908c17..ba0698c 100644
--- a/sys/sparc64/pci/apb.c
+++ b/sys/sparc64/pci/apb.c
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
diff --git a/sys/sparc64/pci/ofw_pci.h b/sys/sparc64/pci/ofw_pci.h
index 252f474..19c2fbe 100644
--- a/sys/sparc64/pci/ofw_pci.h
+++ b/sys/sparc64/pci/ofw_pci.h
@@ -34,7 +34,7 @@
#ifndef _SPARC64_PCI_OFW_PCI_H_
#define _SPARC64_PCI_OFW_PCI_H_
-#include <machine/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
typedef uint32_t ofw_pci_intr_t;
diff --git a/sys/sparc64/pci/ofw_pcib.c b/sys/sparc64/pci/ofw_pcib.c
index 966d77f..8a5b991 100644
--- a/sys/sparc64/pci/ofw_pcib.c
+++ b/sys/sparc64/pci/ofw_pcib.c
@@ -45,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
-#include <machine/ofw_bus.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
diff --git a/sys/sparc64/pci/ofw_pcib_subr.c b/sys/sparc64/pci/ofw_pcib_subr.c
index 9996b7e..6dd0990 100644
--- a/sys/sparc64/pci/ofw_pcib_subr.c
+++ b/sys/sparc64/pci/ofw_pcib_subr.c
@@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
-#include <machine/ofw_bus.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
diff --git a/sys/sparc64/pci/ofw_pcibus.c b/sys/sparc64/pci/ofw_pcibus.c
index 7918370..65a498a 100644
--- a/sys/sparc64/pci/ofw_pcibus.c
+++ b/sys/sparc64/pci/ofw_pcibus.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <sys/pciio.h>
#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/openfirm.h>
@@ -69,6 +68,8 @@ static device_probe_t ofw_pcibus_probe;
static device_attach_t ofw_pcibus_attach;
static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo;
+static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child,
+ char *buf, size_t buflen);
static device_method_t ofw_pcibus_methods[] = {
/* Device interface */
@@ -76,6 +77,7 @@ static device_method_t ofw_pcibus_methods[] = {
DEVMETHOD(device_attach, ofw_pcibus_attach),
/* Bus interface */
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method),
/* PCI interface */
DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
@@ -302,3 +304,18 @@ ofw_pcibus_get_devinfo(device_t bus, device_t dev)
dinfo = device_get_ivars(dev);
return (&dinfo->opd_obdinfo);
}
+
+static int
+ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
+ size_t buflen)
+{
+ pci_child_pnpinfo_str_method(cbdev, child, buf, buflen);
+
+ if (ofw_bus_get_node(child) != -1) {
+ strlcat(buf, " ", buflen); /* Separate info */
+ ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen);
+ }
+
+ return (0);
+}
+
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index d961191..505eec4 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus_private.h>
#include <machine/iommureg.h>
#include <machine/iommuvar.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <machine/ver.h>
diff --git a/sys/sparc64/pci/schizo.c b/sys/sparc64/pci/schizo.c
index 8f01f9c..2425294 100644
--- a/sys/sparc64/pci/schizo.c
+++ b/sys/sparc64/pci/schizo.c
@@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$");
#include <machine/fsr.h>
#include <machine/iommureg.h>
#include <machine/iommuvar.h>
-#include <machine/ofw_bus.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
@@ -395,9 +394,10 @@ schizo_attach(device_t dev)
/*
* Hunt through all the interrupt mapping regs and register
- * the interrupt controller for our interrupt vectors. This
- * is complicated by the fact that a pair of Schizo PBMs
- * share one IGN.
+ * the interrupt controller for our interrupt vectors. We do
+ * this early in order to be able to catch stray interrupts.
+ * This is complicated by the fact that a pair of Schizo PBMs
+ * shares one IGN.
*/
n = OF_getprop(node, "ino-bitmap", (void *)prop_array,
sizeof(prop_array));
@@ -412,8 +412,8 @@ schizo_attach(device_t dev)
continue;
i = schizo_intr_register(sc, n);
if (i != 0)
- panic("%s: could not register interrupt controller "
- "for INO %d (%d)", __func__, n, i);
+ device_printf(dev, "could not register interrupt "
+ "controller for INO %d (%d)\n", n, i);
}
/*
@@ -1128,16 +1128,40 @@ schizo_setup_intr(device_t dev, device_t child, struct resource *ires,
sc = device_get_softc(dev);
/*
- * Make sure the vector is fully specified and we registered
- * our interrupt controller for it.
+ * Make sure the vector is fully specified.
*/
vec = rman_get_start(ires);
- if (INTIGN(vec) != sc->sc_ign ||
- intr_vectors[vec].iv_ic != &schizo_ic) {
+ if (INTIGN(vec) != sc->sc_ign) {
device_printf(dev, "invalid interrupt vector 0x%lx\n", vec);
return (EINVAL);
}
+ if (intr_vectors[vec].iv_ic == &schizo_ic) {
+ /*
+ * Ensure we use the right softc in case the interrupt
+ * is routed to our companion PBM for some odd reason.
+ */
+ sc = ((struct schizo_icarg *)intr_vectors[vec].iv_icarg)->
+ sica_sc;
+ } else if (intr_vectors[vec].iv_ic == NULL) {
+ /*
+ * Work around broken firmware which misses entries in
+ * the ino-bitmap.
+ */
+ error = schizo_intr_register(sc, INTINO(vec));
+ if (error != 0) {
+ device_printf(dev, "could not register interrupt "
+ "controller for vector 0x%lx (%d)\n", vec, error);
+ return (error);
+ }
+ device_printf(dev, "belatedly registered as interrupt "
+ "controller for vector 0x%lx\n", vec);
+ } else {
+ device_printf(dev,
+ "invalid interrupt controller for vector 0x%lx\n", vec);
+ return (EINVAL);
+ }
+
/*
* Install a a wrapper for CDMA flushing/syncing for devices
* behind PCI-PCI bridges if possible.
@@ -1206,7 +1230,7 @@ schizo_setup_intr(device_t dev, device_t child, struct resource *ires,
return (error);
} else if (found != 0)
device_printf(dev, "WARNING: using devices behind PCI-PCI "
- "bridges may cause data corruption");
+ "bridges may cause data corruption\n");
return (bus_generic_setup_intr(dev, child, ires, flags, filt, intr,
arg, cookiep));
}
diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
index a97fd10..d6b8393 100644
--- a/sys/sparc64/sbus/sbus.c
+++ b/sys/sparc64/sbus/sbus.c
@@ -226,6 +226,7 @@ static device_method_t sbus_methods[] = {
DEVMETHOD(bus_get_resource_list, sbus_get_resource_list),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo),
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 0be9af9..4e1e300 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -276,9 +276,10 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
tick_stop();
/*
- * Initialize Open Firmware (needed for console).
+ * Set up Open Firmware entry points
*/
- OF_init(vec);
+ ofw_tba = rdpr(tba);
+ ofw_vec = (u_long)vec;
/*
* Parse metadata if present and fetch parameters. Must be before the
@@ -301,6 +302,12 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
init_param1();
/*
+ * Initialize Open Firmware (needed for console).
+ */
+ OF_install(OFW_STD_DIRECT, 0);
+ OF_init(ofw_entry);
+
+ /*
* Prime our per-CPU data page for use. Note, we are using it for
* our stack, so don't pass the real size (PAGE_SIZE) to pcpu_init
* or it'll zero it out from under us.
@@ -481,14 +488,6 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
}
void
-set_openfirm_callback(ofw_vec_t *vec)
-{
-
- ofw_tba = rdpr(tba);
- ofw_vec = (u_long)vec;
-}
-
-void
sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct trapframe *tf;
@@ -725,7 +724,7 @@ cpu_shutdown(void *args)
#ifdef SMP
cpu_mp_shutdown();
#endif
- openfirmware_exit(args);
+ ofw_exit(args);
}
/* Get current clock frequency for the given CPU ID. */
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index 5cace48..bf79adf 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -221,7 +221,7 @@ sun4u_startcpu(phandle_t cpu, void *func, u_long arg)
args.cpu = cpu;
args.func = (cell_t)func;
args.arg = (cell_t)arg;
- openfirmware(&args);
+ ofw_entry(&args);
}
/*
@@ -238,7 +238,7 @@ sun4u_stopself(void)
(cell_t)SUNW_STOPSELF,
};
- openfirmware_exit(&args);
+ ofw_exit(&args);
panic("%s: failed.", __func__);
}
diff --git a/sys/sparc64/sparc64/ofw_bus.c b/sys/sparc64/sparc64/ofw_bus.c
deleted file mode 100644
index f7458dc..0000000
--- a/sys/sparc64/sparc64/ofw_bus.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*-
- * Copyright (C) 1996 Wolfgang Solfrank.
- * Copyright (C) 1996 TooLs GmbH.
- * 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 TooLs GmbH.
- * 4. The name of TooLs GmbH may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``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 TOOLS GMBH 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.
- */
-/*-
- * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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: $NetBSD: ofw_machdep.c,v 1.16 2001/07/20 00:07:14 eeh Exp $
- *
- * $FreeBSD$
- */
-
-/*
- * Open Firmware bus support code that is (hopefully) independent from the
- * used hardware.
- * Maybe this should go into dev/ofw/; there may however be sparc specific
- * bits left.
- */
-
-#include <sys/param.h>
-#include <sys/malloc.h>
-#include <sys/systm.h>
-
-#include <dev/ofw/openfirm.h>
-
-#include <machine/ofw_bus.h>
-
-static int
-ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
-{
- int rv;
-
- for (; node != 0; node = OF_parent(node)) {
- if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
- return (rv);
- }
- return (-1);
-}
-
-void
-ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
-{
- pcell_t addrc;
- int msksz;
-
- if (OF_getprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1)
- addrc = 2;
- ii->opi_addrc = addrc * sizeof(pcell_t);
-
- ii->opi_imapsz = OF_getprop_alloc(node, "interrupt-map", 1,
- (void **)&ii->opi_imap);
- if (ii->opi_imapsz > 0) {
- msksz = OF_getprop_alloc(node, "interrupt-map-mask", 1,
- (void **)&ii->opi_imapmsk);
- /*
- * Failure to get the mask is ignored; a full mask is used then.
- * Barf on bad mask sizes, however.
- */
- if (msksz != -1 && msksz != ii->opi_addrc + intrsz) {
- panic("ofw_bus_setup_iinfo: bad interrupt-map-mask "
- "property!");
- }
- }
-
-}
-
-int
-ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg,
- int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz,
- void *maskbuf)
-{
- int rv;
-
- if (ii->opi_imapsz <= 0)
- return (0);
- KASSERT(regsz >= ii->opi_addrc,
- ("ofw_bus_lookup_imap: register size too small: %d < %d",
- regsz, ii->opi_addrc));
- rv = OF_getprop(node, "reg", reg, regsz);
- if (rv < regsz)
- panic("ofw_bus_lookup_imap: could not get reg property");
- return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc,
- ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr,
- mintrsz));
-}
-
-/*
- * Map an interrupt using the firmware reg, interrupt-map and
- * interrupt-map-mask properties.
- * The interrupt property to be mapped must be of size intrsz, and pointed to
- * by intr. The regs property of the node for which the mapping is done must
- * be passed as regs. This property is an array of register specifications;
- * the size of the address part of such a specification must be passed as
- * physsz. Only the first element of the property is used.
- * imap and imapsz hold the interrupt mask and it's size.
- * imapmsk is a pointer to the interrupt-map-mask property, which must have
- * a size of physsz + intrsz; it may be NULL, in which case a full mask is
- * assumed.
- * maskbuf must point to a buffer of length physsz + intrsz.
- * The interrupt is returned in result, which must point to a buffer of length
- * rintrsz (which gives the expected size of the mapped interrupt).
- * Returns 1 if a mapping was found, 0 otherwise.
- */
-int
-ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
- void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result,
- int rintrsz)
-{
- phandle_t parent;
- u_int8_t *ref = maskbuf;
- u_int8_t *uiintr = intr;
- u_int8_t *uiregs = regs;
- u_int8_t *uiimapmsk = imapmsk;
- u_int8_t *mptr;
- pcell_t pintrsz;
- int i, rsz, tsz;
-
- rsz = -1;
- if (imapmsk != NULL) {
- for (i = 0; i < physsz; i++)
- ref[i] = uiregs[i] & uiimapmsk[i];
- for (i = 0; i < intrsz; i++)
- ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i];
- } else {
- bcopy(regs, ref, physsz);
- bcopy(intr, ref + physsz, intrsz);
- }
-
- mptr = imap;
- i = imapsz;
- tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
- while (i > 0) {
- KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
- bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
- if (ofw_bus_searchprop(parent, "#interrupt-cells",
- &pintrsz, sizeof(pintrsz)) == -1)
- pintrsz = 1; /* default */
- pintrsz *= sizeof(pcell_t);
- if (pintrsz != rintrsz)
- panic("ofw_bus_search_intrmap: expected interrupt cell "
- "size incorrect: %d != %d", rintrsz, pintrsz);
- if (bcmp(ref, mptr, physsz + intrsz) == 0) {
- bcopy(mptr + physsz + intrsz + sizeof(parent),
- result, rintrsz);
- return (1);
- }
- mptr += tsz;
- i -= tsz;
- }
- return (0);
-}
diff --git a/sys/sparc64/sparc64/ofw_machdep.c b/sys/sparc64/sparc64/ofw_machdep.c
index 7efc807..bcacea7 100644
--- a/sys/sparc64/sparc64/ofw_machdep.c
+++ b/sys/sparc64/sparc64/ofw_machdep.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/idprom.h>
-#include <machine/ofw_bus.h>
#include <machine/ofw_machdep.h>
void
diff --git a/sys/sparc64/sparc64/support.S b/sys/sparc64/sparc64/support.S
index a3f6501..821e694 100644
--- a/sys/sparc64/sparc64/support.S
+++ b/sys/sparc64/sparc64/support.S
@@ -745,9 +745,9 @@ ENTRY(setjmp)
END(setjmp)
/*
- * void openfirmware(cell_t args[])
+ * void ofw_entry(cell_t args[])
*/
-ENTRY(openfirmware)
+ENTRY(ofw_entry)
save %sp, -CCFSZ, %sp
SET(ofw_vec, %l7, %l6)
ldx [%l6], %l6
@@ -758,12 +758,12 @@ ENTRY(openfirmware)
wrpr %l7, 0, %pil
ret
restore %o0, %g0, %o0
-END(openfirmware)
+END(ofw_entry)
/*
- * void openfirmware_exit(cell_t args[])
+ * void ofw_exit(cell_t args[])
*/
-ENTRY(openfirmware_exit)
+ENTRY(ofw_exit)
save %sp, -CCFSZ, %sp
flushw
wrpr %g0, PIL_TICK, %pil
@@ -783,7 +783,7 @@ ENTRY(openfirmware_exit)
call %l6
mov %i0, %o0
! never to return
-END(openfirmware_exit)
+END(ofw_exit)
#ifdef GPROF
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c
index 9de8e26..c10dbc4 100644
--- a/sys/sparc64/sparc64/trap.c
+++ b/sys/sparc64/sparc64/trap.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <security/audit/audit.h>
#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -248,7 +249,7 @@ sun4u_set_traptable(void *tba_addr)
};
args.tba_addr = (cell_t)tba_addr;
- openfirmware(&args);
+ ofw_entry(&args);
}
void
diff --git a/sys/sparc64/sparc64/vm_machdep.c b/sys/sparc64/sparc64/vm_machdep.c
index c163fd8..b769753 100644
--- a/sys/sparc64/sparc64/vm_machdep.c
+++ b/sys/sparc64/sparc64/vm_machdep.c
@@ -334,7 +334,7 @@ cpu_reset(void)
bspec[sizeof(bspec) - 1] = '\0';
}
- openfirmware_exit(&args);
+ ofw_exit(&args);
}
/*
diff --git a/sys/sun4v/conf/DEFAULTS b/sys/sun4v/conf/DEFAULTS
index ba7c539..610d653 100644
--- a/sys/sun4v/conf/DEFAULTS
+++ b/sys/sun4v/conf/DEFAULTS
@@ -9,5 +9,5 @@ machine sun4v
device mem # Memory and kernel memory devices
# Default partitioning schemes
-options GEOM_BSD
-options GEOM_SUNLABEL
+options GEOM_PART_BSD
+options GEOM_PART_VTOC8
diff --git a/sys/sun4v/include/elf.h b/sys/sun4v/include/elf.h
index 76e3a76..108ade1 100644
--- a/sys/sun4v/include/elf.h
+++ b/sys/sun4v/include/elf.h
@@ -78,18 +78,6 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-
-/*
- * The following non-standard values are used for passing information
- * from John Polstra's testbed program to the dynamic linker. These
- * are expected to go away soon.
- *
- * Unfortunately, these overlap the Linux non-standard values, so they
- * must not be used in the same context.
- */
-#define T_BRK 10 /* Starting point for sbrk and brk. */
-#define AT_DEBUG 11 /* Debugging level. */
-
/*
* The following non-standard values are used in Linux ELF binaries.
*/
diff --git a/sys/sun4v/include/ofw_bus.h b/sys/sun4v/include/ofw_bus.h
deleted file mode 100644
index 1e9004e..0000000
--- a/sys/sun4v/include/ofw_bus.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*-
- * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
- *
- * $FreeBSD$
- */
-
-#ifndef _MACHINE_OFW_BUS_H_
-#define _MACHINE_OFW_BUS_H_
-
-#define ORIP_NOINT -1
-#define ORIR_NOTFOUND 0xffffffff
-
-/*
- * Other than in Open Firmware calls, the size of a bus cell seems to be
- * always the same.
- */
-typedef u_int32_t pcell_t;
-
-struct ofw_bus_iinfo {
- u_int8_t *opi_imap;
- u_int8_t *opi_imapmsk;
- int opi_imapsz;
- pcell_t opi_addrc;
-};
-
-void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
-int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
- void *, int, void *, int, void *);
-int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
- void *, void *, int);
-
-#endif /* !_MACHINE_OFW_BUS_H_ */
diff --git a/sys/sun4v/sun4v/machdep.c b/sys/sun4v/sun4v/machdep.c
index 6281f00..b7c0869 100644
--- a/sys/sun4v/sun4v/machdep.c
+++ b/sys/sun4v/sun4v/machdep.c
@@ -310,18 +310,18 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
end = 0;
kmdp = NULL;
- /*
- * Initialize Open Firmware (needed for console).
- */
- OF_init(vec);
-
-
/*
* XXX
*/
bootverbose = 1;
/*
+ * Set up Open Firmware entry points
+ */
+ ofw_tba = rdpr(tba);
+ ofw_vec = (u_long)vec;
+
+ /*
* Parse metadata if present and fetch parameters. Must be before the
* console is inited so cninit gets the right value of boothowto.
*/
@@ -344,6 +344,12 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
init_param1();
+ /*
+ * Initialize Open Firmware (needed for console).
+ */
+ OF_install(OFW_STD_DIRECT, 0);
+ OF_init(ofw_entry);
+
root = OF_peer(0);
for (child = OF_child(root); child != 0; child = OF_peer(child)) {
OF_getprop(child, "device_type", type, sizeof(type));
@@ -516,13 +522,6 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
}
void
-set_openfirm_callback(ofw_vec_t *vec)
-{
- ofw_tba = rdpr(tba);
- ofw_vec = (u_long)vec;
-}
-
-void
sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
struct trapframe *tf;
diff --git a/sys/sun4v/sun4v/mp_machdep.c b/sys/sun4v/sun4v/mp_machdep.c
index 8bd4ba6..5f4f632 100644
--- a/sys/sun4v/sun4v/mp_machdep.c
+++ b/sys/sun4v/sun4v/mp_machdep.c
@@ -272,7 +272,7 @@ start_ap_bycpuid(int cpuid, void *func, u_long arg)
args.cpuid = cpuid;
args.func = (cell_t)func;
args.arg = (cell_t)arg;
- openfirmware(&args);
+ ofw_entry(&args);
return (int)args.result;
}
diff --git a/sys/sun4v/sun4v/support.S b/sys/sun4v/sun4v/support.S
index e6bac5d..699a40f 100644
--- a/sys/sun4v/sun4v/support.S
+++ b/sys/sun4v/sun4v/support.S
@@ -622,9 +622,9 @@ ENTRY(setjmp)
END(setjmp)
/*
- * void openfirmware(cell_t args[])
+ * void ofw_entry(cell_t args[])
*/
-ENTRY(openfirmware)
+ENTRY(ofw_entry)
save %sp, -CCFSZ, %sp
SET(ofw_vec, %l7, %l6)
ldx [%l6], %l6
@@ -635,14 +635,14 @@ ENTRY(openfirmware)
wrpr %l7, 0, %pil
ret
restore %o0, %g0, %o0
-END(openfirmware)
+END(ofw_entry)
#ifdef notyet
/* SUN4V_FIXME - uses a now illegal ASI */
/*
* void ofw_exit(cell_t args[])
*/
-ENTRY(openfirmware_exit)
+ENTRY(ofw_exit)
save %sp, -CCFSZ, %sp
flushw
wrpr %g0, PIL_TICK, %pil
@@ -661,7 +661,7 @@ ENTRY(openfirmware_exit)
call %l6
mov %i0, %o0
! never to return
-END(openfirmware_exit)
+END(ofw_exit)
#endif
ENTRY(set_mmfsa_scratchpad)
diff --git a/sys/sun4v/sun4v/trap.c b/sys/sun4v/sun4v/trap.c
index f04c424..bac4f55 100644
--- a/sys/sun4v/sun4v/trap.c
+++ b/sys/sun4v/sun4v/trap.c
@@ -261,7 +261,7 @@ set_mmfsa_traptable(void *tba_addr, uint64_t mmfsa_ra)
args.tba_addr = (cell_t)tba_addr;
args.mmfsa_ra = mmfsa_ra;
- openfirmware(&args);
+ ofw_entry(&args);
}
void
diff --git a/sys/sys/buf_ring.h b/sys/sys/buf_ring.h
index 6d0cb7d..efea85a 100644
--- a/sys/sys/buf_ring.h
+++ b/sys/sys/buf_ring.h
@@ -48,10 +48,11 @@ struct buf_ring {
volatile uint32_t br_prod_tail;
int br_prod_size;
int br_prod_mask;
+ uint64_t br_drops;
/*
* Pad out to next L2 cache line
*/
- uint64_t _pad0[14];
+ uint64_t _pad0[13];
volatile uint32_t br_cons_head;
volatile uint32_t br_cons_tail;
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
index 95f3352..688fab2 100644
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -101,6 +101,7 @@ typedef struct {
#define ELFOSABI_OPENBSD 12 /* OpenBSD */
#define ELFOSABI_OPENVMS 13 /* Open VMS */
#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
+#define ELFOSABI_AROS 15 /* Amiga Research OS */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
@@ -169,6 +170,61 @@ typedef struct {
#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */
+#define EM_PDSP 63 /* Sony DSP Processor. */
+#define EM_FX66 66 /* Siemens FX66 microcontroller. */
+#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16
+ microcontroller. */
+#define EM_ST7 68 /* STmicroelectronics ST7 8-bit
+ microcontroller. */
+#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */
+#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */
+#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */
+#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */
+#define EM_SVX 73 /* Silicon Graphics SVx. */
+#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */
+#define EM_VAX 75 /* Digital VAX. */
+#define EM_CRIS 76 /* Axis Communications 32-bit embedded
+ processor. */
+#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded
+ processor. */
+#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */
+#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */
+#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */
+#define EM_HUANY 81 /* Harvard University machine-independent
+ object files. */
+#define EM_PRISM 82 /* SiTera Prism. */
+#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */
+#define EM_FR30 84 /* Fujitsu FR30. */
+#define EM_D10V 85 /* Mitsubishi D10V. */
+#define EM_D30V 86 /* Mitsubishi D30V. */
+#define EM_V850 87 /* NEC v850. */
+#define EM_M32R 88 /* Mitsubishi M32R. */
+#define EM_MN10300 89 /* Matsushita MN10300. */
+#define EM_MN10200 90 /* Matsushita MN10200. */
+#define EM_PJ 91 /* picoJava. */
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */
+#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */
+#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */
+#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */
+#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose
+ Processor. */
+#define EM_NS32K 97 /* National Semiconductor 32000 series. */
+#define EM_TPC 98 /* Tenor Network TPC processor. */
+#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */
+#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */
+#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */
+#define EM_MAX 102 /* MAX Processor. */
+#define EM_CR 103 /* National Semiconductor CompactRISC
+ microprocessor. */
+#define EM_F2MC16 104 /* Fujitsu F2MC16. */
+#define EM_MSP430 105 /* Texas Instruments embedded microcontroller
+ msp430. */
+#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */
+#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */
+#define EM_SEP 108 /* Sharp embedded microprocessor. */
+#define EM_ARCA 109 /* Arca RISC Microprocessor. */
+#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd.
+ and MPRC of Peking University */
/* Non-standard or deprecated. */
#define EM_486 6 /* Intel i486. */
@@ -195,12 +251,12 @@ typedef struct {
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4 /* relocation section with addends */
#define SHT_HASH 5 /* symbol hash table section */
-#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_DYNAMIC 6 /* dynamic section */
#define SHT_NOTE 7 /* note section */
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9 /* relocation section - no addends */
#define SHT_SHLIB 10 /* reserved - purpose unknown */
-#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index 663a090..ec1d638 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -52,7 +52,6 @@ typedef struct {
Elf_Size base;
Elf_Size flags;
Elf_Size entry;
- Elf_Size trace;
} __ElfN(Auxargs);
typedef struct {
diff --git a/sys/sys/kobj.h b/sys/sys/kobj.h
index b744db8..64a666a 100644
--- a/sys/sys/kobj.h
+++ b/sys/sys/kobj.h
@@ -246,9 +246,4 @@ kobj_method_t* kobj_lookup_method(kobj_class_t cls,
*/
int kobj_error_method(void);
-/*
- * Machine-dependent initialisation call for boot-time kobj clients
- */
-void kobj_machdep_init(void);
-
#endif /* !_SYS_KOBJ_H_ */
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 51cff5d..60086c6 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -316,6 +316,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
#define MNTK_SOFTDEP 0x00000004 /* async disabled by softdep */
#define MNTK_NOINSMNTQ 0x00000008 /* insmntque is not allowed */
#define MNTK_DRAINING 0x00000010 /* lock draining is happening */
+#define MNTK_REFEXPIRE 0x00000020 /* refcount expiring is happening */
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */
#define MNTK_SUSPEND 0x08000000 /* request write suspension */
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 497b362..fad4d51 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 800058 /* Master, propagated to newvers */
+#define __FreeBSD_version 800060 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/ttyhook.h b/sys/sys/ttyhook.h
index 7a0a0bc..2a6d088 100644
--- a/sys/sys/ttyhook.h
+++ b/sys/sys/ttyhook.h
@@ -66,7 +66,7 @@ struct ttyhook {
th_close_t *th_close;
};
-int ttyhook_register(struct tty **, struct thread *, int,
+int ttyhook_register(struct tty **, struct proc *, int,
struct ttyhook *, void *);
void ttyhook_unregister(struct tty *);
#define ttyhook_softc(tp) ((tp)->t_hooksoftc)
diff --git a/sys/sys/vtoc.h b/sys/sys/vtoc.h
index 83b8547..231da00 100644
--- a/sys/sys/vtoc.h
+++ b/sys/sys/vtoc.h
@@ -72,7 +72,7 @@ struct vtoc8 {
struct {
uint16_t tag;
uint16_t flag;
- } part[VTOC8_NPARTS];
+ } part[VTOC8_NPARTS] __packed;
uint16_t __alignment;
uint32_t bootinfo[3];
uint32_t sanity;
diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c
index 14ce4c6..ac1fbcf 100644
--- a/sys/ufs/ufs/ufs_vfsops.c
+++ b/sys/ufs/ufs/ufs_vfsops.c
@@ -118,9 +118,6 @@ ufs_quotactl(mp, cmds, id, arg, td)
if ((u_int)type >= MAXQUOTAS)
return (EINVAL);
- if (vfs_busy(mp, MBF_NOWAIT))
- return (0);
-
switch (cmd) {
case Q_QUOTAON:
error = quotaon(td, mp, type, arg);
@@ -150,7 +147,6 @@ ufs_quotactl(mp, cmds, id, arg, td)
error = EINVAL;
break;
}
- vfs_unbusy(mp);
return (error);
#endif
}
diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c
index e5047e9..7b639e8 100644
--- a/sys/ufs/ufs/ufs_vnops.c
+++ b/sys/ufs/ufs/ufs_vnops.c
@@ -2013,7 +2013,7 @@ ufs_strategy(ap)
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
bufdone(bp);
- return (error);
+ return (0);
}
if ((long)bp->b_blkno == -1)
vfs_bio_clrbuf(bp);
diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh
index d1041a2..70c0c58 100644
--- a/tools/tools/nanobsd/nanobsd.sh
+++ b/tools/tools/nanobsd/nanobsd.sh
@@ -47,6 +47,7 @@ NANO_TOOLS=tools/tools/nanobsd
# Where cust_pkg() finds packages to install
NANO_PACKAGE_DIR=${NANO_SRC}/${NANO_TOOLS}/Pkg
+NANO_PACKAGE_LIST="*"
# Object tree directory
# default is subdir of /usr/obj
@@ -592,7 +593,11 @@ cust_pkg () (
# Copy packages into chroot
mkdir -p ${NANO_WORLDDIR}/Pkg
- cp ${NANO_PACKAGE_DIR}/* ${NANO_WORLDDIR}/Pkg
+ (
+ cd ${NANO_PACKAGE_DIR}
+ find ${NANO_PACKAGE_LIST} -print |
+ cpio -dumpv ${NANO_WORLDDIR}/Pkg
+ )
# Count & report how many we have to install
todo=`ls ${NANO_WORLDDIR}/Pkg | wc -l`
diff --git a/tools/tools/tionxcl/Makefile b/tools/tools/tionxcl/Makefile
new file mode 100644
index 0000000..99948fb
--- /dev/null
+++ b/tools/tools/tionxcl/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+PROG= tionxcl
+NO_MAN= defined
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/tionxcl/tionxcl.c b/tools/tools/tionxcl/tionxcl.c
new file mode 100644
index 0000000..cac02cd
--- /dev/null
+++ b/tools/tools/tionxcl/tionxcl.c
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2008 Bruce Simpson.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <libgen.h>
+#include <sysexits.h>
+
+#define DEVPATHNAME "/dev"
+
+int
+main(int argc, char *argv[])
+{
+ char *progname;
+ char *ttyname;
+ int fd;
+ int dofree;
+
+ dofree = 0;
+
+ progname = basename(argv[0]);
+ if (argc != 2)
+ errx(EX_USAGE, "usage: %s <ttyname>\n", progname);
+ if (geteuid() != 0)
+ errx(EX_NOPERM, "Sorry\n");
+
+ if (argv[1][0] == '/') {
+ ttyname = argv[1];
+ } else {
+ size_t len, maxpath, result;
+
+ len = strlen(argv[1]) + sizeof(DEVPATHNAME) + 1;
+
+ maxpath = pathconf(DEVPATHNAME, _PC_PATH_MAX);
+ if (len > maxpath) {
+ warnc(ENAMETOOLONG, ttyname);
+ exit(EX_DATAERR);
+ }
+
+ ttyname = malloc(len);
+ if (ttyname == NULL) {
+ warnc(ENOMEM, "malloc");
+ exit(EX_OSERR);
+ }
+ dofree = 1;
+
+ result = snprintf(ttyname, len, "%s/%s", DEVPATHNAME, argv[1]);
+ if (result >= len)
+ warnc(ENOMEM, "snprintf");
+ }
+
+ fd = open(ttyname, O_RDWR);
+ if (fd == -1) {
+ warnc(errno, "open %s", ttyname);
+ if (dofree)
+ free(ttyname);
+ exit(EX_OSERR);
+ }
+
+ if (0 != ioctl(fd, TIOCNXCL, 0))
+ warnc(errno, "ioctl TIOCNXCL %s", ttyname);
+
+ if (dofree)
+ free(ttyname);
+ exit(0);
+}
diff --git a/usr.bin/cpuset/cpuset.1 b/usr.bin/cpuset/cpuset.1
index e8f5593..88e8c98 100644
--- a/usr.bin/cpuset/cpuset.1
+++ b/usr.bin/cpuset/cpuset.1
@@ -35,7 +35,7 @@
.Nm
.Op Fl l Ar cpu-list
.Op Fl s Ar setid
-.Ar cmd
+.Ar cmd ...
.Nm
.Op Fl l Ar cpu-list
.Op Fl s Ar setid
@@ -43,10 +43,10 @@
.Nm
.Op Fl cr
.Op Fl l Ar cpu-list
-.Op Fl j Ar jailid | Fl p Ar pid | Fl r Ar tid | Fl s Ar setid | Fl x Ar irq
+.Op Fl j Ar jailid | Fl p Ar pid | Fl t Ar tid | Fl s Ar setid | Fl x Ar irq
.Nm
.Op Fl cgir
-.Op Fl j Ar jailid | Fl p Ar pid | Fl r Ar tid | Fl s Ar setid | Fl x Ar irq
+.Op Fl j Ar jailid | Fl p Ar pid | Fl t Ar tid | Fl s Ar setid | Fl x Ar irq
.Sh DESCRIPTION
The
.Nm
@@ -104,7 +104,7 @@ target specifier.
.It Fl g
Causes
.Nm
-to print either a list of valid CPUs or, using
+to print either a list of valid CPUs or, using
.Fl i ,
the id of the target.
.It Fl i
@@ -119,14 +119,14 @@ Specification may include
numbers separated by '-' for ranges and commas separating individual numbers.
.It Fl p Ar pid
Specifies a pid as the target of the operation.
-.It Fl s Ar setid
+.It Fl s Ar setid
Specifies a set id as the target of the operation.
.It Fl r
The requested operation should reference the root set available via the
target specifier.
.It Fl t Ar tid
Specifies a thread id as the target of the operation.
-.It Fl x Ar irq
+.It Fl x Ar irq
Specifies an irq as the target of the operation.
.El
.Sh EXIT STATUS
diff --git a/usr.bin/fetch/fetch.1 b/usr.bin/fetch/fetch.1
index 3922db5..0dbbc0b 100644
--- a/usr.bin/fetch/fetch.1
+++ b/usr.bin/fetch/fetch.1
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 11, 2003
+.Dd December 14, 2008
.Dt FETCH 1
.Os
.Sh NAME
@@ -37,17 +37,25 @@
.Nd retrieve a file by Uniform Resource Locator
.Sh SYNOPSIS
.Nm
-.Op Fl 146AFMPRUadlmnpqrsv
+.Op Fl 146AadFlMmnPpqRrsUv
.Op Fl B Ar bytes
+.Op Fl i Ar file
+.Op Fl N Ar file
+.Op Fl o Ar file
.Op Fl S Ar bytes
.Op Fl T Ar seconds
+.Op Fl w Ar seconds
+.Ar URL ...
+.Nm
+.Op Fl 146AadFlMmnPpqRrsUv
+.Op Fl B Ar bytes
+.Op Fl i Ar file
.Op Fl N Ar file
.Op Fl o Ar file
+.Op Fl S Ar bytes
+.Op Fl T Ar seconds
.Op Fl w Ar seconds
-.Op Fl h Ar host
-.Op Fl c Ar dir
-.Op Fl f Ar file
-.Op Ar URL ...
+.Fl h Ar host Fl f Ar file Oo Fl c Ar dir Oc
.Sh DESCRIPTION
The
.Nm
@@ -59,7 +67,7 @@ command line.
.Pp
The following options are available:
.Bl -tag -width Fl
-.It Fl \&1
+.It Fl 1
Stop and return exit code 0 at the first successfully retrieved file.
.It Fl 4
Forces
@@ -110,6 +118,12 @@ The file to retrieve is located on the host
.Ar host .
This option is deprecated and is provided for backward compatibility
only.
+.It Fl i Ar file
+If-Modified-Since mode: the remote file will only be retrieved if it
+is newer than
+.Ar file
+on the local host.
+(HTTP only)
.It Fl l
If the target is a file-scheme URL, make a symbolic link to the target
rather than trying to copy it.
@@ -243,6 +257,12 @@ If multiple URLs are listed on the command line,
.Nm
will attempt to retrieve each one of them in turn, and will return
zero only if they were all successfully retrieved.
+.Pp
+If the
+.Fl i
+argument is used and the remote file is not newer than the
+specified file then the command will still return success,
+although no file is transferred.
.Sh SEE ALSO
.Xr fetch 3
.Sh HISTORY
diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c
index a891a8c..bc5268c 100644
--- a/usr.bin/fetch/fetch.c
+++ b/usr.bin/fetch/fetch.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sysexits.h>
#include <termios.h>
#include <unistd.h>
@@ -60,6 +59,8 @@ int d_flag; /* -d: direct connection */
int F_flag; /* -F: restart without checking mtime */
char *f_filename; /* -f: file to fetch */
char *h_hostname; /* -h: host to fetch from */
+int i_flag; /* -i: specify input file for mtime comparison */
+char *i_filename; /* name of input file */
int l_flag; /* -l: link rather than copy file: URLs */
int m_flag; /* -[Mm]: mirror mode */
char *N_filename; /* -N: netrc file name */
@@ -382,6 +383,14 @@ fetch(char *URL, const char *path)
if (A_flag)
strcat(flags, "A");
timeout = T_secs ? T_secs : http_timeout;
+ if (i_flag) {
+ if (stat(i_filename, &sb)) {
+ warn("%s: stat()", i_filename);
+ goto failure;
+ }
+ url->ims_time = sb.st_mtime;
+ strcat(flags, "i");
+ }
}
/* set the protocol timeout. */
@@ -449,7 +458,14 @@ fetch(char *URL, const char *path)
goto signal;
if (f == NULL) {
warnx("%s: %s", URL, fetchLastErrString);
- goto failure;
+ if (i_flag && strcmp(url->scheme, SCHEME_HTTP) == 0
+ && fetchLastErrCode == FETCH_OK
+ && strcmp(fetchLastErrString, "Not Modified") == 0) {
+ /* HTTP Not Modified Response, return OK. */
+ r = 0;
+ goto done;
+ } else
+ goto failure;
}
if (sigint)
goto signal;
@@ -711,10 +727,11 @@ fetch(char *URL, const char *path)
static void
usage(void)
{
- fprintf(stderr, "%s\n%s\n%s\n",
- "usage: fetch [-146AFMPRUadlmnpqrsv] [-N netrc] [-o outputfile]",
- " [-S bytes] [-B bytes] [-T seconds] [-w seconds]",
- " [-h host -f file [-c dir] | URL ...]");
+ fprintf(stderr, "%s\n%s\n%s\n%s\n",
+"usage: fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [-N file] [-o file] [-S bytes]",
+" [-T seconds] [-w seconds] [-i file] URL ...",
+" fetch [-146AadFlMmnPpqRrsUv] [-B bytes] [-N file] [-o file] [-S bytes]",
+" [-T seconds] [-w seconds] [-i file] -h host -f file [-c dir]");
}
@@ -731,7 +748,7 @@ main(int argc, char *argv[])
int c, e, r;
while ((c = getopt(argc, argv,
- "146AaB:bc:dFf:Hh:lMmN:nPpo:qRrS:sT:tUvw:")) != -1)
+ "146AaB:bc:dFf:Hh:i:lMmN:nPpo:qRrS:sT:tUvw:")) != -1)
switch (c) {
case '1':
once_flag = 1;
@@ -776,6 +793,10 @@ main(int argc, char *argv[])
case 'h':
h_hostname = optarg;
break;
+ case 'i':
+ i_flag = 1;
+ i_filename = optarg;
+ break;
case 'l':
l_flag = 1;
break;
@@ -843,7 +864,7 @@ main(int argc, char *argv[])
break;
default:
usage();
- exit(EX_USAGE);
+ exit(1);
}
argc -= optind;
@@ -852,7 +873,7 @@ main(int argc, char *argv[])
if (h_hostname || f_filename || c_dirname) {
if (!h_hostname || !f_filename || argc) {
usage();
- exit(EX_USAGE);
+ exit(1);
}
/* XXX this is a hack. */
if (strcspn(h_hostname, "@:/") != strlen(h_hostname))
@@ -865,7 +886,7 @@ main(int argc, char *argv[])
if (!argc) {
usage();
- exit(EX_USAGE);
+ exit(1);
}
/* allocate buffer */
@@ -906,10 +927,10 @@ main(int argc, char *argv[])
} else if (stat(o_filename, &sb) == -1) {
if (errno == ENOENT) {
if (argc > 1)
- errx(EX_USAGE, "%s is not a directory",
+ errx(1, "%s is not a directory",
o_filename);
} else {
- err(EX_IOERR, "%s", o_filename);
+ err(1, "%s", o_filename);
}
} else {
if (sb.st_mode & S_IFDIR)
diff --git a/usr.bin/ipcs/ipcs.c b/usr.bin/ipcs/ipcs.c
index eb50ed6..67364d5 100644
--- a/usr.bin/ipcs/ipcs.c
+++ b/usr.bin/ipcs/ipcs.c
@@ -394,15 +394,15 @@ print_kshmtotal(struct shminfo shminfo)
{
printf("shminfo:\n");
- printf("\tshmmax: %12d\t(max shared memory segment size)\n",
+ printf("\tshmmax: %12lu\t(max shared memory segment size)\n",
shminfo.shmmax);
- printf("\tshmmin: %12d\t(min shared memory segment size)\n",
+ printf("\tshmmin: %12lu\t(min shared memory segment size)\n",
shminfo.shmmin);
- printf("\tshmmni: %12d\t(max number of shared memory identifiers)\n",
+ printf("\tshmmni: %12lu\t(max number of shared memory identifiers)\n",
shminfo.shmmni);
- printf("\tshmseg: %12d\t(max shared memory segments per process)\n",
+ printf("\tshmseg: %12lu\t(max shared memory segments per process)\n",
shminfo.shmseg);
- printf("\tshmall: %12d\t(max amount of shared memory in pages)\n\n",
+ printf("\tshmall: %12lu\t(max amount of shared memory in pages)\n\n",
shminfo.shmall);
}
diff --git a/usr.bin/make/globals.h b/usr.bin/make/globals.h
index 04c7da9..5e42a4a 100644
--- a/usr.bin/make/globals.h
+++ b/usr.bin/make/globals.h
@@ -70,6 +70,7 @@ extern struct Path parseIncPath;
extern struct Path sysIncPath;
extern int jobLimit; /* -j argument: maximum number of jobs */
+extern int makeErrors; /* Number of targets not remade due to errors */
extern Boolean jobsRunning; /* True if jobs are running */
extern Boolean compatMake; /* True if we are make compatible */
extern Boolean ignoreErrors; /* True if should ignore all errors */
diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c
index 77a7f86..7cc575e 100644
--- a/usr.bin/make/job.c
+++ b/usr.bin/make/job.c
@@ -263,7 +263,6 @@ TAILQ_HEAD(JobList, Job);
/*
* error handling variables
*/
-static int errors = 0; /* number of errors reported */
static int aborting = 0; /* why is the make aborting? */
#define ABORT_ERROR 1 /* Because of an error */
#define ABORT_INTERRUPT 2 /* Because it was interrupted */
@@ -849,7 +848,7 @@ JobClose(Job *job)
*
* If we got an error and are aborting (aborting == ABORT_ERROR) and
* the job list is now empty, we are done for the day.
- * If we recognized an error (errors !=0), we set the aborting flag
+ * If we recognized an error (makeErrors !=0), we set the aborting flag
* to ABORT_ERROR so no more jobs will be started.
*/
static void
@@ -1124,7 +1123,7 @@ JobFinish(Job *job, int *status)
free(job);
} else if (*status != 0) {
- errors += 1;
+ makeErrors++;
free(job);
}
@@ -1133,7 +1132,7 @@ JobFinish(Job *job, int *status)
/*
* Set aborting if any error.
*/
- if (errors && !keepgoing && aborting != ABORT_INTERRUPT) {
+ if (makeErrors && !keepgoing && aborting != ABORT_INTERRUPT) {
/*
* If we found any errors in this batch of children and the -k
* flag wasn't given, we set the aborting flag so no more jobs
@@ -1146,7 +1145,7 @@ JobFinish(Job *job, int *status)
/*
* If we are aborting and the job table is now empty, we finish.
*/
- Finish(errors);
+ Finish(makeErrors);
}
}
@@ -2347,7 +2346,7 @@ Job_Init(int maxproc)
nJobs = 0;
aborting = 0;
- errors = 0;
+ makeErrors = 0;
lastNode = NULL;
@@ -2539,14 +2538,14 @@ JobInterrupt(int runINTERRUPT, int signo)
* attached to the .END target.
*
* Results:
- * Number of errors reported.
+ * None.
*/
-int
+void
Job_Finish(void)
{
if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) {
- if (errors) {
+ if (makeErrors) {
Error("Errors reported so .END ignored");
} else {
JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL);
@@ -2563,7 +2562,6 @@ Job_Finish(void)
if (fifoMaster)
unlink(fifoName);
}
- return (errors);
}
/**
@@ -3327,7 +3325,6 @@ void
Compat_Run(Lst *targs)
{
GNode *gn = NULL; /* Current root target */
- int error_cnt; /* Number of targets not remade due to errors */
LstNode *ln;
Compat_InstallSignalHandlers();
@@ -3360,7 +3357,7 @@ Compat_Run(Lst *targs)
* ABORTED gn was not remade because one of its inferiors
* could not be made due to errors.
*/
- error_cnt = 0;
+ makeErrors = 0;
while (!Lst_IsEmpty(targs)) {
gn = Lst_DeQueue(targs);
Compat_Make(gn, gn);
@@ -3370,18 +3367,17 @@ Compat_Run(Lst *targs)
} else if (gn->made == ABORTED) {
printf("`%s' not remade because of errors.\n",
gn->name);
- error_cnt += 1;
+ makeErrors++;
}
}
/*
* If the user has defined a .END target, run its commands.
*/
- if (error_cnt == 0) {
+ if (makeErrors == 0) {
LST_FOREACH(ln, &ENDNode->commands) {
if (Compat_RunCommand(Lst_Datum(ln), ENDNode))
break;
}
}
}
-
diff --git a/usr.bin/make/job.h b/usr.bin/make/job.h
index a4c6620..57c99de 100644
--- a/usr.bin/make/job.h
+++ b/usr.bin/make/job.h
@@ -64,7 +64,7 @@ void Job_Make(struct GNode *);
void Job_Init(int);
Boolean Job_Full(void);
Boolean Job_Empty(void);
-int Job_Finish(void);
+void Job_Finish(void);
void Job_Wait(void);
void Job_AbortAll(void);
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 7569d42..7ba0bae 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -130,6 +130,7 @@ Boolean compatMake; /* -B argument */
int debug; /* -d flag */
Boolean ignoreErrors; /* -i flag */
int jobLimit; /* -j argument */
+int makeErrors; /* Number of targets not remade due to errors */
Boolean jobsRunning; /* TRUE if the jobs might be running */
Boolean keepgoing; /* -k flag */
Boolean noExecute; /* -n flag */
@@ -1311,9 +1312,11 @@ main(int argc, char **argv)
if (DEBUG(GRAPH2))
Targ_PrintGraph(2);
- if (queryFlag && outOfDate)
- return (1);
- else
- return (0);
-}
+ if (queryFlag)
+ return (outOfDate);
+
+ if (makeErrors != 0)
+ Finish(makeErrors);
+ return (0);
+}
diff --git a/usr.bin/make/make.c b/usr.bin/make/make.c
index 4ac5bb6..835e855 100644
--- a/usr.bin/make/make.c
+++ b/usr.bin/make/make.c
@@ -713,7 +713,6 @@ Make_Run(Lst *targs)
GNode *gn; /* a temporary pointer */
GNode *cgn;
Lst examine; /* List of targets to examine */
- int errors; /* Number of errors the Job module reports */
LstNode *ln;
Lst_Init(&examine);
@@ -793,15 +792,14 @@ Make_Run(Lst *targs)
MakeStartJobs();
}
- errors = Job_Finish();
+ Job_Finish();
/*
* Print the final status of each target. E.g. if it wasn't made
* because some inferior reported an error.
*/
- errors = ((errors == 0) && (numNodes != 0));
LST_FOREACH(ln, targs)
- MakePrintStatus(Lst_Datum(ln), errors);
+ MakePrintStatus(Lst_Datum(ln), (makeErrors == 0) && (numNodes != 0));
return (TRUE);
}
diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c
index 01311e5..596fcd5 100644
--- a/usr.bin/netstat/route.c
+++ b/usr.bin/netstat/route.c
@@ -89,17 +89,23 @@ struct bits {
{ RTF_DYNAMIC, 'D' },
{ RTF_MODIFIED, 'M' },
{ RTF_DONE, 'd' }, /* Completed -- for routing messages only */
- { RTF_CLONING, 'C' },
{ RTF_XRESOLVE, 'X' },
- { RTF_LLINFO, 'L' },
{ RTF_STATIC, 'S' },
{ RTF_PROTO1, '1' },
{ RTF_PROTO2, '2' },
- { RTF_WASCLONED,'W' },
{ RTF_PRCLONING,'c' },
{ RTF_PROTO3, '3' },
{ RTF_BLACKHOLE,'B' },
{ RTF_BROADCAST,'b' },
+#ifdef RTF_LLINFO
+ { RTF_LLINFO, 'L' },
+#endif
+#ifdef RTF_WASCLONED
+ { RTF_WASCLONED,'W' },
+#endif
+#ifdef RTF_CLONING
+ { RTF_CLONING, 'C' },
+#endif
{ 0 , 0 }
};
@@ -316,23 +322,12 @@ static void
size_cols_rtentry(struct rtentry *rt)
{
static struct ifnet ifnet, *lastif;
- struct rtentry parent;
static char buffer[100];
const char *bp;
struct sockaddr *sa;
sa_u addr, mask;
int len;
- /*
- * Don't print protocol-cloned routes unless -a.
- */
- if (rt->rt_flags & RTF_WASCLONED && !aflag) {
- if (kget(rt->rt_parent, parent) != 0)
- return;
- if (parent.rt_flags & RTF_PRCLONING)
- return;
- }
-
bzero(&addr, sizeof(addr));
if ((sa = kgetsa(rt_key(rt))))
bcopy(sa, &addr, sa->sa_len);
@@ -352,7 +347,7 @@ size_cols_rtentry(struct rtentry *rt)
wid_flags = MAX(len, wid_flags);
if (addr.u_sa.sa_family == AF_INET || Wflag) {
- len = snprintf(buffer, sizeof(buffer), "%ld", rt->rt_refcnt);
+ len = snprintf(buffer, sizeof(buffer), "%d", rt->rt_refcnt);
wid_refs = MAX(len, wid_refs);
len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_use);
wid_use = MAX(len, wid_use);
@@ -761,22 +756,11 @@ static void
p_rtentry(struct rtentry *rt)
{
static struct ifnet ifnet, *lastif;
- struct rtentry parent;
static char buffer[128];
static char prettyname[128];
struct sockaddr *sa;
sa_u addr, mask;
- /*
- * Don't print protocol-cloned routes unless -a.
- */
- if (rt->rt_flags & RTF_WASCLONED && !aflag) {
- if (kget(rt->rt_parent, parent) != 0)
- return;
- if (parent.rt_flags & RTF_PRCLONING)
- return;
- }
-
bzero(&addr, sizeof(addr));
if ((sa = kgetsa(rt_key(rt))))
bcopy(sa, &addr, sa->sa_len);
@@ -788,7 +772,7 @@ p_rtentry(struct rtentry *rt)
snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
p_flags(rt->rt_flags, buffer);
if (addr.u_sa.sa_family == AF_INET || Wflag) {
- printf("%*ld %*lu ", wid_refs, rt->rt_refcnt,
+ printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
wid_use, rt->rt_use);
if (Wflag) {
if (rt->rt_rmx.rmx_mtu != 0)
diff --git a/usr.bin/procstat/procstat.1 b/usr.bin/procstat/procstat.1
index 43761fd..a9b3200 100644
--- a/usr.bin/procstat/procstat.1
+++ b/usr.bin/procstat/procstat.1
@@ -203,7 +203,7 @@ Display kernel thread stacks for a process, allowing further interpretation
of thread wait channels.
If the
.Fl k
-flag is reeated, function offsets, not just function names, are printed.
+flag is repeated, function offsets, not just function names, are printed.
.Pp
This feature requires
.Cd "options STACK"
diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
index 1f620f3..74ec590 100644
--- a/usr.bin/procstat/procstat_files.c
+++ b/usr.bin/procstat/procstat_files.c
@@ -144,6 +144,8 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp)
"PRO", "NAME");
freep = kinfo_getfile(pid, &cnt);
+ if (freep == NULL)
+ return;
for (i = 0; i < cnt; i++) {
kif = &freep[i];
diff --git a/usr.bin/procstat/procstat_vm.c b/usr.bin/procstat/procstat_vm.c
index 79c0e57..1873c4f 100644
--- a/usr.bin/procstat/procstat_vm.c
+++ b/usr.bin/procstat/procstat_vm.c
@@ -54,6 +54,8 @@ procstat_vm(pid_t pid, struct kinfo_proc *kipp __unused)
"PRES", "REF", "SHD", "FL", "TP", "PATH");
freep = kinfo_getvmmap(pid, &cnt);
+ if (freep == NULL)
+ return;
for (i = 0; i < cnt; i++) {
kve = &freep[i];
printf("%5d ", pid);
diff --git a/usr.bin/tar/util.c b/usr.bin/tar/util.c
index 58518fb..9f3fc92 100644
--- a/usr.bin/tar/util.c
+++ b/usr.bin/tar/util.c
@@ -459,7 +459,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
#if HAVE_REGEX_H
r = apply_substitution(bsdtar, name, &subst_name, 0);
if (r == -1) {
- bsdtar_warnc(bsdtar, 0, "Invalid substituion, skipping entry");
+ bsdtar_warnc(bsdtar, 0, "Invalid substitution, skipping entry");
return 1;
}
if (r == 1) {
@@ -475,7 +475,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
if (archive_entry_hardlink(entry)) {
r = apply_substitution(bsdtar, archive_entry_hardlink(entry), &subst_name, 1);
if (r == -1) {
- bsdtar_warnc(bsdtar, 0, "Invalid substituion, skipping entry");
+ bsdtar_warnc(bsdtar, 0, "Invalid substitution, skipping entry");
return 1;
}
if (r == 1) {
@@ -486,7 +486,7 @@ edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
if (archive_entry_symlink(entry) != NULL) {
r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1);
if (r == -1) {
- bsdtar_warnc(bsdtar, 0, "Invalid substituion, skipping entry");
+ bsdtar_warnc(bsdtar, 0, "Invalid substitution, skipping entry");
return 1;
}
if (r == 1) {
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index b84f9e3..26da845 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -86,6 +86,7 @@ SUBDIR= ${_ac} \
${_lptcontrol} \
${_mailstats} \
mailwrapper \
+ makefs \
${_makemap} \
manctl \
memcontrol \
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c
index c8ef3e9..4154c3a1 100644
--- a/usr.sbin/arp/arp.c
+++ b/usr.sbin/arp/arp.c
@@ -370,7 +370,6 @@ set(int argc, char **argv)
if (addr->sin_addr.s_addr != dst->sin_addr.s_addr)
break;
if (sdl->sdl_family == AF_LINK &&
- (rtm->rtm_flags & RTF_LLINFO) &&
!(rtm->rtm_flags & RTF_GATEWAY) &&
valid_type(sdl->sdl_type) )
break;
@@ -426,25 +425,46 @@ delete(char *host, int do_proxy)
struct sockaddr_inarp *addr, *dst;
struct rt_msghdr *rtm;
struct sockaddr_dl *sdl;
+ struct sockaddr_dl sdl_m;
dst = getaddr(host);
if (dst == NULL)
return (1);
dst->sin_other = do_proxy;
+
+ /*
+ * setup the data structure to notify the kernel
+ * it is the ARP entry the RTM_GET is interested
+ * in
+ */
+ bzero(&sdl_m, sizeof(sdl_m));
+ sdl_m.sdl_len = sizeof(sdl_m);
+ sdl_m.sdl_family = AF_LINK;
+
for (;;) { /* try twice */
- rtm = rtmsg(RTM_GET, dst, NULL);
+ rtm = rtmsg(RTM_GET, dst, &sdl_m);
if (rtm == NULL) {
warn("%s", host);
return (1);
}
addr = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr);
- if (addr->sin_addr.s_addr == dst->sin_addr.s_addr &&
- sdl->sdl_family == AF_LINK &&
- (rtm->rtm_flags & RTF_LLINFO) &&
+
+ /*
+ * With the new L2/L3 restructure, the route
+ * returned is a prefix route. The important
+ * piece of information from the previous
+ * RTM_GET is the interface index. In the
+ * case of ECMP, the kernel will traverse
+ * the route group for the given entry.
+ */
+ if (sdl->sdl_family == AF_LINK &&
!(rtm->rtm_flags & RTF_GATEWAY) &&
- valid_type(sdl->sdl_type) )
- break; /* found it */
+ valid_type(sdl->sdl_type) ) {
+ addr->sin_addr.s_addr = dst->sin_addr.s_addr;
+ break;
+ }
+
if (dst->sin_other & SIN_PROXY) {
fprintf(stderr, "delete: cannot locate %s\n",host);
return (1);
@@ -478,7 +498,11 @@ search(u_long addr, action_fn *action)
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
+#ifdef RTF_LLINFO
mib[5] = RTF_LLINFO;
+#else
+ mib[5] = 0;
+#endif
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if (needed == 0) /* empty table */
@@ -563,15 +587,9 @@ print_entry(struct sockaddr_dl *sdl,
printf(" permanent");
if (addr->sin_other & SIN_PROXY)
printf(" published (proxy only)");
- if (rtm->rtm_addrs & RTA_NETMASK) {
- addr = (struct sockaddr_inarp *)
- (SA_SIZE(sdl) + (char *)sdl);
- if (addr->sin_addr.s_addr == 0xffffffff)
- printf(" published");
- if (addr->sin_len != 8)
- printf("(weird)");
- }
- switch(sdl->sdl_type) {
+ if (rtm->rtm_flags & RTF_ANNOUNCE)
+ printf(" published");
+ switch(sdl->sdl_type) {
case IFT_ETHER:
printf(" [ethernet]");
break;
diff --git a/usr.sbin/burncd/Makefile b/usr.sbin/burncd/Makefile
index 6f03273..bd4f285 100644
--- a/usr.sbin/burncd/Makefile
+++ b/usr.sbin/burncd/Makefile
@@ -3,6 +3,6 @@
PROG= burncd
MAN= burncd.8
-WARNS?= 5
+WARNS?= 6
.include <bsd.prog.mk>
diff --git a/usr.sbin/burncd/burncd.c b/usr.sbin/burncd/burncd.c
index 2800f52..5be73e0f 100644
--- a/usr.sbin/burncd/burncd.c
+++ b/usr.sbin/burncd/burncd.c
@@ -29,6 +29,7 @@
*/
#include <unistd.h>
+#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -67,6 +68,8 @@ int write_file(int fd, struct track_info *);
int roundup_blocks(struct track_info *);
void cue_ent(struct cdr_cue_entry *, int, int, int, int, int, int, int);
void cleanup(int);
+void cleanup_flush(void);
+void cleanup_signal(int);
void usage(void);
int
@@ -157,6 +160,9 @@ main(int argc, char **argv)
global_fd_for_cleanup = fd;
err_set_exit(cleanup);
+ signal(SIGHUP, cleanup_signal);
+ signal(SIGINT, cleanup_signal);
+ signal(SIGTERM, cleanup_signal);
for (arg = 0; arg < argc; arg++) {
if (!strcasecmp(argv[arg], "fixate")) {
@@ -319,6 +325,10 @@ main(int argc, char **argv)
if (eject)
if (ioctl(fd, CDIOCEJECT) < 0)
err(EX_IOERR, "ioctl(CDIOCEJECT)");
+
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
close(fd);
exit(EX_OK);
}
@@ -469,8 +479,10 @@ do_DAO(int fd, int test_write, int multi)
err(EX_IOERR, "ioctl(CDRIOCSENDCUE)");
for (i = 0; i < notracks; i++) {
- if (write_file(fd, &tracks[i]))
+ if (write_file(fd, &tracks[i])) {
+ cleanup_flush();
err(EX_IOERR, "write_file");
+ }
}
ioctl(fd, CDRIOCFLUSH);
@@ -499,8 +511,10 @@ do_TAO(int fd, int test_write, int preemp, int dvdrw)
if (!quiet)
fprintf(stderr, "next writeable LBA %d\n",
tracks[i].addr);
- if (write_file(fd, &tracks[i]))
+ if (write_file(fd, &tracks[i])) {
+ cleanup_flush();
err(EX_IOERR, "write_file");
+ }
if (ioctl(fd, CDRIOCFLUSH) < 0)
err(EX_IOERR, "ioctl(CDRIOCFLUSH)");
}
@@ -630,9 +644,11 @@ write_file(int fd, struct track_info *track_info)
track_info->block_size;
}
if ((res = write(fd, buf, count)) != count) {
- if (res == -1)
- fprintf(stderr, "\n%s\n", strerror(errno));
- else
+ if (res == -1) {
+ fprintf(stderr, "\n");
+ close(track_info->file);
+ return errno;
+ } else
fprintf(stderr, "\nonly wrote %d of %jd"
" bytes\n", res, (intmax_t)count);
break;
@@ -693,6 +709,21 @@ cleanup(int dummy __unused)
}
void
+cleanup_flush(void)
+{
+ if (ioctl(global_fd_for_cleanup, CDRIOCFLUSH) < 0)
+ err(EX_IOERR, "ioctl(CDRIOCFLUSH)");
+}
+
+void
+cleanup_signal(int sig __unused)
+{
+ cleanup_flush();
+ fprintf(stderr, "\n");
+ errx(EXIT_FAILURE, "Aborted");
+}
+
+void
usage(void)
{
fprintf(stderr,
diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c
index 5853abc..95f17d4 100644
--- a/usr.sbin/jls/jls.c
+++ b/usr.sbin/jls/jls.c
@@ -48,7 +48,7 @@
#ifdef SUPPORT_OLD_XPRISON
static
-char *print_xprison_v1(void *p, char *end)
+char *print_xprison_v1(void *p, char *end, unsigned flags)
{
struct xprison_v1 *xp;
struct in_addr in;
@@ -57,15 +57,18 @@ char *print_xprison_v1(void *p, char *end)
errx(1, "Invalid length for jail");
xp = (struct xprison_v1 *)p;
- printf("%6d %-29.29s %.74s\n",
- xp->pr_id, xp->pr_host, xp->pr_path);
-
- /* We are not printing an empty line here for state and name. */
- /* We are not printing an empty line here for cpusetid. */
-
- /* IPv4 address. */
- in.s_addr = htonl(xp->pr_ip);
- printf("%6s %-15.15s\n", "", inet_ntoa(in));
+ if (flags & FLAG_V) {
+ printf("%6d %-29.29s %.74s\n",
+ xp->pr_id, xp->pr_host, xp->pr_path);
+ /* We are not printing an empty line here for state and name. */
+ /* We are not printing an empty line here for cpusetid. */
+ /* IPv4 address. */
+ in.s_addr = htonl(xp->pr_ip);
+ printf("%6s %-15.15s\n", "", inet_ntoa(in));
+ } else {
+ printf("%6d %-15.15s %-29.29s %.74s\n",
+ xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path);
+ }
return ((char *)(xp + 1));
}
@@ -104,8 +107,9 @@ char *print_xprison_v3(void *p, char *end, unsigned flags)
return (q);
}
- printf("%6d %-29.29s %.74s\n",
- xp->pr_id, xp->pr_host, xp->pr_path);
+ if (flags & FLAG_V)
+ printf("%6d %-29.29s %.74s\n",
+ xp->pr_id, xp->pr_host, xp->pr_path);
/* Jail state and name. */
if (flags & FLAG_V)
@@ -123,11 +127,12 @@ char *print_xprison_v3(void *p, char *end, unsigned flags)
q += (xp->pr_ip4s * sizeof(struct in_addr));
if (q > end)
errx(1, "Invalid length for jail");
+ in.s_addr = 0;
for (i = 0; i < xp->pr_ip4s; i++) {
- if (i == 0 || flags & FLAG_V) {
+ if (i == 0 || flags & FLAG_V)
in.s_addr = iap[i].s_addr;
+ if (flags & FLAG_V)
printf("%6s %-15.15s\n", "", inet_ntoa(in));
- }
}
/* IPv6 addresses. */
ia6p = (struct in6_addr *)(void *)q;
@@ -141,6 +146,12 @@ char *print_xprison_v3(void *p, char *end, unsigned flags)
}
}
+ /* If requested print the old style single line version. */
+ if (!(flags & FLAG_V))
+ printf("%6d %-15.15s %-29.29s %.74s\n",
+ xp->pr_id, (in.s_addr) ? inet_ntoa(in) : "",
+ xp->pr_host, xp->pr_path);
+
return (q);
}
@@ -206,12 +217,15 @@ main(int argc, char *argv[])
if (version > XPRISON_VERSION)
errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
- printf(" JID Hostname Path\n");
if (flags & FLAG_V) {
+ printf(" JID Hostname Path\n");
printf(" Name State\n");
printf(" CPUSetID\n");
+ printf(" IP Address(es)\n");
+ } else {
+ printf(" JID IP Address Hostname"
+ " Path\n");
}
- printf(" IP Address(es)\n");
for (; q != NULL && (char *)q + sizeof(int) < (char *)p + len;) {
version = *(int *)q;
if (version > XPRISON_VERSION)
@@ -219,7 +233,7 @@ main(int argc, char *argv[])
switch (version) {
#ifdef SUPPORT_OLD_XPRISON
case 1:
- q = print_xprison_v1(q, (char *)p + len);
+ q = print_xprison_v1(q, (char *)p + len, flags);
break;
case 2:
errx(1, "Version 2 was used by multi-IPv4 jail "
diff --git a/usr.sbin/makefs/Makefile b/usr.sbin/makefs/Makefile
new file mode 100644
index 0000000..0356029
--- /dev/null
+++ b/usr.sbin/makefs/Makefile
@@ -0,0 +1,28 @@
+# $FreeBSD$
+
+PROG= makefs
+MAN= makefs.8
+
+WARNS?= 2
+
+CFLAGS+=-I${.CURDIR}
+SRCS= ffs.c getid.c makefs.c walk.c
+
+.PATH: ${.CURDIR}/ffs
+CFLAGS+=-I${.CURDIR}/ffs
+CFLAGS+=-DHAVE_STRUCT_STAT_ST_FLAGS=1
+CFLAGS+=-DHAVE_STRUCT_STAT_ST_GEN=1
+SRCS+= buf.c ffs_alloc.c ffs_balloc.c ffs_bswap.c ffs_subr.c mkfs.c ufs_bmap.c
+
+.PATH: ${.CURDIR}/compat
+CFLAGS+=-I${.CURDIR}/compat
+SRCS+= pwcache.c strsuftoll.c
+
+.PATH: ${.CURDIR}/../mtree
+CFLAGS+=-I${.CURDIR}/../mtree
+SRCS+= misc.c spec.c
+
+.PATH: ${.CURDIR}/../../sys/ufs/ffs
+SRCS+= ffs_tables.c
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/makefs/compat/pwcache.c b/usr.sbin/makefs/compat/pwcache.c
new file mode 100644
index 0000000..0579d26
--- /dev/null
+++ b/usr.sbin/makefs/compat/pwcache.c
@@ -0,0 +1,623 @@
+/* $NetBSD: pwcache.c,v 1.29 2004/06/20 22:20:14 jmc Exp $ */
+
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * 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. 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.
+ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <assert.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __weak_alias
+__weak_alias(user_from_uid,_user_from_uid)
+__weak_alias(group_from_gid,_group_from_gid)
+__weak_alias(pwcache_userdb,_pwcache_userdb)
+__weak_alias(pwcache_groupdb,_pwcache_groupdb)
+#endif
+
+#include "pwcache.h"
+
+/*
+ * routines that control user, group, uid and gid caches (for the archive
+ * member print routine).
+ * IMPORTANT:
+ * these routines cache BOTH hits and misses, a major performance improvement
+ */
+
+/*
+ * function pointers to various name lookup routines.
+ * these may be changed as necessary.
+ */
+static int (*_pwcache_setgroupent)(int) = setgroupent;
+static void (*_pwcache_endgrent)(void) = endgrent;
+static struct group * (*_pwcache_getgrnam)(const char *) = getgrnam;
+static struct group * (*_pwcache_getgrgid)(gid_t) = getgrgid;
+static int (*_pwcache_setpassent)(int) = setpassent;
+static void (*_pwcache_endpwent)(void) = endpwent;
+static struct passwd * (*_pwcache_getpwnam)(const char *) = getpwnam;
+static struct passwd * (*_pwcache_getpwuid)(uid_t) = getpwuid;
+
+/*
+ * internal state
+ */
+static int pwopn; /* is password file open */
+static int gropn; /* is group file open */
+static UIDC **uidtb; /* uid to name cache */
+static GIDC **gidtb; /* gid to name cache */
+static UIDC **usrtb; /* user name to uid cache */
+static GIDC **grptb; /* group name to gid cache */
+
+static int uidtb_fail; /* uidtb_start() failed ? */
+static int gidtb_fail; /* gidtb_start() failed ? */
+static int usrtb_fail; /* usrtb_start() failed ? */
+static int grptb_fail; /* grptb_start() failed ? */
+
+
+static u_int st_hash(const char *, size_t, int);
+static int uidtb_start(void);
+static int gidtb_start(void);
+static int usrtb_start(void);
+static int grptb_start(void);
+
+
+static u_int
+st_hash(const char *name, size_t len, int tabsz)
+{
+ u_int key = 0;
+
+ while (len--) {
+ key += *name++;
+ key = (key << 8) | (key >> 24);
+ }
+
+ return (key % tabsz);
+}
+
+/*
+ * uidtb_start
+ * creates an an empty uidtb
+ * Return:
+ * 0 if ok, -1 otherwise
+ */
+static int
+uidtb_start(void)
+{
+
+ if (uidtb != NULL)
+ return (0);
+ if (uidtb_fail)
+ return (-1);
+ if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
+ ++uidtb_fail;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * gidtb_start
+ * creates an an empty gidtb
+ * Return:
+ * 0 if ok, -1 otherwise
+ */
+static int
+gidtb_start(void)
+{
+
+ if (gidtb != NULL)
+ return (0);
+ if (gidtb_fail)
+ return (-1);
+ if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
+ ++gidtb_fail;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * usrtb_start
+ * creates an an empty usrtb
+ * Return:
+ * 0 if ok, -1 otherwise
+ */
+static int
+usrtb_start(void)
+{
+
+ if (usrtb != NULL)
+ return (0);
+ if (usrtb_fail)
+ return (-1);
+ if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
+ ++usrtb_fail;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * grptb_start
+ * creates an an empty grptb
+ * Return:
+ * 0 if ok, -1 otherwise
+ */
+static int
+grptb_start(void)
+{
+
+ if (grptb != NULL)
+ return (0);
+ if (grptb_fail)
+ return (-1);
+ if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
+ ++grptb_fail;
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * user_from_uid()
+ * caches the name (if any) for the uid. If noname clear, we always
+ * return the stored name (if valid or invalid match).
+ * We use a simple hash table.
+ * Return
+ * Pointer to stored name (or a empty string)
+ */
+const char *
+user_from_uid(uid_t uid, int noname)
+{
+ struct passwd *pw;
+ UIDC *ptr, **pptr;
+
+ if ((uidtb == NULL) && (uidtb_start() < 0))
+ return (NULL);
+
+ /*
+ * see if we have this uid cached
+ */
+ pptr = uidtb + (uid % UID_SZ);
+ ptr = *pptr;
+
+ if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
+ /*
+ * have an entry for this uid
+ */
+ if (!noname || (ptr->valid == VALID))
+ return (ptr->name);
+ return (NULL);
+ }
+
+ /*
+ * No entry for this uid, we will add it
+ */
+ if (!pwopn) {
+ if (_pwcache_setpassent != NULL)
+ (*_pwcache_setpassent)(1);
+ ++pwopn;
+ }
+
+ if (ptr == NULL)
+ *pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
+
+ if ((pw = (*_pwcache_getpwuid)(uid)) == NULL) {
+ /*
+ * no match for this uid in the local password file
+ * a string that is the uid in numeric format
+ */
+ if (ptr == NULL)
+ return (NULL);
+ ptr->uid = uid;
+ (void)snprintf(ptr->name, UNMLEN, "%lu", (long) uid);
+ ptr->valid = INVALID;
+ if (noname)
+ return (NULL);
+ } else {
+ /*
+ * there is an entry for this uid in the password file
+ */
+ if (ptr == NULL)
+ return (pw->pw_name);
+ ptr->uid = uid;
+ (void)strlcpy(ptr->name, pw->pw_name, UNMLEN);
+ ptr->valid = VALID;
+ }
+ return (ptr->name);
+}
+
+/*
+ * group_from_gid()
+ * caches the name (if any) for the gid. If noname clear, we always
+ * return the stored name (if valid or invalid match).
+ * We use a simple hash table.
+ * Return
+ * Pointer to stored name (or a empty string)
+ */
+const char *
+group_from_gid(gid_t gid, int noname)
+{
+ struct group *gr;
+ GIDC *ptr, **pptr;
+
+ if ((gidtb == NULL) && (gidtb_start() < 0))
+ return (NULL);
+
+ /*
+ * see if we have this gid cached
+ */
+ pptr = gidtb + (gid % GID_SZ);
+ ptr = *pptr;
+
+ if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
+ /*
+ * have an entry for this gid
+ */
+ if (!noname || (ptr->valid == VALID))
+ return (ptr->name);
+ return (NULL);
+ }
+
+ /*
+ * No entry for this gid, we will add it
+ */
+ if (!gropn) {
+ if (_pwcache_setgroupent != NULL)
+ (*_pwcache_setgroupent)(1);
+ ++gropn;
+ }
+
+ if (ptr == NULL)
+ *pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
+
+ if ((gr = (*_pwcache_getgrgid)(gid)) == NULL) {
+ /*
+ * no match for this gid in the local group file, put in
+ * a string that is the gid in numberic format
+ */
+ if (ptr == NULL)
+ return (NULL);
+ ptr->gid = gid;
+ (void)snprintf(ptr->name, GNMLEN, "%lu", (long) gid);
+ ptr->valid = INVALID;
+ if (noname)
+ return (NULL);
+ } else {
+ /*
+ * there is an entry for this group in the group file
+ */
+ if (ptr == NULL)
+ return (gr->gr_name);
+ ptr->gid = gid;
+ (void)strlcpy(ptr->name, gr->gr_name, GNMLEN);
+ ptr->valid = VALID;
+ }
+ return (ptr->name);
+}
+
+/*
+ * uid_from_user()
+ * caches the uid for a given user name. We use a simple hash table.
+ * Return
+ * the uid (if any) for a user name, or a -1 if no match can be found
+ */
+int
+uid_from_user(const char *name, uid_t *uid)
+{
+ struct passwd *pw;
+ UIDC *ptr, **pptr;
+ size_t namelen;
+
+ /*
+ * return -1 for mangled names
+ */
+ if (name == NULL || ((namelen = strlen(name)) == 0))
+ return (-1);
+ if ((usrtb == NULL) && (usrtb_start() < 0))
+ return (-1);
+
+ /*
+ * look up in hash table, if found and valid return the uid,
+ * if found and invalid, return a -1
+ */
+ pptr = usrtb + st_hash(name, namelen, UNM_SZ);
+ ptr = *pptr;
+
+ if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
+ if (ptr->valid == INVALID)
+ return (-1);
+ *uid = ptr->uid;
+ return (0);
+ }
+
+ if (!pwopn) {
+ if (_pwcache_setpassent != NULL)
+ (*_pwcache_setpassent)(1);
+ ++pwopn;
+ }
+
+ if (ptr == NULL)
+ *pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
+
+ /*
+ * no match, look it up, if no match store it as an invalid entry,
+ * or store the matching uid
+ */
+ if (ptr == NULL) {
+ if ((pw = (*_pwcache_getpwnam)(name)) == NULL)
+ return (-1);
+ *uid = pw->pw_uid;
+ return (0);
+ }
+ (void)strlcpy(ptr->name, name, UNMLEN);
+ if ((pw = (*_pwcache_getpwnam)(name)) == NULL) {
+ ptr->valid = INVALID;
+ return (-1);
+ }
+ ptr->valid = VALID;
+ *uid = ptr->uid = pw->pw_uid;
+ return (0);
+}
+
+/*
+ * gid_from_group()
+ * caches the gid for a given group name. We use a simple hash table.
+ * Return
+ * the gid (if any) for a group name, or a -1 if no match can be found
+ */
+int
+gid_from_group(const char *name, gid_t *gid)
+{
+ struct group *gr;
+ GIDC *ptr, **pptr;
+ size_t namelen;
+
+ /*
+ * return -1 for mangled names
+ */
+ if (name == NULL || ((namelen = strlen(name)) == 0))
+ return (-1);
+ if ((grptb == NULL) && (grptb_start() < 0))
+ return (-1);
+
+ /*
+ * look up in hash table, if found and valid return the uid,
+ * if found and invalid, return a -1
+ */
+ pptr = grptb + st_hash(name, namelen, GID_SZ);
+ ptr = *pptr;
+
+ if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
+ if (ptr->valid == INVALID)
+ return (-1);
+ *gid = ptr->gid;
+ return (0);
+ }
+
+ if (!gropn) {
+ if (_pwcache_setgroupent != NULL)
+ (*_pwcache_setgroupent)(1);
+ ++gropn;
+ }
+
+ if (ptr == NULL)
+ *pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
+
+ /*
+ * no match, look it up, if no match store it as an invalid entry,
+ * or store the matching gid
+ */
+ if (ptr == NULL) {
+ if ((gr = (*_pwcache_getgrnam)(name)) == NULL)
+ return (-1);
+ *gid = gr->gr_gid;
+ return (0);
+ }
+
+ (void)strlcpy(ptr->name, name, GNMLEN);
+ if ((gr = (*_pwcache_getgrnam)(name)) == NULL) {
+ ptr->valid = INVALID;
+ return (-1);
+ }
+ ptr->valid = VALID;
+ *gid = ptr->gid = gr->gr_gid;
+ return (0);
+}
+
+#define FLUSHTB(arr, len, fail) \
+ do { \
+ if (arr != NULL) { \
+ for (i = 0; i < len; i++) \
+ if (arr[i] != NULL) \
+ free(arr[i]); \
+ arr = NULL; \
+ } \
+ fail = 0; \
+ } while (/* CONSTCOND */0);
+
+int
+pwcache_userdb(
+ int (*a_setpassent)(int),
+ void (*a_endpwent)(void),
+ struct passwd * (*a_getpwnam)(const char *),
+ struct passwd * (*a_getpwuid)(uid_t))
+{
+ int i;
+
+ /* a_setpassent and a_endpwent may be NULL */
+ if (a_getpwnam == NULL || a_getpwuid == NULL)
+ return (-1);
+
+ if (_pwcache_endpwent != NULL)
+ (*_pwcache_endpwent)();
+ FLUSHTB(uidtb, UID_SZ, uidtb_fail);
+ FLUSHTB(usrtb, UNM_SZ, usrtb_fail);
+ pwopn = 0;
+ _pwcache_setpassent = a_setpassent;
+ _pwcache_endpwent = a_endpwent;
+ _pwcache_getpwnam = a_getpwnam;
+ _pwcache_getpwuid = a_getpwuid;
+
+ return (0);
+}
+
+int
+pwcache_groupdb(
+ int (*a_setgroupent)(int),
+ void (*a_endgrent)(void),
+ struct group * (*a_getgrnam)(const char *),
+ struct group * (*a_getgrgid)(gid_t))
+{
+ int i;
+
+ /* a_setgroupent and a_endgrent may be NULL */
+ if (a_getgrnam == NULL || a_getgrgid == NULL)
+ return (-1);
+
+ if (_pwcache_endgrent != NULL)
+ (*_pwcache_endgrent)();
+ FLUSHTB(gidtb, GID_SZ, gidtb_fail);
+ FLUSHTB(grptb, GNM_SZ, grptb_fail);
+ gropn = 0;
+ _pwcache_setgroupent = a_setgroupent;
+ _pwcache_endgrent = a_endgrent;
+ _pwcache_getgrnam = a_getgrnam;
+ _pwcache_getgrgid = a_getgrgid;
+
+ return (0);
+}
+
+
+#ifdef TEST_PWCACHE
+
+struct passwd *
+test_getpwnam(const char *name)
+{
+ static struct passwd foo;
+
+ memset(&foo, 0, sizeof(foo));
+ if (strcmp(name, "toor") == 0) {
+ foo.pw_uid = 666;
+ return &foo;
+ }
+ return (getpwnam(name));
+}
+
+int
+main(int argc, char *argv[])
+{
+ uid_t u;
+ int r, i;
+
+ printf("pass 1 (default userdb)\n");
+ for (i = 1; i < argc; i++) {
+ printf("i: %d, pwopn %d usrtb_fail %d usrtb %p\n",
+ i, pwopn, usrtb_fail, usrtb);
+ r = uid_from_user(argv[i], &u);
+ if (r == -1)
+ printf(" uid_from_user %s: failed\n", argv[i]);
+ else
+ printf(" uid_from_user %s: %d\n", argv[i], u);
+ }
+ printf("pass 1 finish: pwopn %d usrtb_fail %d usrtb %p\n",
+ pwopn, usrtb_fail, usrtb);
+
+ puts("");
+ printf("pass 2 (replacement userdb)\n");
+ printf("pwcache_userdb returned %d\n",
+ pwcache_userdb(setpassent, test_getpwnam, getpwuid));
+ printf("pwopn %d usrtb_fail %d usrtb %p\n", pwopn, usrtb_fail, usrtb);
+
+ for (i = 1; i < argc; i++) {
+ printf("i: %d, pwopn %d usrtb_fail %d usrtb %p\n",
+ i, pwopn, usrtb_fail, usrtb);
+ u = -1;
+ r = uid_from_user(argv[i], &u);
+ if (r == -1)
+ printf(" uid_from_user %s: failed\n", argv[i]);
+ else
+ printf(" uid_from_user %s: %d\n", argv[i], u);
+ }
+ printf("pass 2 finish: pwopn %d usrtb_fail %d usrtb %p\n",
+ pwopn, usrtb_fail, usrtb);
+
+ puts("");
+ printf("pass 3 (null pointers)\n");
+ printf("pwcache_userdb returned %d\n",
+ pwcache_userdb(NULL, NULL, NULL));
+
+ return (0);
+}
+#endif /* TEST_PWCACHE */
diff --git a/usr.sbin/makefs/compat/pwcache.h b/usr.sbin/makefs/compat/pwcache.h
new file mode 100644
index 0000000..1708951
--- /dev/null
+++ b/usr.sbin/makefs/compat/pwcache.h
@@ -0,0 +1,73 @@
+/* $NetBSD: pwcache.h,v 1.5 2003/11/10 08:51:51 wiz Exp $ */
+
+/*-
+ * Copyright (c) 1992 Keith Muller.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego.
+ *
+ * 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. 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.
+ *
+ * @(#)cache.h 8.1 (Berkeley) 5/31/93
+ * $FreeBSD$
+ */
+
+/*
+ * Constants and data structures used to implement group and password file
+ * caches. Traditional passwd/group cache routines perform quite poorly with
+ * archives. The chances of hitting a valid lookup with an archive is quite a
+ * bit worse than with files already resident on the file system. These misses
+ * create a MAJOR performance cost. To address this problem, these routines
+ * cache both hits and misses.
+ *
+ * NOTE: name lengths must be as large as those stored in ANY PROTOCOL and
+ * as stored in the passwd and group files. CACHE SIZES MUST BE PRIME
+ */
+#define UNMLEN 32 /* >= user name found in any protocol */
+#define GNMLEN 32 /* >= group name found in any protocol */
+#define UID_SZ 317 /* size of uid to user_name cache */
+#define UNM_SZ 317 /* size of user_name to uid cache */
+#define GID_SZ 251 /* size of gid to group_name cache */
+#define GNM_SZ 251 /* size of group_name to gid cache */
+#define VALID 1 /* entry and name are valid */
+#define INVALID 2 /* entry valid, name NOT valid */
+
+/*
+ * Node structures used in the user, group, uid, and gid caches.
+ */
+
+typedef struct uidc {
+ int valid; /* is this a valid or a miss entry */
+ char name[UNMLEN]; /* uid name */
+ uid_t uid; /* cached uid */
+} UIDC;
+
+typedef struct gidc {
+ int valid; /* is this a valid or a miss entry */
+ char name[GNMLEN]; /* gid name */
+ gid_t gid; /* cached gid */
+} GIDC;
diff --git a/usr.sbin/makefs/compat/strsuftoll.c b/usr.sbin/makefs/compat/strsuftoll.c
new file mode 100644
index 0000000..f73e3ad
--- /dev/null
+++ b/usr.sbin/makefs/compat/strsuftoll.c
@@ -0,0 +1,229 @@
+/* $NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $ */
+/*-
+ * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Keith Muller of the University of California, San Diego and Lance
+ * Visser of Convex Computer Corporation.
+ *
+ * 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. 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _LIBC
+# ifdef __weak_alias
+__weak_alias(strsuftoll, _strsuftoll)
+__weak_alias(strsuftollx, _strsuftollx)
+# endif
+#endif /* LIBC */
+
+/*
+ * Convert an expression of the following forms to a (u)int64_t.
+ * 1) A positive decimal number.
+ * 2) A positive decimal number followed by a b (mult by 512).
+ * 3) A positive decimal number followed by a k (mult by 1024).
+ * 4) A positive decimal number followed by a m (mult by 1048576).
+ * 5) A positive decimal number followed by a g (mult by 1073741824).
+ * 6) A positive decimal number followed by a t (mult by 1099511627776).
+ * 7) A positive decimal number followed by a w (mult by sizeof int)
+ * 8) Two or more positive decimal numbers (with/without k,b or w).
+ * separated by x (also * for backwards compatibility), specifying
+ * the product of the indicated values.
+ * Returns the result upon successful conversion, or exits with an
+ * appropriate error.
+ *
+ */
+
+/*
+ * As strsuftoll(), but returns the error message into the provided buffer
+ * rather than exiting with it.
+ */
+/* LONGLONG */
+long long
+strsuftollx(const char *desc, const char *val,
+ long long min, long long max, char *ebuf, size_t ebuflen)
+{
+ long long num, t;
+ char *expr;
+
+ errno = 0;
+ ebuf[0] = '\0';
+
+ while (isspace((unsigned char)*val)) /* Skip leading space */
+ val++;
+
+ num = strtoll(val, &expr, 10);
+ if (errno == ERANGE)
+ goto erange; /* Overflow */
+
+ if (expr == val) /* No digits */
+ goto badnum;
+
+ switch (*expr) {
+ case 'b':
+ t = num;
+ num *= 512; /* 1 block */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'k':
+ t = num;
+ num *= 1024; /* 1 kilobyte */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'm':
+ t = num;
+ num *= 1048576; /* 1 megabyte */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'g':
+ t = num;
+ num *= 1073741824; /* 1 gigabyte */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 't':
+ t = num;
+ num *= 1099511627776LL; /* 1 terabyte */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ case 'w':
+ t = num;
+ num *= sizeof(int); /* 1 word */
+ if (t > num)
+ goto erange;
+ ++expr;
+ break;
+ }
+
+ switch (*expr) {
+ case '\0':
+ break;
+ case '*': /* Backward compatible */
+ case 'x':
+ t = num;
+ num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen);
+ if (*ebuf != '\0')
+ return (0);
+ if (t > num) {
+ erange:
+ snprintf(ebuf, ebuflen,
+ "%s: %s", desc, strerror(ERANGE));
+ return (0);
+ }
+ break;
+ default:
+ badnum: snprintf(ebuf, ebuflen,
+ "%s `%s': illegal number", desc, val);
+ return (0);
+ }
+ if (num < min) {
+ /* LONGLONG */
+ snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
+ desc, (long long)num, (long long)min);
+ return (0);
+ }
+ if (num > max) {
+ /* LONGLONG */
+ snprintf(ebuf, ebuflen,
+ "%s %lld is greater than %lld.",
+ desc, (long long)num, (long long)max);
+ return (0);
+ }
+ *ebuf = '\0';
+ return (num);
+}
+
+/* LONGLONG */
+long long
+strsuftoll(const char *desc, const char *val,
+ long long min, long long max)
+{
+ long long result;
+ char errbuf[100];
+
+ result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
+ if (*errbuf != '\0')
+ errx(1, "%s", errbuf);
+ return (result);
+}
diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c
new file mode 100644
index 0000000..ece8c65
--- /dev/null
+++ b/usr.sbin/makefs/ffs.c
@@ -0,0 +1,1093 @@
+/* $NetBSD: ffs.c,v 1.30 2004/06/24 22:30:13 lukem Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Luke Mewburn for Wasabi Systems, 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+/*
+ * Copyright (c) 1982, 1986, 1989, 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. 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.
+ *
+ * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <sys/mount.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "makefs.h"
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ufs/dir.h>
+#include <ufs/ffs/fs.h>
+
+#include "ffs/ufs_bswap.h"
+#include "ffs/ufs_inode.h"
+#include "ffs/newfs_extern.h"
+#include "ffs/ffs_extern.h"
+
+#undef DIP
+#define DIP(dp, field) \
+ ((fsopts->version == 1) ? \
+ (dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field)
+
+/*
+ * Various file system defaults (cribbed from newfs(8)).
+ */
+#define DFL_FRAGSIZE 1024 /* fragment size */
+#define DFL_BLKSIZE 8192 /* block size */
+#define DFL_SECSIZE 512 /* sector size */
+#define DFL_CYLSPERGROUP 65536 /* cylinders per group */
+#define DFL_FRAGSPERINODE 4 /* fragments per inode */
+#define DFL_ROTDELAY 0 /* rotational delay */
+#define DFL_NRPOS 1 /* rotational positions */
+#define DFL_RPM 3600 /* rpm of disk */
+#define DFL_NSECTORS 64 /* # of sectors */
+#define DFL_NTRACKS 16 /* # of tracks */
+
+
+typedef struct {
+ u_char *buf; /* buf for directory */
+ doff_t size; /* full size of buf */
+ doff_t cur; /* offset of current entry */
+} dirbuf_t;
+
+
+static int ffs_create_image(const char *, fsinfo_t *);
+static void ffs_dump_fsinfo(fsinfo_t *);
+static void ffs_dump_dirbuf(dirbuf_t *, const char *, int);
+static void ffs_make_dirbuf(dirbuf_t *, const char *, fsnode *, int);
+static int ffs_populate_dir(const char *, fsnode *, fsinfo_t *);
+static void ffs_size_dir(fsnode *, fsinfo_t *);
+static void ffs_validate(const char *, fsnode *, fsinfo_t *);
+static void ffs_write_file(union dinode *, uint32_t, void *, fsinfo_t *);
+static void ffs_write_inode(union dinode *, uint32_t, const fsinfo_t *);
+static void *ffs_build_dinode1(struct ufs1_dinode *, dirbuf_t *, fsnode *,
+ fsnode *, fsinfo_t *);
+static void *ffs_build_dinode2(struct ufs2_dinode *, dirbuf_t *, fsnode *,
+ fsnode *, fsinfo_t *);
+
+
+
+int sectorsize; /* XXX: for buf.c::getblk() */
+
+ /* publically visible functions */
+
+int
+ffs_parse_opts(const char *option, fsinfo_t *fsopts)
+{
+ option_t ffs_options[] = {
+ { "bsize", &fsopts->bsize, 1, INT_MAX,
+ "block size" },
+ { "fsize", &fsopts->fsize, 1, INT_MAX,
+ "fragment size" },
+ { "density", &fsopts->density, 1, INT_MAX,
+ "bytes per inode" },
+ { "minfree", &fsopts->minfree, 0, 99,
+ "minfree" },
+ { "maxbpf", &fsopts->maxbpg, 1, INT_MAX,
+ "max blocks per file in a cg" },
+ { "avgfilesize", &fsopts->avgfilesize, 1, INT_MAX,
+ "expected average file size" },
+ { "avgfpdir", &fsopts->avgfpdir, 1, INT_MAX,
+ "expected # of files per directory" },
+ { "extent", &fsopts->maxbsize, 1, INT_MAX,
+ "maximum # extent size" },
+ { "maxbpcg", &fsopts->maxblkspercg, 1, INT_MAX,
+ "max # of blocks per group" },
+ { "version", &fsopts->version, 1, 2,
+ "UFS version" },
+ { NULL }
+ };
+
+ char *var, *val;
+ int rv;
+
+ (void)&ffs_options;
+ assert(option != NULL);
+ assert(fsopts != NULL);
+
+ if (debug & DEBUG_FS_PARSE_OPTS)
+ printf("ffs_parse_opts: got `%s'\n", option);
+
+ if ((var = strdup(option)) == NULL)
+ err(1, "Allocating memory for copy of option string");
+ rv = 0;
+
+ if ((val = strchr(var, '=')) == NULL) {
+ warnx("Option `%s' doesn't contain a value", var);
+ goto leave_ffs_parse_opts;
+ }
+ *val++ = '\0';
+
+ if (strcmp(var, "optimization") == 0) {
+ if (strcmp(val, "time") == 0) {
+ fsopts->optimization = FS_OPTTIME;
+ } else if (strcmp(val, "space") == 0) {
+ fsopts->optimization = FS_OPTSPACE;
+ } else {
+ warnx("Invalid optimization `%s'", val);
+ goto leave_ffs_parse_opts;
+ }
+ rv = 1;
+ } else
+ rv = set_option(ffs_options, var, val);
+
+ leave_ffs_parse_opts:
+ if (var)
+ free(var);
+ return (rv);
+}
+
+
+void
+ffs_makefs(const char *image, const char *dir, fsnode *root, fsinfo_t *fsopts)
+{
+ struct fs *superblock;
+ struct timeval start;
+
+ assert(image != NULL);
+ assert(dir != NULL);
+ assert(root != NULL);
+ assert(fsopts != NULL);
+
+ if (debug & DEBUG_FS_MAKEFS)
+ printf("ffs_makefs: image %s directory %s root %p\n",
+ image, dir, root);
+
+ /* validate tree and options */
+ TIMER_START(start);
+ ffs_validate(dir, root, fsopts);
+ TIMER_RESULTS(start, "ffs_validate");
+
+ printf("Calculated size of `%s': %lld bytes, %lld inodes\n",
+ image, (long long)fsopts->size, (long long)fsopts->inodes);
+
+ /* create image */
+ TIMER_START(start);
+ if (ffs_create_image(image, fsopts) == -1)
+ errx(1, "Image file `%s' not created.", image);
+ TIMER_RESULTS(start, "ffs_create_image");
+
+ fsopts->curinode = ROOTINO;
+
+ if (debug & DEBUG_FS_MAKEFS)
+ putchar('\n');
+
+ /* populate image */
+ printf("Populating `%s'\n", image);
+ TIMER_START(start);
+ if (! ffs_populate_dir(dir, root, fsopts))
+ errx(1, "Image file `%s' not populated.", image);
+ TIMER_RESULTS(start, "ffs_populate_dir");
+
+ /* ensure no outstanding buffers remain */
+ if (debug & DEBUG_FS_MAKEFS)
+ bcleanup();
+
+ /* update various superblock parameters */
+ superblock = fsopts->superblock;
+ superblock->fs_fmod = 0;
+ superblock->fs_old_cstotal.cs_ndir = superblock->fs_cstotal.cs_ndir;
+ superblock->fs_old_cstotal.cs_nbfree = superblock->fs_cstotal.cs_nbfree;
+ superblock->fs_old_cstotal.cs_nifree = superblock->fs_cstotal.cs_nifree;
+ superblock->fs_old_cstotal.cs_nffree = superblock->fs_cstotal.cs_nffree;
+
+ /* write out superblock; image is now complete */
+ ffs_write_superblock(fsopts->superblock, fsopts);
+ if (close(fsopts->fd) == -1)
+ err(1, "Closing `%s'", image);
+ fsopts->fd = -1;
+ printf("Image `%s' complete\n", image);
+}
+
+ /* end of public functions */
+
+
+static void
+ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
+{
+ int32_t ncg = 1;
+#if notyet
+ int32_t spc, nspf, ncyl, fssize;
+#endif
+ off_t size;
+
+ assert(dir != NULL);
+ assert(root != NULL);
+ assert(fsopts != NULL);
+
+ if (debug & DEBUG_FS_VALIDATE) {
+ printf("ffs_validate: before defaults set:\n");
+ ffs_dump_fsinfo(fsopts);
+ }
+
+ /* set FFS defaults */
+ if (fsopts->sectorsize == -1)
+ fsopts->sectorsize = DFL_SECSIZE;
+ if (fsopts->fsize == -1)
+ fsopts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize);
+ if (fsopts->bsize == -1)
+ fsopts->bsize = MIN(DFL_BLKSIZE, 8 * fsopts->fsize);
+ if (fsopts->cpg == -1)
+ fsopts->cpg = DFL_CYLSPERGROUP;
+ else
+ fsopts->cpgflg = 1;
+ /* fsopts->density is set below */
+ if (fsopts->nsectors == -1)
+ fsopts->nsectors = DFL_NSECTORS;
+ if (fsopts->minfree == -1)
+ fsopts->minfree = MINFREE;
+ if (fsopts->optimization == -1)
+ fsopts->optimization = DEFAULTOPT;
+ if (fsopts->maxcontig == -1)
+ fsopts->maxcontig =
+ MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / fsopts->bsize);
+ /* XXX ondisk32 */
+ if (fsopts->maxbpg == -1)
+ fsopts->maxbpg = fsopts->bsize / sizeof(int32_t);
+ if (fsopts->avgfilesize == -1)
+ fsopts->avgfilesize = AVFILESIZ;
+ if (fsopts->avgfpdir == -1)
+ fsopts->avgfpdir = AFPDIR;
+
+ /* calculate size of tree */
+ ffs_size_dir(root, fsopts);
+ fsopts->inodes += ROOTINO; /* include first two inodes */
+
+ if (debug & DEBUG_FS_VALIDATE)
+ printf("ffs_validate: size of tree: %lld bytes, %lld inodes\n",
+ (long long)fsopts->size, (long long)fsopts->inodes);
+
+ /* add requested slop */
+ fsopts->size += fsopts->freeblocks;
+ fsopts->inodes += fsopts->freefiles;
+ if (fsopts->freefilepc > 0)
+ fsopts->inodes =
+ fsopts->inodes * (100 + fsopts->freefilepc) / 100;
+ if (fsopts->freeblockpc > 0)
+ fsopts->size =
+ fsopts->size * (100 + fsopts->freeblockpc) / 100;
+
+ /* add space needed for superblocks */
+ /*
+ * The old SBOFF (SBLOCK_UFS1) is used here because makefs is
+ * typically used for small filesystems where space matters.
+ * XXX make this an option.
+ */
+ fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg;
+ /* add space needed to store inodes, x3 for blockmaps, etc */
+ if (fsopts->version == 1)
+ fsopts->size += ncg * DINODE1_SIZE *
+ roundup(fsopts->inodes / ncg, fsopts->bsize / DINODE1_SIZE);
+ else
+ fsopts->size += ncg * DINODE2_SIZE *
+ roundup(fsopts->inodes / ncg, fsopts->bsize / DINODE2_SIZE);
+
+ /* add minfree */
+ if (fsopts->minfree > 0)
+ fsopts->size =
+ fsopts->size * (100 + fsopts->minfree) / 100;
+ /*
+ * XXX any other fs slop to add, such as csum's, bitmaps, etc ??
+ */
+
+ if (fsopts->size < fsopts->minsize) /* ensure meets minimum size */
+ fsopts->size = fsopts->minsize;
+
+ /* round up to the next block */
+ size = roundup(fsopts->size, fsopts->bsize);
+
+ /* now check calculated sizes vs requested sizes */
+ if (fsopts->maxsize > 0 && size > fsopts->maxsize) {
+ if (debug & DEBUG_FS_VALIDATE) {
+ printf("%s: `%s' size of %lld is larger than the "
+ "maxsize of %lld; rounding down to %lld.",
+ __func__, dir, (long long)size,
+ (long long)fsopts->maxsize,
+ (long long) rounddown(fsopts->size, fsopts->bsize));
+ }
+ size = rounddown(fsopts->size, fsopts->bsize);
+ }
+ fsopts->size = size;
+
+ /* calculate density if necessary */
+ if (fsopts->density == -1)
+ fsopts->density = fsopts->size / fsopts->inodes + 1;
+
+ if (debug & DEBUG_FS_VALIDATE) {
+ printf("ffs_validate: after defaults set:\n");
+ ffs_dump_fsinfo(fsopts);
+ printf("ffs_validate: dir %s; %lld bytes, %lld inodes\n",
+ dir, (long long)fsopts->size, (long long)fsopts->inodes);
+ }
+ sectorsize = fsopts->sectorsize; /* XXX - see earlier */
+}
+
+
+static void
+ffs_dump_fsinfo(fsinfo_t *f)
+{
+
+ printf("fsopts at %p\n", f);
+
+ printf("\tsize %lld, inodes %lld, curinode %u\n",
+ (long long)f->size, (long long)f->inodes, f->curinode);
+
+ printf("\tminsize %lld, maxsize %lld\n",
+ (long long)f->minsize, (long long)f->maxsize);
+ printf("\tfree files %lld, freefile %% %d\n",
+ (long long)f->freefiles, f->freefilepc);
+ printf("\tfree blocks %lld, freeblock %% %d\n",
+ (long long)f->freeblocks, f->freeblockpc);
+ printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize);
+
+ printf("\tbsize %d, fsize %d, cpg %d, density %d\n",
+ f->bsize, f->fsize, f->cpg, f->density);
+ printf("\tnsectors %d, rpm %d, minfree %d\n",
+ f->nsectors, f->rpm, f->minfree);
+ printf("\tmaxcontig %d, maxbpg %d\n",
+ f->maxcontig, f->maxbpg);
+ printf("\toptimization %s\n",
+ f->optimization == FS_OPTSPACE ? "space" : "time");
+}
+
+
+static int
+ffs_create_image(const char *image, fsinfo_t *fsopts)
+{
+#if HAVE_STRUCT_STATVFS_F_IOSIZE
+ struct statvfs sfs;
+#endif
+ struct fs *fs;
+ char *buf;
+ int i, bufsize;
+ off_t bufrem;
+
+ assert (image != NULL);
+ assert (fsopts != NULL);
+
+ /* create image */
+ if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0777))
+ == -1) {
+ warn("Can't open `%s' for writing", image);
+ return (-1);
+ }
+
+ /* zero image */
+#if HAVE_STRUCT_STATVFS_F_IOSIZE
+ if (fstatvfs(fsopts->fd, &sfs) == -1) {
+#endif
+ bufsize = 8192;
+#if HAVE_STRUCT_STATVFS_F_IOSIZE
+ warn("can't fstatvfs `%s', using default %d byte chunk",
+ image, bufsize);
+ } else
+ bufsize = sfs.f_iosize;
+#endif
+ bufrem = fsopts->size;
+ if (debug & DEBUG_FS_CREATE_IMAGE)
+ printf(
+ "zero-ing image `%s', %lld sectors, using %d byte chunks\n",
+ image, (long long)bufrem, bufsize);
+ if ((buf = calloc(1, bufsize)) == NULL) {
+ warn("Can't create buffer for sector");
+ return (-1);
+ }
+ while (bufrem > 0) {
+ i = write(fsopts->fd, buf, MIN(bufsize, bufrem));
+ if (i == -1) {
+ warn("zeroing image, %lld bytes to go",
+ (long long)bufrem);
+ return (-1);
+ }
+ bufrem -= i;
+ }
+
+ /* make the file system */
+ if (debug & DEBUG_FS_CREATE_IMAGE)
+ printf("calling mkfs(\"%s\", ...)\n", image);
+ fs = ffs_mkfs(image, fsopts);
+ fsopts->superblock = (void *)fs;
+ if (debug & DEBUG_FS_CREATE_IMAGE) {
+ time_t t;
+
+ t = (time_t)((struct fs *)fsopts->superblock)->fs_time;
+ printf("mkfs returned %p; fs_time %s",
+ fsopts->superblock, ctime(&t));
+ printf("fs totals: nbfree %lld, nffree %lld, nifree %lld, ndir %lld\n",
+ (long long)fs->fs_cstotal.cs_nbfree,
+ (long long)fs->fs_cstotal.cs_nffree,
+ (long long)fs->fs_cstotal.cs_nifree,
+ (long long)fs->fs_cstotal.cs_ndir);
+ }
+
+ if (fs->fs_cstotal.cs_nifree + ROOTINO < fsopts->inodes) {
+ warnx(
+ "Image file `%s' has %lld free inodes; %lld are required.",
+ image,
+ (long long)fs->fs_cstotal.cs_nifree + ROOTINO,
+ (long long)fsopts->inodes);
+ return (-1);
+ }
+ return (fsopts->fd);
+}
+
+
+static void
+ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
+{
+ struct direct tmpdir;
+ fsnode * node;
+ int curdirsize, this;
+
+ /* node may be NULL (empty directory) */
+ assert(fsopts != NULL);
+
+ if (debug & DEBUG_FS_SIZE_DIR)
+ printf("ffs_size_dir: entry: bytes %lld inodes %lld\n",
+ (long long)fsopts->size, (long long)fsopts->inodes);
+
+#define ADDDIRENT(e) do { \
+ tmpdir.d_namlen = strlen((e)); \
+ this = DIRSIZ_SWAP(0, &tmpdir, 0); \
+ if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
+ printf("ADDDIRENT: was: %s (%d) this %d cur %d\n", \
+ e, tmpdir.d_namlen, this, curdirsize); \
+ if (this + curdirsize > roundup(curdirsize, DIRBLKSIZ)) \
+ curdirsize = roundup(curdirsize, DIRBLKSIZ); \
+ curdirsize += this; \
+ if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
+ printf("ADDDIRENT: now: %s (%d) this %d cur %d\n", \
+ e, tmpdir.d_namlen, this, curdirsize); \
+} while (0);
+
+ /*
+ * XXX this needs to take into account extra space consumed
+ * by indirect blocks, etc.
+ */
+#define ADDSIZE(x) do { \
+ fsopts->size += roundup((x), fsopts->fsize); \
+} while (0);
+
+ curdirsize = 0;
+ for (node = root; node != NULL; node = node->next) {
+ ADDDIRENT(node->name);
+ if (FSNODE_EXCLUDE_P(fsopts, node))
+ continue;
+ if (node == root) { /* we're at "." */
+ assert(strcmp(node->name, ".") == 0);
+ ADDDIRENT("..");
+ } else if ((node->inode->flags & FI_SIZED) == 0) {
+ /* don't count duplicate names */
+ node->inode->flags |= FI_SIZED;
+ if (debug & DEBUG_FS_SIZE_DIR_NODE)
+ printf("ffs_size_dir: `%s' size %lld\n",
+ node->name,
+ (long long)node->inode->st.st_size);
+ fsopts->inodes++;
+ if (node->type == S_IFREG)
+ ADDSIZE(node->inode->st.st_size);
+ if (node->type == S_IFLNK) {
+ int slen;
+
+ slen = strlen(node->symlink) + 1;
+ if (slen >= (fsopts->version == 1 ?
+ MAXSYMLINKLEN_UFS1 :
+ MAXSYMLINKLEN_UFS2))
+ ADDSIZE(slen);
+ }
+ }
+ if (node->type == S_IFDIR)
+ ffs_size_dir(node->child, fsopts);
+ }
+ ADDSIZE(curdirsize);
+
+ if (debug & DEBUG_FS_SIZE_DIR)
+ printf("ffs_size_dir: exit: size %lld inodes %lld\n",
+ (long long)fsopts->size, (long long)fsopts->inodes);
+}
+
+static void *
+ffs_build_dinode1(struct ufs1_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
+ fsnode *root, fsinfo_t *fsopts)
+{
+ int slen;
+ void *membuf;
+
+ memset(dinp, 0, sizeof(*dinp));
+ dinp->di_mode = cur->inode->st.st_mode;
+ dinp->di_nlink = cur->inode->nlink;
+ dinp->di_size = cur->inode->st.st_size;
+ dinp->di_atime = cur->inode->st.st_atime;
+ dinp->di_mtime = cur->inode->st.st_mtime;
+ dinp->di_ctime = cur->inode->st.st_ctime;
+#if HAVE_STRUCT_STAT_ST_MTIMENSEC
+ dinp->di_atimensec = cur->inode->st.st_atimensec;
+ dinp->di_mtimensec = cur->inode->st.st_mtimensec;
+ dinp->di_ctimensec = cur->inode->st.st_ctimensec;
+#endif
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ dinp->di_flags = cur->inode->st.st_flags;
+#endif
+#if HAVE_STRUCT_STAT_ST_GEN
+ dinp->di_gen = cur->inode->st.st_gen;
+#endif
+ dinp->di_uid = cur->inode->st.st_uid;
+ dinp->di_gid = cur->inode->st.st_gid;
+ /* not set: di_db, di_ib, di_blocks, di_spare */
+
+ membuf = NULL;
+ if (cur == root) { /* "."; write dirbuf */
+ membuf = dbufp->buf;
+ dinp->di_size = dbufp->size;
+ } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
+ dinp->di_size = 0; /* a device */
+ dinp->di_rdev =
+ ufs_rw32(cur->inode->st.st_rdev, fsopts->needswap);
+ } else if (S_ISLNK(cur->type)) { /* symlink */
+ slen = strlen(cur->symlink);
+ if (slen < MAXSYMLINKLEN_UFS1) { /* short link */
+ memcpy(dinp->di_db, cur->symlink, slen);
+ } else
+ membuf = cur->symlink;
+ dinp->di_size = slen;
+ }
+ return membuf;
+}
+
+static void *
+ffs_build_dinode2(struct ufs2_dinode *dinp, dirbuf_t *dbufp, fsnode *cur,
+ fsnode *root, fsinfo_t *fsopts)
+{
+ int slen;
+ void *membuf;
+
+ memset(dinp, 0, sizeof(*dinp));
+ dinp->di_mode = cur->inode->st.st_mode;
+ dinp->di_nlink = cur->inode->nlink;
+ dinp->di_size = cur->inode->st.st_size;
+ dinp->di_atime = cur->inode->st.st_atime;
+ dinp->di_mtime = cur->inode->st.st_mtime;
+ dinp->di_ctime = cur->inode->st.st_ctime;
+#if HAVE_STRUCT_STAT_ST_MTIMENSEC
+ dinp->di_atimensec = cur->inode->st.st_atimensec;
+ dinp->di_mtimensec = cur->inode->st.st_mtimensec;
+ dinp->di_ctimensec = cur->inode->st.st_ctimensec;
+#endif
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ dinp->di_flags = cur->inode->st.st_flags;
+#endif
+#if HAVE_STRUCT_STAT_ST_GEN
+ dinp->di_gen = cur->inode->st.st_gen;
+#endif
+#if HAVE_STRUCT_STAT_BIRTHTIME
+ dinp->di_birthtime = cur->inode->st.st_birthtime;
+ dinp->di_birthnsec = cur->inode->st.st_birthtimensec;
+#endif
+ dinp->di_uid = cur->inode->st.st_uid;
+ dinp->di_gid = cur->inode->st.st_gid;
+ /* not set: di_db, di_ib, di_blocks, di_spare */
+
+ membuf = NULL;
+ if (cur == root) { /* "."; write dirbuf */
+ membuf = dbufp->buf;
+ dinp->di_size = dbufp->size;
+ } else if (S_ISBLK(cur->type) || S_ISCHR(cur->type)) {
+ dinp->di_size = 0; /* a device */
+ dinp->di_rdev =
+ ufs_rw64(cur->inode->st.st_rdev, fsopts->needswap);
+ } else if (S_ISLNK(cur->type)) { /* symlink */
+ slen = strlen(cur->symlink);
+ if (slen < MAXSYMLINKLEN_UFS2) { /* short link */
+ memcpy(dinp->di_db, cur->symlink, slen);
+ } else
+ membuf = cur->symlink;
+ dinp->di_size = slen;
+ }
+ return membuf;
+}
+
+static int
+ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
+{
+ fsnode *cur;
+ dirbuf_t dirbuf;
+ union dinode din;
+ void *membuf;
+ char path[MAXPATHLEN + 1];
+
+ assert(dir != NULL);
+ assert(root != NULL);
+ assert(fsopts != NULL);
+
+ (void)memset(&dirbuf, 0, sizeof(dirbuf));
+
+ if (debug & DEBUG_FS_POPULATE)
+ printf("ffs_populate_dir: PASS 1 dir %s node %p\n", dir, root);
+
+ /*
+ * pass 1: allocate inode numbers, build directory `file'
+ */
+ for (cur = root; cur != NULL; cur = cur->next) {
+ if (FSNODE_EXCLUDE_P(fsopts, cur))
+ continue;
+ if ((cur->inode->flags & FI_ALLOCATED) == 0) {
+ cur->inode->flags |= FI_ALLOCATED;
+ if (cur == root && cur->parent != NULL)
+ cur->inode->ino = cur->parent->inode->ino;
+ else {
+ cur->inode->ino = fsopts->curinode;
+ fsopts->curinode++;
+ }
+ }
+ ffs_make_dirbuf(&dirbuf, cur->name, cur, fsopts->needswap);
+ if (cur == root) { /* we're at "."; add ".." */
+ ffs_make_dirbuf(&dirbuf, "..",
+ cur->parent == NULL ? cur : cur->parent->first,
+ fsopts->needswap);
+ root->inode->nlink++; /* count my parent's link */
+ } else if (cur->child != NULL)
+ root->inode->nlink++; /* count my child's link */
+
+ /*
+ * XXX possibly write file and long symlinks here,
+ * ensuring that blocks get written before inodes?
+ * otoh, this isn't a real filesystem, so who
+ * cares about ordering? :-)
+ */
+ }
+ if (debug & DEBUG_FS_POPULATE_DIRBUF)
+ ffs_dump_dirbuf(&dirbuf, dir, fsopts->needswap);
+
+ /*
+ * pass 2: write out dirbuf, then non-directories at this level
+ */
+ if (debug & DEBUG_FS_POPULATE)
+ printf("ffs_populate_dir: PASS 2 dir %s\n", dir);
+ for (cur = root; cur != NULL; cur = cur->next) {
+ if (FSNODE_EXCLUDE_P(fsopts, cur))
+ continue;
+ if (cur->inode->flags & FI_WRITTEN)
+ continue; /* skip hard-linked entries */
+ cur->inode->flags |= FI_WRITTEN;
+
+ if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
+ >= sizeof(path))
+ errx(1, "Pathname too long.");
+
+ if (cur->child != NULL)
+ continue; /* child creates own inode */
+
+ /* build on-disk inode */
+ if (fsopts->version == 1)
+ membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur,
+ root, fsopts);
+ else
+ membuf = ffs_build_dinode2(&din.ffs2_din, &dirbuf, cur,
+ root, fsopts);
+
+ if (debug & DEBUG_FS_POPULATE_NODE) {
+ printf("ffs_populate_dir: writing ino %d, %s",
+ cur->inode->ino, inode_type(cur->type));
+ if (cur->inode->nlink > 1)
+ printf(", nlink %d", cur->inode->nlink);
+ putchar('\n');
+ }
+
+ if (membuf != NULL) {
+ ffs_write_file(&din, cur->inode->ino, membuf, fsopts);
+ } else if (S_ISREG(cur->type)) {
+ ffs_write_file(&din, cur->inode->ino, path, fsopts);
+ } else {
+ assert (! S_ISDIR(cur->type));
+ ffs_write_inode(&din, cur->inode->ino, fsopts);
+ }
+ }
+
+ /*
+ * pass 3: write out sub-directories
+ */
+ if (debug & DEBUG_FS_POPULATE)
+ printf("ffs_populate_dir: PASS 3 dir %s\n", dir);
+ for (cur = root; cur != NULL; cur = cur->next) {
+ if (FSNODE_EXCLUDE_P(fsopts, cur))
+ continue;
+ if (cur->child == NULL)
+ continue;
+ if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
+ >= sizeof(path))
+ errx(1, "Pathname too long.");
+ if (! ffs_populate_dir(path, cur->child, fsopts))
+ return (0);
+ }
+
+ if (debug & DEBUG_FS_POPULATE)
+ printf("ffs_populate_dir: DONE dir %s\n", dir);
+
+ /* cleanup */
+ if (dirbuf.buf != NULL)
+ free(dirbuf.buf);
+ return (1);
+}
+
+
+static void
+ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
+{
+ int isfile, ffd;
+ char *fbuf, *p;
+ off_t bufleft, chunk, offset;
+ struct inode in;
+ struct buf * bp;
+
+ assert (din != NULL);
+ assert (buf != NULL);
+ assert (fsopts != NULL);
+
+ isfile = S_ISREG(DIP(din, mode));
+ fbuf = NULL;
+ ffd = -1;
+
+ in.i_fs = (struct fs *)fsopts->superblock;
+
+ if (debug & DEBUG_FS_WRITE_FILE) {
+ printf(
+ "ffs_write_file: ino %u, din %p, isfile %d, %s, size %lld",
+ ino, din, isfile, inode_type(DIP(din, mode) & S_IFMT),
+ (long long)DIP(din, size));
+ if (isfile)
+ printf(", file '%s'\n", (char *)buf);
+ else
+ printf(", buffer %p\n", buf);
+ }
+
+ in.i_number = ino;
+ in.i_size = DIP(din, size);
+ if (fsopts->version == 1)
+ memcpy(&in.i_din.ffs1_din, &din->ffs1_din,
+ sizeof(in.i_din.ffs1_din));
+ else
+ memcpy(&in.i_din.ffs2_din, &din->ffs2_din,
+ sizeof(in.i_din.ffs2_din));
+ in.i_fd = fsopts->fd;
+
+ if (DIP(din, size) == 0)
+ goto write_inode_and_leave; /* mmm, cheating */
+
+ if (isfile) {
+ if ((fbuf = malloc(fsopts->bsize)) == NULL)
+ err(1, "Allocating memory for write buffer");
+ if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) {
+ warn("Can't open `%s' for reading", (char *)buf);
+ goto leave_ffs_write_file;
+ }
+ } else {
+ p = buf;
+ }
+
+ chunk = 0;
+ for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) {
+ chunk = MIN(bufleft, fsopts->bsize);
+ if (isfile) {
+ if (read(ffd, fbuf, chunk) != chunk)
+ err(1, "Reading `%s', %lld bytes to go",
+ (char *)buf, (long long)bufleft);
+ p = fbuf;
+ }
+ offset = DIP(din, size) - bufleft;
+ if (debug & DEBUG_FS_WRITE_FILE_BLOCK)
+ printf(
+ "ffs_write_file: write %p offset %lld size %lld left %lld\n",
+ p, (long long)offset,
+ (long long)chunk, (long long)bufleft);
+ /*
+ * XXX if holey support is desired, do the check here
+ *
+ * XXX might need to write out last bit in fragroundup
+ * sized chunk. however, ffs_balloc() handles this for us
+ */
+ errno = ffs_balloc(&in, offset, chunk, &bp);
+ bad_ffs_write_file:
+ if (errno != 0)
+ err(1,
+ "Writing inode %d (%s), bytes %lld + %lld",
+ ino,
+ isfile ? (char *)buf :
+ inode_type(DIP(din, mode) & S_IFMT),
+ (long long)offset, (long long)chunk);
+ memcpy(bp->b_data, p, chunk);
+ errno = bwrite(bp);
+ if (errno != 0)
+ goto bad_ffs_write_file;
+ brelse(bp);
+ if (!isfile)
+ p += chunk;
+ }
+
+ write_inode_and_leave:
+ ffs_write_inode(&in.i_din, in.i_number, fsopts);
+
+ leave_ffs_write_file:
+ if (fbuf)
+ free(fbuf);
+ if (ffd != -1)
+ close(ffd);
+}
+
+
+static void
+ffs_dump_dirbuf(dirbuf_t *dbuf, const char *dir, int needswap)
+{
+ doff_t i;
+ struct direct *de;
+ uint16_t reclen;
+
+ assert (dbuf != NULL);
+ assert (dir != NULL);
+ printf("ffs_dump_dirbuf: dir %s size %d cur %d\n",
+ dir, dbuf->size, dbuf->cur);
+
+ for (i = 0; i < dbuf->size; ) {
+ de = (struct direct *)(dbuf->buf + i);
+ reclen = ufs_rw16(de->d_reclen, needswap);
+ printf(
+ " inode %4d %7s offset %4d reclen %3d namlen %3d name %s\n",
+ ufs_rw32(de->d_ino, needswap),
+ inode_type(DTTOIF(de->d_type)), i, reclen,
+ de->d_namlen, de->d_name);
+ i += reclen;
+ assert(reclen > 0);
+ }
+}
+
+static void
+ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
+{
+ struct direct de, *dp;
+ uint16_t llen, reclen;
+ char *newbuf;
+
+ assert (dbuf != NULL);
+ assert (name != NULL);
+ assert (node != NULL);
+ /* create direct entry */
+ (void)memset(&de, 0, sizeof(de));
+ de.d_ino = ufs_rw32(node->inode->ino, needswap);
+ de.d_type = IFTODT(node->type);
+ de.d_namlen = (uint8_t)strlen(name);
+ strcpy(de.d_name, name);
+ reclen = DIRSIZ_SWAP(0, &de, needswap);
+ de.d_reclen = ufs_rw16(reclen, needswap);
+
+ dp = (struct direct *)(dbuf->buf + dbuf->cur);
+ llen = 0;
+ if (dp != NULL)
+ llen = DIRSIZ_SWAP(0, dp, needswap);
+
+ if (debug & DEBUG_FS_MAKE_DIRBUF)
+ printf(
+ "ffs_make_dirbuf: dbuf siz %d cur %d lastlen %d\n"
+ " ino %d type %d reclen %d namlen %d name %.30s\n",
+ dbuf->size, dbuf->cur, llen,
+ ufs_rw32(de.d_ino, needswap), de.d_type, reclen,
+ de.d_namlen, de.d_name);
+
+ if (reclen + dbuf->cur + llen > roundup(dbuf->size, DIRBLKSIZ)) {
+ if (debug & DEBUG_FS_MAKE_DIRBUF)
+ printf("ffs_make_dirbuf: growing buf to %d\n",
+ dbuf->size + DIRBLKSIZ);
+ if ((newbuf = realloc(dbuf->buf, dbuf->size + DIRBLKSIZ)) == NULL)
+ err(1, "Allocating memory for directory buffer");
+ dbuf->buf = newbuf;
+ dbuf->size += DIRBLKSIZ;
+ memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ);
+ dbuf->cur = dbuf->size - DIRBLKSIZ;
+ } else { /* shrink end of previous */
+ dp->d_reclen = ufs_rw16(llen,needswap);
+ dbuf->cur += llen;
+ }
+ dp = (struct direct *)(dbuf->buf + dbuf->cur);
+ memcpy(dp, &de, reclen);
+ dp->d_reclen = ufs_rw16(dbuf->size - dbuf->cur, needswap);
+}
+
+/*
+ * cribbed from sys/ufs/ffs/ffs_alloc.c
+ */
+static void
+ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
+{
+ char *buf;
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2, *dip;
+ struct cg *cgp;
+ struct fs *fs;
+ int cg, cgino, i;
+ daddr_t d;
+ char sbbuf[FFS_MAXBSIZE];
+ int32_t initediblk;
+
+ assert (dp != NULL);
+ assert (ino > 0);
+ assert (fsopts != NULL);
+
+ fs = (struct fs *)fsopts->superblock;
+ cg = ino_to_cg(fs, ino);
+ cgino = ino % fs->fs_ipg;
+ if (debug & DEBUG_FS_WRITE_INODE)
+ printf("ffs_write_inode: din %p ino %u cg %d cgino %d\n",
+ dp, ino, cg, cgino);
+
+ ffs_rdfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
+ fsopts);
+ cgp = (struct cg *)sbbuf;
+ if (!cg_chkmagic_swap(cgp, fsopts->needswap))
+ errx(1, "ffs_write_inode: cg %d: bad magic number", cg);
+
+ assert (isclr(cg_inosused_swap(cgp, fsopts->needswap), cgino));
+
+ buf = malloc(fs->fs_bsize);
+ if (buf == NULL)
+ errx(1, "ffs_write_inode: cg %d: can't alloc inode block", cg);
+
+ dp1 = (struct ufs1_dinode *)buf;
+ dp2 = (struct ufs2_dinode *)buf;
+
+ if (fs->fs_cstotal.cs_nifree == 0)
+ errx(1, "ffs_write_inode: fs out of inodes for ino %u",
+ ino);
+ if (fs->fs_cs(fs, cg).cs_nifree == 0)
+ errx(1,
+ "ffs_write_inode: cg %d out of inodes for ino %u",
+ cg, ino);
+ setbit(cg_inosused_swap(cgp, fsopts->needswap), cgino);
+ ufs_add32(cgp->cg_cs.cs_nifree, -1, fsopts->needswap);
+ fs->fs_cstotal.cs_nifree--;
+ fs->fs_cs(fs, cg).cs_nifree--;
+ if (S_ISDIR(DIP(dp, mode))) {
+ ufs_add32(cgp->cg_cs.cs_ndir, 1, fsopts->needswap);
+ fs->fs_cstotal.cs_ndir++;
+ fs->fs_cs(fs, cg).cs_ndir++;
+ }
+
+ /*
+ * Initialize inode blocks on the fly for UFS2.
+ */
+ initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap);
+ if (fsopts->version == 2 && cgino + INOPB(fs) > initediblk &&
+ initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
+ memset(buf, 0, fs->fs_bsize);
+ dip = (struct ufs2_dinode *)buf;
+ srandom(time(NULL));
+ for (i = 0; i < INOPB(fs); i++) {
+ dip->di_gen = random() / 2 + 1;
+ dip++;
+ }
+ ffs_wtfs(fsbtodb(fs, ino_to_fsba(fs,
+ cg * fs->fs_ipg + initediblk)),
+ fs->fs_bsize, buf, fsopts);
+ initediblk += INOPB(fs);
+ cgp->cg_initediblk = ufs_rw32(initediblk, fsopts->needswap);
+ }
+
+
+ ffs_wtfs(fsbtodb(fs, cgtod(fs, cg)), (int)fs->fs_cgsize, &sbbuf,
+ fsopts);
+
+ /* now write inode */
+ d = fsbtodb(fs, ino_to_fsba(fs, ino));
+ ffs_rdfs(d, fs->fs_bsize, buf, fsopts);
+ if (fsopts->needswap) {
+ if (fsopts->version == 1)
+ ffs_dinode1_swap(&dp->ffs1_din,
+ &dp1[ino_to_fsbo(fs, ino)]);
+ else
+ ffs_dinode2_swap(&dp->ffs2_din,
+ &dp2[ino_to_fsbo(fs, ino)]);
+ } else {
+ if (fsopts->version == 1)
+ dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din;
+ else
+ dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din;
+ }
+ ffs_wtfs(d, fs->fs_bsize, buf, fsopts);
+ free(buf);
+}
+
+void
+panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ exit(1);
+}
diff --git a/usr.sbin/makefs/ffs/buf.c b/usr.sbin/makefs/ffs/buf.c
new file mode 100644
index 0000000..08fb627
--- /dev/null
+++ b/usr.sbin/makefs/ffs/buf.c
@@ -0,0 +1,222 @@
+/* $NetBSD: buf.c,v 1.12 2004/06/20 22:20:18 jmc Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Luke Mewburn for Wasabi Systems, 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "makefs.h"
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include "ffs/buf.h"
+#include "ffs/ufs_inode.h"
+
+extern int sectorsize; /* XXX: from ffs.c & mkfs.c */
+
+TAILQ_HEAD(buftailhead,buf) buftail;
+
+int
+bread(int fd, struct fs *fs, daddr_t blkno, int size, struct buf **bpp)
+{
+ off_t offset;
+ ssize_t rv;
+
+ assert (fs != NULL);
+ assert (bpp != NULL);
+
+ if (debug & DEBUG_BUF_BREAD)
+ printf("bread: fs %p blkno %lld size %d\n",
+ fs, (long long)blkno, size);
+ *bpp = getblk(fd, fs, blkno, size);
+ offset = (*bpp)->b_blkno * sectorsize; /* XXX */
+ if (debug & DEBUG_BUF_BREAD)
+ printf("bread: bp %p blkno %lld offset %lld bcount %ld\n",
+ (*bpp), (long long)(*bpp)->b_blkno, (long long) offset,
+ (*bpp)->b_bcount);
+ if (lseek((*bpp)->b_fd, offset, SEEK_SET) == -1)
+ err(1, "bread: lseek %lld (%lld)",
+ (long long)(*bpp)->b_blkno, (long long)offset);
+ rv = read((*bpp)->b_fd, (*bpp)->b_data, (*bpp)->b_bcount);
+ if (debug & DEBUG_BUF_BREAD)
+ printf("bread: read %ld (%lld) returned %d\n",
+ (*bpp)->b_bcount, (long long)offset, (int)rv);
+ if (rv == -1) /* read error */
+ err(1, "bread: read %ld (%lld) returned %d",
+ (*bpp)->b_bcount, (long long)offset, (int)rv);
+ else if (rv != (*bpp)->b_bcount) /* short read */
+ err(1, "bread: read %ld (%lld) returned %d",
+ (*bpp)->b_bcount, (long long)offset, (int)rv);
+ else
+ return (0);
+}
+
+void
+brelse(struct buf *bp)
+{
+
+ assert (bp != NULL);
+ assert (bp->b_data != NULL);
+
+ if (bp->b_lblkno < 0) {
+ /*
+ * XXX don't remove any buffers with negative logical block
+ * numbers (lblkno), so that we retain the mapping
+ * of negative lblkno -> real blkno that ffs_balloc()
+ * sets up.
+ *
+ * if we instead released these buffers, and implemented
+ * ufs_strategy() (and ufs_bmaparray()) and called those
+ * from bread() and bwrite() to convert the lblkno to
+ * a real blkno, we'd add a lot more code & complexity
+ * and reading off disk, for little gain, because this
+ * simple hack works for our purpose.
+ */
+ bp->b_bcount = 0;
+ return;
+ }
+
+ TAILQ_REMOVE(&buftail, bp, b_tailq);
+ free(bp->b_data);
+ free(bp);
+}
+
+int
+bwrite(struct buf *bp)
+{
+ off_t offset;
+ ssize_t rv;
+
+ assert (bp != NULL);
+ offset = bp->b_blkno * sectorsize; /* XXX */
+ if (debug & DEBUG_BUF_BWRITE)
+ printf("bwrite: bp %p blkno %lld offset %lld bcount %ld\n",
+ bp, (long long)bp->b_blkno, (long long) offset,
+ bp->b_bcount);
+ if (lseek(bp->b_fd, offset, SEEK_SET) == -1)
+ return (errno);
+ rv = write(bp->b_fd, bp->b_data, bp->b_bcount);
+ if (debug & DEBUG_BUF_BWRITE)
+ printf("bwrite: write %ld (offset %lld) returned %lld\n",
+ bp->b_bcount, (long long)offset, (long long)rv);
+ if (rv == bp->b_bcount)
+ return (0);
+ else if (rv == -1) /* write error */
+ return (errno);
+ else /* short write ? */
+ return (EAGAIN);
+}
+
+void
+bcleanup(void)
+{
+ struct buf *bp;
+
+ /*
+ * XXX this really shouldn't be necessary, but i'm curious to
+ * know why there's still some buffers lying around that
+ * aren't brelse()d
+ */
+
+ if (TAILQ_EMPTY(&buftail))
+ return;
+
+ printf("bcleanup: unflushed buffers:\n");
+ TAILQ_FOREACH(bp, &buftail, b_tailq) {
+ printf("\tlblkno %10lld blkno %10lld count %6ld bufsize %6ld\n",
+ (long long)bp->b_lblkno, (long long)bp->b_blkno,
+ bp->b_bcount, bp->b_bufsize);
+ }
+ printf("bcleanup: done\n");
+}
+
+struct buf *
+getblk(int fd, struct fs *fs, daddr_t blkno, int size)
+{
+ static int buftailinitted;
+ struct buf *bp;
+ void *n;
+
+ assert (fs != NULL);
+ if (debug & DEBUG_BUF_GETBLK)
+ printf("getblk: fs %p blkno %lld size %d\n", fs,
+ (long long)blkno, size);
+
+ bp = NULL;
+ if (!buftailinitted) {
+ if (debug & DEBUG_BUF_GETBLK)
+ printf("getblk: initialising tailq\n");
+ TAILQ_INIT(&buftail);
+ buftailinitted = 1;
+ } else {
+ TAILQ_FOREACH(bp, &buftail, b_tailq) {
+ if (bp->b_lblkno != blkno)
+ continue;
+ break;
+ }
+ }
+ if (bp == NULL) {
+ if ((bp = calloc(1, sizeof(struct buf))) == NULL)
+ err(1, "getblk: calloc");
+
+ bp->b_bufsize = 0;
+ bp->b_blkno = bp->b_lblkno = blkno;
+ bp->b_fd = fd;
+ bp->b_fs = fs;
+ bp->b_data = NULL;
+ TAILQ_INSERT_HEAD(&buftail, bp, b_tailq);
+ }
+ bp->b_bcount = size;
+ if (bp->b_data == NULL || bp->b_bcount > bp->b_bufsize) {
+ n = realloc(bp->b_data, size);
+ if (n == NULL)
+ err(1, "getblk: realloc b_data %ld", bp->b_bcount);
+ bp->b_data = n;
+ bp->b_bufsize = size;
+ }
+
+ return (bp);
+}
diff --git a/usr.sbin/makefs/ffs/buf.h b/usr.sbin/makefs/ffs/buf.h
new file mode 100644
index 0000000..02c6713
--- /dev/null
+++ b/usr.sbin/makefs/ffs/buf.h
@@ -0,0 +1,67 @@
+/* $NetBSD: buf.h,v 1.2 2001/11/02 03:12:49 lukem Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Luke Mewburn for Wasabi Systems, 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _FFS_BUF_H
+#define _FFS_BUF_H
+
+#include <sys/param.h>
+#include <sys/queue.h>
+
+struct buf {
+ void * b_data;
+ long b_bufsize;
+ long b_bcount;
+ daddr_t b_blkno;
+ daddr_t b_lblkno;
+ int b_fd;
+ struct fs * b_fs;
+
+ TAILQ_ENTRY(buf) b_tailq;
+};
+
+void bcleanup(void);
+int bread(int, struct fs *, daddr_t, int, struct buf **);
+void brelse(struct buf *);
+int bwrite(struct buf *);
+struct buf * getblk(int, struct fs *, daddr_t, int);
+
+#define bdwrite(bp) bwrite(bp)
+#define clrbuf(bp) memset((bp)->b_data, 0, (u_int)(bp)->b_bcount)
+
+#endif /* _FFS_BUF_H */
diff --git a/usr.sbin/makefs/ffs/ffs_alloc.c b/usr.sbin/makefs/ffs/ffs_alloc.c
new file mode 100644
index 0000000..0fe65e6
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ffs_alloc.c
@@ -0,0 +1,683 @@
+/* $NetBSD: ffs_alloc.c,v 1.14 2004/06/20 22:20:18 jmc Exp $ */
+/* From: NetBSD: ffs_alloc.c,v 1.50 2001/09/06 02:16:01 lukem Exp */
+
+/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1986, 1989, 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. 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.
+ *
+ * @(#)ffs_alloc.c 8.19 (Berkeley) 7/13/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <errno.h>
+
+#include "makefs.h"
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include "ffs/ufs_bswap.h"
+#include "ffs/buf.h"
+#include "ffs/ufs_inode.h"
+#include "ffs/ffs_extern.h"
+
+static int scanc(u_int, const u_char *, const u_char *, int);
+
+static daddr_t ffs_alloccg(struct inode *, int, daddr_t, int);
+static daddr_t ffs_alloccgblk(struct inode *, struct buf *, daddr_t);
+static daddr_t ffs_hashalloc(struct inode *, int, daddr_t, int,
+ daddr_t (*)(struct inode *, int, daddr_t, int));
+static int32_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int);
+
+/*
+ * Allocate a block in the file system.
+ *
+ * The size of the requested block is given, which must be some
+ * multiple of fs_fsize and <= fs_bsize.
+ * A preference may be optionally specified. If a preference is given
+ * the following hierarchy is used to allocate a block:
+ * 1) allocate the requested block.
+ * 2) allocate a rotationally optimal block in the same cylinder.
+ * 3) allocate a block in the same cylinder group.
+ * 4) quadradically rehash into other cylinder groups, until an
+ * available block is located.
+ * If no block preference is given the following hierarchy is used
+ * to allocate a block:
+ * 1) allocate a block in the cylinder group that contains the
+ * inode for the file.
+ * 2) quadradically rehash into other cylinder groups, until an
+ * available block is located.
+ */
+int
+ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size,
+ daddr_t *bnp)
+{
+ struct fs *fs = ip->i_fs;
+ daddr_t bno;
+ int cg;
+
+ *bnp = 0;
+ if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
+ errx(1, "ffs_alloc: bad size: bsize %d size %d",
+ fs->fs_bsize, size);
+ }
+ if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
+ goto nospace;
+ if (bpref >= fs->fs_size)
+ bpref = 0;
+ if (bpref == 0)
+ cg = ino_to_cg(fs, ip->i_number);
+ else
+ cg = dtog(fs, bpref);
+ bno = ffs_hashalloc(ip, cg, bpref, size, ffs_alloccg);
+ if (bno > 0) {
+ if (ip->i_fs->fs_magic == FS_UFS1_MAGIC)
+ ip->i_ffs1_blocks += size / DEV_BSIZE;
+ else
+ ip->i_ffs2_blocks += size / DEV_BSIZE;
+ *bnp = bno;
+ return (0);
+ }
+nospace:
+ return (ENOSPC);
+}
+
+/*
+ * Select the desired position for the next block in a file. The file is
+ * logically divided into sections. The first section is composed of the
+ * direct blocks. Each additional section contains fs_maxbpg blocks.
+ *
+ * If no blocks have been allocated in the first section, the policy is to
+ * request a block in the same cylinder group as the inode that describes
+ * the file. If no blocks have been allocated in any other section, the
+ * policy is to place the section in a cylinder group with a greater than
+ * average number of free blocks. An appropriate cylinder group is found
+ * by using a rotor that sweeps the cylinder groups. When a new group of
+ * blocks is needed, the sweep begins in the cylinder group following the
+ * cylinder group from which the previous allocation was made. The sweep
+ * continues until a cylinder group with greater than the average number
+ * of free blocks is found. If the allocation is for the first block in an
+ * indirect block, the information on the previous allocation is unavailable;
+ * here a best guess is made based upon the logical block number being
+ * allocated.
+ *
+ * If a section is already partially allocated, the policy is to
+ * contiguously allocate fs_maxcontig blocks. The end of one of these
+ * contiguous blocks and the beginning of the next is physically separated
+ * so that the disk head will be in transit between them for at least
+ * fs_rotdelay milliseconds. This is to allow time for the processor to
+ * schedule another I/O transfer.
+ */
+/* XXX ondisk32 */
+daddr_t
+ffs_blkpref_ufs1(struct inode *ip, daddr_t lbn, int indx, int32_t *bap)
+{
+ struct fs *fs;
+ int cg;
+ int avgbfree, startcg;
+
+ fs = ip->i_fs;
+ if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
+ if (lbn < NDADDR + NINDIR(fs)) {
+ cg = ino_to_cg(fs, ip->i_number);
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ }
+ /*
+ * Find a cylinder with greater than average number of
+ * unused data blocks.
+ */
+ if (indx == 0 || bap[indx - 1] == 0)
+ startcg =
+ ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg;
+ else
+ startcg = dtog(fs,
+ ufs_rw32(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + 1);
+ startcg %= fs->fs_ncg;
+ avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
+ for (cg = startcg; cg < fs->fs_ncg; cg++)
+ if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree)
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ for (cg = 0; cg <= startcg; cg++)
+ if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree)
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ return (0);
+ }
+ /*
+ * We just always try to lay things out contiguously.
+ */
+ return ufs_rw32(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + fs->fs_frag;
+}
+
+daddr_t
+ffs_blkpref_ufs2(ip, lbn, indx, bap)
+ struct inode *ip;
+ daddr_t lbn;
+ int indx;
+ int64_t *bap;
+{
+ struct fs *fs;
+ int cg;
+ int avgbfree, startcg;
+
+ fs = ip->i_fs;
+ if (indx % fs->fs_maxbpg == 0 || bap[indx - 1] == 0) {
+ if (lbn < NDADDR + NINDIR(fs)) {
+ cg = ino_to_cg(fs, ip->i_number);
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ }
+ /*
+ * Find a cylinder with greater than average number of
+ * unused data blocks.
+ */
+ if (indx == 0 || bap[indx - 1] == 0)
+ startcg =
+ ino_to_cg(fs, ip->i_number) + lbn / fs->fs_maxbpg;
+ else
+ startcg = dtog(fs,
+ ufs_rw64(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + 1);
+ startcg %= fs->fs_ncg;
+ avgbfree = fs->fs_cstotal.cs_nbfree / fs->fs_ncg;
+ for (cg = startcg; cg < fs->fs_ncg; cg++)
+ if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ }
+ for (cg = 0; cg < startcg; cg++)
+ if (fs->fs_cs(fs, cg).cs_nbfree >= avgbfree) {
+ return (fs->fs_fpg * cg + fs->fs_frag);
+ }
+ return (0);
+ }
+ /*
+ * We just always try to lay things out contiguously.
+ */
+ return ufs_rw64(bap[indx - 1], UFS_FSNEEDSWAP(fs)) + fs->fs_frag;
+}
+
+/*
+ * Implement the cylinder overflow algorithm.
+ *
+ * The policy implemented by this algorithm is:
+ * 1) allocate the block in its requested cylinder group.
+ * 2) quadradically rehash on the cylinder group number.
+ * 3) brute force search for a free block.
+ *
+ * `size': size for data blocks, mode for inodes
+ */
+/*VARARGS5*/
+static daddr_t
+ffs_hashalloc(struct inode *ip, int cg, daddr_t pref, int size,
+ daddr_t (*allocator)(struct inode *, int, daddr_t, int))
+{
+ struct fs *fs;
+ daddr_t result;
+ int i, icg = cg;
+
+ fs = ip->i_fs;
+ /*
+ * 1: preferred cylinder group
+ */
+ result = (*allocator)(ip, cg, pref, size);
+ if (result)
+ return (result);
+ /*
+ * 2: quadratic rehash
+ */
+ for (i = 1; i < fs->fs_ncg; i *= 2) {
+ cg += i;
+ if (cg >= fs->fs_ncg)
+ cg -= fs->fs_ncg;
+ result = (*allocator)(ip, cg, 0, size);
+ if (result)
+ return (result);
+ }
+ /*
+ * 3: brute force search
+ * Note that we start at i == 2, since 0 was checked initially,
+ * and 1 is always checked in the quadratic rehash.
+ */
+ cg = (icg + 2) % fs->fs_ncg;
+ for (i = 2; i < fs->fs_ncg; i++) {
+ result = (*allocator)(ip, cg, 0, size);
+ if (result)
+ return (result);
+ cg++;
+ if (cg == fs->fs_ncg)
+ cg = 0;
+ }
+ return (0);
+}
+
+/*
+ * Determine whether a block can be allocated.
+ *
+ * Check to see if a block of the appropriate size is available,
+ * and if it is, allocate it.
+ */
+static daddr_t
+ffs_alloccg(struct inode *ip, int cg, daddr_t bpref, int size)
+{
+ struct cg *cgp;
+ struct buf *bp;
+ daddr_t bno, blkno;
+ int error, frags, allocsiz, i;
+ struct fs *fs = ip->i_fs;
+ const int needswap = UFS_FSNEEDSWAP(fs);
+
+ if (fs->fs_cs(fs, cg).cs_nbfree == 0 && size == fs->fs_bsize)
+ return (0);
+ error = bread(ip->i_fd, ip->i_fs, fsbtodb(fs, cgtod(fs, cg)),
+ (int)fs->fs_cgsize, &bp);
+ if (error) {
+ brelse(bp);
+ return (0);
+ }
+ cgp = (struct cg *)bp->b_data;
+ if (!cg_chkmagic_swap(cgp, needswap) ||
+ (cgp->cg_cs.cs_nbfree == 0 && size == fs->fs_bsize)) {
+ brelse(bp);
+ return (0);
+ }
+ if (size == fs->fs_bsize) {
+ bno = ffs_alloccgblk(ip, bp, bpref);
+ bdwrite(bp);
+ return (bno);
+ }
+ /*
+ * check to see if any fragments are already available
+ * allocsiz is the size which will be allocated, hacking
+ * it down to a smaller size if necessary
+ */
+ frags = numfrags(fs, size);
+ for (allocsiz = frags; allocsiz < fs->fs_frag; allocsiz++)
+ if (cgp->cg_frsum[allocsiz] != 0)
+ break;
+ if (allocsiz == fs->fs_frag) {
+ /*
+ * no fragments were available, so a block will be
+ * allocated, and hacked up
+ */
+ if (cgp->cg_cs.cs_nbfree == 0) {
+ brelse(bp);
+ return (0);
+ }
+ bno = ffs_alloccgblk(ip, bp, bpref);
+ bpref = dtogd(fs, bno);
+ for (i = frags; i < fs->fs_frag; i++)
+ setbit(cg_blksfree_swap(cgp, needswap), bpref + i);
+ i = fs->fs_frag - frags;
+ ufs_add32(cgp->cg_cs.cs_nffree, i, needswap);
+ fs->fs_cstotal.cs_nffree += i;
+ fs->fs_cs(fs, cg).cs_nffree += i;
+ fs->fs_fmod = 1;
+ ufs_add32(cgp->cg_frsum[i], 1, needswap);
+ bdwrite(bp);
+ return (bno);
+ }
+ bno = ffs_mapsearch(fs, cgp, bpref, allocsiz);
+ for (i = 0; i < frags; i++)
+ clrbit(cg_blksfree_swap(cgp, needswap), bno + i);
+ ufs_add32(cgp->cg_cs.cs_nffree, -frags, needswap);
+ fs->fs_cstotal.cs_nffree -= frags;
+ fs->fs_cs(fs, cg).cs_nffree -= frags;
+ fs->fs_fmod = 1;
+ ufs_add32(cgp->cg_frsum[allocsiz], -1, needswap);
+ if (frags != allocsiz)
+ ufs_add32(cgp->cg_frsum[allocsiz - frags], 1, needswap);
+ blkno = cg * fs->fs_fpg + bno;
+ bdwrite(bp);
+ return blkno;
+}
+
+/*
+ * Allocate a block in a cylinder group.
+ *
+ * This algorithm implements the following policy:
+ * 1) allocate the requested block.
+ * 2) allocate a rotationally optimal block in the same cylinder.
+ * 3) allocate the next available block on the block rotor for the
+ * specified cylinder group.
+ * Note that this routine only allocates fs_bsize blocks; these
+ * blocks may be fragmented by the routine that allocates them.
+ */
+static daddr_t
+ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref)
+{
+ struct cg *cgp;
+ daddr_t blkno;
+ int32_t bno;
+ struct fs *fs = ip->i_fs;
+ const int needswap = UFS_FSNEEDSWAP(fs);
+ u_int8_t *blksfree;
+
+ cgp = (struct cg *)bp->b_data;
+ blksfree = cg_blksfree_swap(cgp, needswap);
+ if (bpref == 0 || dtog(fs, bpref) != ufs_rw32(cgp->cg_cgx, needswap)) {
+ bpref = ufs_rw32(cgp->cg_rotor, needswap);
+ } else {
+ bpref = blknum(fs, bpref);
+ bno = dtogd(fs, bpref);
+ /*
+ * if the requested block is available, use it
+ */
+ if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno)))
+ goto gotit;
+ }
+ /*
+ * Take the next available one in this cylinder group.
+ */
+ bno = ffs_mapsearch(fs, cgp, bpref, (int)fs->fs_frag);
+ if (bno < 0)
+ return (0);
+ cgp->cg_rotor = ufs_rw32(bno, needswap);
+gotit:
+ blkno = fragstoblks(fs, bno);
+ ffs_clrblock(fs, blksfree, (long)blkno);
+ ffs_clusteracct(fs, cgp, blkno, -1);
+ ufs_add32(cgp->cg_cs.cs_nbfree, -1, needswap);
+ fs->fs_cstotal.cs_nbfree--;
+ fs->fs_cs(fs, ufs_rw32(cgp->cg_cgx, needswap)).cs_nbfree--;
+ fs->fs_fmod = 1;
+ blkno = ufs_rw32(cgp->cg_cgx, needswap) * fs->fs_fpg + bno;
+ return (blkno);
+}
+
+/*
+ * Free a block or fragment.
+ *
+ * The specified block or fragment is placed back in the
+ * free map. If a fragment is deallocated, a possible
+ * block reassembly is checked.
+ */
+void
+ffs_blkfree(struct inode *ip, daddr_t bno, long size)
+{
+ struct cg *cgp;
+ struct buf *bp;
+ int32_t fragno, cgbno;
+ int i, error, cg, blk, frags, bbase;
+ struct fs *fs = ip->i_fs;
+ const int needswap = UFS_FSNEEDSWAP(fs);
+
+ if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
+ fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
+ errx(1, "blkfree: bad size: bno %lld bsize %d size %ld",
+ (long long)bno, fs->fs_bsize, size);
+ }
+ cg = dtog(fs, bno);
+ if (bno >= fs->fs_size) {
+ warnx("bad block %lld, ino %d", (long long)bno, ip->i_number);
+ return;
+ }
+ error = bread(ip->i_fd, ip->i_fs, fsbtodb(fs, cgtod(fs, cg)),
+ (int)fs->fs_cgsize, &bp);
+ if (error) {
+ brelse(bp);
+ return;
+ }
+ cgp = (struct cg *)bp->b_data;
+ if (!cg_chkmagic_swap(cgp, needswap)) {
+ brelse(bp);
+ return;
+ }
+ cgbno = dtogd(fs, bno);
+ if (size == fs->fs_bsize) {
+ fragno = fragstoblks(fs, cgbno);
+ if (!ffs_isfreeblock(fs, cg_blksfree_swap(cgp, needswap), fragno)) {
+ errx(1, "blkfree: freeing free block %lld",
+ (long long)bno);
+ }
+ ffs_setblock(fs, cg_blksfree_swap(cgp, needswap), fragno);
+ ffs_clusteracct(fs, cgp, fragno, 1);
+ ufs_add32(cgp->cg_cs.cs_nbfree, 1, needswap);
+ fs->fs_cstotal.cs_nbfree++;
+ fs->fs_cs(fs, cg).cs_nbfree++;
+ } else {
+ bbase = cgbno - fragnum(fs, cgbno);
+ /*
+ * decrement the counts associated with the old frags
+ */
+ blk = blkmap(fs, cg_blksfree_swap(cgp, needswap), bbase);
+ ffs_fragacct_swap(fs, blk, cgp->cg_frsum, -1, needswap);
+ /*
+ * deallocate the fragment
+ */
+ frags = numfrags(fs, size);
+ for (i = 0; i < frags; i++) {
+ if (isset(cg_blksfree_swap(cgp, needswap), cgbno + i)) {
+ errx(1, "blkfree: freeing free frag: block %lld",
+ (long long)(cgbno + i));
+ }
+ setbit(cg_blksfree_swap(cgp, needswap), cgbno + i);
+ }
+ ufs_add32(cgp->cg_cs.cs_nffree, i, needswap);
+ fs->fs_cstotal.cs_nffree += i;
+ fs->fs_cs(fs, cg).cs_nffree += i;
+ /*
+ * add back in counts associated with the new frags
+ */
+ blk = blkmap(fs, cg_blksfree_swap(cgp, needswap), bbase);
+ ffs_fragacct_swap(fs, blk, cgp->cg_frsum, 1, needswap);
+ /*
+ * if a complete block has been reassembled, account for it
+ */
+ fragno = fragstoblks(fs, bbase);
+ if (ffs_isblock(fs, cg_blksfree_swap(cgp, needswap), fragno)) {
+ ufs_add32(cgp->cg_cs.cs_nffree, -fs->fs_frag, needswap);
+ fs->fs_cstotal.cs_nffree -= fs->fs_frag;
+ fs->fs_cs(fs, cg).cs_nffree -= fs->fs_frag;
+ ffs_clusteracct(fs, cgp, fragno, 1);
+ ufs_add32(cgp->cg_cs.cs_nbfree, 1, needswap);
+ fs->fs_cstotal.cs_nbfree++;
+ fs->fs_cs(fs, cg).cs_nbfree++;
+ }
+ }
+ fs->fs_fmod = 1;
+ bdwrite(bp);
+}
+
+
+static int
+scanc(u_int size, const u_char *cp, const u_char table[], int mask)
+{
+ const u_char *end = &cp[size];
+
+ while (cp < end && (table[*cp] & mask) == 0)
+ cp++;
+ return (end - cp);
+}
+
+/*
+ * Find a block of the specified size in the specified cylinder group.
+ *
+ * It is a panic if a request is made to find a block if none are
+ * available.
+ */
+static int32_t
+ffs_mapsearch(struct fs *fs, struct cg *cgp, daddr_t bpref, int allocsiz)
+{
+ int32_t bno;
+ int start, len, loc, i;
+ int blk, field, subfield, pos;
+ int ostart, olen;
+ const int needswap = UFS_FSNEEDSWAP(fs);
+
+ /*
+ * find the fragment by searching through the free block
+ * map for an appropriate bit pattern
+ */
+ if (bpref)
+ start = dtogd(fs, bpref) / NBBY;
+ else
+ start = ufs_rw32(cgp->cg_frotor, needswap) / NBBY;
+ len = howmany(fs->fs_fpg, NBBY) - start;
+ ostart = start;
+ olen = len;
+ loc = scanc((u_int)len,
+ (const u_char *)&cg_blksfree_swap(cgp, needswap)[start],
+ (const u_char *)fragtbl[fs->fs_frag],
+ (1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
+ if (loc == 0) {
+ len = start + 1;
+ start = 0;
+ loc = scanc((u_int)len,
+ (const u_char *)&cg_blksfree_swap(cgp, needswap)[0],
+ (const u_char *)fragtbl[fs->fs_frag],
+ (1 << (allocsiz - 1 + (fs->fs_frag % NBBY))));
+ if (loc == 0) {
+ errx(1,
+ "ffs_alloccg: map corrupted: start %d len %d offset %d %ld",
+ ostart, olen,
+ ufs_rw32(cgp->cg_freeoff, needswap),
+ (long)cg_blksfree_swap(cgp, needswap) - (long)cgp);
+ /* NOTREACHED */
+ }
+ }
+ bno = (start + len - loc) * NBBY;
+ cgp->cg_frotor = ufs_rw32(bno, needswap);
+ /*
+ * found the byte in the map
+ * sift through the bits to find the selected frag
+ */
+ for (i = bno + NBBY; bno < i; bno += fs->fs_frag) {
+ blk = blkmap(fs, cg_blksfree_swap(cgp, needswap), bno);
+ blk <<= 1;
+ field = around[allocsiz];
+ subfield = inside[allocsiz];
+ for (pos = 0; pos <= fs->fs_frag - allocsiz; pos++) {
+ if ((blk & field) == subfield)
+ return (bno + pos);
+ field <<= 1;
+ subfield <<= 1;
+ }
+ }
+ errx(1, "ffs_alloccg: block not in map: bno %lld", (long long)bno);
+ return (-1);
+}
+
+/*
+ * Update the cluster map because of an allocation or free.
+ *
+ * Cnt == 1 means free; cnt == -1 means allocating.
+ */
+void
+ffs_clusteracct(struct fs *fs, struct cg *cgp, int32_t blkno, int cnt)
+{
+ int32_t *sump;
+ int32_t *lp;
+ u_char *freemapp, *mapp;
+ int i, start, end, forw, back, map, bit;
+ const int needswap = UFS_FSNEEDSWAP(fs);
+
+ if (fs->fs_contigsumsize <= 0)
+ return;
+ freemapp = cg_clustersfree_swap(cgp, needswap);
+ sump = cg_clustersum_swap(cgp, needswap);
+ /*
+ * Allocate or clear the actual block.
+ */
+ if (cnt > 0)
+ setbit(freemapp, blkno);
+ else
+ clrbit(freemapp, blkno);
+ /*
+ * Find the size of the cluster going forward.
+ */
+ start = blkno + 1;
+ end = start + fs->fs_contigsumsize;
+ if (end >= ufs_rw32(cgp->cg_nclusterblks, needswap))
+ end = ufs_rw32(cgp->cg_nclusterblks, needswap);
+ mapp = &freemapp[start / NBBY];
+ map = *mapp++;
+ bit = 1 << (start % NBBY);
+ for (i = start; i < end; i++) {
+ if ((map & bit) == 0)
+ break;
+ if ((i & (NBBY - 1)) != (NBBY - 1)) {
+ bit <<= 1;
+ } else {
+ map = *mapp++;
+ bit = 1;
+ }
+ }
+ forw = i - start;
+ /*
+ * Find the size of the cluster going backward.
+ */
+ start = blkno - 1;
+ end = start - fs->fs_contigsumsize;
+ if (end < 0)
+ end = -1;
+ mapp = &freemapp[start / NBBY];
+ map = *mapp--;
+ bit = 1 << (start % NBBY);
+ for (i = start; i > end; i--) {
+ if ((map & bit) == 0)
+ break;
+ if ((i & (NBBY - 1)) != 0) {
+ bit >>= 1;
+ } else {
+ map = *mapp--;
+ bit = 1 << (NBBY - 1);
+ }
+ }
+ back = start - i;
+ /*
+ * Account for old cluster and the possibly new forward and
+ * back clusters.
+ */
+ i = back + forw + 1;
+ if (i > fs->fs_contigsumsize)
+ i = fs->fs_contigsumsize;
+ ufs_add32(sump[i], cnt, needswap);
+ if (back > 0)
+ ufs_add32(sump[back], -cnt, needswap);
+ if (forw > 0)
+ ufs_add32(sump[forw], -cnt, needswap);
+
+ /*
+ * Update cluster summary information.
+ */
+ lp = &sump[fs->fs_contigsumsize];
+ for (i = fs->fs_contigsumsize; i > 0; i--)
+ if (ufs_rw32(*lp--, needswap) > 0)
+ break;
+ fs->fs_maxcluster[ufs_rw32(cgp->cg_cgx, needswap)] = i;
+}
diff --git a/usr.sbin/makefs/ffs/ffs_balloc.c b/usr.sbin/makefs/ffs/ffs_balloc.c
new file mode 100644
index 0000000..0a048ad
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ffs_balloc.c
@@ -0,0 +1,578 @@
+/* $NetBSD: ffs_balloc.c,v 1.13 2004/06/20 22:20:18 jmc Exp $ */
+/* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 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. 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.
+ *
+ * @(#)ffs_balloc.c 8.8 (Berkeley) 6/16/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "makefs.h"
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include "ffs/ufs_bswap.h"
+#include "ffs/buf.h"
+#include "ffs/ufs_inode.h"
+#include "ffs/ffs_extern.h"
+
+static int ffs_balloc_ufs1(struct inode *, off_t, int, struct buf **);
+static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **);
+
+/*
+ * Balloc defines the structure of file system storage
+ * by allocating the physical blocks on a device given
+ * the inode and the logical block number in a file.
+ *
+ * Assume: flags == B_SYNC | B_CLRBUF
+ */
+
+int
+ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
+{
+ if (ip->i_fs->fs_magic == FS_UFS2_MAGIC)
+ return ffs_balloc_ufs2(ip, offset, bufsize, bpp);
+ else
+ return ffs_balloc_ufs1(ip, offset, bufsize, bpp);
+}
+
+static int
+ffs_balloc_ufs1(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
+{
+ daddr_t lbn, lastlbn;
+ int size;
+ int32_t nb;
+ struct buf *bp, *nbp;
+ struct fs *fs = ip->i_fs;
+ struct indir indirs[NIADDR + 2];
+ daddr_t newb, pref;
+ int32_t *bap;
+ int osize, nsize, num, i, error;
+ int32_t *allocblk, allociblk[NIADDR + 1];
+ int32_t *allocib;
+ const int needswap = UFS_FSNEEDSWAP(fs);
+
+ lbn = lblkno(fs, offset);
+ size = blkoff(fs, offset) + bufsize;
+ if (bpp != NULL) {
+ *bpp = NULL;
+ }
+
+ assert(size <= fs->fs_bsize);
+ if (lbn < 0)
+ return (EFBIG);
+
+ /*
+ * If the next write will extend the file into a new block,
+ * and the file is currently composed of a fragment
+ * this fragment has to be extended to be a full block.
+ */
+
+ lastlbn = lblkno(fs, ip->i_ffs1_size);
+ if (lastlbn < NDADDR && lastlbn < lbn) {
+ nb = lastlbn;
+ osize = blksize(fs, ip, nb);
+ if (osize < fs->fs_bsize && osize > 0) {
+ warnx("need to ffs_realloccg; not supported!");
+ abort();
+ }
+ }
+
+ /*
+ * The first NDADDR blocks are direct blocks
+ */
+
+ if (lbn < NDADDR) {
+ nb = ufs_rw32(ip->i_ffs1_db[lbn], needswap);
+ if (nb != 0 && ip->i_ffs1_size >= lblktosize(fs, lbn + 1)) {
+
+ /*
+ * The block is an already-allocated direct block
+ * and the file already extends past this block,
+ * thus this must be a whole block.
+ * Just read the block (if requested).
+ */
+
+ if (bpp != NULL) {
+ error = bread(ip->i_fd, ip->i_fs, lbn,
+ fs->fs_bsize, bpp);
+ if (error) {
+ brelse(*bpp);
+ return (error);
+ }
+ }
+ return (0);
+ }
+ if (nb != 0) {
+
+ /*
+ * Consider need to reallocate a fragment.
+ */
+
+ osize = fragroundup(fs, blkoff(fs, ip->i_ffs1_size));
+ nsize = fragroundup(fs, size);
+ if (nsize <= osize) {
+
+ /*
+ * The existing block is already
+ * at least as big as we want.
+ * Just read the block (if requested).
+ */
+
+ if (bpp != NULL) {
+ error = bread(ip->i_fd, ip->i_fs, lbn,
+ osize, bpp);
+ if (error) {
+ brelse(*bpp);
+ return (error);
+ }
+ }
+ return 0;
+ } else {
+ warnx("need to ffs_realloccg; not supported!");
+ abort();
+ }
+ } else {
+
+ /*
+ * the block was not previously allocated,
+ * allocate a new block or fragment.
+ */
+
+ if (ip->i_ffs1_size < lblktosize(fs, lbn + 1))
+ nsize = fragroundup(fs, size);
+ else
+ nsize = fs->fs_bsize;
+ error = ffs_alloc(ip, lbn,
+ ffs_blkpref_ufs1(ip, lbn, (int)lbn,
+ &ip->i_ffs1_db[0]),
+ nsize, &newb);
+ if (error)
+ return (error);
+ if (bpp != NULL) {
+ bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
+ bp->b_blkno = fsbtodb(fs, newb);
+ clrbuf(bp);
+ *bpp = bp;
+ }
+ }
+ ip->i_ffs1_db[lbn] = ufs_rw32((int32_t)newb, needswap);
+ return (0);
+ }
+
+ /*
+ * Determine the number of levels of indirection.
+ */
+
+ pref = 0;
+ if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
+ return (error);
+
+ if (num < 1) {
+ warnx("ffs_balloc: ufs_getlbns returned indirect block");
+ abort();
+ }
+
+ /*
+ * Fetch the first indirect block allocating if necessary.
+ */
+
+ --num;
+ nb = ufs_rw32(ip->i_ffs1_ib[indirs[0].in_off], needswap);
+ allocib = NULL;
+ allocblk = allociblk;
+ if (nb == 0) {
+ pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
+ if (error)
+ return error;
+ nb = newb;
+ *allocblk++ = nb;
+ bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
+ bp->b_blkno = fsbtodb(fs, nb);
+ clrbuf(bp);
+ /*
+ * Write synchronously so that indirect blocks
+ * never point at garbage.
+ */
+ if ((error = bwrite(bp)) != 0)
+ return error;
+ allocib = &ip->i_ffs1_ib[indirs[0].in_off];
+ *allocib = ufs_rw32((int32_t)nb, needswap);
+ }
+
+ /*
+ * Fetch through the indirect blocks, allocating as necessary.
+ */
+
+ for (i = 1;;) {
+ error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
+ fs->fs_bsize, &bp);
+ if (error) {
+ brelse(bp);
+ return error;
+ }
+ bap = (int32_t *)bp->b_data;
+ nb = ufs_rw32(bap[indirs[i].in_off], needswap);
+ if (i == num)
+ break;
+ i++;
+ if (nb != 0) {
+ brelse(bp);
+ continue;
+ }
+ if (pref == 0)
+ pref = ffs_blkpref_ufs1(ip, lbn, 0, (int32_t *)0);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
+ if (error) {
+ brelse(bp);
+ return error;
+ }
+ nb = newb;
+ *allocblk++ = nb;
+ nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
+ fs->fs_bsize);
+ nbp->b_blkno = fsbtodb(fs, nb);
+ clrbuf(nbp);
+ /*
+ * Write synchronously so that indirect blocks
+ * never point at garbage.
+ */
+
+ if ((error = bwrite(nbp)) != 0) {
+ brelse(bp);
+ return error;
+ }
+ bap[indirs[i - 1].in_off] = ufs_rw32(nb, needswap);
+
+ bwrite(bp);
+ }
+
+ /*
+ * Get the data block, allocating if necessary.
+ */
+
+ if (nb == 0) {
+ pref = ffs_blkpref_ufs1(ip, lbn, indirs[num].in_off, &bap[0]);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
+ if (error) {
+ brelse(bp);
+ return error;
+ }
+ nb = newb;
+ *allocblk++ = nb;
+ if (bpp != NULL) {
+ nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
+ nbp->b_blkno = fsbtodb(fs, nb);
+ clrbuf(nbp);
+ *bpp = nbp;
+ }
+ bap[indirs[num].in_off] = ufs_rw32(nb, needswap);
+
+ /*
+ * If required, write synchronously, otherwise use
+ * delayed write.
+ */
+ bwrite(bp);
+ return (0);
+ }
+ brelse(bp);
+ if (bpp != NULL) {
+ error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
+ if (error) {
+ brelse(nbp);
+ return error;
+ }
+ *bpp = nbp;
+ }
+ return (0);
+}
+
+static int
+ffs_balloc_ufs2(struct inode *ip, off_t offset, int bufsize, struct buf **bpp)
+{
+ daddr_t lbn, lastlbn;
+ int size;
+ struct buf *bp, *nbp;
+ struct fs *fs = ip->i_fs;
+ struct indir indirs[NIADDR + 2];
+ daddr_t newb, pref, nb;
+ int64_t *bap;
+ int osize, nsize, num, i, error;
+ int64_t *allocblk, allociblk[NIADDR + 1];
+ int64_t *allocib;
+ const int needswap = UFS_FSNEEDSWAP(fs);
+
+ lbn = lblkno(fs, offset);
+ size = blkoff(fs, offset) + bufsize;
+ if (bpp != NULL) {
+ *bpp = NULL;
+ }
+
+ assert(size <= fs->fs_bsize);
+ if (lbn < 0)
+ return (EFBIG);
+
+ /*
+ * If the next write will extend the file into a new block,
+ * and the file is currently composed of a fragment
+ * this fragment has to be extended to be a full block.
+ */
+
+ lastlbn = lblkno(fs, ip->i_ffs2_size);
+ if (lastlbn < NDADDR && lastlbn < lbn) {
+ nb = lastlbn;
+ osize = blksize(fs, ip, nb);
+ if (osize < fs->fs_bsize && osize > 0) {
+ warnx("need to ffs_realloccg; not supported!");
+ abort();
+ }
+ }
+
+ /*
+ * The first NDADDR blocks are direct blocks
+ */
+
+ if (lbn < NDADDR) {
+ nb = ufs_rw64(ip->i_ffs2_db[lbn], needswap);
+ if (nb != 0 && ip->i_ffs2_size >= lblktosize(fs, lbn + 1)) {
+
+ /*
+ * The block is an already-allocated direct block
+ * and the file already extends past this block,
+ * thus this must be a whole block.
+ * Just read the block (if requested).
+ */
+
+ if (bpp != NULL) {
+ error = bread(ip->i_fd, ip->i_fs, lbn,
+ fs->fs_bsize, bpp);
+ if (error) {
+ brelse(*bpp);
+ return (error);
+ }
+ }
+ return (0);
+ }
+ if (nb != 0) {
+
+ /*
+ * Consider need to reallocate a fragment.
+ */
+
+ osize = fragroundup(fs, blkoff(fs, ip->i_ffs2_size));
+ nsize = fragroundup(fs, size);
+ if (nsize <= osize) {
+
+ /*
+ * The existing block is already
+ * at least as big as we want.
+ * Just read the block (if requested).
+ */
+
+ if (bpp != NULL) {
+ error = bread(ip->i_fd, ip->i_fs, lbn,
+ osize, bpp);
+ if (error) {
+ brelse(*bpp);
+ return (error);
+ }
+ }
+ return 0;
+ } else {
+ warnx("need to ffs_realloccg; not supported!");
+ abort();
+ }
+ } else {
+
+ /*
+ * the block was not previously allocated,
+ * allocate a new block or fragment.
+ */
+
+ if (ip->i_ffs2_size < lblktosize(fs, lbn + 1))
+ nsize = fragroundup(fs, size);
+ else
+ nsize = fs->fs_bsize;
+ error = ffs_alloc(ip, lbn,
+ ffs_blkpref_ufs2(ip, lbn, (int)lbn,
+ &ip->i_ffs2_db[0]),
+ nsize, &newb);
+ if (error)
+ return (error);
+ if (bpp != NULL) {
+ bp = getblk(ip->i_fd, ip->i_fs, lbn, nsize);
+ bp->b_blkno = fsbtodb(fs, newb);
+ clrbuf(bp);
+ *bpp = bp;
+ }
+ }
+ ip->i_ffs2_db[lbn] = ufs_rw64(newb, needswap);
+ return (0);
+ }
+
+ /*
+ * Determine the number of levels of indirection.
+ */
+
+ pref = 0;
+ if ((error = ufs_getlbns(ip, lbn, indirs, &num)) != 0)
+ return (error);
+
+ if (num < 1) {
+ warnx("ffs_balloc: ufs_getlbns returned indirect block");
+ abort();
+ }
+
+ /*
+ * Fetch the first indirect block allocating if necessary.
+ */
+
+ --num;
+ nb = ufs_rw64(ip->i_ffs2_ib[indirs[0].in_off], needswap);
+ allocib = NULL;
+ allocblk = allociblk;
+ if (nb == 0) {
+ pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
+ if (error)
+ return error;
+ nb = newb;
+ *allocblk++ = nb;
+ bp = getblk(ip->i_fd, ip->i_fs, indirs[1].in_lbn, fs->fs_bsize);
+ bp->b_blkno = fsbtodb(fs, nb);
+ clrbuf(bp);
+ /*
+ * Write synchronously so that indirect blocks
+ * never point at garbage.
+ */
+ if ((error = bwrite(bp)) != 0)
+ return error;
+ allocib = &ip->i_ffs2_ib[indirs[0].in_off];
+ *allocib = ufs_rw64(nb, needswap);
+ }
+
+ /*
+ * Fetch through the indirect blocks, allocating as necessary.
+ */
+
+ for (i = 1;;) {
+ error = bread(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
+ fs->fs_bsize, &bp);
+ if (error) {
+ brelse(bp);
+ return error;
+ }
+ bap = (int64_t *)bp->b_data;
+ nb = ufs_rw64(bap[indirs[i].in_off], needswap);
+ if (i == num)
+ break;
+ i++;
+ if (nb != 0) {
+ brelse(bp);
+ continue;
+ }
+ if (pref == 0)
+ pref = ffs_blkpref_ufs2(ip, lbn, 0, (int64_t *)0);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
+ if (error) {
+ brelse(bp);
+ return error;
+ }
+ nb = newb;
+ *allocblk++ = nb;
+ nbp = getblk(ip->i_fd, ip->i_fs, indirs[i].in_lbn,
+ fs->fs_bsize);
+ nbp->b_blkno = fsbtodb(fs, nb);
+ clrbuf(nbp);
+ /*
+ * Write synchronously so that indirect blocks
+ * never point at garbage.
+ */
+
+ if ((error = bwrite(nbp)) != 0) {
+ brelse(bp);
+ return error;
+ }
+ bap[indirs[i - 1].in_off] = ufs_rw64(nb, needswap);
+
+ bwrite(bp);
+ }
+
+ /*
+ * Get the data block, allocating if necessary.
+ */
+
+ if (nb == 0) {
+ pref = ffs_blkpref_ufs2(ip, lbn, indirs[num].in_off, &bap[0]);
+ error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, &newb);
+ if (error) {
+ brelse(bp);
+ return error;
+ }
+ nb = newb;
+ *allocblk++ = nb;
+ if (bpp != NULL) {
+ nbp = getblk(ip->i_fd, ip->i_fs, lbn, fs->fs_bsize);
+ nbp->b_blkno = fsbtodb(fs, nb);
+ clrbuf(nbp);
+ *bpp = nbp;
+ }
+ bap[indirs[num].in_off] = ufs_rw64(nb, needswap);
+
+ /*
+ * If required, write synchronously, otherwise use
+ * delayed write.
+ */
+ bwrite(bp);
+ return (0);
+ }
+ brelse(bp);
+ if (bpp != NULL) {
+ error = bread(ip->i_fd, ip->i_fs, lbn, (int)fs->fs_bsize, &nbp);
+ if (error) {
+ brelse(nbp);
+ return error;
+ }
+ *bpp = nbp;
+ }
+ return (0);
+}
diff --git a/usr.sbin/makefs/ffs/ffs_bswap.c b/usr.sbin/makefs/ffs/ffs_bswap.c
new file mode 100644
index 0000000..d560884
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ffs_bswap.c
@@ -0,0 +1,270 @@
+/* $NetBSD: ffs_bswap.c,v 1.28 2004/05/25 14:54:59 hannken Exp $ */
+
+/*
+ * Copyright (c) 1998 Manuel Bouyer.
+ *
+ * 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 Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#if defined(_KERNEL)
+#include <sys/systm.h>
+#endif
+
+#include <ufs/ufs/dinode.h>
+#include "ffs/ufs_bswap.h"
+#include <ufs/ffs/fs.h>
+/* XXX temporary */
+struct ufsmount;
+struct bufobj;
+struct mount;
+struct vnode;
+typedef int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
+ struct vnode **vpp);
+#include <ufs/ffs/ffs_extern.h>
+
+#if !defined(_KERNEL)
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define panic(x) printf("%s\n", (x)), abort()
+#endif
+
+#define fs_old_postbloff fs_spare5[0]
+#define fs_old_rotbloff fs_spare5[1]
+#define fs_old_postbl_start fs_maxbsize
+#define fs_old_headswitch fs_id[0]
+#define fs_old_trkseek fs_id[1]
+#define fs_old_csmask fs_spare1[0]
+#define fs_old_csshift fs_spare1[1]
+
+#define FS_42POSTBLFMT -1 /* 4.2BSD rotational table format */
+#define FS_DYNAMICPOSTBLFMT 1 /* dynamic rotational table format */
+
+void ffs_csum_swap(struct csum *o, struct csum *n, int size);
+void ffs_csumtotal_swap(struct csum_total *o, struct csum_total *n);
+
+void
+ffs_sb_swap(struct fs *o, struct fs *n)
+{
+ int i;
+ u_int32_t *o32, *n32;
+
+ /*
+ * In order to avoid a lot of lines, as the first N fields (52)
+ * of the superblock up to fs_fmod are u_int32_t, we just loop
+ * here to convert them.
+ */
+ o32 = (u_int32_t *)o;
+ n32 = (u_int32_t *)n;
+ for (i = 0; i < offsetof(struct fs, fs_fmod) / sizeof(u_int32_t); i++)
+ n32[i] = bswap32(o32[i]);
+
+ n->fs_swuid = bswap64(o->fs_swuid);
+ n->fs_cgrotor = bswap32(o->fs_cgrotor); /* Unused */
+ n->fs_old_cpc = bswap32(o->fs_old_cpc);
+
+ /* These fields overlap with a possible location for the
+ * historic FS_DYNAMICPOSTBLFMT postbl table, and with the
+ * first half of the historic FS_42POSTBLFMT postbl table.
+ */
+ n->fs_maxbsize = bswap32(o->fs_maxbsize);
+ n->fs_sblockloc = bswap64(o->fs_sblockloc);
+ ffs_csumtotal_swap(&o->fs_cstotal, &n->fs_cstotal);
+ n->fs_time = bswap64(o->fs_time);
+ n->fs_size = bswap64(o->fs_size);
+ n->fs_dsize = bswap64(o->fs_dsize);
+ n->fs_csaddr = bswap64(o->fs_csaddr);
+ n->fs_pendingblocks = bswap64(o->fs_pendingblocks);
+ n->fs_pendinginodes = bswap32(o->fs_pendinginodes);
+
+ /* These fields overlap with the second half of the
+ * historic FS_42POSTBLFMT postbl table
+ */
+ for (i = 0; i < FSMAXSNAP; i++)
+ n->fs_snapinum[i] = bswap32(o->fs_snapinum[i]);
+ n->fs_avgfilesize = bswap32(o->fs_avgfilesize);
+ n->fs_avgfpdir = bswap32(o->fs_avgfpdir);
+ /* fs_sparecon[28] - ignore for now */
+ n->fs_flags = bswap32(o->fs_flags);
+ n->fs_contigsumsize = bswap32(o->fs_contigsumsize);
+ n->fs_maxsymlinklen = bswap32(o->fs_maxsymlinklen);
+ n->fs_old_inodefmt = bswap32(o->fs_old_inodefmt);
+ n->fs_maxfilesize = bswap64(o->fs_maxfilesize);
+ n->fs_qbmask = bswap64(o->fs_qbmask);
+ n->fs_qfmask = bswap64(o->fs_qfmask);
+ n->fs_state = bswap32(o->fs_state);
+ n->fs_old_postblformat = bswap32(o->fs_old_postblformat);
+ n->fs_old_nrpos = bswap32(o->fs_old_nrpos);
+ n->fs_old_postbloff = bswap32(o->fs_old_postbloff);
+ n->fs_old_rotbloff = bswap32(o->fs_old_rotbloff);
+
+ n->fs_magic = bswap32(o->fs_magic);
+}
+
+void
+ffs_dinode1_swap(struct ufs1_dinode *o, struct ufs1_dinode *n)
+{
+
+ n->di_mode = bswap16(o->di_mode);
+ n->di_nlink = bswap16(o->di_nlink);
+ n->di_u.oldids[0] = bswap16(o->di_u.oldids[0]);
+ n->di_u.oldids[1] = bswap16(o->di_u.oldids[1]);
+ n->di_size = bswap64(o->di_size);
+ n->di_atime = bswap32(o->di_atime);
+ n->di_atimensec = bswap32(o->di_atimensec);
+ n->di_mtime = bswap32(o->di_mtime);
+ n->di_mtimensec = bswap32(o->di_mtimensec);
+ n->di_ctime = bswap32(o->di_ctime);
+ n->di_ctimensec = bswap32(o->di_ctimensec);
+ memcpy(n->di_db, o->di_db, (NDADDR + NIADDR) * sizeof(u_int32_t));
+ n->di_flags = bswap32(o->di_flags);
+ n->di_blocks = bswap32(o->di_blocks);
+ n->di_gen = bswap32(o->di_gen);
+ n->di_uid = bswap32(o->di_uid);
+ n->di_gid = bswap32(o->di_gid);
+}
+
+void
+ffs_dinode2_swap(struct ufs2_dinode *o, struct ufs2_dinode *n)
+{
+ n->di_mode = bswap16(o->di_mode);
+ n->di_nlink = bswap16(o->di_nlink);
+ n->di_uid = bswap32(o->di_uid);
+ n->di_gid = bswap32(o->di_gid);
+ n->di_blksize = bswap32(o->di_blksize);
+ n->di_size = bswap64(o->di_size);
+ n->di_blocks = bswap64(o->di_blocks);
+ n->di_atime = bswap64(o->di_atime);
+ n->di_atimensec = bswap32(o->di_atimensec);
+ n->di_mtime = bswap64(o->di_mtime);
+ n->di_mtimensec = bswap32(o->di_mtimensec);
+ n->di_ctime = bswap64(o->di_ctime);
+ n->di_ctimensec = bswap32(o->di_ctimensec);
+ n->di_birthtime = bswap64(o->di_ctime);
+ n->di_birthnsec = bswap32(o->di_ctimensec);
+ n->di_gen = bswap32(o->di_gen);
+ n->di_kernflags = bswap32(o->di_kernflags);
+ n->di_flags = bswap32(o->di_flags);
+ n->di_extsize = bswap32(o->di_extsize);
+ memcpy(n->di_extb, o->di_extb, (NXADDR + NDADDR + NIADDR) * 8);
+}
+
+void
+ffs_csum_swap(struct csum *o, struct csum *n, int size)
+{
+ int i;
+ u_int32_t *oint, *nint;
+
+ oint = (u_int32_t*)o;
+ nint = (u_int32_t*)n;
+
+ for (i = 0; i < size / sizeof(u_int32_t); i++)
+ nint[i] = bswap32(oint[i]);
+}
+
+void
+ffs_csumtotal_swap(struct csum_total *o, struct csum_total *n)
+{
+ n->cs_ndir = bswap64(o->cs_ndir);
+ n->cs_nbfree = bswap64(o->cs_nbfree);
+ n->cs_nifree = bswap64(o->cs_nifree);
+ n->cs_nffree = bswap64(o->cs_nffree);
+}
+
+/*
+ * Note that ffs_cg_swap may be called with o == n.
+ */
+void
+ffs_cg_swap(struct cg *o, struct cg *n, struct fs *fs)
+{
+ int i;
+ u_int32_t *n32, *o32;
+ u_int16_t *n16, *o16;
+ int32_t btotoff, boff, clustersumoff;
+
+ n->cg_firstfield = bswap32(o->cg_firstfield);
+ n->cg_magic = bswap32(o->cg_magic);
+ n->cg_old_time = bswap32(o->cg_old_time);
+ n->cg_cgx = bswap32(o->cg_cgx);
+ n->cg_old_ncyl = bswap16(o->cg_old_ncyl);
+ n->cg_old_niblk = bswap16(o->cg_old_niblk);
+ n->cg_ndblk = bswap32(o->cg_ndblk);
+ n->cg_cs.cs_ndir = bswap32(o->cg_cs.cs_ndir);
+ n->cg_cs.cs_nbfree = bswap32(o->cg_cs.cs_nbfree);
+ n->cg_cs.cs_nifree = bswap32(o->cg_cs.cs_nifree);
+ n->cg_cs.cs_nffree = bswap32(o->cg_cs.cs_nffree);
+ n->cg_rotor = bswap32(o->cg_rotor);
+ n->cg_frotor = bswap32(o->cg_frotor);
+ n->cg_irotor = bswap32(o->cg_irotor);
+ for (i = 0; i < MAXFRAG; i++)
+ n->cg_frsum[i] = bswap32(o->cg_frsum[i]);
+
+ n->cg_old_btotoff = bswap32(o->cg_old_btotoff);
+ n->cg_old_boff = bswap32(o->cg_old_boff);
+ n->cg_iusedoff = bswap32(o->cg_iusedoff);
+ n->cg_freeoff = bswap32(o->cg_freeoff);
+ n->cg_nextfreeoff = bswap32(o->cg_nextfreeoff);
+ n->cg_clustersumoff = bswap32(o->cg_clustersumoff);
+ n->cg_clusteroff = bswap32(o->cg_clusteroff);
+ n->cg_nclusterblks = bswap32(o->cg_nclusterblks);
+ n->cg_niblk = bswap32(o->cg_niblk);
+ n->cg_initediblk = bswap32(o->cg_initediblk);
+ n->cg_time = bswap64(o->cg_time);
+
+ if (fs->fs_magic == FS_UFS2_MAGIC)
+ return;
+
+ if (n->cg_magic == CG_MAGIC) {
+ btotoff = n->cg_old_btotoff;
+ boff = n->cg_old_boff;
+ clustersumoff = n->cg_clustersumoff;
+ } else {
+ btotoff = bswap32(n->cg_old_btotoff);
+ boff = bswap32(n->cg_old_boff);
+ clustersumoff = bswap32(n->cg_clustersumoff);
+ }
+ n32 = (u_int32_t *)((u_int8_t *)n + btotoff);
+ o32 = (u_int32_t *)((u_int8_t *)o + btotoff);
+ n16 = (u_int16_t *)((u_int8_t *)n + boff);
+ o16 = (u_int16_t *)((u_int8_t *)o + boff);
+
+ for (i = 0; i < fs->fs_old_cpg; i++)
+ n32[i] = bswap32(o32[i]);
+
+ for (i = 0; i < fs->fs_old_cpg * fs->fs_old_nrpos; i++)
+ n16[i] = bswap16(o16[i]);
+
+ n32 = (u_int32_t *)((u_int8_t *)n + clustersumoff);
+ o32 = (u_int32_t *)((u_int8_t *)o + clustersumoff);
+ for (i = 1; i < fs->fs_contigsumsize + 1; i++)
+ n32[i] = bswap32(o32[i]);
+}
diff --git a/usr.sbin/makefs/ffs/ffs_extern.h b/usr.sbin/makefs/ffs/ffs_extern.h
new file mode 100644
index 0000000..d95e69b
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ffs_extern.h
@@ -0,0 +1,77 @@
+/* $NetBSD: ffs_extern.h,v 1.6 2003/08/07 11:25:33 agc Exp $ */
+/* From: NetBSD: ffs_extern.h,v 1.19 2001/08/17 02:18:48 lukem Exp */
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * 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. 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.
+ *
+ * @(#)ffs_extern.h 8.6 (Berkeley) 3/30/95
+ * $FreeBSD$
+ */
+
+#include "ffs/buf.h"
+
+/*
+ * Structure used to pass around logical block paths generated by
+ * ufs_getlbns and used by truncate and bmap code.
+ */
+struct indir {
+ daddr_t in_lbn; /* Logical block number. */
+ int in_off; /* Offset in buffer. */
+ int in_exists; /* Flag if the block exists. */
+};
+
+ /* ffs.c */
+void panic(const char *, ...)
+ __attribute__((__noreturn__,__format__(__printf__,1,2)));
+
+ /* ffs_alloc.c */
+int ffs_alloc(struct inode *, daddr_t, daddr_t, int, daddr_t *);
+daddr_t ffs_blkpref_ufs1(struct inode *, daddr_t, int, int32_t *);
+daddr_t ffs_blkpref_ufs2(struct inode *, daddr_t, int, int64_t *);
+void ffs_blkfree(struct inode *, daddr_t, long);
+void ffs_clusteracct(struct fs *, struct cg *, int32_t, int);
+
+ /* ffs_balloc.c */
+int ffs_balloc(struct inode *, off_t, int, struct buf **);
+
+ /* ffs_bswap.c */
+void ffs_sb_swap(struct fs*, struct fs *);
+void ffs_dinode1_swap(struct ufs1_dinode *, struct ufs1_dinode *);
+void ffs_dinode2_swap(struct ufs2_dinode *, struct ufs2_dinode *);
+void ffs_csum_swap(struct csum *, struct csum *, int);
+void ffs_cg_swap(struct cg *, struct cg *, struct fs *);
+
+ /* ffs_subr.c */
+void ffs_fragacct(struct fs *, int, int32_t[], int, int);
+int ffs_isblock(struct fs *, u_char *, int32_t);
+int ffs_isfreeblock(struct fs *, u_char *, int32_t);
+void ffs_clrblock(struct fs *, u_char *, int32_t);
+void ffs_setblock(struct fs *, u_char *, int32_t);
+
+ /* ufs_bmap.c */
+int ufs_getlbns(struct inode *, daddr_t, struct indir *, int *);
diff --git a/usr.sbin/makefs/ffs/ffs_subr.c b/usr.sbin/makefs/ffs/ffs_subr.c
new file mode 100644
index 0000000..5f9b6f2
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ffs_subr.c
@@ -0,0 +1,202 @@
+/* $NetBSD: ffs_subr.c,v 1.32 2003/12/30 12:33:24 pk Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1989, 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. 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.
+ *
+ * @(#)ffs_subr.c 8.5 (Berkeley) 3/21/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+/* XXX temporary */
+struct ufsmount;
+struct bufobj;
+struct mount;
+struct vnode;
+typedef int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
+ struct vnode **vpp);
+#include <ufs/ffs/ffs_extern.h>
+#include "ffs/ufs_bswap.h"
+void panic __P((const char *, ...))
+ __attribute__((__noreturn__,__format__(__printf__,1,2)));
+
+/*
+ * Update the frsum fields to reflect addition or deletion
+ * of some frags.
+ */
+void
+ffs_fragacct_swap(struct fs *fs, int fragmap, int32_t fraglist[], int cnt, int needswap)
+{
+ int inblk;
+ int field, subfield;
+ int siz, pos;
+
+ inblk = (int)(fragtbl[fs->fs_frag][fragmap]) << 1;
+ fragmap <<= 1;
+ for (siz = 1; siz < fs->fs_frag; siz++) {
+ if ((inblk & (1 << (siz + (fs->fs_frag & (NBBY - 1))))) == 0)
+ continue;
+ field = around[siz];
+ subfield = inside[siz];
+ for (pos = siz; pos <= fs->fs_frag; pos++) {
+ if ((fragmap & field) == subfield) {
+ fraglist[siz] = ufs_rw32(
+ ufs_rw32(fraglist[siz], needswap) + cnt,
+ needswap);
+ pos += siz;
+ field <<= siz;
+ subfield <<= siz;
+ }
+ field <<= 1;
+ subfield <<= 1;
+ }
+ }
+}
+
+/*
+ * block operations
+ *
+ * check if a block is available
+ * returns true if all the correponding bits in the free map are 1
+ * returns false if any corresponding bit in the free map is 0
+ */
+int
+ffs_isblock(fs, cp, h)
+ struct fs *fs;
+ u_char *cp;
+ int32_t h;
+{
+ u_char mask;
+
+ switch ((int)fs->fs_fragshift) {
+ case 3:
+ return (cp[h] == 0xff);
+ case 2:
+ mask = 0x0f << ((h & 0x1) << 2);
+ return ((cp[h >> 1] & mask) == mask);
+ case 1:
+ mask = 0x03 << ((h & 0x3) << 1);
+ return ((cp[h >> 2] & mask) == mask);
+ case 0:
+ mask = 0x01 << (h & 0x7);
+ return ((cp[h >> 3] & mask) == mask);
+ default:
+ panic("ffs_isblock: unknown fs_fragshift %d",
+ (int)fs->fs_fragshift);
+ }
+}
+
+/*
+ * check if a block is completely allocated
+ * returns true if all the corresponding bits in the free map are 0
+ * returns false if any corresponding bit in the free map is 1
+ */
+int
+ffs_isfreeblock(fs, cp, h)
+ struct fs *fs;
+ u_char *cp;
+ int32_t h;
+{
+
+ switch ((int)fs->fs_fragshift) {
+ case 3:
+ return (cp[h] == 0);
+ case 2:
+ return ((cp[h >> 1] & (0x0f << ((h & 0x1) << 2))) == 0);
+ case 1:
+ return ((cp[h >> 2] & (0x03 << ((h & 0x3) << 1))) == 0);
+ case 0:
+ return ((cp[h >> 3] & (0x01 << (h & 0x7))) == 0);
+ default:
+ panic("ffs_isfreeblock: unknown fs_fragshift %d",
+ (int)fs->fs_fragshift);
+ }
+}
+
+/*
+ * take a block out of the map
+ */
+void
+ffs_clrblock(fs, cp, h)
+ struct fs *fs;
+ u_char *cp;
+ int32_t h;
+{
+
+ switch ((int)fs->fs_fragshift) {
+ case 3:
+ cp[h] = 0;
+ return;
+ case 2:
+ cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
+ return;
+ case 1:
+ cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
+ return;
+ case 0:
+ cp[h >> 3] &= ~(0x01 << (h & 0x7));
+ return;
+ default:
+ panic("ffs_clrblock: unknown fs_fragshift %d",
+ (int)fs->fs_fragshift);
+ }
+}
+
+/*
+ * put a block into the map
+ */
+void
+ffs_setblock(fs, cp, h)
+ struct fs *fs;
+ u_char *cp;
+ int32_t h;
+{
+
+ switch ((int)fs->fs_fragshift) {
+ case 3:
+ cp[h] = 0xff;
+ return;
+ case 2:
+ cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
+ return;
+ case 1:
+ cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
+ return;
+ case 0:
+ cp[h >> 3] |= (0x01 << (h & 0x7));
+ return;
+ default:
+ panic("ffs_setblock: unknown fs_fragshift %d",
+ (int)fs->fs_fragshift);
+ }
+}
diff --git a/usr.sbin/makefs/ffs/mkfs.c b/usr.sbin/makefs/ffs/mkfs.c
new file mode 100644
index 0000000..ce9ec59
--- /dev/null
+++ b/usr.sbin/makefs/ffs/mkfs.c
@@ -0,0 +1,832 @@
+/* $NetBSD: mkfs.c,v 1.20 2004/06/24 22:30:13 lukem Exp $ */
+
+/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1980, 1989, 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. 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "makefs.h"
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include "ffs/ufs_bswap.h"
+#include "ffs/ufs_inode.h"
+#include "ffs/ffs_extern.h"
+#include "ffs/newfs_extern.h"
+
+static void initcg(int, time_t, const fsinfo_t *);
+static int ilog2(int);
+
+static int count_digits(int);
+
+/*
+ * make file system for cylinder-group style file systems
+ */
+#define UMASK 0755
+#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
+
+union {
+ struct fs fs;
+ char pad[SBLOCKSIZE];
+} fsun;
+#define sblock fsun.fs
+struct csum *fscs;
+
+union {
+ struct cg cg;
+ char pad[FFS_MAXBSIZE];
+} cgun;
+#define acg cgun.cg
+
+char *iobuf;
+int iobufsize;
+
+char writebuf[FFS_MAXBSIZE];
+
+static int Oflag; /* format as an 4.3BSD file system */
+static int64_t fssize; /* file system size */
+static int sectorsize; /* bytes/sector */
+static int fsize; /* fragment size */
+static int bsize; /* block size */
+static int maxbsize; /* maximum clustering */
+static int maxblkspercg;
+static int minfree; /* free space threshold */
+static int opt; /* optimization preference (space or time) */
+static int density; /* number of bytes per inode */
+static int maxcontig; /* max contiguous blocks to allocate */
+static int maxbpg; /* maximum blocks per file in a cyl group */
+static int sbsize; /* superblock size */
+static int avgfilesize; /* expected average file size */
+static int avgfpdir; /* expected number of files per directory */
+
+struct fs *
+ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
+{
+ int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg;
+ int32_t cylno, i, csfrags;
+ long long sizepb;
+ void *space;
+ int size, blks;
+ int nprintcols, printcolwidth;
+
+ Oflag = fsopts->version;
+ fssize = fsopts->size / fsopts->sectorsize;
+ sectorsize = fsopts->sectorsize;
+ fsize = fsopts->fsize;
+ bsize = fsopts->bsize;
+ maxbsize = fsopts->maxbsize;
+ maxblkspercg = fsopts->maxblkspercg;
+ minfree = fsopts->minfree;
+ opt = fsopts->optimization;
+ density = fsopts->density;
+ maxcontig = fsopts->maxcontig;
+ maxbpg = fsopts->maxbpg;
+ avgfilesize = fsopts->avgfilesize;
+ avgfpdir = fsopts->avgfpdir;
+ sbsize = SBLOCKSIZE;
+
+ if (Oflag == 0) {
+ sblock.fs_old_inodefmt = FS_42INODEFMT;
+ sblock.fs_maxsymlinklen = 0;
+ sblock.fs_old_flags = 0;
+ } else {
+ sblock.fs_old_inodefmt = FS_44INODEFMT;
+ sblock.fs_maxsymlinklen = (Oflag == 1 ? MAXSYMLINKLEN_UFS1 :
+ MAXSYMLINKLEN_UFS2);
+ sblock.fs_old_flags = FS_FLAGS_UPDATED;
+ sblock.fs_flags = 0;
+ }
+ /*
+ * Validate the given file system size.
+ * Verify that its last block can actually be accessed.
+ * Convert to file system fragment sized units.
+ */
+ if (fssize <= 0) {
+ printf("preposterous size %lld\n", (long long)fssize);
+ exit(13);
+ }
+ ffs_wtfs(fssize - 1, sectorsize, (char *)&sblock, fsopts);
+
+ /*
+ * collect and verify the filesystem density info
+ */
+ sblock.fs_avgfilesize = avgfilesize;
+ sblock.fs_avgfpdir = avgfpdir;
+ if (sblock.fs_avgfilesize <= 0)
+ printf("illegal expected average file size %d\n",
+ sblock.fs_avgfilesize), exit(14);
+ if (sblock.fs_avgfpdir <= 0)
+ printf("illegal expected number of files per directory %d\n",
+ sblock.fs_avgfpdir), exit(15);
+ /*
+ * collect and verify the block and fragment sizes
+ */
+ sblock.fs_bsize = bsize;
+ sblock.fs_fsize = fsize;
+ if (!POWEROF2(sblock.fs_bsize)) {
+ printf("block size must be a power of 2, not %d\n",
+ sblock.fs_bsize);
+ exit(16);
+ }
+ if (!POWEROF2(sblock.fs_fsize)) {
+ printf("fragment size must be a power of 2, not %d\n",
+ sblock.fs_fsize);
+ exit(17);
+ }
+ if (sblock.fs_fsize < sectorsize) {
+ printf("fragment size %d is too small, minimum is %d\n",
+ sblock.fs_fsize, sectorsize);
+ exit(18);
+ }
+ if (sblock.fs_bsize < MINBSIZE) {
+ printf("block size %d is too small, minimum is %d\n",
+ sblock.fs_bsize, MINBSIZE);
+ exit(19);
+ }
+ if (sblock.fs_bsize > FFS_MAXBSIZE) {
+ printf("block size %d is too large, maximum is %d\n",
+ sblock.fs_bsize, FFS_MAXBSIZE);
+ exit(19);
+ }
+ if (sblock.fs_bsize < sblock.fs_fsize) {
+ printf("block size (%d) cannot be smaller than fragment size (%d)\n",
+ sblock.fs_bsize, sblock.fs_fsize);
+ exit(20);
+ }
+
+ if (maxbsize < bsize || !POWEROF2(maxbsize)) {
+ sblock.fs_maxbsize = sblock.fs_bsize;
+ printf("Extent size set to %d\n", sblock.fs_maxbsize);
+ } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) {
+ sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize;
+ printf("Extent size reduced to %d\n", sblock.fs_maxbsize);
+ } else {
+ sblock.fs_maxbsize = maxbsize;
+ }
+ sblock.fs_maxcontig = maxcontig;
+ if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
+ sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize;
+ printf("Maxcontig raised to %d\n", sblock.fs_maxbsize);
+ }
+
+ if (sblock.fs_maxcontig > 1)
+ sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG);
+
+ sblock.fs_bmask = ~(sblock.fs_bsize - 1);
+ sblock.fs_fmask = ~(sblock.fs_fsize - 1);
+ sblock.fs_qbmask = ~sblock.fs_bmask;
+ sblock.fs_qfmask = ~sblock.fs_fmask;
+ for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
+ sblock.fs_bshift++;
+ for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
+ sblock.fs_fshift++;
+ sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
+ for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
+ sblock.fs_fragshift++;
+ if (sblock.fs_frag > MAXFRAG) {
+ printf("fragment size %d is too small, "
+ "minimum with block size %d is %d\n",
+ sblock.fs_fsize, sblock.fs_bsize,
+ sblock.fs_bsize / MAXFRAG);
+ exit(21);
+ }
+ sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize);
+ sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
+
+ if (Oflag <= 1) {
+ sblock.fs_magic = FS_UFS1_MAGIC;
+ sblock.fs_sblockloc = SBLOCK_UFS1;
+ sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t);
+ sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode);
+ sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) *
+ sizeof (int32_t));
+ sblock.fs_old_inodefmt = FS_44INODEFMT;
+ sblock.fs_old_cgoffset = 0;
+ sblock.fs_old_cgmask = 0xffffffff;
+ sblock.fs_old_size = sblock.fs_size;
+ sblock.fs_old_rotdelay = 0;
+ sblock.fs_old_rps = 60;
+ sblock.fs_old_nspf = sblock.fs_fsize / sectorsize;
+ sblock.fs_old_cpg = 1;
+ sblock.fs_old_interleave = 1;
+ sblock.fs_old_trackskew = 0;
+ sblock.fs_old_cpc = 0;
+ sblock.fs_old_postblformat = 1;
+ sblock.fs_old_nrpos = 1;
+ } else {
+ sblock.fs_magic = FS_UFS2_MAGIC;
+#if 0 /* XXX makefs is used for small filesystems. */
+ sblock.fs_sblockloc = SBLOCK_UFS2;
+#else
+ sblock.fs_sblockloc = SBLOCK_UFS1;
+#endif
+ sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t);
+ sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode);
+ sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) *
+ sizeof (int64_t));
+ }
+
+ sblock.fs_sblkno =
+ roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize),
+ sblock.fs_frag);
+ sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
+ roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag));
+ sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
+ sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
+ for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) {
+ sizepb *= NINDIR(&sblock);
+ sblock.fs_maxfilesize += sizepb;
+ }
+
+ /*
+ * Calculate the number of blocks to put into each cylinder group.
+ *
+ * This algorithm selects the number of blocks per cylinder
+ * group. The first goal is to have at least enough data blocks
+ * in each cylinder group to meet the density requirement. Once
+ * this goal is achieved we try to expand to have at least
+ * 1 cylinder group. Once this goal is achieved, we pack as
+ * many blocks into each cylinder group map as will fit.
+ *
+ * We start by calculating the smallest number of blocks that we
+ * can put into each cylinder group. If this is too big, we reduce
+ * the density until it fits.
+ */
+ origdensity = density;
+ for (;;) {
+ fragsperinode = MAX(numfrags(&sblock, density), 1);
+ minfpg = fragsperinode * INOPB(&sblock);
+ if (minfpg > sblock.fs_size)
+ minfpg = sblock.fs_size;
+ sblock.fs_ipg = INOPB(&sblock);
+ sblock.fs_fpg = roundup(sblock.fs_iblkno +
+ sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
+ if (sblock.fs_fpg < minfpg)
+ sblock.fs_fpg = minfpg;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ sblock.fs_fpg = roundup(sblock.fs_iblkno +
+ sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
+ if (sblock.fs_fpg < minfpg)
+ sblock.fs_fpg = minfpg;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ break;
+ density -= sblock.fs_fsize;
+ }
+ if (density != origdensity)
+ printf("density reduced from %d to %d\n", origdensity, density);
+
+ if (maxblkspercg <= 0 || maxblkspercg >= fssize)
+ maxblkspercg = fssize - 1;
+ /*
+ * Start packing more blocks into the cylinder group until
+ * it cannot grow any larger, the number of cylinder groups
+ * drops below 1, or we reach the size requested.
+ */
+ for ( ; sblock.fs_fpg < maxblkspercg; sblock.fs_fpg += sblock.fs_frag) {
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ if (sblock.fs_size / sblock.fs_fpg < 1)
+ break;
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ continue;
+ if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
+ break;
+ sblock.fs_fpg -= sblock.fs_frag;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ break;
+ }
+ /*
+ * Check to be sure that the last cylinder group has enough blocks
+ * to be viable. If it is too small, reduce the number of blocks
+ * per cylinder group which will have the effect of moving more
+ * blocks into the last cylinder group.
+ */
+ optimalfpg = sblock.fs_fpg;
+ for (;;) {
+ sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
+ lastminfpg = roundup(sblock.fs_iblkno +
+ sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
+ if (sblock.fs_size < lastminfpg) {
+ printf("Filesystem size %lld < minimum size of %d\n",
+ (long long)sblock.fs_size, lastminfpg);
+ exit(28);
+ }
+ if (sblock.fs_size % sblock.fs_fpg >= lastminfpg ||
+ sblock.fs_size % sblock.fs_fpg == 0)
+ break;
+ sblock.fs_fpg -= sblock.fs_frag;
+ sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
+ INOPB(&sblock));
+ }
+ if (optimalfpg != sblock.fs_fpg)
+ printf("Reduced frags per cylinder group from %d to %d %s\n",
+ optimalfpg, sblock.fs_fpg, "to enlarge last cyl group");
+ sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
+ sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
+ if (Oflag <= 1) {
+ sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf;
+ sblock.fs_old_nsect = sblock.fs_old_spc;
+ sblock.fs_old_npsect = sblock.fs_old_spc;
+ sblock.fs_old_ncyl = sblock.fs_ncg;
+ }
+
+ /*
+ * fill in remaining fields of the super block
+ */
+ sblock.fs_csaddr = cgdmin(&sblock, 0);
+ sblock.fs_cssize =
+ fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
+
+ /*
+ * Setup memory for temporary in-core cylgroup summaries.
+ * Cribbed from ffs_mountfs().
+ */
+ size = sblock.fs_cssize;
+ blks = howmany(size, sblock.fs_fsize);
+ if (sblock.fs_contigsumsize > 0)
+ size += sblock.fs_ncg * sizeof(int32_t);
+ if ((space = (char *)calloc(1, size)) == NULL)
+ err(1, "memory allocation error for cg summaries");
+ sblock.fs_csp = space;
+ space = (char *)space + sblock.fs_cssize;
+ if (sblock.fs_contigsumsize > 0) {
+ int32_t *lp;
+
+ sblock.fs_maxcluster = lp = space;
+ for (i = 0; i < sblock.fs_ncg; i++)
+ *lp++ = sblock.fs_contigsumsize;
+ }
+
+ sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
+ if (sblock.fs_sbsize > SBLOCKSIZE)
+ sblock.fs_sbsize = SBLOCKSIZE;
+ sblock.fs_minfree = minfree;
+ sblock.fs_maxcontig = maxcontig;
+ sblock.fs_maxbpg = maxbpg;
+ sblock.fs_optim = opt;
+ sblock.fs_cgrotor = 0;
+ sblock.fs_pendingblocks = 0;
+ sblock.fs_pendinginodes = 0;
+ sblock.fs_cstotal.cs_ndir = 0;
+ sblock.fs_cstotal.cs_nbfree = 0;
+ sblock.fs_cstotal.cs_nifree = 0;
+ sblock.fs_cstotal.cs_nffree = 0;
+ sblock.fs_fmod = 0;
+ sblock.fs_ronly = 0;
+ sblock.fs_state = 0;
+ sblock.fs_clean = FS_ISCLEAN;
+ sblock.fs_ronly = 0;
+ sblock.fs_id[0] = start_time.tv_sec;
+ sblock.fs_id[1] = random();
+ sblock.fs_fsmnt[0] = '\0';
+ csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize);
+ sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno -
+ sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno);
+ sblock.fs_cstotal.cs_nbfree =
+ fragstoblks(&sblock, sblock.fs_dsize) -
+ howmany(csfrags, sblock.fs_frag);
+ sblock.fs_cstotal.cs_nffree =
+ fragnum(&sblock, sblock.fs_size) +
+ (fragnum(&sblock, csfrags) > 0 ?
+ sblock.fs_frag - fragnum(&sblock, csfrags) : 0);
+ sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - ROOTINO;
+ sblock.fs_cstotal.cs_ndir = 0;
+ sblock.fs_dsize -= csfrags;
+ sblock.fs_time = start_time.tv_sec;
+ if (Oflag <= 1) {
+ sblock.fs_old_time = start_time.tv_sec;
+ sblock.fs_old_dsize = sblock.fs_dsize;
+ sblock.fs_old_csaddr = sblock.fs_csaddr;
+ sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
+ sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
+ sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
+ sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
+ }
+ /*
+ * Dump out summary information about file system.
+ */
+#define B2MBFACTOR (1 / (1024.0 * 1024.0))
+ printf("%s: %.1fMB (%lld sectors) block size %d, "
+ "fragment size %d\n",
+ fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
+ (long long)fsbtodb(&sblock, sblock.fs_size),
+ sblock.fs_bsize, sblock.fs_fsize);
+ printf("\tusing %d cylinder groups of %.2fMB, %d blks, "
+ "%d inodes.\n",
+ sblock.fs_ncg,
+ (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
+ sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
+#undef B2MBFACTOR
+ /*
+ * Now determine how wide each column will be, and calculate how
+ * many columns will fit in a 76 char line. 76 is the width of the
+ * subwindows in sysinst.
+ */
+ printcolwidth = count_digits(
+ fsbtodb(&sblock, cgsblock(&sblock, sblock.fs_ncg -1)));
+ nprintcols = 76 / (printcolwidth + 2);
+
+ /*
+ * allocate space for superblock, cylinder group map, and
+ * two sets of inode blocks.
+ */
+ if (sblock.fs_bsize < SBLOCKSIZE)
+ iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize;
+ else
+ iobufsize = 4 * sblock.fs_bsize;
+ if ((iobuf = malloc(iobufsize)) == 0) {
+ printf("Cannot allocate I/O buffer\n");
+ exit(38);
+ }
+ memset(iobuf, 0, iobufsize);
+ /*
+ * Make a copy of the superblock into the buffer that we will be
+ * writing out in each cylinder group.
+ */
+ memcpy(writebuf, &sblock, sbsize);
+ if (fsopts->needswap)
+ ffs_sb_swap(&sblock, (struct fs*)writebuf);
+ memcpy(iobuf, writebuf, SBLOCKSIZE);
+
+ printf("super-block backups (for fsck -b #) at:");
+ for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
+ initcg(cylno, start_time.tv_sec, fsopts);
+ if (cylno % nprintcols == 0)
+ printf("\n");
+ printf(" %*lld,", printcolwidth,
+ (long long)fsbtodb(&sblock, cgsblock(&sblock, cylno)));
+ fflush(stdout);
+ }
+ printf("\n");
+
+ /*
+ * Now construct the initial file system,
+ * then write out the super-block.
+ */
+ sblock.fs_time = start_time.tv_sec;
+ if (Oflag <= 1) {
+ sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
+ sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
+ sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
+ sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
+ }
+ if (fsopts->needswap)
+ sblock.fs_flags |= FS_SWAPPED;
+ ffs_write_superblock(&sblock, fsopts);
+ return (&sblock);
+}
+
+/*
+ * Write out the superblock and its duplicates,
+ * and the cylinder group summaries
+ */
+void
+ffs_write_superblock(struct fs *fs, const fsinfo_t *fsopts)
+{
+ int cylno, size, blks, i, saveflag;
+ void *space;
+ char *wrbuf;
+
+ saveflag = fs->fs_flags & FS_INTERNAL;
+ fs->fs_flags &= ~FS_INTERNAL;
+
+ memcpy(writebuf, &sblock, sbsize);
+ if (fsopts->needswap)
+ ffs_sb_swap(fs, (struct fs*)writebuf);
+ ffs_wtfs(fs->fs_sblockloc / sectorsize, sbsize, writebuf, fsopts);
+
+ /* Write out the duplicate super blocks */
+ for (cylno = 0; cylno < fs->fs_ncg; cylno++)
+ ffs_wtfs(fsbtodb(fs, cgsblock(fs, cylno)),
+ sbsize, writebuf, fsopts);
+
+ /* Write out the cylinder group summaries */
+ size = fs->fs_cssize;
+ blks = howmany(size, fs->fs_fsize);
+ space = (void *)fs->fs_csp;
+ if ((wrbuf = malloc(size)) == NULL)
+ err(1, "ffs_write_superblock: malloc %d", size);
+ for (i = 0; i < blks; i+= fs->fs_frag) {
+ size = fs->fs_bsize;
+ if (i + fs->fs_frag > blks)
+ size = (blks - i) * fs->fs_fsize;
+ if (fsopts->needswap)
+ ffs_csum_swap((struct csum *)space,
+ (struct csum *)wrbuf, size);
+ else
+ memcpy(wrbuf, space, (u_int)size);
+ ffs_wtfs(fsbtodb(fs, fs->fs_csaddr + i), size, wrbuf, fsopts);
+ space = (char *)space + size;
+ }
+ free(wrbuf);
+ fs->fs_flags |= saveflag;
+}
+
+/*
+ * Initialize a cylinder group.
+ */
+static void
+initcg(int cylno, time_t utime, const fsinfo_t *fsopts)
+{
+ daddr_t cbase, dmax;
+ int32_t i, j, d, dlower, dupper, blkno;
+ struct ufs1_dinode *dp1;
+ struct ufs2_dinode *dp2;
+ int start;
+
+ /*
+ * Determine block bounds for cylinder group.
+ * Allow space for super block summary information in first
+ * cylinder group.
+ */
+ cbase = cgbase(&sblock, cylno);
+ dmax = cbase + sblock.fs_fpg;
+ if (dmax > sblock.fs_size)
+ dmax = sblock.fs_size;
+ dlower = cgsblock(&sblock, cylno) - cbase;
+ dupper = cgdmin(&sblock, cylno) - cbase;
+ if (cylno == 0)
+ dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
+ memset(&acg, 0, sblock.fs_cgsize);
+ acg.cg_time = utime;
+ acg.cg_magic = CG_MAGIC;
+ acg.cg_cgx = cylno;
+ acg.cg_niblk = sblock.fs_ipg;
+ acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ?
+ sblock.fs_ipg : 2 * INOPB(&sblock);
+ acg.cg_ndblk = dmax - cbase;
+ if (sblock.fs_contigsumsize > 0)
+ acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift;
+ start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
+ if (Oflag == 2) {
+ acg.cg_iusedoff = start;
+ } else {
+ if (cylno == sblock.fs_ncg - 1)
+ acg.cg_old_ncyl = howmany(acg.cg_ndblk,
+ sblock.fs_fpg / sblock.fs_old_cpg);
+ else
+ acg.cg_old_ncyl = sblock.fs_old_cpg;
+ acg.cg_old_time = acg.cg_time;
+ acg.cg_time = 0;
+ acg.cg_old_niblk = acg.cg_niblk;
+ acg.cg_niblk = 0;
+ acg.cg_initediblk = 0;
+ acg.cg_old_btotoff = start;
+ acg.cg_old_boff = acg.cg_old_btotoff +
+ sblock.fs_old_cpg * sizeof(int32_t);
+ acg.cg_iusedoff = acg.cg_old_boff +
+ sblock.fs_old_cpg * sizeof(u_int16_t);
+ }
+ acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
+ if (sblock.fs_contigsumsize <= 0) {
+ acg.cg_nextfreeoff = acg.cg_freeoff +
+ howmany(sblock.fs_fpg, CHAR_BIT);
+ } else {
+ acg.cg_clustersumoff = acg.cg_freeoff +
+ howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t);
+ acg.cg_clustersumoff =
+ roundup(acg.cg_clustersumoff, sizeof(int32_t));
+ acg.cg_clusteroff = acg.cg_clustersumoff +
+ (sblock.fs_contigsumsize + 1) * sizeof(int32_t);
+ acg.cg_nextfreeoff = acg.cg_clusteroff +
+ howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
+ }
+ if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
+ printf("Panic: cylinder group too big\n");
+ exit(37);
+ }
+ acg.cg_cs.cs_nifree += sblock.fs_ipg;
+ if (cylno == 0)
+ for (i = 0; i < ROOTINO; i++) {
+ setbit(cg_inosused_swap(&acg, 0), i);
+ acg.cg_cs.cs_nifree--;
+ }
+ if (cylno > 0) {
+ /*
+ * In cylno 0, beginning space is reserved
+ * for boot and super blocks.
+ */
+ for (d = 0, blkno = 0; d < dlower;) {
+ ffs_setblock(&sblock, cg_blksfree_swap(&acg, 0), blkno);
+ if (sblock.fs_contigsumsize > 0)
+ setbit(cg_clustersfree_swap(&acg, 0), blkno);
+ acg.cg_cs.cs_nbfree++;
+ d += sblock.fs_frag;
+ blkno++;
+ }
+ }
+ if ((i = (dupper & (sblock.fs_frag - 1))) != 0) {
+ acg.cg_frsum[sblock.fs_frag - i]++;
+ for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
+ setbit(cg_blksfree_swap(&acg, 0), dupper);
+ acg.cg_cs.cs_nffree++;
+ }
+ }
+ for (d = dupper, blkno = dupper >> sblock.fs_fragshift;
+ d + sblock.fs_frag <= acg.cg_ndblk; ) {
+ ffs_setblock(&sblock, cg_blksfree_swap(&acg, 0), blkno);
+ if (sblock.fs_contigsumsize > 0)
+ setbit(cg_clustersfree_swap(&acg, 0), blkno);
+ acg.cg_cs.cs_nbfree++;
+ d += sblock.fs_frag;
+ blkno++;
+ }
+ if (d < acg.cg_ndblk) {
+ acg.cg_frsum[acg.cg_ndblk - d]++;
+ for (; d < acg.cg_ndblk; d++) {
+ setbit(cg_blksfree_swap(&acg, 0), d);
+ acg.cg_cs.cs_nffree++;
+ }
+ }
+ if (sblock.fs_contigsumsize > 0) {
+ int32_t *sump = cg_clustersum_swap(&acg, 0);
+ u_char *mapp = cg_clustersfree_swap(&acg, 0);
+ int map = *mapp++;
+ int bit = 1;
+ int run = 0;
+
+ for (i = 0; i < acg.cg_nclusterblks; i++) {
+ if ((map & bit) != 0) {
+ run++;
+ } else if (run != 0) {
+ if (run > sblock.fs_contigsumsize)
+ run = sblock.fs_contigsumsize;
+ sump[run]++;
+ run = 0;
+ }
+ if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) {
+ bit <<= 1;
+ } else {
+ map = *mapp++;
+ bit = 1;
+ }
+ }
+ if (run != 0) {
+ if (run > sblock.fs_contigsumsize)
+ run = sblock.fs_contigsumsize;
+ sump[run]++;
+ }
+ }
+ sblock.fs_cs(&sblock, cylno) = acg.cg_cs;
+ /*
+ * Write out the duplicate super block, the cylinder group map
+ * and two blocks worth of inodes in a single write.
+ */
+ start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE;
+ memcpy(&iobuf[start], &acg, sblock.fs_cgsize);
+ if (fsopts->needswap)
+ ffs_cg_swap(&acg, (struct cg*)&iobuf[start], &sblock);
+ start += sblock.fs_bsize;
+ dp1 = (struct ufs1_dinode *)(&iobuf[start]);
+ dp2 = (struct ufs2_dinode *)(&iobuf[start]);
+ for (i = 0; i < acg.cg_initediblk; i++) {
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ /* No need to swap, it'll stay random */
+ dp1->di_gen = random();
+ dp1++;
+ } else {
+ dp2->di_gen = random();
+ dp2++;
+ }
+ }
+ ffs_wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf,
+ fsopts);
+ /*
+ * For the old file system, we have to initialize all the inodes.
+ */
+ if (Oflag <= 1) {
+ for (i = 2 * sblock.fs_frag;
+ i < sblock.fs_ipg / INOPF(&sblock);
+ i += sblock.fs_frag) {
+ dp1 = (struct ufs1_dinode *)(&iobuf[start]);
+ for (j = 0; j < INOPB(&sblock); j++) {
+ dp1->di_gen = random();
+ dp1++;
+ }
+ ffs_wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
+ sblock.fs_bsize, &iobuf[start], fsopts);
+ }
+ }
+}
+
+/*
+ * read a block from the file system
+ */
+void
+ffs_rdfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
+{
+ int n;
+ off_t offset;
+
+ offset = bno;
+ offset *= fsopts->sectorsize;
+ if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
+ err(1, "ffs_rdfs: seek error for sector %lld: %s\n",
+ (long long)bno, strerror(errno));
+ n = read(fsopts->fd, bf, size);
+ if (n == -1) {
+ abort();
+ err(1, "ffs_rdfs: read error bno %lld size %d", (long long)bno,
+ size);
+ }
+ else if (n != size)
+ errx(1, "ffs_rdfs: read error for sector %lld: %s\n",
+ (long long)bno, strerror(errno));
+}
+
+/*
+ * write a block to the file system
+ */
+void
+ffs_wtfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
+{
+ int n;
+ off_t offset;
+
+ offset = bno;
+ offset *= fsopts->sectorsize;
+ if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
+ err(1, "wtfs: seek error for sector %lld: %s\n",
+ (long long)bno, strerror(errno));
+ n = write(fsopts->fd, bf, size);
+ if (n == -1)
+ err(1, "wtfs: write error for sector %lld: %s\n",
+ (long long)bno, strerror(errno));
+ else if (n != size)
+ errx(1, "wtfs: write error for sector %lld: %s\n",
+ (long long)bno, strerror(errno));
+}
+
+
+/* Determine how many digits are needed to print a given integer */
+static int
+count_digits(int num)
+{
+ int ndig;
+
+ for(ndig = 1; num > 9; num /=10, ndig++);
+
+ return (ndig);
+}
+
+static int
+ilog2(int val)
+{
+ u_int n;
+
+ for (n = 0; n < sizeof(n) * CHAR_BIT; n++)
+ if (1 << n == val)
+ return (n);
+ errx(1, "ilog2: %d is not a power of 2\n", val);
+}
diff --git a/usr.sbin/makefs/ffs/newfs_extern.h b/usr.sbin/makefs/ffs/newfs_extern.h
new file mode 100644
index 0000000..88559b6
--- /dev/null
+++ b/usr.sbin/makefs/ffs/newfs_extern.h
@@ -0,0 +1,41 @@
+/* $NetBSD: newfs_extern.h,v 1.2 2004/06/24 22:30:13 lukem Exp $ */
+/* From: NetBSD: extern.h,v 1.3 2000/12/01 12:03:27 simonb Exp $ */
+
+/*
+ * Copyright (c) 1997 Christos Zoulas. 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 Christos Zoulas.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+/* prototypes */
+struct fs *ffs_mkfs(const char *, const fsinfo_t *);
+void ffs_write_superblock(struct fs *, const fsinfo_t *);
+void ffs_rdfs(daddr_t, int, void *, const fsinfo_t *);
+void ffs_wtfs(daddr_t, int, void *, const fsinfo_t *);
+
+#define FFS_MAXBSIZE 65536
diff --git a/usr.sbin/makefs/ffs/ufs_bmap.c b/usr.sbin/makefs/ffs/ufs_bmap.c
new file mode 100644
index 0000000..85c1d87
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ufs_bmap.c
@@ -0,0 +1,142 @@
+/* $NetBSD: ufs_bmap.c,v 1.14 2004/06/20 22:20:18 jmc Exp $ */
+/* From: NetBSD: ufs_bmap.c,v 1.14 2001/11/08 05:00:51 chs Exp */
+
+/*
+ * Copyright (c) 1989, 1991, 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. 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.
+ *
+ * @(#)ufs_bmap.c 8.8 (Berkeley) 8/11/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <strings.h>
+
+#include "makefs.h"
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include "ffs/ufs_bswap.h"
+#include "ffs/ufs_inode.h"
+#include "ffs/ffs_extern.h"
+
+/*
+ * Create an array of logical block number/offset pairs which represent the
+ * path of indirect blocks required to access a data block. The first "pair"
+ * contains the logical block number of the appropriate single, double or
+ * triple indirect block and the offset into the inode indirect block array.
+ * Note, the logical block number of the inode single/double/triple indirect
+ * block appears twice in the array, once with the offset into the i_ffs_ib and
+ * once with the offset into the page itself.
+ */
+int
+ufs_getlbns(struct inode *ip, daddr_t bn, struct indir *ap, int *nump)
+{
+ daddr_t metalbn, realbn;
+ int64_t blockcnt;
+ int lbc;
+ int i, numlevels, off;
+ u_long lognindir;
+
+ lognindir = ffs(NINDIR(ip->i_fs)) - 1;
+ if (nump)
+ *nump = 0;
+ numlevels = 0;
+ realbn = bn;
+ if ((long)bn < 0)
+ bn = -(long)bn;
+
+ assert (bn >= NDADDR);
+
+ /*
+ * Determine the number of levels of indirection. After this loop
+ * is done, blockcnt indicates the number of data blocks possible
+ * at the given level of indirection, and NIADDR - i is the number
+ * of levels of indirection needed to locate the requested block.
+ */
+
+ bn -= NDADDR;
+ for (lbc = 0, i = NIADDR;; i--, bn -= blockcnt) {
+ if (i == 0)
+ return (EFBIG);
+
+ lbc += lognindir;
+ blockcnt = (int64_t)1 << lbc;
+
+ if (bn < blockcnt)
+ break;
+ }
+
+ /* Calculate the address of the first meta-block. */
+ if (realbn >= 0)
+ metalbn = -(realbn - bn + NIADDR - i);
+ else
+ metalbn = -(-realbn - bn + NIADDR - i);
+
+ /*
+ * At each iteration, off is the offset into the bap array which is
+ * an array of disk addresses at the current level of indirection.
+ * The logical block number and the offset in that block are stored
+ * into the argument array.
+ */
+ ap->in_lbn = metalbn;
+ ap->in_off = off = NIADDR - i;
+ ap->in_exists = 0;
+ ap++;
+ for (++numlevels; i <= NIADDR; i++) {
+ /* If searching for a meta-data block, quit when found. */
+ if (metalbn == realbn)
+ break;
+
+ lbc -= lognindir;
+ blockcnt = (int64_t)1 << lbc;
+ off = (bn >> lbc) & (NINDIR(ip->i_fs) - 1);
+
+ ++numlevels;
+ ap->in_lbn = metalbn;
+ ap->in_off = off;
+ ap->in_exists = 0;
+ ++ap;
+
+ metalbn -= -1 + (off << lbc);
+ }
+ if (nump)
+ *nump = numlevels;
+ return (0);
+}
diff --git a/usr.sbin/makefs/ffs/ufs_bswap.h b/usr.sbin/makefs/ffs/ufs_bswap.h
new file mode 100644
index 0000000..a6b1270
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ufs_bswap.h
@@ -0,0 +1,94 @@
+/* $NetBSD: ufs_bswap.h,v 1.13 2003/10/05 17:48:50 bouyer Exp $ */
+
+/*
+ * Copyright (c) 1998 Manuel Bouyer.
+ *
+ * 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 Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _UFS_UFS_BSWAP_H_
+#define _UFS_UFS_BSWAP_H_
+
+#if defined(_KERNEL_OPT)
+#include "opt_ffs.h"
+#endif
+
+#include <sys/endian.h>
+
+/* Macros to access UFS flags */
+#ifdef FFS_EI
+#define UFS_MPNEEDSWAP(mp) (VFSTOUFS(mp)->um_flags & UFS_NEEDSWAP)
+#define UFS_FSNEEDSWAP(fs) ((fs)->fs_flags & FS_SWAPPED)
+#define UFS_IPNEEDSWAP(ip) UFS_MPNEEDSWAP(ITOV(ip)->v_mount)
+#else
+#define UFS_MPNEEDSWAP(mp) (0)
+#define UFS_FSNEEDSWAP(fs) (0)
+#define UFS_IPNEEDSWAP(ip) (0)
+#endif
+
+#if !defined(_KERNEL) || defined(FFS_EI)
+/* inlines for access to swapped data */
+static __inline u_int16_t ufs_rw16 __P((u_int16_t, int));
+static __inline u_int32_t ufs_rw32 __P((u_int32_t, int));
+static __inline u_int64_t ufs_rw64 __P((u_int64_t, int));
+
+static __inline u_int16_t
+ufs_rw16(a, ns)
+ u_int16_t a;
+ int ns;
+{
+ return ((ns) ? bswap16(a) : (a));
+}
+static __inline u_int32_t
+ufs_rw32(a, ns)
+ u_int32_t a;
+ int ns;
+{
+ return ((ns) ? bswap32(a) : (a));
+}
+static __inline u_int64_t
+ufs_rw64(a, ns)
+ u_int64_t a;
+ int ns;
+{
+ return ((ns) ? bswap64(a) : (a));
+}
+#else
+#define ufs_rw16(a, ns) ((uint16_t)(a))
+#define ufs_rw32(a, ns) ((uint32_t)(a))
+#define ufs_rw64(a, ns) ((uint64_t)(a))
+#endif
+
+#define ufs_add16(a, b, ns) \
+ (a) = ufs_rw16(ufs_rw16((a), (ns)) + (b), (ns))
+#define ufs_add32(a, b, ns) \
+ (a) = ufs_rw32(ufs_rw32((a), (ns)) + (b), (ns))
+#define ufs_add64(a, b, ns) \
+ (a) = ufs_rw64(ufs_rw64((a), (ns)) + (b), (ns))
+
+#endif /* !_UFS_UFS_BSWAP_H_ */
diff --git a/usr.sbin/makefs/ffs/ufs_inode.h b/usr.sbin/makefs/ffs/ufs_inode.h
new file mode 100644
index 0000000..8286f86
--- /dev/null
+++ b/usr.sbin/makefs/ffs/ufs_inode.h
@@ -0,0 +1,97 @@
+/* $NetBSD: ufs_inode.h,v 1.3 2003/08/07 11:25:34 agc Exp $ */
+/* From: NetBSD: inode.h,v 1.27 2001/12/18 10:57:23 fvdl Exp $ */
+
+/*
+ * Copyright (c) 1982, 1989, 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. 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.
+ *
+ * @(#)inode.h 8.9 (Berkeley) 5/14/95
+ * $FreeBSD$
+ */
+
+union dinode {
+ struct ufs1_dinode ffs1_din;
+ struct ufs2_dinode ffs2_din;
+};
+
+struct inode {
+ ino_t i_number; /* The identity of the inode. */
+ struct fs *i_fs; /* File system */
+ union dinode i_din;
+ int i_fd; /* File descriptor */
+ uint64_t i_size;
+};
+
+#define i_ffs1_atime i_din.ffs1_din.di_atime
+#define i_ffs1_atimensec i_din.ffs1_din.di_atimensec
+#define i_ffs1_blocks i_din.ffs1_din.di_blocks
+#define i_ffs1_ctime i_din.ffs1_din.di_ctime
+#define i_ffs1_ctimensec i_din.ffs1_din.di_ctimensec
+#define i_ffs1_db i_din.ffs1_din.di_db
+#define i_ffs1_flags i_din.ffs1_din.di_flags
+#define i_ffs1_gen i_din.ffs1_din.di_gen
+#define i_ffs11_gid i_din.ffs1_din.di_gid
+#define i_ffs1_ib i_din.ffs1_din.di_ib
+#define i_ffs1_mode i_din.ffs1_din.di_mode
+#define i_ffs1_mtime i_din.ffs1_din.di_mtime
+#define i_ffs1_mtimensec i_din.ffs1_din.di_mtimensec
+#define i_ffs1_nlink i_din.ffs1_din.di_nlink
+#define i_ffs1_rdev i_din.ffs1_din.di_rdev
+#define i_ffs1_shortlink i_din.ffs1_din.db
+#define i_ffs1_size i_din.ffs1_din.di_size
+#define i_ffs1_uid i_din.ffs1_din.di_uid
+
+#define i_ffs2_atime i_din.ffs2_din.di_atime
+#define i_ffs2_atimensec i_din.ffs2_din.di_atimensec
+#define i_ffs2_blocks i_din.ffs2_din.di_blocks
+#define i_ffs2_ctime i_din.ffs2_din.di_ctime
+#define i_ffs2_ctimensec i_din.ffs2_din.di_ctimensec
+#define i_ffs2_birthtime i_din.ffs2_din.di_birthtime
+#define i_ffs2_birthnsec i_din.ffs2_din.di_birthnsec
+#define i_ffs2_db i_din.ffs2_din.di_db
+#define i_ffs2_flags i_din.ffs2_din.di_flags
+#define i_ffs2_gen i_din.ffs2_din.di_gen
+#define i_ffs21_gid i_din.ffs2_din.di_gid
+#define i_ffs2_ib i_din.ffs2_din.di_ib
+#define i_ffs2_mode i_din.ffs2_din.di_mode
+#define i_ffs2_mtime i_din.ffs2_din.di_mtime
+#define i_ffs2_mtimensec i_din.ffs2_din.di_mtimensec
+#define i_ffs2_nlink i_din.ffs2_din.di_nlink
+#define i_ffs2_rdev i_din.ffs2_din.di_rdev
+#define i_ffs2_shortlink i_din.ffs2_din.db
+#define i_ffs2_size i_din.ffs2_din.di_size
+#define i_ffs2_uid i_din.ffs2_din.di_uid
+
+#undef DIP
+#define DIP(ip, field) \
+ (((ip)->i_fs->fs_magic == FS_UFS1_MAGIC) ? \
+ (ip)->i_ffs1_##field : (ip)->i_ffs2_##field)
diff --git a/usr.sbin/makefs/getid.c b/usr.sbin/makefs/getid.c
new file mode 100644
index 0000000..ca52fa3
--- /dev/null
+++ b/usr.sbin/makefs/getid.c
@@ -0,0 +1,436 @@
+/* $NetBSD: getid.c,v 1.5 2004/06/20 22:20:18 jmc Exp $ */
+/* from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */
+/* from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */
+
+/*
+ * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
+ * 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. 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.
+ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn of Wasabi Systems.
+ *
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <grp.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "makefs.h"
+
+#include "mtree.h"
+#include "extern.h"
+
+static struct group * gi_getgrnam(const char *);
+static struct group * gi_getgrgid(gid_t);
+static int gi_setgroupent(int);
+static void gi_endgrent(void);
+static int grstart(void);
+static int grscan(int, gid_t, const char *);
+static int grmatchline(int, gid_t, const char *);
+
+static struct passwd * gi_getpwnam(const char *);
+static struct passwd * gi_getpwuid(uid_t);
+static int gi_setpassent(int);
+static void gi_endpwent(void);
+static int pwstart(void);
+static int pwscan(int, uid_t, const char *);
+static int pwmatchline(int, uid_t, const char *);
+
+#define MAXGRP 200
+#define MAXLINELENGTH 1024
+
+static FILE *_gr_fp;
+static struct group _gr_group;
+static int _gr_stayopen;
+static int _gr_filesdone;
+static FILE *_pw_fp;
+static struct passwd _pw_passwd; /* password structure */
+static int _pw_stayopen; /* keep fd's open */
+static int _pw_filesdone;
+
+static char grfile[MAXPATHLEN];
+static char pwfile[MAXPATHLEN];
+
+static char *members[MAXGRP];
+static char grline[MAXLINELENGTH];
+static char pwline[MAXLINELENGTH];
+
+int
+setup_getid(const char *dir)
+{
+ if (dir == NULL)
+ return (0);
+
+ /* close existing databases */
+ gi_endgrent();
+ gi_endpwent();
+
+ /* build paths to new databases */
+ snprintf(grfile, sizeof(grfile), "%s/group", dir);
+ snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
+
+ /* try to open new databases */
+ if (!grstart() || !pwstart())
+ return (0);
+
+ /* switch pwcache(3) lookup functions */
+ if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
+ gi_getgrnam, gi_getgrgid) == -1
+ || pwcache_userdb(gi_setpassent, gi_endpwent,
+ gi_getpwnam, gi_getpwuid) == -1)
+ return (0);
+
+ return (1);
+}
+
+
+/*
+ * group lookup functions
+ */
+
+static struct group *
+gi_getgrnam(const char *name)
+{
+ int rval;
+
+ if (!grstart())
+ return NULL;
+ rval = grscan(1, 0, name);
+ if (!_gr_stayopen)
+ endgrent();
+ return (rval) ? &_gr_group : NULL;
+}
+
+static struct group *
+gi_getgrgid(gid_t gid)
+{
+ int rval;
+
+ if (!grstart())
+ return NULL;
+ rval = grscan(1, gid, NULL);
+ if (!_gr_stayopen)
+ endgrent();
+ return (rval) ? &_gr_group : NULL;
+}
+
+static int
+gi_setgroupent(int stayopen)
+{
+
+ if (!grstart())
+ return 0;
+ _gr_stayopen = stayopen;
+ return 1;
+}
+
+static void
+gi_endgrent(void)
+{
+
+ _gr_filesdone = 0;
+ if (_gr_fp) {
+ (void)fclose(_gr_fp);
+ _gr_fp = NULL;
+ }
+}
+
+static int
+grstart(void)
+{
+
+ _gr_filesdone = 0;
+ if (_gr_fp) {
+ rewind(_gr_fp);
+ return 1;
+ }
+ if (grfile[0] == '\0') /* sanity check */
+ return 0;
+ return (_gr_fp = fopen(grfile, "r")) ? 1 : 0;
+}
+
+
+static int
+grscan(int search, gid_t gid, const char *name)
+{
+
+ if (_gr_filesdone)
+ return 0;
+ for (;;) {
+ if (!fgets(grline, sizeof(grline), _gr_fp)) {
+ if (!search)
+ _gr_filesdone = 1;
+ return 0;
+ }
+ /* skip lines that are too big */
+ if (!strchr(grline, '\n')) {
+ int ch;
+
+ while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
+ ;
+ continue;
+ }
+ if (grmatchline(search, gid, name))
+ return 1;
+ }
+ /* NOTREACHED */
+}
+
+static int
+grmatchline(int search, gid_t gid, const char *name)
+{
+ unsigned long id;
+ char **m;
+ char *cp, *bp, *ep;
+
+ /* name may be NULL if search is nonzero */
+
+ bp = grline;
+ memset(&_gr_group, 0, sizeof(_gr_group));
+ _gr_group.gr_name = strsep(&bp, ":\n");
+ if (search && name && strcmp(_gr_group.gr_name, name))
+ return 0;
+ _gr_group.gr_passwd = strsep(&bp, ":\n");
+ if (!(cp = strsep(&bp, ":\n")))
+ return 0;
+ id = strtoul(cp, &ep, 10);
+ if (id > GID_MAX || *ep != '\0')
+ return 0;
+ _gr_group.gr_gid = (gid_t)id;
+ if (search && name == NULL && _gr_group.gr_gid != gid)
+ return 0;
+ cp = NULL;
+ if (bp == NULL)
+ return 0;
+ for (_gr_group.gr_mem = m = members;; bp++) {
+ if (m == &members[MAXGRP - 1])
+ break;
+ if (*bp == ',') {
+ if (cp) {
+ *bp = '\0';
+ *m++ = cp;
+ cp = NULL;
+ }
+ } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
+ if (cp) {
+ *bp = '\0';
+ *m++ = cp;
+ }
+ break;
+ } else if (cp == NULL)
+ cp = bp;
+ }
+ *m = NULL;
+ return 1;
+}
+
+
+/*
+ * user lookup functions
+ */
+
+static struct passwd *
+gi_getpwnam(const char *name)
+{
+ int rval;
+
+ if (!pwstart())
+ return NULL;
+ rval = pwscan(1, 0, name);
+ if (!_pw_stayopen)
+ endpwent();
+ return (rval) ? &_pw_passwd : NULL;
+}
+
+static struct passwd *
+gi_getpwuid(uid_t uid)
+{
+ int rval;
+
+ if (!pwstart())
+ return NULL;
+ rval = pwscan(1, uid, NULL);
+ if (!_pw_stayopen)
+ endpwent();
+ return (rval) ? &_pw_passwd : NULL;
+}
+
+static int
+gi_setpassent(int stayopen)
+{
+
+ if (!pwstart())
+ return 0;
+ _pw_stayopen = stayopen;
+ return 1;
+}
+
+static void
+gi_endpwent(void)
+{
+
+ _pw_filesdone = 0;
+ if (_pw_fp) {
+ (void)fclose(_pw_fp);
+ _pw_fp = NULL;
+ }
+}
+
+static int
+pwstart(void)
+{
+
+ _pw_filesdone = 0;
+ if (_pw_fp) {
+ rewind(_pw_fp);
+ return 1;
+ }
+ if (pwfile[0] == '\0') /* sanity check */
+ return 0;
+ return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0;
+}
+
+
+static int
+pwscan(int search, uid_t uid, const char *name)
+{
+
+ if (_pw_filesdone)
+ return 0;
+ for (;;) {
+ if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
+ if (!search)
+ _pw_filesdone = 1;
+ return 0;
+ }
+ /* skip lines that are too big */
+ if (!strchr(pwline, '\n')) {
+ int ch;
+
+ while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
+ ;
+ continue;
+ }
+ if (pwmatchline(search, uid, name))
+ return 1;
+ }
+ /* NOTREACHED */
+}
+
+static int
+pwmatchline(int search, uid_t uid, const char *name)
+{
+ unsigned long id;
+ char *cp, *bp, *ep;
+
+ /* name may be NULL if search is nonzero */
+
+ bp = pwline;
+ memset(&_pw_passwd, 0, sizeof(_pw_passwd));
+ _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */
+ if (search && name && strcmp(_pw_passwd.pw_name, name))
+ return 0;
+
+ _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */
+
+ if (!(cp = strsep(&bp, ":\n"))) /* uid */
+ return 0;
+ id = strtoul(cp, &ep, 10);
+ if (id > UID_MAX || *ep != '\0')
+ return 0;
+ _pw_passwd.pw_uid = (uid_t)id;
+ if (search && name == NULL && _pw_passwd.pw_uid != uid)
+ return 0;
+
+ if (!(cp = strsep(&bp, ":\n"))) /* gid */
+ return 0;
+ id = strtoul(cp, &ep, 10);
+ if (id > GID_MAX || *ep != '\0')
+ return 0;
+ _pw_passwd.pw_gid = (gid_t)id;
+
+ if (!(ep = strsep(&bp, ":"))) /* class */
+ return 0;
+ if (!(ep = strsep(&bp, ":"))) /* change */
+ return 0;
+ if (!(ep = strsep(&bp, ":"))) /* expire */
+ return 0;
+
+ if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */
+ return 0;
+ if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */
+ return 0;
+ if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */
+ return 0;
+
+ if (strchr(bp, ':') != NULL)
+ return 0;
+
+ return 1;
+}
diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8
new file mode 100644
index 0000000..101366a
--- /dev/null
+++ b/usr.sbin/makefs/makefs.8
@@ -0,0 +1,288 @@
+.\" $NetBSD: makefs.8,v 1.13 2004/02/13 17:56:18 wiz Exp $
+.\"
+.\" Copyright (c) 2001-2003 Wasabi Systems, Inc.
+.\" All rights reserved.
+.\"
+.\" Written by Luke Mewburn for Wasabi Systems, 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 for the NetBSD Project by
+.\" Wasabi Systems, Inc.
+.\" 4. The name of Wasabi Systems, Inc. may not be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+.\" 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 30, 2003
+.Dt MAKEFS 8
+.Os
+.Sh NAME
+.Nm makefs
+.Nd create a file system image from a directory tree
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl t Ar fs-type
+.Ek
+.Bk -words
+.Op Fl o Ar fs-options
+.Ek
+.Bk -words
+.Op Fl d Ar debug-mask
+.Ek
+.Bk -words
+.Op Fl B Ar byte-order
+.Ek
+.Bk -words
+.Op Fl S Ar sector-size
+.Ek
+.Bk -words
+.Op Fl M Ar minimum-size
+.Ek
+.Bk -words
+.Op Fl m Ar maximum-size
+.Ek
+.Bk -words
+.Op Fl s Ar image-size
+.Ek
+.Bk -words
+.Op Fl b Ar free-blocks
+.Ek
+.Bk -words
+.Op Fl f Ar free-files
+.Ek
+.Bk -words
+.Op Fl F Ar specfile
+.Ek
+.Op Fl x
+.Bk -words
+.Op Fl N Ar userdb-dir
+.Ek
+.Ar image-file
+.Ar directory
+.Sh DESCRIPTION
+The utility
+.Nm
+creates a file system image into
+.Ar image-file
+from the directory tree
+.Ar directory .
+No special devices or privileges are required to perform this task.
+.Pp
+The options are as follows:
+.Bl -tag -width flag
+.It Fl t Ar fs-type
+Create an
+.Ar fs-type
+file system image.
+The following file system types are supported:
+.Bl -tag -width ffs -offset indent
+.It Sy ffs
+BSD fast file system (default).
+.El
+.It Fl o Ar fs-options
+Set file system specific options.
+.Ar fs-options
+is a comma separated list of options.
+Valid file system specific options are detailed below.
+.It Fl d Ar debug-mask
+Enable various levels of debugging, depending upon which bits are set
+in
+.Ar debug-mask .
+XXX: document these
+.It Fl B Ar byte-order
+Set the byte order of the image to
+.Ar byte-order .
+Valid byte orders are
+.Ql 4321 ,
+.Ql big
+or
+.Ql be
+for big endian, and
+.Ql 1234 ,
+.Ql little
+or
+.Ql le
+for little endian.
+Some file systems may have a fixed byte order; in those cases this
+argument will be ignored.
+.It Fl S Ar sector-size
+Set the file system sector size to
+.Ar sector-size .
+Defaults to 512.
+.It Fl M Ar minimum-size
+Set the minimum size of the file system image to
+.Ar minimum-size .
+.It Fl m Ar maximum-size
+Set the maximum size of the file system image to
+.Ar maximum-size .
+An error will be raised if the target file system needs to be larger
+than this to accommodate the provided directory tree.
+.It Fl s Ar image-size
+Set the size of the file system image to
+.Ar image-size .
+.It Fl b Ar free-blocks
+Ensure that a minimum of
+.Ar free-blocks
+free blocks exist in the image.
+An optional
+.Ql %
+suffix may be provided to indicate that
+.Ar free-blocks
+indicates a percentage of the calculated image size
+.It Fl f Ar free-files
+Ensure that a minimum of
+.Ar free-files
+free files (inodes) exist in the image.
+An optional
+.Ql %
+suffix may be provided to indicate that
+.Ar free-blocks
+indicates a percentage of the calculated image size
+.It Fl F Ar specfile
+Use
+.Ar specfile
+as an
+.Xr mtree 8
+.Sq specfile
+specification.
+.Pp
+If a specfile entry exists in the underlying file system, its permissions and
+modification time will be used unless specifically overridden by the specfile.
+An error will be raised if the type of entry in the specfile conflicts
+with that of an existing entry.
+.Pp
+In the opposite case
+(where a specfile entry does not have an entry in the underlying file system)
+the following occurs:
+If the specfile entry is marked
+.Sy optional ,
+the specfile entry is ignored.
+Otherwise, the entry will be created in the image,
+and it is necessary to specify at least the following parameters
+in the specfile:
+.Sy type ,
+.Sy mode ,
+.Sy gname
+or
+.Sy gid ,
+and
+.Sy uname
+or
+.Sy uid ,
+.Sy device
+(in the case of block or character devices), and
+.Sy link
+(in the case of symbolic links).
+If
+.Sy time
+isn't provided, the current time will be used.
+If
+.Sy flags
+isn't provided, the current file flags will be used.
+Missing regular file entries will be created as zero-length files.
+.It Fl x
+Exclude file system nodes not explcitly listed in the specfile.
+.It Fl N Ar dbdir
+Use the user database text file
+.Pa master.passwd
+and group database text file
+.Pa group
+from
+.Ar dbdir ,
+rather than using the results from the system's
+.Xr getpwnam 3
+and
+.Xr getgrnam 3
+(and related) library calls.
+.El
+.Pp
+Where sizes are specified, a decimal number of bytes is expected.
+Two or more numbers may be separated by an
+.Dq x
+to indicate a product.
+Each number may have one of the following optional suffixes:
+.Bl -tag -width 3n -offset indent -compact
+.It b
+Block; multiply by 512
+.It k
+Kilo; multiply by 1024 (1 KB)
+.It m
+Mega; multiply by 1048576 (1 MB)
+.It g
+Giga; multiply by 1073741824 (1 GB)
+.It t
+Tera; multiply by 1099511627776 (1 TB)
+.It w
+Word; multiply by the number of bytes in an integer
+.El
+.\"
+.\"
+.Ss FFS-specific options
+.Sy ffs
+images have ffs-specific optional parameters that may be provided.
+Each of the options consists of a keyword, an equals sign
+.Pq Ql = ,
+and a value.
+The following keywords are supported:
+.Pp
+.Bl -tag -width optimization -offset indent -compact
+.It Sy avgfilesize
+Expected average file size
+.It Sy avgfpdir
+Expected number of files per directory
+.It Sy bsize
+Block size
+.It Sy density
+Bytes per inode
+.It Sy fsize
+Fragment size
+.It Sy maxbpg
+Maximum blocks per file in a cylinder group
+.It Sy minfree
+Minimum % free
+.It Sy optimization
+Optimization preference; one of
+.Ql space
+or
+.Ql time .
+.It Sy extent
+Maximum extent size
+.It Sy maxbpcg
+Maximum total number of blocks in a cylinder group
+.It Sy version
+UFS version. 1 for FFS (default), 2 for UFS2
+.El
+.Sh SEE ALSO
+.Xr mtree 8 ,
+.Xr newfs 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Nx 1.6 .
+.Sh AUTHORS
+.An Luke Mewburn
+.Aq lukem@NetBSD.org .
diff --git a/usr.sbin/makefs/makefs.c b/usr.sbin/makefs/makefs.c
new file mode 100644
index 0000000..c3e4bd2
--- /dev/null
+++ b/usr.sbin/makefs/makefs.c
@@ -0,0 +1,314 @@
+/* $NetBSD: makefs.c,v 1.20 2004/06/20 22:20:18 jmc Exp $ */
+
+/*
+ * Copyright (c) 2001-2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Luke Mewburn for Wasabi Systems, 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "makefs.h"
+#include "mtree.h"
+
+/*
+ * list of supported file systems and dispatch functions
+ */
+typedef struct {
+ const char *type;
+ int (*parse_options)(const char *, fsinfo_t *);
+ void (*make_fs)(const char *, const char *, fsnode *,
+ fsinfo_t *);
+} fstype_t;
+
+static fstype_t fstypes[] = {
+ { "ffs", ffs_parse_opts, ffs_makefs },
+ { NULL },
+};
+
+u_int debug;
+struct timespec start_time;
+
+static fstype_t *get_fstype(const char *);
+static void usage(void);
+int main(int, char *[]);
+
+int
+main(int argc, char *argv[])
+{
+ struct timeval start;
+ fstype_t *fstype;
+ fsinfo_t fsoptions;
+ fsnode *root;
+ int ch, len;
+ char *specfile;
+
+ setprogname(argv[0]);
+
+ debug = 0;
+ if ((fstype = get_fstype(DEFAULT_FSTYPE)) == NULL)
+ errx(1, "Unknown default fs type `%s'.", DEFAULT_FSTYPE);
+
+ /* set default fsoptions */
+ (void)memset(&fsoptions, 0, sizeof(fsoptions));
+ fsoptions.fd = -1;
+ fsoptions.sectorsize = -1;
+ fsoptions.bsize= -1;
+ fsoptions.fsize= -1;
+ fsoptions.cpg= -1;
+ fsoptions.density= -1;
+ fsoptions.minfree= -1;
+ fsoptions.optimization= -1;
+ fsoptions.maxcontig= -1;
+ fsoptions.maxbpg= -1;
+ fsoptions.avgfilesize= -1;
+ fsoptions.avgfpdir= -1;
+ fsoptions.version = 1;
+
+ specfile = NULL;
+ if (gettimeofday(&start, NULL) == -1)
+ err(1, "Unable to get system time");
+
+ start_time.tv_sec = start.tv_sec;
+ start_time.tv_nsec = start.tv_usec * 1000;
+
+ while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:o:s:S:t:x")) != -1) {
+ switch (ch) {
+
+ case 'B':
+ if (strcmp(optarg, "be") == 0 ||
+ strcmp(optarg, "4321") == 0 ||
+ strcmp(optarg, "big") == 0) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ fsoptions.needswap = 1;
+#endif
+ } else if (strcmp(optarg, "le") == 0 ||
+ strcmp(optarg, "1234") == 0 ||
+ strcmp(optarg, "little") == 0) {
+#if BYTE_ORDER == BIG_ENDIAN
+ fsoptions.needswap = 1;
+#endif
+ } else {
+ warnx("Invalid endian `%s'.", optarg);
+ usage();
+ }
+ break;
+
+ case 'b':
+ len = strlen(optarg) - 1;
+ if (optarg[len] == '%') {
+ optarg[len] = '\0';
+ fsoptions.freeblockpc =
+ strsuftoll("free block percentage",
+ optarg, 0, 99);
+ } else {
+ fsoptions.freeblocks =
+ strsuftoll("free blocks",
+ optarg, 0, LLONG_MAX);
+ }
+ break;
+
+ case 'd':
+ debug =
+ (int)strsuftoll("debug mask", optarg, 0, UINT_MAX);
+ break;
+
+ case 'f':
+ len = strlen(optarg) - 1;
+ if (optarg[len] == '%') {
+ optarg[len] = '\0';
+ fsoptions.freefilepc =
+ strsuftoll("free file percentage",
+ optarg, 0, 99);
+ } else {
+ fsoptions.freefiles =
+ strsuftoll("free files",
+ optarg, 0, LLONG_MAX);
+ }
+ break;
+
+ case 'F':
+ specfile = optarg;
+ break;
+
+ case 'M':
+ fsoptions.minsize =
+ strsuftoll("minimum size", optarg, 1LL, LLONG_MAX);
+ break;
+
+ case 'N':
+ if (! setup_getid(optarg))
+ errx(1,
+ "Unable to use user and group databases in `%s'",
+ optarg);
+ break;
+
+ case 'm':
+ fsoptions.maxsize =
+ strsuftoll("maximum size", optarg, 1LL, LLONG_MAX);
+ break;
+
+ case 'o':
+ {
+ char *p;
+
+ while ((p = strsep(&optarg, ",")) != NULL) {
+ if (*p == '\0')
+ errx(1, "Empty option");
+ if (! fstype->parse_options(p, &fsoptions))
+ usage();
+ }
+ break;
+ }
+
+ case 's':
+ fsoptions.minsize = fsoptions.maxsize =
+ strsuftoll("size", optarg, 1LL, LLONG_MAX);
+ break;
+
+ case 'S':
+ fsoptions.sectorsize =
+ (int)strsuftoll("sector size", optarg,
+ 1LL, INT_MAX);
+ break;
+
+ case 't':
+ if ((fstype = get_fstype(optarg)) == NULL)
+ errx(1, "Unknown fs type `%s'.", optarg);
+ break;
+
+ case 'x':
+ fsoptions.onlyspec = 1;
+ break;
+
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+
+ }
+ }
+ if (debug) {
+ printf("debug mask: 0x%08x\n", debug);
+ printf("start time: %ld.%ld, %s",
+ (long)start_time.tv_sec, (long)start_time.tv_nsec,
+ ctime(&start_time.tv_sec));
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ /* -x must be accompanied by -F */
+ if (fsoptions.onlyspec != 0 && specfile == NULL)
+ errx(1, "-x requires -F mtree-specfile.");
+
+ /* walk the tree */
+ TIMER_START(start);
+ root = walk_dir(argv[1], NULL);
+ TIMER_RESULTS(start, "walk_dir");
+
+ if (specfile) { /* apply a specfile */
+ TIMER_START(start);
+ apply_specfile(specfile, argv[1], root);
+ TIMER_RESULTS(start, "apply_specfile");
+ }
+
+ if (debug & DEBUG_DUMP_FSNODES) {
+ printf("\nparent: %s\n", argv[1]);
+ dump_fsnodes(".", root);
+ putchar('\n');
+ }
+
+ /* build the file system */
+ TIMER_START(start);
+ fstype->make_fs(argv[0], argv[1], root, &fsoptions);
+ TIMER_RESULTS(start, "make_fs");
+
+ exit(0);
+ /* NOTREACHED */
+}
+
+
+int
+set_option(option_t *options, const char *var, const char *val)
+{
+ int i;
+
+ for (i = 0; options[i].name != NULL; i++) {
+ if (strcmp(options[i].name, var) != 0)
+ continue;
+ *options[i].value = (int)strsuftoll(options[i].desc, val,
+ options[i].minimum, options[i].maximum);
+ return (1);
+ }
+ warnx("Unknown option `%s'", var);
+ return (0);
+}
+
+
+static fstype_t *
+get_fstype(const char *type)
+{
+ int i;
+
+ for (i = 0; fstypes[i].type != NULL; i++)
+ if (strcmp(fstypes[i].type, type) == 0)
+ return (&fstypes[i]);
+ return (NULL);
+}
+
+static void
+usage(void)
+{
+ const char *prog;
+
+ prog = getprogname();
+ fprintf(stderr,
+"usage: %s [-t fs-type] [-o fs-options] [-d debug-mask] [-B endian]\n"
+"\t[-S sector-size] [-M minimum-size] [-m maximum-size] [-s image-size]\n"
+"\t[-b free-blocks] [-f free-files] [-F mtree-specfile] [-x]\n"
+"\t[-N userdb-dir] image-file directory\n",
+ prog);
+ exit(1);
+}
diff --git a/usr.sbin/makefs/makefs.h b/usr.sbin/makefs/makefs.h
new file mode 100644
index 0000000..ce18bf8
--- /dev/null
+++ b/usr.sbin/makefs/makefs.h
@@ -0,0 +1,305 @@
+/* $NetBSD: makefs.h,v 1.14 2004/06/20 22:20:18 jmc Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Luke Mewburn for Wasabi Systems, 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MAKEFS_H
+#define _MAKEFS_H
+
+#include <sys/stat.h>
+#include <err.h>
+
+/*
+ * fsnode -
+ * a component of the tree; contains a filename, a pointer to
+ * fsinode, optional symlink name, and tree pointers
+ *
+ * fsinode -
+ * equivalent to an inode, containing target file system inode number,
+ * refcount (nlink), and stat buffer
+ *
+ * A tree of fsnodes looks like this:
+ *
+ * name "." "bin" "netbsd"
+ * type S_IFDIR S_IFDIR S_IFREG
+ * next > > NULL
+ * parent NULL NULL NULL
+ * child NULL v
+ *
+ * name "." "ls"
+ * type S_IFDIR S_IFREG
+ * next > NULL
+ * parent ^ ^ (to "bin")
+ * child NULL NULL
+ *
+ * Notes:
+ * - first always points to first entry, at current level, which
+ * must be "." when the tree has been built; during build it may
+ * not be if "." hasn't yet been found by readdir(2).
+ */
+
+enum fi_flags {
+ FI_SIZED = 1<<0, /* inode sized */
+ FI_ALLOCATED = 1<<1, /* fsinode->ino allocated */
+ FI_WRITTEN = 1<<2, /* inode written */
+};
+
+typedef struct {
+ uint32_t ino; /* inode number used on target fs */
+ uint32_t nlink; /* number of links to this entry */
+ enum fi_flags flags; /* flags used by fs specific code */
+ struct stat st; /* stat entry */
+} fsinode;
+
+typedef struct _fsnode {
+ struct _fsnode *parent; /* parent (NULL if root) */
+ struct _fsnode *child; /* child (if type == S_IFDIR) */
+ struct _fsnode *next; /* next */
+ struct _fsnode *first; /* first node of current level (".") */
+ uint32_t type; /* type of entry */
+ fsinode *inode; /* actual inode data */
+ char *symlink; /* symlink target */
+ char *name; /* file name */
+ int flags; /* misc flags */
+} fsnode;
+
+#define FSNODE_F_HASSPEC 0x01 /* fsnode has a spec entry */
+
+/*
+ * fsinfo_t - contains various settings and parameters pertaining to
+ * the image, including current settings, global options, and fs
+ * specific options
+ */
+typedef struct {
+ /* current settings */
+ off_t size; /* total size */
+ off_t inodes; /* number of inodes */
+ uint32_t curinode; /* current inode */
+
+ /* image settings */
+ int fd; /* file descriptor of image */
+ void *superblock; /* superblock */
+ int onlyspec; /* only add entries in specfile */
+
+
+ /* global options */
+ off_t minsize; /* minimum size image should be */
+ off_t maxsize; /* maximum size image can be */
+ off_t freefiles; /* free file entries to leave */
+ int freefilepc; /* free file % */
+ off_t freeblocks; /* free blocks to leave */
+ int freeblockpc; /* free block % */
+ int needswap; /* non-zero if byte swapping needed */
+ int sectorsize; /* sector size */
+
+ /* ffs specific options */
+ int bsize; /* block size */
+ int fsize; /* fragment size */
+ int cpg; /* cylinders per group */
+ int cpgflg; /* cpg was specified by user */
+ int density; /* bytes per inode */
+ int ntracks; /* number of tracks */
+ int nsectors; /* number of sectors */
+ int rpm; /* rpm */
+ int minfree; /* free space threshold */
+ int optimization; /* optimization (space or time) */
+ int maxcontig; /* max contiguous blocks to allocate */
+ int rotdelay; /* rotational delay between blocks */
+ int maxbpg; /* maximum blocks per file in a cyl group */
+ int nrpos; /* # of distinguished rotational positions */
+ int avgfilesize; /* expected average file size */
+ int avgfpdir; /* expected # of files per directory */
+ int version; /* filesystem version (1 = FFS, 2 = UFS2) */
+ int maxbsize; /* maximum extent size */
+ int maxblkspercg; /* max # of blocks per cylinder group */
+ /* XXX: support `old' file systems ? */
+} fsinfo_t;
+
+
+/*
+ * option_t - contains option name, description, pointer to location to store
+ * result, and range checks for the result. Used to simplify fs specific
+ * option setting
+ */
+typedef struct {
+ const char *name; /* option name */
+ int *value; /* where to stuff the value */
+ int minimum; /* minimum for value */
+ int maximum; /* maximum for value */
+ const char *desc; /* option description */
+} option_t;
+
+
+void apply_specfile(const char *, const char *, fsnode *);
+void dump_fsnodes(const char *, fsnode *);
+const char * inode_type(mode_t);
+int set_option(option_t *, const char *, const char *);
+fsnode * walk_dir(const char *, fsnode *);
+
+int ffs_parse_opts(const char *, fsinfo_t *);
+void ffs_makefs(const char *, const char *, fsnode *, fsinfo_t *);
+
+
+
+extern u_int debug;
+extern struct timespec start_time;
+
+/*
+ * If -x is specified, we want to exclude nodes which do not appear
+ * in the spec file.
+ */
+#define FSNODE_EXCLUDE_P(opts, fsnode) \
+ ((opts)->onlyspec != 0 && ((fsnode)->flags & FSNODE_F_HASSPEC) == 0)
+
+#define DEBUG_TIME 0x00000001
+ /* debug bits 1..3 unused at this time */
+#define DEBUG_WALK_DIR 0x00000010
+#define DEBUG_WALK_DIR_NODE 0x00000020
+#define DEBUG_WALK_DIR_LINKCHECK 0x00000040
+#define DEBUG_DUMP_FSNODES 0x00000080
+#define DEBUG_DUMP_FSNODES_VERBOSE 0x00000100
+#define DEBUG_FS_PARSE_OPTS 0x00000200
+#define DEBUG_FS_MAKEFS 0x00000400
+#define DEBUG_FS_VALIDATE 0x00000800
+#define DEBUG_FS_CREATE_IMAGE 0x00001000
+#define DEBUG_FS_SIZE_DIR 0x00002000
+#define DEBUG_FS_SIZE_DIR_NODE 0x00004000
+#define DEBUG_FS_SIZE_DIR_ADD_DIRENT 0x00008000
+#define DEBUG_FS_POPULATE 0x00010000
+#define DEBUG_FS_POPULATE_DIRBUF 0x00020000
+#define DEBUG_FS_POPULATE_NODE 0x00040000
+#define DEBUG_FS_WRITE_FILE 0x00080000
+#define DEBUG_FS_WRITE_FILE_BLOCK 0x00100000
+#define DEBUG_FS_MAKE_DIRBUF 0x00200000
+#define DEBUG_FS_WRITE_INODE 0x00400000
+#define DEBUG_BUF_BREAD 0x00800000
+#define DEBUG_BUF_BWRITE 0x01000000
+#define DEBUG_BUF_GETBLK 0x02000000
+#define DEBUG_APPLY_SPECFILE 0x04000000
+#define DEBUG_APPLY_SPECENTRY 0x08000000
+
+
+#define TIMER_START(x) \
+ if (debug & DEBUG_TIME) \
+ gettimeofday(&(x), NULL)
+
+#define TIMER_RESULTS(x,d) \
+ if (debug & DEBUG_TIME) { \
+ struct timeval end, td; \
+ gettimeofday(&end, NULL); \
+ timersub(&end, &(x), &td); \
+ printf("%s took %ld.%06ld seconds\n", \
+ (d), (long) td.tv_sec, (long) td.tv_usec); \
+ }
+
+
+#ifndef DEFAULT_FSTYPE
+#define DEFAULT_FSTYPE "ffs"
+#endif
+
+
+/*
+ * ffs specific settings
+ * ---------------------
+ */
+
+#define FFS_EI /* for opposite endian support in ffs headers */
+
+/*
+ * Write-arounds/compat shims for endian-agnostic support.
+ * These belong in the kernel if/when it's possible to mount
+ * filesystems w/ either byte order.
+ */
+
+/*
+ * File system internal flags, also in fs_flags.
+ * (Pick highest number to avoid conflicts with others)
+ */
+#define FS_SWAPPED 0x80000000 /* file system is endian swapped */
+#define FS_INTERNAL 0x80000000 /* mask for internal flags */
+
+#define FS_ISCLEAN 1
+
+#define DINODE1_SIZE (sizeof(struct ufs1_dinode))
+#define DINODE2_SIZE (sizeof(struct ufs2_dinode))
+
+#define MAXSYMLINKLEN_UFS1 ((NDADDR + NIADDR) * sizeof(ufs1_daddr_t))
+#define MAXSYMLINKLEN_UFS2 ((NDADDR + NIADDR) * sizeof(ufs2_daddr_t))
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#define DIRSIZ_SWAP(oldfmt, dp, needswap) \
+ (((oldfmt) && !(needswap)) ? \
+ DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
+#else
+#define DIRSIZ_SWAP(oldfmt, dp, needswap) \
+ (((oldfmt) && (needswap)) ? \
+ DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
+#endif
+
+#define cg_chkmagic_swap(cgp, ns) \
+ (ufs_rw32((cgp)->cg_magic, (ns)) == CG_MAGIC)
+#define cg_inosused_swap(cgp, ns) \
+ ((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_iusedoff, (ns))))
+#define cg_blksfree_swap(cgp, ns) \
+ ((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_freeoff, (ns))))
+#define cg_clustersfree_swap(cgp, ns) \
+ ((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_clusteroff, (ns))))
+#define cg_clustersum_swap(cgp, ns) \
+ ((int32_t *)((uintptr_t)(cgp) + ufs_rw32((cgp)->cg_clustersumoff, ns)))
+
+struct fs;
+void ffs_fragacct_swap(struct fs *, int, int32_t [], int, int);
+
+/*
+ * Declarations for compat routines.
+ */
+long long strsuftoll(const char *, const char *, long long, long long);
+long long strsuftollx(const char *, const char *,
+ long long, long long, char *, size_t);
+
+struct passwd;
+int uid_from_user(const char *, uid_t *);
+int pwcache_userdb(int (*)(int), void (*)(void),
+ struct passwd * (*)(const char *), struct passwd * (*)(uid_t));
+struct group;
+int gid_from_group(const char *, gid_t *);
+int pwcache_groupdb(int (*)(int), void (*)(void),
+ struct group * (*)(const char *), struct group * (*)(gid_t));
+
+int setup_getid(const char *dir);
+
+#endif /* _MAKEFS_H */
diff --git a/usr.sbin/makefs/walk.c b/usr.sbin/makefs/walk.c
new file mode 100644
index 0000000..e485787
--- /dev/null
+++ b/usr.sbin/makefs/walk.c
@@ -0,0 +1,568 @@
+/* $NetBSD: walk.c,v 1.17 2004/06/20 22:20:18 jmc Exp $ */
+
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Luke Mewburn for Wasabi Systems, 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
+/*
+ * The function link_check() was inspired from NetBSD's usr.bin/du/du.c,
+ * which has the following copyright notice:
+ *
+ *
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Newcomb.
+ *
+ * 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. 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "makefs.h"
+
+#include "mtree.h"
+#include "extern.h" /* NB: mtree */
+
+static void apply_specdir(const char *, NODE *, fsnode *);
+static void apply_specentry(const char *, NODE *, fsnode *);
+static fsnode *create_fsnode(const char *, struct stat *);
+static fsinode *link_check(fsinode *);
+
+
+/*
+ * walk_dir --
+ * build a tree of fsnodes from `dir', with a parent fsnode of `parent'
+ * (which may be NULL for the root of the tree).
+ * each "level" is a directory, with the "." entry guaranteed to be
+ * at the start of the list, and without ".." entries.
+ */
+fsnode *
+walk_dir(const char *dir, fsnode *parent)
+{
+ fsnode *first, *cur, *prev;
+ DIR *dirp;
+ struct dirent *dent;
+ char path[MAXPATHLEN + 1];
+ struct stat stbuf;
+
+ assert(dir != NULL);
+
+ if (debug & DEBUG_WALK_DIR)
+ printf("walk_dir: %s %p\n", dir, parent);
+ if ((dirp = opendir(dir)) == NULL)
+ err(1, "Can't opendir `%s'", dir);
+ first = prev = NULL;
+ while ((dent = readdir(dirp)) != NULL) {
+ if (strcmp(dent->d_name, "..") == 0)
+ continue;
+ if (debug & DEBUG_WALK_DIR_NODE)
+ printf("scanning %s/%s\n", dir, dent->d_name);
+ if (snprintf(path, sizeof(path), "%s/%s", dir, dent->d_name)
+ >= sizeof(path))
+ errx(1, "Pathname too long.");
+ if (lstat(path, &stbuf) == -1)
+ err(1, "Can't lstat `%s'", path);
+#ifdef S_ISSOCK
+ if (S_ISSOCK(stbuf.st_mode & S_IFMT)) {
+ if (debug & DEBUG_WALK_DIR_NODE)
+ printf(" skipping socket %s\n", path);
+ continue;
+ }
+#endif
+
+ cur = create_fsnode(dent->d_name, &stbuf);
+ cur->parent = parent;
+ if (strcmp(dent->d_name, ".") == 0) {
+ /* ensure "." is at the start of the list */
+ cur->next = first;
+ first = cur;
+ if (! prev)
+ prev = cur;
+ } else { /* not "." */
+ if (prev)
+ prev->next = cur;
+ prev = cur;
+ if (!first)
+ first = cur;
+ if (S_ISDIR(cur->type)) {
+ cur->child = walk_dir(path, cur);
+ continue;
+ }
+ }
+ if (stbuf.st_nlink > 1) {
+ fsinode *curino;
+
+ curino = link_check(cur->inode);
+ if (curino != NULL) {
+ free(cur->inode);
+ cur->inode = curino;
+ cur->inode->nlink++;
+ }
+ }
+ if (S_ISLNK(cur->type)) {
+ char slink[PATH_MAX+1];
+ int llen;
+
+ llen = readlink(path, slink, sizeof(slink) - 1);
+ if (llen == -1)
+ err(1, "Readlink `%s'", path);
+ slink[llen] = '\0';
+ if ((cur->symlink = strdup(slink)) == NULL)
+ err(1, "Memory allocation error");
+ }
+ }
+ for (cur = first; cur != NULL; cur = cur->next)
+ cur->first = first;
+ if (closedir(dirp) == -1)
+ err(1, "Can't closedir `%s'", dir);
+ return (first);
+}
+
+static fsnode *
+create_fsnode(const char *name, struct stat *stbuf)
+{
+ fsnode *cur;
+
+ if ((cur = calloc(1, sizeof(fsnode))) == NULL ||
+ (cur->name = strdup(name)) == NULL ||
+ (cur->inode = calloc(1, sizeof(fsinode))) == NULL)
+ err(1, "Memory allocation error");
+ cur->type = stbuf->st_mode & S_IFMT;
+ cur->inode->nlink = 1;
+ cur->inode->st = *stbuf;
+ return (cur);
+}
+
+/*
+ * apply_specfile --
+ * read in the mtree(8) specfile, and apply it to the tree
+ * at dir,parent. parameters in parent on equivalent types
+ * will be changed to those found in specfile, and missing
+ * entries will be added.
+ */
+void
+apply_specfile(const char *specfile, const char *dir, fsnode *parent)
+{
+ struct timeval start;
+ FILE *fp;
+ NODE *root;
+
+ assert(specfile != NULL);
+ assert(parent != NULL);
+
+ if (debug & DEBUG_APPLY_SPECFILE)
+ printf("apply_specfile: %s, %s %p\n", specfile, dir, parent);
+
+ /* read in the specfile */
+ if ((fp = fopen(specfile, "r")) == NULL)
+ err(1, "Can't open `%s'", specfile);
+ TIMER_START(start);
+ root = mtree_readspec(fp);
+ TIMER_RESULTS(start, "spec");
+ if (fclose(fp) == EOF)
+ err(1, "Can't close `%s'", specfile);
+
+ /* perform some sanity checks */
+ if (root == NULL)
+ errx(1, "Specfile `%s' did not contain a tree", specfile);
+ assert(strcmp(root->name, ".") == 0);
+ assert(root->type == F_DIR);
+
+ /* merge in the changes */
+ apply_specdir(dir, root, parent);
+}
+
+static u_int
+nodetoino(u_int type)
+{
+
+ switch (type) {
+ case F_BLOCK:
+ return S_IFBLK;
+ case F_CHAR:
+ return S_IFCHR;
+ case F_DIR:
+ return S_IFDIR;
+ case F_FIFO:
+ return S_IFIFO;
+ case F_FILE:
+ return S_IFREG;
+ case F_LINK:
+ return S_IFLNK;
+ case F_SOCK:
+ return S_IFSOCK;
+ default:
+ printf("unknown type %d", type);
+ abort();
+ }
+ /* NOTREACHED */
+}
+
+static void
+apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
+{
+ char path[MAXPATHLEN + 1];
+ NODE *curnode;
+ fsnode *curfsnode;
+
+ assert(specnode != NULL);
+ assert(dirnode != NULL);
+
+ if (debug & DEBUG_APPLY_SPECFILE)
+ printf("apply_specdir: %s %p %p\n", dir, specnode, dirnode);
+
+ if (specnode->type != F_DIR)
+ errx(1, "Specfile node `%s/%s' is not a directory",
+ dir, specnode->name);
+ if (dirnode->type != S_IFDIR)
+ errx(1, "Directory node `%s/%s' is not a directory",
+ dir, dirnode->name);
+
+ apply_specentry(dir, specnode, dirnode);
+
+ /* now walk specnode->child matching up with dirnode */
+ for (curnode = specnode->child; curnode != NULL;
+ curnode = curnode->next) {
+ if (debug & DEBUG_APPLY_SPECENTRY)
+ printf("apply_specdir: spec %s\n",
+ curnode->name);
+ for (curfsnode = dirnode->next; curfsnode != NULL;
+ curfsnode = curfsnode->next) {
+#if 0 /* too verbose for now */
+ if (debug & DEBUG_APPLY_SPECENTRY)
+ printf("apply_specdir: dirent %s\n",
+ curfsnode->name);
+#endif
+ if (strcmp(curnode->name, curfsnode->name) == 0)
+ break;
+ }
+ if (snprintf(path, sizeof(path), "%s/%s",
+ dir, curnode->name) >= sizeof(path))
+ errx(1, "Pathname too long.");
+ if (curfsnode == NULL) { /* need new entry */
+ struct stat stbuf;
+
+ /*
+ * don't add optional spec entries
+ * that lack an existing fs entry
+ */
+ if ((curnode->flags & F_OPT) &&
+ lstat(path, &stbuf) == -1)
+ continue;
+
+ /* check that enough info is provided */
+#define NODETEST(t, m) \
+ if (!(t)) \
+ errx(1, "`%s': %s not provided", path, m)
+ NODETEST(curnode->flags & F_TYPE, "type");
+ NODETEST(curnode->flags & F_MODE, "mode");
+ /* XXX: require F_TIME ? */
+ NODETEST(curnode->flags & F_GID ||
+ curnode->flags & F_GNAME, "group");
+ NODETEST(curnode->flags & F_UID ||
+ curnode->flags & F_UNAME, "user");
+#undef NODETEST
+
+ if (debug & DEBUG_APPLY_SPECFILE)
+ printf("apply_specdir: adding %s\n",
+ curnode->name);
+ /* build minimal fsnode */
+ memset(&stbuf, 0, sizeof(stbuf));
+ stbuf.st_mode = nodetoino(curnode->type);
+ stbuf.st_nlink = 1;
+ stbuf.st_mtime = stbuf.st_atime =
+ stbuf.st_ctime = start_time.tv_sec;
+#if HAVE_STRUCT_STAT_ST_MTIMENSEC
+ stbuf.st_mtimensec = stbuf.st_atimensec =
+ stbuf.st_ctimensec = start_time.tv_nsec;
+#endif
+ curfsnode = create_fsnode(curnode->name, &stbuf);
+ curfsnode->parent = dirnode->parent;
+ curfsnode->first = dirnode;
+ curfsnode->next = dirnode->next;
+ dirnode->next = curfsnode;
+ if (curfsnode->type == S_IFDIR) {
+ /* for dirs, make "." entry as well */
+ curfsnode->child = create_fsnode(".", &stbuf);
+ curfsnode->child->parent = curfsnode;
+ curfsnode->child->first = curfsnode->child;
+ }
+ if (curfsnode->type == S_IFLNK) {
+ assert(curnode->slink != NULL);
+ /* for symlinks, copy the target */
+ if ((curfsnode->symlink =
+ strdup(curnode->slink)) == NULL)
+ err(1, "Memory allocation error");
+ }
+ }
+ apply_specentry(dir, curnode, curfsnode);
+ if (curnode->type == F_DIR) {
+ if (curfsnode->type != S_IFDIR)
+ errx(1, "`%s' is not a directory", path);
+ assert (curfsnode->child != NULL);
+ apply_specdir(path, curnode, curfsnode->child);
+ }
+ }
+}
+
+static void
+apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
+{
+
+ assert(specnode != NULL);
+ assert(dirnode != NULL);
+
+ if (nodetoino(specnode->type) != dirnode->type)
+ errx(1, "`%s/%s' type mismatch: specfile %s, tree %s",
+ dir, specnode->name, inode_type(nodetoino(specnode->type)),
+ inode_type(dirnode->type));
+
+ if (debug & DEBUG_APPLY_SPECENTRY)
+ printf("apply_specentry: %s/%s\n", dir, dirnode->name);
+
+#define ASEPRINT(t, b, o, n) \
+ if (debug & DEBUG_APPLY_SPECENTRY) \
+ printf("\t\t\tchanging %s from " b " to " b "\n", \
+ t, o, n)
+
+ if (specnode->flags & (F_GID | F_GNAME)) {
+ ASEPRINT("gid", "%d",
+ dirnode->inode->st.st_gid, specnode->st_gid);
+ dirnode->inode->st.st_gid = specnode->st_gid;
+ }
+ if (specnode->flags & F_MODE) {
+ ASEPRINT("mode", "%#o",
+ dirnode->inode->st.st_mode & ALLPERMS, specnode->st_mode);
+ dirnode->inode->st.st_mode &= ~ALLPERMS;
+ dirnode->inode->st.st_mode |= (specnode->st_mode & ALLPERMS);
+ }
+ /* XXX: ignoring F_NLINK for now */
+ if (specnode->flags & F_SIZE) {
+ ASEPRINT("size", "%lld",
+ (long long)dirnode->inode->st.st_size,
+ (long long)specnode->st_size);
+ dirnode->inode->st.st_size = specnode->st_size;
+ }
+ if (specnode->flags & F_SLINK) {
+ assert(dirnode->symlink != NULL);
+ assert(specnode->slink != NULL);
+ ASEPRINT("symlink", "%s", dirnode->symlink, specnode->slink);
+ free(dirnode->symlink);
+ if ((dirnode->symlink = strdup(specnode->slink)) == NULL)
+ err(1, "Memory allocation error");
+ }
+ if (specnode->flags & F_TIME) {
+ ASEPRINT("time", "%ld",
+ (long)dirnode->inode->st.st_mtime,
+ (long)specnode->st_mtimespec.tv_sec);
+ dirnode->inode->st.st_mtime = specnode->st_mtimespec.tv_sec;
+ dirnode->inode->st.st_atime = specnode->st_mtimespec.tv_sec;
+ dirnode->inode->st.st_ctime = start_time.tv_sec;
+#if HAVE_STRUCT_STAT_ST_MTIMENSEC
+ dirnode->inode->st.st_mtimensec = specnode->st_mtimespec.tv_nsec;
+ dirnode->inode->st.st_atimensec = specnode->st_mtimespec.tv_nsec;
+ dirnode->inode->st.st_ctimensec = start_time.tv_nsec;
+#endif
+ }
+ if (specnode->flags & (F_UID | F_UNAME)) {
+ ASEPRINT("uid", "%d",
+ dirnode->inode->st.st_uid, specnode->st_uid);
+ dirnode->inode->st.st_uid = specnode->st_uid;
+ }
+#if HAVE_STRUCT_STAT_ST_FLAGS
+ if (specnode->flags & F_FLAGS) {
+ ASEPRINT("flags", "%#lX",
+ (unsigned long)dirnode->inode->st.st_flags,
+ (unsigned long)specnode->st_flags);
+ dirnode->inode->st.st_flags = specnode->st_flags;
+ }
+#endif
+#undef ASEPRINT
+
+ dirnode->flags |= FSNODE_F_HASSPEC;
+}
+
+
+/*
+ * dump_fsnodes --
+ * dump the fsnodes from `cur', based in the directory `dir'
+ */
+void
+dump_fsnodes(const char *dir, fsnode *root)
+{
+ fsnode *cur;
+ char path[MAXPATHLEN + 1];
+
+ assert (dir != NULL);
+ printf("dump_fsnodes: %s %p\n", dir, root);
+ for (cur = root; cur != NULL; cur = cur->next) {
+ if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
+ >= sizeof(path))
+ errx(1, "Pathname too long.");
+
+ if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
+ printf("cur=%8p parent=%8p first=%8p ",
+ cur, cur->parent, cur->first);
+ printf("%7s: %s", inode_type(cur->type), path);
+ if (S_ISLNK(cur->type)) {
+ assert(cur->symlink != NULL);
+ printf(" -> %s", cur->symlink);
+ } else {
+ assert (cur->symlink == NULL);
+ }
+ if (cur->inode->nlink > 1)
+ printf(", nlinks=%d", cur->inode->nlink);
+ putchar('\n');
+
+ if (cur->child) {
+ assert (cur->type == S_IFDIR);
+ dump_fsnodes(path, cur->child);
+ }
+ }
+ printf("dump_fsnodes: finished %s\n", dir);
+}
+
+
+/*
+ * inode_type --
+ * for a given inode type `mode', return a descriptive string.
+ */
+const char *
+inode_type(mode_t mode)
+{
+
+ if (S_ISREG(mode))
+ return ("file");
+ if (S_ISLNK(mode))
+ return ("symlink");
+ if (S_ISDIR(mode))
+ return ("dir");
+ if (S_ISLNK(mode))
+ return ("link");
+ if (S_ISFIFO(mode))
+ return ("fifo");
+ if (S_ISSOCK(mode))
+ return ("socket");
+ /* XXX should not happen but handle them */
+ if (S_ISCHR(mode))
+ return ("char");
+ if (S_ISBLK(mode))
+ return ("block");
+ return ("unknown");
+}
+
+
+/*
+ * link_check --
+ * return pointer to fsnode matching `entry's st_ino & st_dev if it exists,
+ * otherwise add `entry' to table and return NULL
+ */
+static fsinode *
+link_check(fsinode *entry)
+{
+ static struct dupnode {
+ uint32_t dev;
+ uint64_t ino;
+ fsinode *dup;
+ } *dups, *newdups;
+ static int ndups, maxdups;
+
+ int i;
+
+ assert (entry != NULL);
+
+ /* XXX; maybe traverse in reverse for speed? */
+ for (i = 0; i < ndups; i++) {
+ if (dups[i].dev == entry->st.st_dev &&
+ dups[i].ino == entry->st.st_ino) {
+ if (debug & DEBUG_WALK_DIR_LINKCHECK)
+ printf("link_check: found [%d,%d]\n",
+ entry->st.st_dev, entry->st.st_ino);
+ return (dups[i].dup);
+ }
+ }
+
+ if (debug & DEBUG_WALK_DIR_LINKCHECK)
+ printf("link_check: no match for [%d, %d]\n",
+ entry->st.st_dev, entry->st.st_ino);
+ if (ndups == maxdups) {
+ if ((newdups = realloc(dups, sizeof(struct dupnode) * (maxdups + 128)))
+ == NULL)
+ err(1, "Memory allocation error");
+ dups = newdups;
+ maxdups += 128;
+ }
+ dups[ndups].dev = entry->st.st_dev;
+ dups[ndups].ino = entry->st.st_ino;
+ dups[ndups].dup = entry;
+ ndups++;
+
+ return (NULL);
+}
diff --git a/usr.sbin/mergemaster/mergemaster.sh b/usr.sbin/mergemaster/mergemaster.sh
index f8504ec..ee6d2aa 100755
--- a/usr.sbin/mergemaster/mergemaster.sh
+++ b/usr.sbin/mergemaster/mergemaster.sh
@@ -412,7 +412,11 @@ DIFF_FLAG=${DIFF_FLAG:--u}
# Assign the source directory
#
-SOURCEDIR=${SOURCEDIR:-/usr/src/etc}
+SOURCEDIR=${SOURCEDIR:-/usr/src}
+
+#
+# Setup make to use system files from SOURCEDIR
+MAKE="make -m ${SOURCEDIR}/share/mk"
# Check DESTDIR against the mergemaster mtree database to see what
# files the user changed from the reference files.
@@ -548,20 +552,20 @@ case "${RERUN}" in
case "${PRE_WORLD}" in
'')
- { cd ${SOURCEDIR} &&
+ { cd ${SOURCEDIR}/etc &&
case "${DESTDIR}" in
'') ;;
*)
- make DESTDIR=${DESTDIR} ${ARCHSTRING} distrib-dirs
+ ${MAKE} DESTDIR=${DESTDIR} ${ARCHSTRING} distrib-dirs
;;
esac
- make DESTDIR=${TEMPROOT} ${ARCHSTRING} distrib-dirs &&
- MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj make ${ARCHSTRING} obj &&
- MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj make ${ARCHSTRING} all &&
- MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj make ${ARCHSTRING} \
+ ${MAKE} DESTDIR=${TEMPROOT} ${ARCHSTRING} distrib-dirs &&
+ MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj ${MAKE} ${ARCHSTRING} obj &&
+ MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj ${MAKE} ${ARCHSTRING} all &&
+ MAKEOBJDIRPREFIX=${TEMPROOT}/usr/obj ${MAKE} ${ARCHSTRING} \
DESTDIR=${TEMPROOT} distribution;} ||
{ echo '';
- echo " *** FATAL ERROR: Cannot 'cd' to ${SOURCEDIR} and install files to";
+ echo " *** FATAL ERROR: Cannot 'cd' to ${SOURCEDIR}/etc and install files to";
echo " the temproot environment";
echo '';
exit 1;}
@@ -569,8 +573,8 @@ case "${RERUN}" in
*)
# Only set up files that are crucial to {build|install}world
{ mkdir -p ${TEMPROOT}/etc &&
- cp -p ${SOURCEDIR}/master.passwd ${TEMPROOT}/etc &&
- cp -p ${SOURCEDIR}/group ${TEMPROOT}/etc;} ||
+ cp -p ${SOURCEDIR}/etc/master.passwd ${TEMPROOT}/etc &&
+ cp -p ${SOURCEDIR}/etc/group ${TEMPROOT}/etc;} ||
{ echo '';
echo ' *** FATAL ERROR: Cannot copy files to the temproot environment';
echo '';
@@ -647,7 +651,7 @@ if [ -z "${NEW_UMASK}" -a -z "${AUTO_RUN}" ]; then
echo ''
echo " *** Your umask is currently set to ${USER_UMASK}. By default, this script"
echo " installs all files with the same user, group and modes that"
- echo " they are created with by ${SOURCEDIR}/Makefile, compared to"
+ echo " they are created with by ${SOURCEDIR}/etc/Makefile, compared to"
echo " a umask of 022. This umask allows world read permission when"
echo " the file's default permissions have it."
echo ''
@@ -904,7 +908,7 @@ if [ -r "${MM_PRE_COMPARE_SCRIPT}" ]; then
fi
# Using -size +0 avoids uselessly checking the empty log files created
-# by ${SOURCEDIR}/Makefile and the device entries in ./dev, but does
+# by ${SOURCEDIR}/etc/Makefile and the device entries in ./dev, but does
# check the scripts in ./dev, as we'd like (assuming no devfs of course).
#
for COMPFILE in `find . -type f -size +0`; do
@@ -1206,7 +1210,7 @@ esac
case "${PRE_WORLD}" in
'') ;;
*)
- MAKE_CONF="${SOURCEDIR%etc}share/examples/etc/make.conf"
+ MAKE_CONF="${SOURCEDIR}/share/examples/etc/make.conf"
(echo ''
echo '*** Comparing make variables'
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c
index 86bd124..a158fb2 100644
--- a/usr.sbin/ndp/ndp.c
+++ b/usr.sbin/ndp/ndp.c
@@ -114,6 +114,11 @@
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+#define NEXTADDR(w, s) \
+ if (rtm->rtm_addrs & (w)) { \
+ bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
+
+
static pid_t pid;
static int nflag;
static int tflag;
@@ -428,7 +433,6 @@ set(argc, argv)
sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin6_len) + (char *)sin);
if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) {
if (sdl->sdl_family == AF_LINK &&
- (rtm->rtm_flags & RTF_LLINFO) &&
!(rtm->rtm_flags & RTF_GATEWAY)) {
switch (sdl->sdl_type) {
case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
@@ -499,6 +503,7 @@ delete(host)
{
struct sockaddr_in6 *sin = &sin_m;
register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
+ register char *cp = m_rtmsg.m_space;
struct sockaddr_dl *sdl;
struct addrinfo hints, *res;
int gai_error;
@@ -529,7 +534,6 @@ delete(host)
sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin6_len) + (char *)sin);
if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) {
if (sdl->sdl_family == AF_LINK &&
- (rtm->rtm_flags & RTF_LLINFO) &&
!(rtm->rtm_flags & RTF_GATEWAY)) {
goto delete;
}
@@ -545,6 +549,11 @@ delete:
printf("cannot locate %s\n", host);
return (1);
}
+ /*
+ * need to reinit the field because it has rt_key
+ * but we want the actual address
+ */
+ NEXTADDR(RTA_DST, sin_m);
if (rtmsg(RTM_DELETE) == 0) {
struct sockaddr_in6 s6 = *sin; /* XXX: for safety */
@@ -603,7 +612,11 @@ again:;
mib[2] = 0;
mib[3] = AF_INET6;
mib[4] = NET_RT_FLAGS;
+#ifdef RTF_LLINFO
mib[5] = RTF_LLINFO;
+#else
+ mib[5] = 0;
+#endif
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "sysctl(PF_ROUTE estimate)");
if (needed > 0) {
@@ -893,9 +906,6 @@ rtmsg(cmd)
case RTM_GET:
rtm->rtm_addrs |= RTA_DST;
}
-#define NEXTADDR(w, s) \
- if (rtm->rtm_addrs & (w)) { \
- bcopy((char *)&s, cp, sizeof(s)); cp += SA_SIZE(&s);}
NEXTADDR(RTA_DST, sin_m);
NEXTADDR(RTA_GATEWAY, sdl_m);
@@ -1616,3 +1626,5 @@ ts_print(tvp)
(void)printf("%02d:%02d:%02d.%06u ",
s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
}
+
+#undef NEXTADDR
diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c
index fdc6002..7609681 100644
--- a/usr.sbin/ppp/route.c
+++ b/usr.sbin/ppp/route.c
@@ -157,13 +157,21 @@ static struct bits {
{ RTF_DYNAMIC, 'D' },
{ RTF_MODIFIED, 'M' },
{ RTF_DONE, 'd' },
- { RTF_CLONING, 'C' },
{ RTF_XRESOLVE, 'X' },
- { RTF_LLINFO, 'L' },
+#ifdef RTF_CLONING
+ { RTF_CLONING, 'C' },
+#endif
{ RTF_STATIC, 'S' },
{ RTF_PROTO1, '1' },
{ RTF_PROTO2, '2' },
{ RTF_BLACKHOLE, 'B' },
+
+#ifdef RTF_LLINFO
+ { RTF_LLINFO, 'L' },
+#endif
+#ifdef RTF_CLONING
+ { RTF_CLONING, 'C' },
+#endif
#ifdef RTF_WASCLONED
{ RTF_WASCLONED, 'W' },
#endif
@@ -902,8 +910,10 @@ rt_Update(struct bundle *bundle, const struct sockaddr *dst,
p += memcpy_roundup(p, dst, dst->sa_len);
}
- rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
+ if (gw != NULL && (gw->sa_family != AF_LINK))
+ rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
p += memcpy_roundup(p, gw, gw->sa_len);
+
if (mask) {
rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
p += memcpy_roundup(p, mask, mask->sa_len);
diff --git a/usr.sbin/route6d/route6d.c b/usr.sbin/route6d/route6d.c
index 17ddb58..0205a03 100644
--- a/usr.sbin/route6d/route6d.c
+++ b/usr.sbin/route6d/route6d.c
@@ -1752,7 +1752,6 @@ rtrecv()
continue;
case RTM_LOSING:
case RTM_MISS:
- case RTM_RESOLVE:
case RTM_GET:
case RTM_LOCK:
/* nothing to be done here */
@@ -1790,7 +1789,6 @@ rtrecv()
case RTM_ADD:
case RTM_LOSING:
case RTM_MISS:
- case RTM_RESOLVE:
case RTM_GET:
case RTM_LOCK:
/* should already be handled */
@@ -2141,10 +2139,7 @@ ifrt(ifcp, again)
rrt->rrt_info.rip6_tag = htons(routetag & 0xffff);
rrt->rrt_info.rip6_metric = 1 + ifcp->ifc_metric;
rrt->rrt_info.rip6_plen = ifa->ifa_plen;
- if (ifa->ifa_plen == 128)
- rrt->rrt_flags = RTF_HOST;
- else
- rrt->rrt_flags = RTF_CLONING;
+ rrt->rrt_flags = RTF_HOST;
rrt->rrt_rflags |= RRTF_CHANGED;
applyplen(&rrt->rrt_info.rip6_dest, ifa->ifa_plen);
memset(&rrt->rrt_gw, 0, sizeof(struct in6_addr));
@@ -2433,7 +2428,6 @@ do { \
RTTYPE("LOCK", RTM_LOCK);
RTTYPE("OLDADD", RTM_OLDADD);
RTTYPE("OLDDEL", RTM_OLDDEL);
- RTTYPE("RESOLVE", RTM_RESOLVE);
RTTYPE("NEWADDR", RTM_NEWADDR);
RTTYPE("DELADDR", RTM_DELADDR);
RTTYPE("IFINFO", RTM_IFINFO);
@@ -2484,7 +2478,9 @@ do { \
#ifdef RTF_MASK
RTFLAG("m", RTF_MASK);
#endif
+#ifdef RTF_CLONING
RTFLAG("C", RTF_CLONING);
+#endif
#ifdef RTF_CLONED
RTFLAG("c", RTF_CLONED);
#endif
@@ -2495,7 +2491,9 @@ do { \
RTFLAG("W", RTF_WASCLONED);
#endif
RTFLAG("X", RTF_XRESOLVE);
+#ifdef RTF_LLINFO
RTFLAG("L", RTF_LLINFO);
+#endif
RTFLAG("S", RTF_STATIC);
RTFLAG("B", RTF_BLACKHOLE);
#ifdef RTF_PROTO3
@@ -2631,7 +2629,7 @@ rt_entry(rtm, again)
sin6_dst = sin6_gw = sin6_mask = sin6_genmask = sin6_ifp = 0;
if ((rtm->rtm_flags & RTF_UP) == 0 || rtm->rtm_flags &
- (RTF_CLONING|RTF_XRESOLVE|RTF_LLINFO|RTF_BLACKHOLE)) {
+ (RTF_XRESOLVE|RTF_BLACKHOLE)) {
return; /* not interested in the link route */
}
/* do not look at cloned routes */
diff --git a/usr.sbin/sysinstall/Makefile b/usr.sbin/sysinstall/Makefile
index d9aeb5c..5cbd2e5 100644
--- a/usr.sbin/sysinstall/Makefile
+++ b/usr.sbin/sysinstall/Makefile
@@ -11,7 +11,7 @@ SRCS= anonFTP.c cdrom.c command.c config.c devices.c dhcp.c \
ftp.c globals.c http.c index.c install.c installUpgrade.c keymap.c \
label.c main.c makedevs.c media.c menus.c misc.c modules.c \
mouse.c msg.c network.c nfs.c options.c package.c \
- system.c tape.c tcpip.c termcap.c ttys.c ufs.c user.c \
+ system.c tcpip.c termcap.c ttys.c ufs.c user.c \
variable.c ${_wizard} keymap.h countries.h
CFLAGS+= -DUSE_GZIP=1
diff --git a/usr.sbin/sysinstall/cdrom.c b/usr.sbin/sysinstall/cdrom.c
index 7264c47..a5029ec 100644
--- a/usr.sbin/sysinstall/cdrom.c
+++ b/usr.sbin/sysinstall/cdrom.c
@@ -164,9 +164,7 @@ mediaInitCDROM(Device *dev)
}
if ((cp = property_find(cd_attr, "CD_MACHINE_ARCH")) != NULL) {
if (strcmp(cp, "any") &&
-#ifdef __alpha__
- strcmp(cp, "alpha")) {
-#elif defined(PC98)
+#if defined(PC98)
strcmp(cp, "pc98")) {
#elif defined(__sparc64__)
strcmp(cp, "sparc64")) {
diff --git a/usr.sbin/sysinstall/config.c b/usr.sbin/sysinstall/config.c
index 89bf247..7693833 100644
--- a/usr.sbin/sysinstall/config.c
+++ b/usr.sbin/sysinstall/config.c
@@ -817,7 +817,7 @@ configNFSServer(dialogMenuItem *self)
"kinds of access to your local file systems.\n"
"Press [ENTER] now to invoke an editor on /etc/exports\n");
vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
- vsystem("echo '#/usr/src and /usr/ports read-only to machines named after trouble makers' >> /etc/exports");
+ vsystem("echo '#/usr/src and /usr/obj read-only to machines named after trouble makers,' >> /etc/exports");
vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
vsystem("echo '#and, /a to a network of privileged machines allowed to write on it as root.' >> /etc/exports");
vsystem("echo '#/usr huey louie dewie' >> /etc/exports");
diff --git a/usr.sbin/sysinstall/devices.c b/usr.sbin/sysinstall/devices.c
index 9cda538..f5b16e5 100644
--- a/usr.sbin/sysinstall/devices.c
+++ b/usr.sbin/sysinstall/devices.c
@@ -57,8 +57,6 @@ static int numDevs;
#define CDROM(name, descr, max) \
DEVICE_ENTRY(DEVICE_TYPE_CDROM, name, descr, max)
-#define TAPE(name, descr, max) \
- DEVICE_ENTRY(DEVICE_TYPE_TAPE, name, descr, max)
#define DISK(name, descr, max) \
DEVICE_ENTRY(DEVICE_TYPE_DISK, name, descr, max)
#define FLOPPY(name, descr, max) \
@@ -78,8 +76,6 @@ static struct _devname {
CDROM("mcd%d", "Mitsumi (old model) CDROM drive", 4),
CDROM("scd%d", "Sony CDROM drive - CDU31/33A type", 4),
CDROM("acd%d", "ATAPI/IDE CDROM", 4),
- TAPE("sa%d", "SCSI tape drive", 4),
- TAPE("rwt%d", "Wangtek tape drive", 4),
DISK("da%d", "SCSI disk device", 16),
DISK("ad%d", "ATA/IDE disk device", 16),
DISK("ar%d", "ATA/IDE RAID device", 16),
@@ -367,20 +363,6 @@ skipif:
}
break;
- case DEVICE_TYPE_TAPE:
- fd = deviceTry(device_names[i], try, j);
- if (fd >= 0) {
- char n[BUFSIZ];
-
- close(fd);
- snprintf(n, sizeof n, device_names[i].name, j);
- deviceRegister(strdup(n), device_names[i].description, strdup(try),
- DEVICE_TYPE_TAPE, TRUE, mediaInitTape, mediaGetTape, mediaShutdownTape, NULL);
- if (isDebug())
- msgDebug("Found a TAPE device for %s\n", try);
- }
- break;
-
case DEVICE_TYPE_DISK:
/* nothing to do */
break;
diff --git a/usr.sbin/sysinstall/dispatch.c b/usr.sbin/sysinstall/dispatch.c
index b1d0099..3a891c9 100644
--- a/usr.sbin/sysinstall/dispatch.c
+++ b/usr.sbin/sysinstall/dispatch.c
@@ -70,10 +70,8 @@ static struct _word {
{ "distSetCustom", distSetCustom },
{ "distUnsetCustom", distUnsetCustom },
{ "distSetDeveloper", distSetDeveloper },
- { "distSetXDeveloper", distSetXDeveloper },
{ "distSetKernDeveloper", distSetKernDeveloper },
{ "distSetUser", distSetUser },
- { "distSetXUser", distSetXUser },
{ "distSetMinimum", distSetMinimum },
{ "distSetEverything", distSetEverything },
{ "distSetSrc", distSetSrc },
@@ -97,7 +95,6 @@ static struct _word {
{ "mediaSetCDROM", mediaSetCDROM },
{ "mediaSetFloppy", mediaSetFloppy },
{ "mediaSetDOS", mediaSetDOS },
- { "mediaSetTape", mediaSetTape },
{ "mediaSetFTP", mediaSetFTP },
{ "mediaSetFTPActive", mediaSetFTPActive },
{ "mediaSetFTPPassive", mediaSetFTPPassive },
diff --git a/usr.sbin/sysinstall/dist.c b/usr.sbin/sysinstall/dist.c
index 8e6c229..c3ec4c1 100644
--- a/usr.sbin/sysinstall/dist.c
+++ b/usr.sbin/sysinstall/dist.c
@@ -45,7 +45,6 @@
unsigned int Dists;
unsigned int SrcDists;
-unsigned int XOrgDists;
unsigned int KernelDists;
enum _disttype { DT_TARBALL, DT_SUBDIST, DT_PACKAGE };
@@ -63,7 +62,6 @@ typedef struct _dist {
static Distribution KernelDistTable[];
static Distribution SrcDistTable[];
-static Distribution XOrgDistTable[];
#define DTE_TARBALL(name, mask, flag, directory) \
{ name, mask, DIST_ ## flag, DT_TARBALL, { directory } }
@@ -92,7 +90,6 @@ static Distribution DistTable[] = {
DTE_SUBDIST("src", &Dists, SRC, SrcDistTable),
DTE_TARBALL("ports", &Dists, PORTS, "/usr"),
DTE_TARBALL("local", &Dists, LOCAL, "/"),
- DTE_PACKAGE("X.Org", &Dists, XORG, "xorg"),
DTE_END,
};
@@ -138,15 +135,11 @@ distVerifyFlags(void)
{
if (SrcDists)
Dists |= DIST_SRC;
- if (XOrgDists)
- Dists |= DIST_XORG;
if (KernelDists)
Dists |= DIST_KERNEL;
- if (isDebug()) {
+ if (isDebug())
msgDebug("Dist Masks: Dists: %0x, Srcs: %0x Kernels: %0x\n", Dists,
SrcDists, KernelDists);
- msgDebug("XServer: %0x\n", XOrgDists);
- }
}
int
@@ -154,7 +147,6 @@ distReset(dialogMenuItem *self)
{
Dists = 0;
SrcDists = 0;
- XOrgDists = 0;
KernelDists = 0;
return DITEM_SUCCESS | DITEM_REDRAW;
}
@@ -172,9 +164,6 @@ distConfig(dialogMenuItem *self)
if ((cp = variable_get(VAR_DIST_SRC)) != NULL)
SrcDists = atoi(cp);
- if ((cp = variable_get(VAR_DIST_X11)) != NULL)
- XOrgDists = atoi(cp);
-
if ((cp = variable_get(VAR_DIST_KERNEL)) != NULL)
KernelDists = atoi(cp);
@@ -182,14 +171,6 @@ distConfig(dialogMenuItem *self)
return DITEM_SUCCESS | DITEM_REDRAW;
}
-static int
-distSetX(void)
-{
- Dists |= DIST_XORG;
- XOrgDists = DIST_XORG_ALL;
- return DITEM_SUCCESS;
-}
-
int
selectKernel(void)
{
@@ -216,17 +197,6 @@ distSetDeveloper(dialogMenuItem *self)
}
int
-distSetXDeveloper(dialogMenuItem *self)
-{
- int i;
-
- i = distSetDeveloper(self);
- i |= distSetX();
- distVerifyFlags();
- return i;
-}
-
-int
distSetKernDeveloper(dialogMenuItem *self)
{
int i;
@@ -241,17 +211,6 @@ distSetKernDeveloper(dialogMenuItem *self)
}
int
-distSetXKernDeveloper(dialogMenuItem *self)
-{
- int i;
-
- i = distSetKernDeveloper(self);
- i |= distSetX();
- distVerifyFlags();
- return i;
-}
-
-int
distSetUser(dialogMenuItem *self)
{
int i;
@@ -265,17 +224,6 @@ distSetUser(dialogMenuItem *self)
}
int
-distSetXUser(dialogMenuItem *self)
-{
- int i;
-
- i = distSetUser(self);
- i |= distSetX();
- distVerifyFlags();
- return i;
-}
-
-int
distSetMinimum(dialogMenuItem *self)
{
distReset(NULL);
@@ -292,7 +240,6 @@ distSetEverything(dialogMenuItem *self)
Dists = DIST_ALL;
SrcDists = DIST_SRC_ALL;
- XOrgDists = DIST_XORG_ALL;
KernelDists = DIST_KERNEL_ALL;
i = distMaybeSetPorts(self);
distVerifyFlags();
diff --git a/usr.sbin/sysinstall/dist.h b/usr.sbin/sysinstall/dist.h
index cfa8202..0eb42e1 100644
--- a/usr.sbin/sysinstall/dist.h
+++ b/usr.sbin/sysinstall/dist.h
@@ -12,7 +12,6 @@
#define DIST_SRC 0x00020
#define DIST_DOC 0x00040
#define DIST_INFO 0x00080
-#define DIST_XORG 0x00100
#define DIST_CATPAGES 0x00200
#define DIST_PORTS 0x00400
#define DIST_LOCAL 0x00800
@@ -46,9 +45,6 @@
#define DIST_SRC_CDDL 0x100000
#define DIST_SRC_ALL 0x3FFFFF
-/* Subtypes for X.Org packages */
-#define DIST_XORG_ALL 0xFFFFF
-
/* Subtypes for KERNEL distribution */
#define DIST_KERNEL_GENERIC 0x00001
#define DIST_KERNEL_SMP 0x00002
diff --git a/usr.sbin/sysinstall/label.c b/usr.sbin/sysinstall/label.c
index a60c8dc..08690f6 100644
--- a/usr.sbin/sysinstall/label.c
+++ b/usr.sbin/sysinstall/label.c
@@ -61,7 +61,7 @@
/*
* Minimum partition sizes
*/
-#if defined(__alpha__) || defined(__ia64__) || defined(__sparc64__) || defined(__amd64__)
+#if defined(__ia64__) || defined(__sparc64__) || defined(__amd64__)
#define ROOT_MIN_SIZE 128
#else
#define ROOT_MIN_SIZE 118
@@ -1094,27 +1094,6 @@ diskLabel(Device *dev)
break;
}
-#ifdef __alpha__
- /*
- * SRM requires that the root partition is at the
- * begining of the disk and cannot boot otherwise.
- * Warn Alpha users if they are about to shoot themselves in
- * the foot in this way.
- *
- * Since partitions may not start precisely at offset 0 we
- * check for a "close to 0" instead. :-(
- */
- if ((flags & CHUNK_IS_ROOT) && (tmp->offset > 1024)) {
- msgConfirm("Your root partition `a' does not seem to be the first\n"
- "partition. The Alpha's firmware can only boot from the\n"
- "first partition. So it is unlikely that your current\n"
- "disk layout will be bootable boot after installation.\n"
- "\n"
- "Please allocate the root partition before allocating\n"
- "any others.\n");
- }
-#endif /* alpha */
-
tmp->private_data = p;
tmp->private_free = safe_free;
if (variable_cmp(DISK_LABELLED, "written"))
diff --git a/usr.sbin/sysinstall/main.c b/usr.sbin/sysinstall/main.c
index abea76c..36e8f68 100644
--- a/usr.sbin/sysinstall/main.c
+++ b/usr.sbin/sysinstall/main.c
@@ -198,11 +198,10 @@ main(int argc, char **argv)
choice = scroll = curr = max = 0;
dmenuOpen(&MenuInitial, &choice, &scroll, &curr, &max, TRUE);
if (getpid() != 1
-#if defined(__alpha__) || defined(__sparc64__)
+#if defined(__sparc64__)
|| !msgNoYes("Are you sure you wish to exit? The system will halt.")
#else
- || !msgNoYes("Are you sure you wish to exit? The system will reboot\n"
- "(be sure to remove any floppies/CDs/DVDs from the drives).")
+ || !msgNoYes("Are you sure you wish to exit? The system will reboot.")
#endif
)
break;
diff --git a/usr.sbin/sysinstall/media.c b/usr.sbin/sysinstall/media.c
index 5af902a..643f28b 100644
--- a/usr.sbin/sysinstall/media.c
+++ b/usr.sbin/sysinstall/media.c
@@ -260,61 +260,6 @@ mediaSetDOS(dialogMenuItem *self)
return (mediaDevice ? DITEM_LEAVE_MENU : DITEM_FAILURE);
}
-static int
-tapeHook(dialogMenuItem *self)
-{
- return genericHook(self, DEVICE_TYPE_TAPE);
-}
-
-/*
- * Return 1 if we successfully found and set the installation type to
- * be a tape drive.
- */
-int
-mediaSetTape(dialogMenuItem *self)
-{
- Device **devs;
- int cnt;
-
- mediaClose();
- devs = deviceFind(NULL, DEVICE_TYPE_TAPE);
- cnt = deviceCount(devs);
- if (!cnt) {
- msgConfirm("No tape drive devices found! Please check that your system's configuration\n"
- "is correct. For more information, consult the hardware guide in the Doc\n"
- "menu.");
- return DITEM_FAILURE | DITEM_CONTINUE;
- }
- else if (cnt > 1) {
- DMenu *menu;
- int status;
-
- menu = deviceCreateMenu(&MenuMediaTape, DEVICE_TYPE_TAPE, tapeHook, NULL);
- if (!menu)
- msgFatal("Unable to create tape drive menu! Something is seriously wrong.");
- status = dmenuOpenSimple(menu, FALSE);
- free(menu);
- if (!status)
- return DITEM_FAILURE;
- }
- else
- mediaDevice = devs[0];
- if (mediaDevice) {
- char *val;
-
- val = msgGetInput("/var/tmp", "Please enter the name of a temporary directory containing\n"
- "sufficient space for holding the contents of this tape (or\n"
- "tapes). The contents of this directory will be removed\n"
- "after installation, so be sure to specify a directory that\n"
- "can be erased afterwards!\n");
- if (!val)
- mediaDevice = NULL;
- else
- mediaDevice->private = strdup(val);
- }
- return (mediaDevice ? DITEM_LEAVE_MENU : DITEM_FAILURE);
-}
-
/*
* Return 0 if we successfully found and set the installation type to
* be an ftp server
diff --git a/usr.sbin/sysinstall/menus.c b/usr.sbin/sysinstall/menus.c
index a600da1..7cec25a 100644
--- a/usr.sbin/sysinstall/menus.c
+++ b/usr.sbin/sysinstall/menus.c
@@ -87,36 +87,18 @@ checkDistDeveloper(dialogMenuItem *self)
}
static int
-checkDistXDeveloper(dialogMenuItem *self)
-{
- return IS_DEVELOPER(Dists, DIST_XORG) && _IS_SET(SrcDists, DIST_SRC_ALL);
-}
-
-static int
checkDistKernDeveloper(dialogMenuItem *self)
{
return IS_DEVELOPER(Dists, 0) && _IS_SET(SrcDists, DIST_SRC_SYS);
}
static int
-checkDistXKernDeveloper(dialogMenuItem *self)
-{
- return IS_DEVELOPER(Dists, DIST_XORG) && _IS_SET(SrcDists, DIST_SRC_SYS);
-}
-
-static int
checkDistUser(dialogMenuItem *self)
{
return IS_USER(Dists, 0);
}
static int
-checkDistXUser(dialogMenuItem *self)
-{
- return IS_USER(Dists, DIST_XORG);
-}
-
-static int
checkDistMinimum(dialogMenuItem *self)
{
return Dists == (DIST_BASE | DIST_KERNEL);
@@ -127,7 +109,6 @@ checkDistEverything(dialogMenuItem *self)
{
return Dists == DIST_ALL &&
_IS_SET(SrcDists, DIST_SRC_ALL) &&
- _IS_SET(XOrgDists, DIST_XORG_ALL) &&
_IS_SET(KernelDists, DIST_KERNEL_ALL);
}
@@ -138,17 +119,6 @@ srcFlagCheck(dialogMenuItem *item)
}
static int
-x11FlagCheck(dialogMenuItem *item)
-{
- if (XOrgDists != 0)
- Dists |= DIST_XORG;
- else
- Dists &= ~DIST_XORG;
-
- return Dists & DIST_XORG;
-}
-
-static int
kernelFlagCheck(dialogMenuItem *item)
{
return KernelDists;
@@ -191,10 +161,8 @@ DMenu MenuIndex = {
{ " Dists, Basic", "Basic FreeBSD distribution menu.", NULL, dmenuSubmenu, NULL, &MenuSubDistributions },
{ " Dists, Developer", "Select developer's distribution.", checkDistDeveloper, distSetDeveloper },
{ " Dists, Src", "Src distribution menu.", NULL, dmenuSubmenu, NULL, &MenuSrcDistributions },
- { " Dists, X Developer", "Select X developer's distribution.", checkDistXDeveloper, distSetXDeveloper },
{ " Dists, Kern Developer", "Select kernel developer's distribution.", checkDistKernDeveloper, distSetKernDeveloper },
{ " Dists, User", "Select average user distribution.", checkDistUser, distSetUser },
- { " Dists, X User", "Select average X user distribution.", checkDistXUser, distSetXUser },
{ " Distributions, Adding", "Installing additional distribution sets", NULL, distExtractAll },
{ " Documentation", "Installation instructions, README, etc.", NULL, dmenuSubmenu, NULL, &MenuDocumentation },
{ " Doc, README", "The distribution README file.", NULL, dmenuDisplayFile, NULL, "README" },
@@ -218,7 +186,6 @@ DMenu MenuIndex = {
{ " Install, Custom", "The custom installation menu", NULL, dmenuSubmenu, NULL, &MenuInstallCustom },
{ " Label", "The disk Label editor", NULL, diskLabelEditor },
{ " Media", "Top level media selection menu.", NULL, dmenuSubmenu, NULL, &MenuMedia },
- { " Media, Tape", "Select tape installation media.", NULL, mediaSetTape },
{ " Media, NFS", "Select NFS installation media.", NULL, mediaSetNFS },
{ " Media, Floppy", "Select floppy installation media.", NULL, mediaSetFloppy },
{ " Media, CDROM/DVD", "Select CDROM/DVD installation media.", NULL, mediaSetCDROM },
@@ -826,20 +793,6 @@ DMenu MenuMediaFTP = {
{ NULL } }
};
-DMenu MenuMediaTape = {
- DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS,
- "Choose a tape drive type",
- "FreeBSD can be installed from tape drive, though this installation\n"
- "method requires a certain amount of temporary storage in addition\n"
- "to the space required by the distribution itself (tape drives make\n"
- "poor random-access devices, so we extract _everything_ on the tape\n"
- "in one pass). If you have sufficient space for this, then you should\n"
- "select one of the following tape devices detected on your system.",
- NULL,
- NULL,
- { { NULL } },
-};
-
DMenu MenuNetworkDevice = {
DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS,
"Network interface information required",
@@ -884,7 +837,6 @@ DMenu MenuMedia = {
{ "6 NFS", "Install over NFS", NULL, mediaSetNFS },
{ "7 File System", "Install from an existing filesystem", NULL, mediaSetUFS },
{ "8 Floppy", "Install from a floppy disk set", NULL, mediaSetFloppy },
- { "9 Tape", "Install from SCSI or QIC tape", NULL, mediaSetTape },
{ "X Options", "Go to the Options screen", NULL, optionsEditor },
{ NULL } },
};
@@ -904,22 +856,16 @@ DMenu MenuDistributions = {
"distributions",
{ { "X Exit", "Exit this menu (returning to previous)",
checkTrue, dmenuExit, NULL, NULL, '<', '<', '<' },
- { "All", "All system sources, binaries and X Window System",
+ { "All", "All system sources and binaries",
checkDistEverything, distSetEverything, NULL, NULL, ' ', ' ', ' ' },
{ "Reset", "Reset selected distribution list to nothing",
NULL, distReset, NULL, NULL, ' ', ' ', ' ' },
{ "4 Developer", "Full sources, binaries and doc but no games",
checkDistDeveloper, distSetDeveloper },
- { "5 X-Developer", "Same as above + X Window System",
- checkDistXDeveloper, distSetXDeveloper },
- { "6 Kern-Developer", "Full binaries and doc, kernel sources only",
+ { "5 Kern-Developer", "Full binaries and doc, kernel sources only",
checkDistKernDeveloper, distSetKernDeveloper },
- { "7 X-Kern-Developer", "Same as above + X Window System",
- checkDistXKernDeveloper, distSetXKernDeveloper },
- { "8 User", "Average user - binaries and doc only",
+ { "6 User", "Average user - binaries and doc only",
checkDistUser, distSetUser },
- { "9 X-User", "Same as above + X Window System",
- checkDistXUser, distSetXUser },
{ "A Minimal", "The smallest configuration possible",
checkDistMinimum, distSetMinimum },
{ "B Custom", "Specify your own distribution set",
@@ -936,7 +882,7 @@ DMenu MenuSubDistributions = {
NULL,
{ { "X Exit", "Exit this menu (returning to previous)",
checkTrue, dmenuExit, NULL, NULL, '<', '<', '<' },
- { "All", "All system sources, binaries and X Window System",
+ { "All", "All system sources and binaries",
NULL, distSetEverything, NULL, NULL, ' ', ' ', ' ' },
{ "Reset", "Reset all of the below",
NULL, distReset, NULL, NULL, ' ', ' ', ' ' },
@@ -968,8 +914,6 @@ DMenu MenuSubDistributions = {
dmenuFlagCheck, dmenuSetFlag, NULL, &Dists, '[', 'X', ']', DIST_PORTS },
{ " local", "Local additions collection",
dmenuFlagCheck, dmenuSetFlag, NULL, &Dists, '[', 'X', ']', DIST_LOCAL},
- { " X.Org", "The X.Org distribution",
- dmenuFlagCheck, dmenuSetFlag, NULL, &Dists, '[', 'X', ']', DIST_XORG },
{ NULL } },
};
diff --git a/usr.sbin/sysinstall/options.c b/usr.sbin/sysinstall/options.c
index 8634c69..d840891 100644
--- a/usr.sbin/sysinstall/options.c
+++ b/usr.sbin/sysinstall/options.c
@@ -78,9 +78,6 @@ mediaCheck(Option *opt)
case DEVICE_TYPE_CDROM:
return "CDROM";
- case DEVICE_TYPE_TAPE:
- return "Tape";
-
case DEVICE_TYPE_DOS:
return "DOS";
diff --git a/usr.sbin/sysinstall/sysinstall.8 b/usr.sbin/sysinstall/sysinstall.8
index cb1de79..3a9a20a 100644
--- a/usr.sbin/sysinstall/sysinstall.8
+++ b/usr.sbin/sysinstall/sysinstall.8
@@ -470,38 +470,6 @@ The ports collection.
/usr/src/usr.bin
.It Li susbin
/usr/src/usr.sbin
-.It Li Xbin
-X.Org client applications.
-.It Li Xlib
-X.Org libraries.
-.It Li Xman
-X.Org manual pages.
-.It Li Xdoc
-X.Org protocol and library documentation.
-.It Li Xprog
-X.Org imake distribution.
-.It Li Xsrv
-X.Org X server.
-.It Li Xnest
-X.Org nested X server.
-.It Li Xprt
-X.Org print server.
-.It Li Xvfb
-X.Org virtual frame-buffer X server.
-.It Li Xfmsc
-X.Org miscellaneous font set.
-.It Li Xf75
-X.Org 75DPI font set.
-.It Li Xf100
-X.Org 100DPI font set.
-.It Li Xfcyr
-X.Org Cyrillic font set.
-.It Li Xft1
-X.Org Type 1 font set.
-.It Li Xftt
-X.Org TrueType font set.
-.It Li Xfs
-X.Org font server.
.It Li local
Local additions collection.
.El
@@ -511,26 +479,11 @@ Selects the standard Developer's distribution set.
.Pp
.Sy Variables :
None
-.It distSetXDeveloper
-Selects the standard X Developer's distribution set.
-.Pp
-.Sy Variables :
-None
-.It distSetKernDeveloper
-Selects the standard kernel Developer's distribution set.
-.Pp
-.Sy Variables :
-None
.It distSetUser
Selects the standard user distribution set.
.Pp
.Sy Variables :
None
-.It distSetXUser
-Selects the standard X user's distribution set.
-.Pp
-.Sy Variables :
-None
.It distSetMinimum
Selects the very minimum distribution set.
.Pp
@@ -546,11 +499,6 @@ Interactively select source subcomponents.
.Pp
.Sy Variables :
None
-.It distSetXOrg
-Interactively select X.Org subcomponents.
-.Pp
-.Sy Variables :
-None
.It distExtractAll
Install all currently selected distributions (requires that
media device also be selected).
@@ -667,11 +615,6 @@ The first primary partition found is used (e.g.\& C:).
.Pp
.Sy Variables :
None
-.It mediaSetTape
-Select a tape device as the installation media.
-.Pp
-.Sy Variables :
-None
.It mediaSetFTP
Select an FTP site as the installation media.
.Pp
@@ -878,9 +821,9 @@ This property is normally only used with
.Fx
products that contain
CDs for different architectures, to provide better error messages if
-users try to install Alpha packages on an i386 machine.
+users try to install packages built for the wrong architecture.
For example,
-.Dq Li "CD_MACHINE_ARCH = alpha" .
+.Dq Li "CD_MACHINE_ARCH = amd64" .
.It Va CD_VOLUME
In a multi-volume collection (such as the
.Fx
diff --git a/usr.sbin/sysinstall/sysinstall.h b/usr.sbin/sysinstall/sysinstall.h
index 107a2ac..f09d765 100644
--- a/usr.sbin/sysinstall/sysinstall.h
+++ b/usr.sbin/sysinstall/sysinstall.h
@@ -52,7 +52,7 @@
/*** Defines ***/
-#if defined(__i386__) || defined(__alpha__) || defined(__amd64__)
+#if defined(__i386__) || defined(__amd64__)
#define WITH_SYSCONS
#define WITH_MICE
#endif
@@ -102,7 +102,6 @@
#define VAR_DISTS "dists"
#define VAR_DIST_MAIN "distMain"
#define VAR_DIST_SRC "distSRC"
-#define VAR_DIST_X11 "distX11"
#define VAR_DIST_KERNEL "distKernel"
#define VAR_DEDICATE_DISK "dedicateDisk"
#define VAR_DOMAINNAME "domainname"
@@ -191,7 +190,6 @@
#define VAR_VAR_SIZE "varSize"
#define VAR_TMP_SIZE "tmpSize"
#define VAR_HOME_SIZE "homeSize"
-#define VAR_XORG_CONFIG "_xorgconfig"
#define VAR_TERM "TERM"
#define VAR_CONSTERM "_consterm"
@@ -273,7 +271,6 @@ typedef enum {
DEVICE_TYPE_FTP,
DEVICE_TYPE_NETWORK,
DEVICE_TYPE_CDROM,
- DEVICE_TYPE_TAPE,
DEVICE_TYPE_DOS,
DEVICE_TYPE_UFS,
DEVICE_TYPE_NFS,
@@ -417,7 +414,6 @@ extern Variable *VarHead; /* The head of the variable chain */
extern Device *mediaDevice; /* Where we're getting our distribution from */
extern unsigned int Dists; /* Which distributions we want */
extern unsigned int SrcDists; /* Which src distributions we want */
-extern unsigned int XOrgDists; /* Which X.Org dists we want */
extern unsigned int KernelDists; /* Which kernel dists we want */
extern int BootMgr; /* Which boot manager to use */
extern int StatusLine; /* Where to print our status messages */
@@ -446,7 +442,6 @@ extern DMenu MenuMediaCDROM; /* CDROM media menu */
extern DMenu MenuMediaDOS; /* DOS media menu */
extern DMenu MenuMediaFloppy; /* Floppy media menu */
extern DMenu MenuMediaFTP; /* FTP media menu */
-extern DMenu MenuMediaTape; /* Tape media menu */
extern DMenu MenuNetworkDevice; /* Network device menu */
extern DMenu MenuNTP; /* NTP time server menu */
extern DMenu MenuSecurity; /* System security options menu */
@@ -593,11 +588,8 @@ extern int distConfig(dialogMenuItem *self);
extern int distSetCustom(dialogMenuItem *self);
extern int distUnsetCustom(dialogMenuItem *self);
extern int distSetDeveloper(dialogMenuItem *self);
-extern int distSetXDeveloper(dialogMenuItem *self);
extern int distSetKernDeveloper(dialogMenuItem *self);
-extern int distSetXKernDeveloper(dialogMenuItem *self);
extern int distSetUser(dialogMenuItem *self);
-extern int distSetXUser(dialogMenuItem *self);
extern int distSetMinimum(dialogMenuItem *self);
extern int distSetEverything(dialogMenuItem *self);
extern int distSetSrc(dialogMenuItem *self);
@@ -723,7 +715,6 @@ extern int mediaTimeout(void);
extern int mediaSetCDROM(dialogMenuItem *self);
extern int mediaSetFloppy(dialogMenuItem *self);
extern int mediaSetDOS(dialogMenuItem *self);
-extern int mediaSetTape(dialogMenuItem *self);
extern int mediaSetFTP(dialogMenuItem *self);
extern int mediaSetFTPActive(dialogMenuItem *self);
extern int mediaSetFTPPassive(dialogMenuItem *self);
@@ -841,11 +832,6 @@ extern void systemChangeScreenmap(const u_char newmap[]);
extern void systemCreateHoloshell(void);
extern int vsystem(char *fmt, ...) __printflike(1, 2);
-/* tape.c */
-extern Boolean mediaInitTape(Device *dev);
-extern FILE *mediaGetTape(Device *dev, char *file, Boolean probe);
-extern void mediaShutdownTape(Device *dev);
-
/* tcpip.c */
extern int tcpOpenDialog(Device *dev);
extern int tcpMenuSelect(dialogMenuItem *self);
diff --git a/usr.sbin/sysinstall/system.c b/usr.sbin/sysinstall/system.c
index a5d8aa9..a0e60d0 100644
--- a/usr.sbin/sysinstall/system.c
+++ b/usr.sbin/sysinstall/system.c
@@ -187,13 +187,9 @@ systemInitialize(int argc, char **argv)
printf("%s running as init on %s\n", argv[0], OnVTY ? "vty0" : "serial console");
ioctl(0, TIOCSCTTY, (char *)NULL);
setlogin("root");
- setenv("PATH", "/stand:/bin:/sbin:/usr/sbin:/usr/bin:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin:/usr/X11R6/bin", 1);
+ setenv("PATH", "/stand:/bin:/sbin:/usr/sbin:/usr/bin:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin", 1);
setbuf(stdin, 0);
setbuf(stderr, 0);
-#ifdef __alpha__
- i = 0;
- sysctlbyname("machdep.unaligned_print", NULL, 0, &i, sizeof(i));
-#endif
#if 0
signal(SIGCHLD, reap_children);
#endif
@@ -239,8 +235,13 @@ void
systemShutdown(int status)
{
/* If some media is open, close it down */
- if (status >=0)
- mediaClose();
+ if (status >=0) {
+ if (mediaDevice != NULL && mediaDevice->type == DEVICE_TYPE_CDROM) {
+ mediaClose();
+ msgConfirm("Be sure to remove the media from the drive.");
+ } else
+ mediaClose();
+ }
/* write out any changes to rc.conf .. */
configRC_conf();
@@ -261,7 +262,7 @@ systemShutdown(int status)
if (RunningAsInit) {
/* Put the console back */
ioctl(0, VT_ACTIVATE, 2);
-#if defined(__alpha__) || defined(__sparc64__)
+#if defined(__sparc64__)
reboot(RB_HALT);
#else
reboot(RB_AUTOBOOT);
diff --git a/usr.sbin/sysinstall/tape.c b/usr.sbin/sysinstall/tape.c
deleted file mode 100644
index d5631d0..0000000
--- a/usr.sbin/sysinstall/tape.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * The new sysinstall program.
- *
- * This is probably the last attempt in the `sysinstall' line, the next
- * generation being slated to essentially a complete rewrite.
- *
- * $FreeBSD$
- *
- * Copyright (c) 1995
- * Jordan Hubbard. 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,
- * verbatim and that no modifications are made prior to this
- * point in the file.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``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 JORDAN HUBBARD OR HIS PETS 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, LIFE 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.
- *
- */
-
-/* These routines deal with getting things off of tape media */
-
-#include "sysinstall.h"
-#include <sys/fcntl.h>
-#include <sys/param.h>
-
-static Boolean tapeInitted;
-
-Boolean
-mediaInitTape(Device *dev)
-{
- /* This is REALLY gross, but we need to do the init later in get due to the fact
- * that media is initialized BEFORE a filesystem is mounted now.
- */
- return TRUE;
-}
-
-FILE *
-mediaGetTape(Device *dev, char *file, Boolean probe)
-{
- char buf[PATH_MAX];
- FILE *fp;
-
- int i;
-
- if (!tapeInitted) {
- WINDOW *w = savescr();
-
- msgDebug("Tape init routine called for %s (private dir is %s)\n",
- dev->name, (char *)dev->private);
- Mkdir(dev->private);
- if (chdir(dev->private)) {
- msgConfirm("Unable to CD to %s before extracting tape!\n"
- "Tape media is not selected and thus cannot be installed from.",
- (char *)dev->private);
- return (FILE *)IO_ERROR;
- }
- /* We know the tape is already in the drive, so go for it */
- msgNotify("First extracting distributions from %s...", dev->description);
- if (!strcmp(dev->name, "rft0"))
- i = vsystem("ft | cpio -idum %s", cpioVerbosity());
- else
- i = vsystem("cpio -idum %s -I %s", cpioVerbosity(), dev->devname);
- if (!i) {
- tapeInitted = TRUE;
- msgDebug("Tape initialized successfully.\n");
- }
- else {
- msgConfirm("Tape extract command failed with status %d!\n"
- "Unable to use tape media.", i);
- restorescr(w);
- return (FILE *)IO_ERROR;
- }
- restorescr(w);
- }
-
- sprintf(buf, "%s/%s", (char *)dev->private, file);
- if (isDebug())
- msgDebug("Request for %s from tape (looking in %s)\n", file, buf);
- if (file_readable(buf))
- fp = fopen(buf, "r");
- else {
- sprintf(buf, "%s/releases/%s", (char *)dev->private, file);
- fp = fopen(buf, "r");
- }
- /* Nuke the files behind us to save space */
- if (fp)
- unlink(buf);
- return fp;
-}
-
-void
-mediaShutdownTape(Device *dev)
-{
- if (!tapeInitted)
- return;
- if (file_readable((char *)dev->private)) {
- msgDebug("Cleaning up results of tape extract in %s..\n",
- (char *)dev->private);
- (void)vsystem("rm -rf %s", (char *)dev->private);
- }
- tapeInitted = FALSE;
-}
diff --git a/usr.sbin/sysinstall/user.c b/usr.sbin/sysinstall/user.c
index 8bddc1f..3bba68e 100644
--- a/usr.sbin/sysinstall/user.c
+++ b/usr.sbin/sysinstall/user.c
@@ -63,6 +63,7 @@ static char gname[GNAME_FIELD_LEN],
gmemb[GMEMB_FIELD_LEN],
uname[UT_NAMESIZE + 1],
passwd[PASSWD_FIELD_LEN],
+ confpasswd[PASSWD_FIELD_LEN],
uid[UID_FIELD_LEN],
ugroup[UGROUP_FIELD_LEN],
gecos[GECOS_FIELD_LEN],
@@ -78,7 +79,7 @@ static int okbutton, cancelbutton;
#define USER_DIALOG_Y 0
#define USER_DIALOG_X 8
#define USER_DIALOG_WIDTH COLS - 16
-#define USER_DIALOG_HEIGHT LINES - 2
+#define USER_DIALOG_HEIGHT LINES - 1
/* The group configuration menu. */
static Layout groupLayout[] = {
@@ -108,42 +109,46 @@ static Layout groupLayout[] = {
/* The user configuration menu. */
static Layout userLayout[] = {
#define LAYOUT_UNAME 0
- { 3, 6, UT_NAMESIZE, UT_NAMESIZE + 1,
+ { 2, 6, UT_NAMESIZE, UT_NAMESIZE + 1,
"Login ID:", "The login name of the new user (mandatory)",
uname, STRINGOBJ, NULL },
#define LAYOUT_UID 1
- { 3, 23, 8, UID_FIELD_LEN - 1,
+ { 2, 23, 8, UID_FIELD_LEN - 1,
"UID:", "The numerical ID for this user (leave blank for automatic choice)",
uid, STRINGOBJ, NULL },
#define LAYOUT_UGROUP 2
- { 3, 33, 8, UGROUP_FIELD_LEN - 1,
+ { 2, 33, 8, UGROUP_FIELD_LEN - 1,
"Group:", "The login group name for this user (leave blank for automatic choice)",
ugroup, STRINGOBJ, NULL },
#define LAYOUT_PASSWD 3
- { 3, 43, 15, PASSWD_FIELD_LEN - 1,
+ { 6, 6, 20, PASSWD_FIELD_LEN - 1,
"Password:", "The password for this user (enter this field with care!)",
passwd, NO_ECHO_OBJ(STRINGOBJ), NULL },
-#define LAYOUT_GECOS 4
- { 8, 6, 33, GECOS_FIELD_LEN - 1,
+#define LAYOUT_CONFPASSWD 4
+ { 6, 28, 20, PASSWD_FIELD_LEN - 1,
+ "Confirm Password:", "Confirm what you typed for the password",
+ confpasswd, NO_ECHO_OBJ(STRINGOBJ), NULL },
+#define LAYOUT_GECOS 5
+ { 10, 6, 33, GECOS_FIELD_LEN - 1,
"Full name:", "The user's full name (comment)",
gecos, STRINGOBJ, NULL },
-#define LAYOUT_UMEMB 5
- { 8, 43, 15, UMEMB_FIELD_LEN - 1,
+#define LAYOUT_UMEMB 6
+ { 10, 43, 15, UMEMB_FIELD_LEN - 1,
"Member groups:", "The groups this user belongs to (i.e. gets access rights for)",
umemb, STRINGOBJ, NULL },
-#define LAYOUT_HOMEDIR 6
- { 13, 6, 20, HOMEDIR_FIELD_LEN - 1,
+#define LAYOUT_HOMEDIR 7
+ { 14, 6, 20, HOMEDIR_FIELD_LEN - 1,
"Home directory:", "The user's home directory (leave blank for default)",
homedir, STRINGOBJ, NULL },
-#define LAYOUT_SHELL 7
- { 13, 29, 29, SHELL_FIELD_LEN - 1,
+#define LAYOUT_SHELL 8
+ { 14, 29, 29, SHELL_FIELD_LEN - 1,
"Login shell:", "The user's login shell (leave blank for default)",
shell, STRINGOBJ, NULL },
-#define LAYOUT_U_OKBUTTON 8
+#define LAYOUT_U_OKBUTTON 9
{ 18, 15, 0, 0,
"OK", "Select this if you are happy with these settings",
&okbutton, BUTTONOBJ, NULL },
-#define LAYOUT_U_CANCELBUTTON 9
+#define LAYOUT_U_CANCELBUTTON 10
{ 18, 35, 0, 0,
"CANCEL", "Select this if you wish to cancel this screen",
&cancelbutton, BUTTONOBJ, NULL },
@@ -421,6 +426,10 @@ verifyUserSettings(WINDOW *ds_win)
return 0;
}
}
+ if (strcmp(passwd, confpasswd)) {
+ feepout("Passwords don't match");
+ return 0;
+ }
if ((homedir[0]!=0) && (homedir[0]!='/')) {
feepout("The pathname for home directories must begin with a '/'.");
return 0;
@@ -682,7 +691,7 @@ userAddUser(dialogMenuItem *self)
draw_box(ds_win, USER_DIALOG_Y + 1, USER_DIALOG_X + 3, USER_DIALOG_HEIGHT - 6,
USER_DIALOG_WIDTH - 6, dialog_attr, border_attr);
wattrset(ds_win, dialog_attr);
- mvwaddstr(ds_win, USER_DIALOG_Y + 1, USER_DIALOG_X + 22, " Add a new user ");
+ mvwaddstr(ds_win, USER_DIALOG_Y + 1, USER_DIALOG_X + 24, " Add a new user ");
CLEAR(uname);
CLEAR(uid);
diff --git a/usr.sbin/syslogd/Makefile b/usr.sbin/syslogd/Makefile
index 96d85c2..1682b49 100644
--- a/usr.sbin/syslogd/Makefile
+++ b/usr.sbin/syslogd/Makefile
@@ -12,7 +12,7 @@ SRCS= syslogd.c ttymsg.c
DPADD= ${LIBUTIL}
LDADD= -lutil
-WARNS?= 1
+WARNS?= 3
.if ${MK_INET6_SUPPORT} != "no"
CFLAGS+= -DINET6
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index a6940ac..3e628a2 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -128,7 +128,7 @@ const char ctty[] = _PATH_CONSOLE;
*/
struct funix {
int s;
- char *name;
+ const char *name;
mode_t mode;
STAILQ_ENTRY(funix) next;
};
@@ -331,7 +331,7 @@ static void reapchild(int);
static void usage(void);
static int validate(struct sockaddr *, const char *);
static void unmapped(struct sockaddr *);
-static void wallmsg(struct filed *, struct iovec *);
+static void wallmsg(struct filed *, struct iovec *, const int iovlen);
static int waitdaemon(int, int, int);
static void timedout(int);
static void double_rbuf(int);
@@ -1065,10 +1065,11 @@ dofsync(void)
}
}
+#define IOV_SIZE 7
static void
fprintlog(struct filed *f, int flags, const char *msg)
{
- struct iovec iov[7];
+ struct iovec iov[IOV_SIZE];
struct iovec *v;
struct addrinfo *r;
int i, l, lsent = 0;
@@ -1253,7 +1254,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
dprintf(" %s\n", f->f_un.f_fname);
v->iov_base = lf;
v->iov_len = 1;
- if (writev(f->f_file, iov, 7) < 0) {
+ if (writev(f->f_file, iov, IOV_SIZE) < 0) {
/*
* If writev(2) fails for potentially transient errors
* like the filesystem being full, ignore it.
@@ -1284,7 +1285,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
break;
}
}
- if (writev(f->f_file, iov, 7) < 0) {
+ if (writev(f->f_file, iov, IOV_SIZE) < 0) {
int e = errno;
(void)close(f->f_file);
if (f->f_un.f_pipe.f_pid > 0)
@@ -1309,7 +1310,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
v->iov_len = 2;
errno = 0; /* ttymsg() only sometimes returns an errno */
- if ((msgret = ttymsg(iov, 7, f->f_un.f_fname, 10))) {
+ if ((msgret = ttymsg(iov, IOV_SIZE, f->f_un.f_fname, 10))) {
f->f_type = F_UNUSED;
logerror(msgret);
}
@@ -1320,7 +1321,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
dprintf("\n");
v->iov_base = crlf;
v->iov_len = 2;
- wallmsg(f, iov);
+ wallmsg(f, iov, IOV_SIZE);
break;
}
f->f_prevcount = 0;
@@ -1334,7 +1335,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
* world, or a list of approved users.
*/
static void
-wallmsg(struct filed *f, struct iovec *iov)
+wallmsg(struct filed *f, struct iovec *iov, const int iovlen)
{
static int reenter; /* avoid calling ourselves */
FILE *uf;
@@ -1358,7 +1359,8 @@ wallmsg(struct filed *f, struct iovec *iov)
strncpy(line, ut.ut_line, sizeof(line) - 1);
line[sizeof(line) - 1] = '\0';
if (f->f_type == F_WALL) {
- if ((p = ttymsg(iov, 7, line, TTYMSGTIME)) != NULL) {
+ if ((p = ttymsg(iov, iovlen, line, TTYMSGTIME)) !=
+ NULL) {
errno = 0; /* already in msg */
logerror(p);
}
@@ -1370,8 +1372,8 @@ wallmsg(struct filed *f, struct iovec *iov)
break;
if (!strncmp(f->f_un.f_uname[i], ut.ut_name,
UT_NAMESIZE)) {
- if ((p = ttymsg(iov, 7, line, TTYMSGTIME))
- != NULL) {
+ if ((p = ttymsg(iov, iovlen, line, TTYMSGTIME))
+ != NULL) {
errno = 0; /* already in msg */
logerror(p);
}
@@ -2183,10 +2185,13 @@ allowaddr(char *s)
char *cp1, *cp2;
struct allowedpeer ap;
struct servent *se;
- int masklen = -1, i;
+ int masklen = -1;
struct addrinfo hints, *res;
struct in_addr *addrp, *maskp;
+#ifdef INET6
+ int i;
u_int32_t *addr6p, *mask6p;
+#endif
char ip[NI_MAXHOST];
#ifdef INET6
@@ -2342,12 +2347,15 @@ allowaddr(char *s)
static int
validate(struct sockaddr *sa, const char *hname)
{
- int i, j, reject;
+ int i;
size_t l1, l2;
char *cp, name[NI_MAXHOST], ip[NI_MAXHOST], port[NI_MAXSERV];
struct allowedpeer *ap;
struct sockaddr_in *sin4, *a4p = NULL, *m4p = NULL;
+#ifdef INET6
+ int j, reject;
struct sockaddr_in6 *sin6, *a6p = NULL, *m6p = NULL;
+#endif
struct addrinfo hints, *res;
u_short sport;
OpenPOWER on IntegriCloud