aboutsummaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
Diffstat (limited to 'sbin')
-rw-r--r--sbin/Makefile11
-rw-r--r--sbin/Makefile.amd643
-rw-r--r--sbin/Makefile.arm2
-rw-r--r--sbin/Makefile.i3863
-rw-r--r--sbin/Makefile.inc3
-rw-r--r--sbin/Makefile.powerpc642
-rw-r--r--sbin/adjkerntz/Makefile2
-rw-r--r--sbin/adjkerntz/Makefile.depend2
-rw-r--r--sbin/adjkerntz/adjkerntz.874
-rw-r--r--sbin/adjkerntz/adjkerntz.c14
-rw-r--r--sbin/adjkerntz/pathnames.h4
-rw-r--r--sbin/bectl/Makefile6
-rw-r--r--sbin/bectl/Makefile.depend14
-rw-r--r--sbin/bectl/bectl.8240
-rw-r--r--sbin/bectl/bectl.c119
-rw-r--r--sbin/bectl/bectl.h27
-rw-r--r--sbin/bectl/bectl_jail.c33
-rw-r--r--sbin/bectl/bectl_list.c43
-rw-r--r--sbin/bectl/tests/Makefile2
-rw-r--r--sbin/bectl/tests/Makefile.depend10
-rwxr-xr-xsbin/bectl/tests/bectl_test.sh180
-rw-r--r--sbin/bsdlabel/Makefile3
-rw-r--r--sbin/bsdlabel/Makefile.depend4
-rw-r--r--sbin/bsdlabel/bsdlabel.828
-rw-r--r--sbin/bsdlabel/bsdlabel.c31
-rw-r--r--sbin/bsdlabel/disktab1
-rw-r--r--sbin/bsdlabel/pathnames.h3
-rw-r--r--sbin/camcontrol/Makefile25
-rw-r--r--sbin/camcontrol/Makefile.depend3
-rw-r--r--sbin/camcontrol/attrib.c6
-rw-r--r--sbin/camcontrol/camcontrol.835
-rw-r--r--sbin/camcontrol/camcontrol.c508
-rw-r--r--sbin/camcontrol/camcontrol.h6
-rw-r--r--sbin/camcontrol/depop.c3
-rw-r--r--sbin/camcontrol/epc.c13
-rw-r--r--sbin/camcontrol/fwdownload.c18
-rw-r--r--sbin/camcontrol/modeedit.c18
-rw-r--r--sbin/camcontrol/persist.c2
-rw-r--r--sbin/camcontrol/progress.c4
-rw-r--r--sbin/camcontrol/progress.h4
-rw-r--r--sbin/camcontrol/timestamp.c3
-rw-r--r--sbin/camcontrol/util.c2
-rw-r--r--sbin/camcontrol/zone.c13
-rw-r--r--sbin/ccdconfig/Makefile2
-rw-r--r--sbin/ccdconfig/Makefile.depend4
-rw-r--r--sbin/ccdconfig/ccdconfig.864
-rw-r--r--sbin/ccdconfig/ccdconfig.c3
-rw-r--r--sbin/ccdconfig/pathnames.h3
-rw-r--r--sbin/clri/Makefile5
-rw-r--r--sbin/clri/Makefile.depend3
-rw-r--r--sbin/clri/clri.83
-rw-r--r--sbin/clri/clri.c15
-rw-r--r--sbin/comcontrol/Makefile3
-rw-r--r--sbin/comcontrol/Makefile.depend2
-rw-r--r--sbin/comcontrol/comcontrol.823
-rw-r--r--sbin/comcontrol/comcontrol.c36
-rw-r--r--sbin/conscontrol/Makefile2
-rw-r--r--sbin/conscontrol/Makefile.depend2
-rw-r--r--sbin/conscontrol/conscontrol.88
-rw-r--r--sbin/conscontrol/conscontrol.c5
-rw-r--r--sbin/ddb/Makefile2
-rw-r--r--sbin/ddb/Makefile.depend3
-rw-r--r--sbin/ddb/ddb.83
-rw-r--r--sbin/ddb/ddb.c4
-rw-r--r--sbin/ddb/ddb.conf1
-rw-r--r--sbin/ddb/ddb.h4
-rw-r--r--sbin/ddb/ddb_capture.c5
-rw-r--r--sbin/ddb/ddb_script.c5
-rw-r--r--sbin/decryptcore/Makefile3
-rw-r--r--sbin/decryptcore/Makefile.depend5
-rw-r--r--sbin/decryptcore/decryptcore.84
-rw-r--r--sbin/decryptcore/decryptcore.c8
-rw-r--r--sbin/devd/Makefile47
-rw-r--r--sbin/devd/Makefile.depend4
-rw-r--r--sbin/devd/apple.conf1
-rw-r--r--sbin/devd/asus.conf1
-rw-r--r--sbin/devd/autofs.conf9
-rw-r--r--sbin/devd/bluetooth.conf9
-rw-r--r--sbin/devd/devd.810
-rw-r--r--sbin/devd/devd.cc47
-rw-r--r--sbin/devd/devd.conf117
-rw-r--r--sbin/devd/devd.conf.5225
-rw-r--r--sbin/devd/devd.h4
-rw-r--r--sbin/devd/devd.hh4
-rw-r--r--sbin/devd/devmatch.conf27
-rw-r--r--sbin/devd/dhclient.conf19
-rw-r--r--sbin/devd/hyperv.conf2
-rw-r--r--sbin/devd/moused.conf44
-rw-r--r--sbin/devd/nvmf.conf7
-rw-r--r--sbin/devd/parse.y4
-rw-r--r--sbin/devd/power_profile.conf6
-rw-r--r--sbin/devd/snd.conf26
-rw-r--r--sbin/devd/syscons.conf9
-rw-r--r--sbin/devd/tests/Makefile2
-rw-r--r--sbin/devd/tests/Makefile.depend1
-rw-r--r--sbin/devd/tests/client_test.c35
-rw-r--r--sbin/devd/token.l4
-rw-r--r--sbin/devd/uath.conf1
-rw-r--r--sbin/devd/ulpt.conf1
-rw-r--r--sbin/devd/zfs.conf1
-rw-r--r--sbin/devfs/Makefile2
-rw-r--r--sbin/devfs/Makefile.depend2
-rw-r--r--sbin/devfs/devfs.818
-rw-r--r--sbin/devfs/devfs.c5
-rw-r--r--sbin/devfs/devfs.conf1
-rw-r--r--sbin/devfs/devfs.rules3
-rw-r--r--sbin/devfs/extern.h4
-rw-r--r--sbin/devfs/rule.c5
-rw-r--r--sbin/devmatch/Makefile3
-rw-r--r--sbin/devmatch/Makefile.depend1
-rw-r--r--sbin/devmatch/devmatch.829
-rw-r--r--sbin/devmatch/devmatch.c46
-rw-r--r--sbin/dhclient/Makefile3
-rw-r--r--sbin/dhclient/Makefile.depend2
-rw-r--r--sbin/dhclient/Makefile.depend.options1
-rw-r--r--sbin/dhclient/alloc.c2
-rw-r--r--sbin/dhclient/bpf.c2
-rw-r--r--sbin/dhclient/clparse.c6
-rw-r--r--sbin/dhclient/conflex.c4
-rw-r--r--sbin/dhclient/convert.c2
-rwxr-xr-xsbin/dhclient/dhclient-script8
-rw-r--r--sbin/dhclient/dhclient-script.82
-rw-r--r--sbin/dhclient/dhclient.88
-rw-r--r--sbin/dhclient/dhclient.c88
-rw-r--r--sbin/dhclient/dhclient.conf1
-rw-r--r--sbin/dhclient/dhclient.conf.59
-rw-r--r--sbin/dhclient/dhclient.leases.52
-rw-r--r--sbin/dhclient/dhcp-options.52
-rw-r--r--sbin/dhclient/dhcp.h4
-rw-r--r--sbin/dhclient/dhcpd.h10
-rw-r--r--sbin/dhclient/dhctoken.h3
-rw-r--r--sbin/dhclient/dispatch.c69
-rw-r--r--sbin/dhclient/errwarn.c2
-rw-r--r--sbin/dhclient/hash.c2
-rw-r--r--sbin/dhclient/inet.c2
-rw-r--r--sbin/dhclient/options.c2
-rw-r--r--sbin/dhclient/packet.c55
-rw-r--r--sbin/dhclient/parse.c30
-rw-r--r--sbin/dhclient/privsep.c2
-rw-r--r--sbin/dhclient/privsep.h2
-rw-r--r--sbin/dhclient/tables.c2
-rw-r--r--sbin/dhclient/tests/Makefile8
-rw-r--r--sbin/dhclient/tests/Makefile.depend1
-rw-r--r--sbin/dhclient/tests/fake.c16
-rw-r--r--sbin/dhclient/tests/option-domain-search.c48
-rw-r--r--sbin/dhclient/tree.c2
-rw-r--r--sbin/dhclient/tree.h2
-rw-r--r--sbin/dmesg/Makefile3
-rw-r--r--sbin/dmesg/Makefile.depend3
-rw-r--r--sbin/dmesg/dmesg.85
-rw-r--r--sbin/dmesg/dmesg.c14
-rw-r--r--sbin/dump/Makefile5
-rw-r--r--sbin/dump/Makefile.depend3
-rw-r--r--sbin/dump/cache.c2
-rw-r--r--sbin/dump/dump.83
-rw-r--r--sbin/dump/dump.h6
-rw-r--r--sbin/dump/dumprmt.c8
-rw-r--r--sbin/dump/itime.c8
-rw-r--r--sbin/dump/main.c16
-rw-r--r--sbin/dump/optr.c8
-rw-r--r--sbin/dump/pathnames.h3
-rw-r--r--sbin/dump/tape.c62
-rw-r--r--sbin/dump/traverse.c12
-rw-r--r--sbin/dump/unctime.c8
-rw-r--r--sbin/dumpfs/Makefile5
-rw-r--r--sbin/dumpfs/Makefile.depend2
-rw-r--r--sbin/dumpfs/dumpfs.86
-rw-r--r--sbin/dumpfs/dumpfs.c84
-rw-r--r--sbin/dumpon/Makefile3
-rw-r--r--sbin/dumpon/Makefile.depend2
-rw-r--r--sbin/dumpon/Makefile.depend.options1
-rw-r--r--sbin/dumpon/dumpon.89
-rw-r--r--sbin/dumpon/dumpon.c36
-rw-r--r--sbin/etherswitchcfg/Makefile3
-rw-r--r--sbin/etherswitchcfg/Makefile.depend2
-rw-r--r--sbin/etherswitchcfg/etherswitchcfg.82
-rw-r--r--sbin/etherswitchcfg/etherswitchcfg.c6
-rw-r--r--sbin/etherswitchcfg/ifmedia.c1
-rw-r--r--sbin/fdisk/Makefile2
-rw-r--r--sbin/fdisk/Makefile.depend4
-rw-r--r--sbin/fdisk/fdisk.819
-rw-r--r--sbin/fdisk/fdisk.c32
-rw-r--r--sbin/fdisk/fdisk_mbr_enc.c5
-rw-r--r--sbin/fdisk/fdisk_mbr_enc.h4
-rw-r--r--sbin/fdisk/runtest.sh1
-rw-r--r--sbin/ffsinfo/Makefile5
-rw-r--r--sbin/ffsinfo/Makefile.depend2
-rw-r--r--sbin/ffsinfo/ffsinfo.85
-rw-r--r--sbin/ffsinfo/ffsinfo.c32
-rw-r--r--sbin/fsck/Makefile2
-rw-r--r--sbin/fsck/Makefile.depend2
-rw-r--r--sbin/fsck/fsck.82
-rw-r--r--sbin/fsck/fsck.c10
-rw-r--r--sbin/fsck/fsutil.c46
-rw-r--r--sbin/fsck/fsutil.h3
-rw-r--r--sbin/fsck/preen.c11
-rw-r--r--sbin/fsck_ffs/Makefile13
-rw-r--r--sbin/fsck_ffs/Makefile.depend2
-rw-r--r--sbin/fsck_ffs/dir.c195
-rw-r--r--sbin/fsck_ffs/ea.c12
-rw-r--r--sbin/fsck_ffs/fsck.h95
-rw-r--r--sbin/fsck_ffs/fsck_ffs.86
-rw-r--r--sbin/fsck_ffs/fsutil.c430
-rw-r--r--sbin/fsck_ffs/gjournal.c21
-rw-r--r--sbin/fsck_ffs/globs.c46
-rw-r--r--sbin/fsck_ffs/inode.c606
-rw-r--r--sbin/fsck_ffs/main.c178
-rw-r--r--sbin/fsck_ffs/pass1.c129
-rw-r--r--sbin/fsck_ffs/pass1b.c10
-rw-r--r--sbin/fsck_ffs/pass2.c169
-rw-r--r--sbin/fsck_ffs/pass3.c16
-rw-r--r--sbin/fsck_ffs/pass4.c8
-rw-r--r--sbin/fsck_ffs/pass5.c63
-rw-r--r--sbin/fsck_ffs/setup.c434
-rw-r--r--sbin/fsck_ffs/suj.c210
-rw-r--r--sbin/fsck_ffs/utilities.c8
-rw-r--r--sbin/fsck_msdosfs/Makefile1
-rw-r--r--sbin/fsck_msdosfs/Makefile.depend3
-rw-r--r--sbin/fsck_msdosfs/boot.c4
-rw-r--r--sbin/fsck_msdosfs/check.c4
-rw-r--r--sbin/fsck_msdosfs/dir.c6
-rw-r--r--sbin/fsck_msdosfs/dosfs.h3
-rw-r--r--sbin/fsck_msdosfs/ext.h3
-rw-r--r--sbin/fsck_msdosfs/fat.c2
-rw-r--r--sbin/fsck_msdosfs/fsck_msdosfs.821
-rw-r--r--sbin/fsck_msdosfs/main.c7
-rw-r--r--sbin/fsdb/Makefile4
-rw-r--r--sbin/fsdb/Makefile.depend3
-rw-r--r--sbin/fsdb/fsdb.82
-rw-r--r--sbin/fsdb/fsdb.c160
-rw-r--r--sbin/fsdb/fsdb.h5
-rw-r--r--sbin/fsdb/fsdbutil.c5
-rw-r--r--sbin/fsirand/Makefile3
-rw-r--r--sbin/fsirand/Makefile.depend3
-rw-r--r--sbin/fsirand/fsirand.81
-rw-r--r--sbin/fsirand/fsirand.c15
-rw-r--r--sbin/gbde/Makefile33
-rw-r--r--sbin/gbde/gbde.8273
-rw-r--r--sbin/gbde/gbde.c892
-rw-r--r--sbin/gbde/image.uu3305
-rw-r--r--sbin/gbde/template.txt32
-rw-r--r--sbin/gbde/test.sh67
-rw-r--r--sbin/geom/Makefile6
-rw-r--r--sbin/geom/Makefile.depend3
-rw-r--r--sbin/geom/core/Makefile.depend1
-rw-r--r--sbin/geom/core/geom.836
-rw-r--r--sbin/geom/core/geom.c251
-rw-r--r--sbin/geom/core/geom.h4
-rw-r--r--sbin/geom/misc/subr.c7
-rw-r--r--sbin/geom/misc/subr.h4
-rw-r--r--sbin/ggate/Makefile2
-rw-r--r--sbin/ggate/Makefile.inc2
-rw-r--r--sbin/ggate/ggatec/Makefile2
-rw-r--r--sbin/ggate/ggatec/Makefile.depend4
-rw-r--r--sbin/ggate/ggatec/ggatec.827
-rw-r--r--sbin/ggate/ggatec/ggatec.c16
-rw-r--r--sbin/ggate/ggated/Makefile2
-rw-r--r--sbin/ggate/ggated/Makefile.depend2
-rw-r--r--sbin/ggate/ggated/ggated.856
-rw-r--r--sbin/ggate/ggated/ggated.c106
-rw-r--r--sbin/ggate/ggatel/Makefile2
-rw-r--r--sbin/ggate/ggatel/Makefile.depend4
-rw-r--r--sbin/ggate/ggatel/ggatel.845
-rw-r--r--sbin/ggate/ggatel/ggatel.c24
-rw-r--r--sbin/ggate/shared/ggate.c4
-rw-r--r--sbin/ggate/shared/ggate.h11
-rw-r--r--sbin/growfs/Makefile10
-rw-r--r--sbin/growfs/Makefile.depend2
-rw-r--r--sbin/growfs/debug.c9
-rw-r--r--sbin/growfs/debug.h1
-rw-r--r--sbin/growfs/growfs.821
-rw-r--r--sbin/growfs/growfs.c174
-rw-r--r--sbin/growfs/tests/Makefile2
-rw-r--r--sbin/growfs/tests/Makefile.depend1
-rwxr-xr-xsbin/growfs/tests/legacy_test.pl7
-rw-r--r--sbin/gvinum/Makefile15
-rw-r--r--sbin/gvinum/Makefile.depend23
-rw-r--r--sbin/gvinum/gvinum.8462
-rw-r--r--sbin/gvinum/gvinum.c1452
-rw-r--r--sbin/gvinum/gvinum.h42
-rw-r--r--sbin/hastctl/Makefile5
-rw-r--r--sbin/hastctl/Makefile.depend3
-rw-r--r--sbin/hastctl/hastctl.83
-rw-r--r--sbin/hastctl/hastctl.c6
-rw-r--r--sbin/hastd/Makefile6
-rw-r--r--sbin/hastd/Makefile.depend5
-rw-r--r--sbin/hastd/activemap.c6
-rw-r--r--sbin/hastd/activemap.h5
-rw-r--r--sbin/hastd/control.c6
-rw-r--r--sbin/hastd/control.h5
-rw-r--r--sbin/hastd/crc32.c115
-rw-r--r--sbin/hastd/crc32.h28
-rw-r--r--sbin/hastd/ebuf.c6
-rw-r--r--sbin/hastd/ebuf.h5
-rw-r--r--sbin/hastd/event.c4
-rw-r--r--sbin/hastd/event.h4
-rw-r--r--sbin/hastd/hast.conf.52
-rw-r--r--sbin/hastd/hast.h4
-rw-r--r--sbin/hastd/hast_checksum.c10
-rw-r--r--sbin/hastd/hast_checksum.h4
-rw-r--r--sbin/hastd/hast_compression.c4
-rw-r--r--sbin/hastd/hast_compression.h4
-rw-r--r--sbin/hastd/hast_proto.c4
-rw-r--r--sbin/hastd/hast_proto.h5
-rw-r--r--sbin/hastd/hastd.83
-rw-r--r--sbin/hastd/hastd.c5
-rw-r--r--sbin/hastd/hastd.h5
-rw-r--r--sbin/hastd/hooks.c5
-rw-r--r--sbin/hastd/hooks.h4
-rw-r--r--sbin/hastd/lzf.c4
-rw-r--r--sbin/hastd/lzf.h6
-rw-r--r--sbin/hastd/metadata.c5
-rw-r--r--sbin/hastd/metadata.h5
-rw-r--r--sbin/hastd/nv.c15
-rw-r--r--sbin/hastd/nv.h5
-rw-r--r--sbin/hastd/parse.y4
-rw-r--r--sbin/hastd/pjdlog.c5
-rw-r--r--sbin/hastd/pjdlog.h4
-rw-r--r--sbin/hastd/primary.c7
-rw-r--r--sbin/hastd/proto.c6
-rw-r--r--sbin/hastd/proto.h5
-rw-r--r--sbin/hastd/proto_common.c5
-rw-r--r--sbin/hastd/proto_impl.h5
-rw-r--r--sbin/hastd/proto_socketpair.c6
-rw-r--r--sbin/hastd/proto_tcp.c5
-rw-r--r--sbin/hastd/proto_uds.c5
-rw-r--r--sbin/hastd/rangelock.c5
-rw-r--r--sbin/hastd/rangelock.h5
-rw-r--r--sbin/hastd/refcnt.h4
-rw-r--r--sbin/hastd/secondary.c5
-rw-r--r--sbin/hastd/subr.c16
-rw-r--r--sbin/hastd/subr.h4
-rw-r--r--sbin/hastd/synch.h5
-rw-r--r--sbin/hastd/token.l4
-rw-r--r--sbin/ifconfig/Makefile10
-rw-r--r--sbin/ifconfig/Makefile.depend6
-rw-r--r--sbin/ifconfig/Makefile.depend.options1
-rw-r--r--sbin/ifconfig/af_inet.c360
-rw-r--r--sbin/ifconfig/af_inet6.c489
-rw-r--r--sbin/ifconfig/af_link.c142
-rw-r--r--sbin/ifconfig/af_nd6.c87
-rw-r--r--sbin/ifconfig/carp.c196
-rw-r--r--sbin/ifconfig/ifbridge.c614
-rw-r--r--sbin/ifconfig/ifclone.c40
-rw-r--r--sbin/ifconfig/ifconfig.8410
-rw-r--r--sbin/ifconfig/ifconfig.c1338
-rw-r--r--sbin/ifconfig/ifconfig.h198
-rw-r--r--sbin/ifconfig/ifconfig_netlink.c495
-rw-r--r--sbin/ifconfig/ifconfig_netlink.h37
-rw-r--r--sbin/ifconfig/iffib.c28
-rw-r--r--sbin/ifconfig/ifgif.c33
-rw-r--r--sbin/ifconfig/ifgre.c52
-rw-r--r--sbin/ifconfig/ifgroup.c46
-rw-r--r--sbin/ifconfig/ifieee80211.c1740
-rw-r--r--sbin/ifconfig/ifipsec.c18
-rw-r--r--sbin/ifconfig/iflagg.c89
-rw-r--r--sbin/ifconfig/ifmac.c14
-rw-r--r--sbin/ifconfig/ifmedia.c77
-rw-r--r--sbin/ifconfig/ifpfsync.c406
-rw-r--r--sbin/ifconfig/ifstf.c26
-rw-r--r--sbin/ifconfig/ifvlan.c133
-rw-r--r--sbin/ifconfig/ifvxlan.c166
-rw-r--r--sbin/ifconfig/sfp.c16
-rw-r--r--sbin/ifconfig/tests/Makefile7
-rw-r--r--sbin/ifconfig/tests/Makefile.depend1
-rw-r--r--sbin/ifconfig/tests/inet6.sh113
-rw-r--r--sbin/init/Makefile9
-rw-r--r--sbin/init/Makefile.depend2
-rw-r--r--sbin/init/init.84
-rw-r--r--sbin/init/init.c89
-rw-r--r--sbin/init/pathnames.h3
-rw-r--r--sbin/init/ttys8
-rw-r--r--sbin/ipf/Makefile2
-rw-r--r--sbin/ipf/Makefile.inc3
-rw-r--r--sbin/ipf/common/genmask.c6
-rw-r--r--sbin/ipf/common/ipf.h16
-rw-r--r--sbin/ipf/common/ipf_y.y1
-rw-r--r--sbin/ipf/common/ipmon.h3
-rw-r--r--sbin/ipf/common/ipt.h1
-rw-r--r--sbin/ipf/common/kmem.h1
-rw-r--r--sbin/ipf/common/lexer.c11
-rw-r--r--sbin/ipf/common/lexer.h1
-rw-r--r--sbin/ipf/common/opts.h1
-rw-r--r--sbin/ipf/common/pcap-ipf.h1
-rw-r--r--sbin/ipf/ipf/Makefile3
-rw-r--r--sbin/ipf/ipf/Makefile.depend3
-rw-r--r--sbin/ipf/ipf/bpf-ipf.h7
-rw-r--r--sbin/ipf/ipf/bpf_filter.c26
-rw-r--r--sbin/ipf/ipf/ipf.44
-rw-r--r--sbin/ipf/ipf/ipf.578
-rw-r--r--sbin/ipf/ipf/ipf.89
-rw-r--r--sbin/ipf/ipf/ipf.c7
-rw-r--r--sbin/ipf/ipf/ipfcomp.c7
-rw-r--r--sbin/ipf/ipf/ipfilter.46
-rw-r--r--sbin/ipf/ipf/ipfilter.52
-rw-r--r--sbin/ipf/ipf/ipl.41
-rw-r--r--sbin/ipf/ipfs/Makefile2
-rw-r--r--sbin/ipf/ipfs/Makefile.depend3
-rw-r--r--sbin/ipf/ipfs/ipfs.84
-rw-r--r--sbin/ipf/ipfs/ipfs.c4
-rw-r--r--sbin/ipf/ipfstat/Makefile2
-rw-r--r--sbin/ipf/ipfstat/Makefile.depend6
-rw-r--r--sbin/ipf/ipfstat/ipfstat.81
-rw-r--r--sbin/ipf/ipfstat/ipfstat.c12
-rw-r--r--sbin/ipf/ipfsync/ipfsyncd.c4
-rw-r--r--sbin/ipf/ipfsync/ipsyncm.c5
-rw-r--r--sbin/ipf/ipfsync/ipsyncs.c5
-rw-r--r--sbin/ipf/ipftest/Makefile2
-rw-r--r--sbin/ipf/ipftest/Makefile.depend1
-rw-r--r--sbin/ipf/ipftest/ip_fil.c7
-rw-r--r--sbin/ipf/ipftest/ipftest.14
-rw-r--r--sbin/ipf/ipftest/ipftest.c5
-rw-r--r--sbin/ipf/ipftest/md5.c1
-rw-r--r--sbin/ipf/ipftest/md5.h1
-rw-r--r--sbin/ipf/iplang/iplang.h1
-rw-r--r--sbin/ipf/iplang/iplang_l.l1
-rw-r--r--sbin/ipf/iplang/iplang_y.y11
-rw-r--r--sbin/ipf/ipmon/Makefile3
-rw-r--r--sbin/ipf/ipmon/Makefile.depend3
-rw-r--r--sbin/ipf/ipmon/ipmon.54
-rw-r--r--sbin/ipf/ipmon/ipmon.83
-rw-r--r--sbin/ipf/ipmon/ipmon.c25
-rw-r--r--sbin/ipf/ipmon/ipmon_y.y1
-rw-r--r--sbin/ipf/ipnat/Makefile3
-rw-r--r--sbin/ipf/ipnat/Makefile.depend3
-rw-r--r--sbin/ipf/ipnat/ipnat.11
-rw-r--r--sbin/ipf/ipnat/ipnat.42
-rw-r--r--sbin/ipf/ipnat/ipnat.528
-rw-r--r--sbin/ipf/ipnat/ipnat.82
-rw-r--r--sbin/ipf/ipnat/ipnat.c5
-rw-r--r--sbin/ipf/ipnat/ipnat_y.y1
-rw-r--r--sbin/ipf/ippool/Makefile3
-rw-r--r--sbin/ipf/ippool/Makefile.depend3
-rw-r--r--sbin/ipf/ippool/ippool.511
-rw-r--r--sbin/ipf/ippool/ippool.88
-rw-r--r--sbin/ipf/ippool/ippool.c69
-rw-r--r--sbin/ipf/ippool/ippool_y.y1
-rw-r--r--sbin/ipf/ipresend/Makefile2
-rw-r--r--sbin/ipf/ipresend/Makefile.depend1
-rw-r--r--sbin/ipf/ipscan/Makefile2
-rw-r--r--sbin/ipf/ipscan/ipscan.54
-rw-r--r--sbin/ipf/ipscan/ipscan.82
-rw-r--r--sbin/ipf/ipscan/ipscan_y.y1
-rw-r--r--sbin/ipf/ipsend/44arp.c1
-rw-r--r--sbin/ipf/ipsend/arp.c5
-rw-r--r--sbin/ipf/ipsend/dlcommon.c1
-rw-r--r--sbin/ipf/ipsend/dltest.h1
-rw-r--r--sbin/ipf/ipsend/ip.c7
-rw-r--r--sbin/ipf/ipsend/ipresend.14
-rw-r--r--sbin/ipf/ipsend/ipresend.c5
-rw-r--r--sbin/ipf/ipsend/ipsend.16
-rw-r--r--sbin/ipf/ipsend/ipsend.56
-rw-r--r--sbin/ipf/ipsend/ipsend.c30
-rw-r--r--sbin/ipf/ipsend/ipsend.h3
-rw-r--r--sbin/ipf/ipsend/ipsopt.c5
-rw-r--r--sbin/ipf/ipsend/iptest.13
-rw-r--r--sbin/ipf/ipsend/iptest.c5
-rw-r--r--sbin/ipf/ipsend/iptests.c32
-rw-r--r--sbin/ipf/ipsend/resend.c11
-rw-r--r--sbin/ipf/ipsend/sbpf.c5
-rw-r--r--sbin/ipf/ipsend/sdlpi.c5
-rw-r--r--sbin/ipf/ipsend/snit.c5
-rw-r--r--sbin/ipf/ipsend/sock.c6
-rw-r--r--sbin/ipf/ipsend/sockraw.c4
-rw-r--r--sbin/ipf/libipf/Makefile2
-rw-r--r--sbin/ipf/libipf/Makefile.depend1
-rw-r--r--sbin/ipf/libipf/addicmp.c1
-rw-r--r--sbin/ipf/libipf/addipopt.c1
-rw-r--r--sbin/ipf/libipf/bcopywrap.c1
-rw-r--r--sbin/ipf/libipf/binprint.c1
-rw-r--r--sbin/ipf/libipf/buildopts.c1
-rw-r--r--sbin/ipf/libipf/checkrev.c1
-rw-r--r--sbin/ipf/libipf/connecttcp.c2
-rw-r--r--sbin/ipf/libipf/count4bits.c1
-rw-r--r--sbin/ipf/libipf/count6bits.c1
-rw-r--r--sbin/ipf/libipf/debug.c1
-rw-r--r--sbin/ipf/libipf/facpri.c8
-rw-r--r--sbin/ipf/libipf/facpri.h1
-rw-r--r--sbin/ipf/libipf/fill6bits.c1
-rw-r--r--sbin/ipf/libipf/flags.c10
-rw-r--r--sbin/ipf/libipf/gethost.c1
-rw-r--r--sbin/ipf/libipf/getifname.c1
-rw-r--r--sbin/ipf/libipf/getnattype.c4
-rw-r--r--sbin/ipf/libipf/getport.c1
-rw-r--r--sbin/ipf/libipf/getportproto.c1
-rw-r--r--sbin/ipf/libipf/getproto.c1
-rw-r--r--sbin/ipf/libipf/getsumd.c1
-rw-r--r--sbin/ipf/libipf/hostname.c1
-rw-r--r--sbin/ipf/libipf/icmpcode.c1
-rw-r--r--sbin/ipf/libipf/inet_addr.c5
-rw-r--r--sbin/ipf/libipf/initparse.c1
-rw-r--r--sbin/ipf/libipf/interror.c22
-rw-r--r--sbin/ipf/libipf/ionames.c1
-rw-r--r--sbin/ipf/libipf/ipf_dotuning.c3
-rw-r--r--sbin/ipf/libipf/ipft_hx.c5
-rw-r--r--sbin/ipf/libipf/ipft_pc.c4
-rw-r--r--sbin/ipf/libipf/ipft_tx.c33
-rw-r--r--sbin/ipf/libipf/ipoptsec.c1
-rw-r--r--sbin/ipf/libipf/kmem.c5
-rw-r--r--sbin/ipf/libipf/kmem.h1
-rw-r--r--sbin/ipf/libipf/kmemcpywrap.c1
-rw-r--r--sbin/ipf/libipf/kvatoname.c1
-rw-r--r--sbin/ipf/libipf/load_hash.c1
-rw-r--r--sbin/ipf/libipf/load_hashnode.c24
-rw-r--r--sbin/ipf/libipf/load_http.c3
-rw-r--r--sbin/ipf/libipf/load_pool.c1
-rw-r--r--sbin/ipf/libipf/load_poolnode.c28
-rw-r--r--sbin/ipf/libipf/mutex_emul.c6
-rw-r--r--sbin/ipf/libipf/nametokva.c1
-rw-r--r--sbin/ipf/libipf/nat_setgroupmap.c4
-rw-r--r--sbin/ipf/libipf/ntomask.c1
-rw-r--r--sbin/ipf/libipf/optname.c1
-rw-r--r--sbin/ipf/libipf/optprint.c1
-rw-r--r--sbin/ipf/libipf/optprintv6.c1
-rw-r--r--sbin/ipf/libipf/optvalue.c1
-rw-r--r--sbin/ipf/libipf/parseipfexpr.c8
-rw-r--r--sbin/ipf/libipf/poolio.c5
-rw-r--r--sbin/ipf/libipf/portname.c1
-rw-r--r--sbin/ipf/libipf/print_toif.c1
-rw-r--r--sbin/ipf/libipf/printactiveaddr.c3
-rw-r--r--sbin/ipf/libipf/printactivenat.c4
-rw-r--r--sbin/ipf/libipf/printaps.c4
-rw-r--r--sbin/ipf/libipf/printbuf.c1
-rw-r--r--sbin/ipf/libipf/printdstl_live.c3
-rw-r--r--sbin/ipf/libipf/printdstlist.c2
-rw-r--r--sbin/ipf/libipf/printdstlistdata.c5
-rw-r--r--sbin/ipf/libipf/printfr.c1
-rw-r--r--sbin/ipf/libipf/printfraginfo.c8
-rw-r--r--sbin/ipf/libipf/printhash.c1
-rw-r--r--sbin/ipf/libipf/printhash_live.c11
-rw-r--r--sbin/ipf/libipf/printhashdata.c19
-rw-r--r--sbin/ipf/libipf/printhashnode.c1
-rw-r--r--sbin/ipf/libipf/printhostmap.c1
-rw-r--r--sbin/ipf/libipf/printhostmask.c1
-rw-r--r--sbin/ipf/libipf/printifname.c1
-rw-r--r--sbin/ipf/libipf/printip.c1
-rw-r--r--sbin/ipf/libipf/printlog.c1
-rw-r--r--sbin/ipf/libipf/printmask.c1
-rw-r--r--sbin/ipf/libipf/printnat.c4
-rw-r--r--sbin/ipf/libipf/printnataddr.c3
-rw-r--r--sbin/ipf/libipf/printpacket.c26
-rw-r--r--sbin/ipf/libipf/printpacket6.c1
-rw-r--r--sbin/ipf/libipf/printpool.c1
-rw-r--r--sbin/ipf/libipf/printpool_live.c18
-rw-r--r--sbin/ipf/libipf/printpooldata.c12
-rw-r--r--sbin/ipf/libipf/printpoolnode.c1
-rw-r--r--sbin/ipf/libipf/printportcmp.c1
-rw-r--r--sbin/ipf/libipf/printproto.c3
-rw-r--r--sbin/ipf/libipf/printsbuf.c1
-rw-r--r--sbin/ipf/libipf/printstate.c1
-rw-r--r--sbin/ipf/libipf/printtcpflags.c6
-rw-r--r--sbin/ipf/libipf/printtunable.c1
-rw-r--r--sbin/ipf/libipf/remove_hash.c1
-rw-r--r--sbin/ipf/libipf/remove_hashnode.c1
-rw-r--r--sbin/ipf/libipf/remove_pool.c1
-rw-r--r--sbin/ipf/libipf/remove_poolnode.c1
-rw-r--r--sbin/ipf/libipf/resetlexer.c1
-rw-r--r--sbin/ipf/libipf/rwlock_emul.c1
-rw-r--r--sbin/ipf/libipf/tcp_flags.c13
-rw-r--r--sbin/ipf/libipf/tcpflags.c12
-rw-r--r--sbin/ipf/libipf/tcpoptnames.c1
-rw-r--r--sbin/ipf/libipf/v6ionames.c1
-rw-r--r--sbin/ipf/libipf/v6optvalue.c1
-rw-r--r--sbin/ipf/libipf/var.c4
-rw-r--r--sbin/ipf/libipf/verbose.c1
-rw-r--r--sbin/ipfw/Makefile5
-rw-r--r--sbin/ipfw/Makefile.depend3
-rw-r--r--sbin/ipfw/altq.c2
-rw-r--r--sbin/ipfw/dummynet.c50
-rw-r--r--sbin/ipfw/ipfw.8284
-rw-r--r--sbin/ipfw/ipfw2.c975
-rw-r--r--sbin/ipfw/ipfw2.h16
-rw-r--r--sbin/ipfw/ipv6.c9
-rw-r--r--sbin/ipfw/main.c13
-rw-r--r--sbin/ipfw/nat.c13
-rw-r--r--sbin/ipfw/nat64clat.c8
-rw-r--r--sbin/ipfw/nat64lsn.c24
-rw-r--r--sbin/ipfw/nat64stl.c8
-rw-r--r--sbin/ipfw/nptv6.c55
-rw-r--r--sbin/ipfw/tables.c61
-rw-r--r--sbin/ipfw/tests/Makefile6
-rw-r--r--sbin/ipfw/tests/ipfw_test.sh107
-rwxr-xr-xsbin/ipfw/tests/test_add_rule.py493
-rw-r--r--sbin/kldconfig/Makefile1
-rw-r--r--sbin/kldconfig/Makefile.depend2
-rw-r--r--sbin/kldconfig/kldconfig.82
-rw-r--r--sbin/kldconfig/kldconfig.c5
-rw-r--r--sbin/kldload/Makefile1
-rw-r--r--sbin/kldload/Makefile.depend2
-rw-r--r--sbin/kldload/kldload.85
-rw-r--r--sbin/kldload/kldload.c5
-rw-r--r--sbin/kldstat/Makefile1
-rw-r--r--sbin/kldstat/Makefile.depend2
-rw-r--r--sbin/kldstat/kldstat.822
-rw-r--r--sbin/kldstat/kldstat.c9
-rw-r--r--sbin/kldunload/Makefile1
-rw-r--r--sbin/kldunload/Makefile.depend2
-rw-r--r--sbin/kldunload/kldunload.82
-rw-r--r--sbin/kldunload/kldunload.c5
-rw-r--r--sbin/ldconfig/Makefile2
-rw-r--r--sbin/ldconfig/Makefile.depend2
-rw-r--r--sbin/ldconfig/elfhints.c50
-rw-r--r--sbin/ldconfig/ldconfig.841
-rw-r--r--sbin/ldconfig/ldconfig.c19
-rw-r--r--sbin/ldconfig/ldconfig.h6
-rw-r--r--sbin/md5/Makefile22
-rw-r--r--sbin/md5/Makefile.depend4
-rw-r--r--sbin/md5/Makefile.depend.host11
-rw-r--r--sbin/md5/md5.1344
-rw-r--r--sbin/md5/md5.c767
-rw-r--r--sbin/md5/tests/1.inp0
-rw-r--r--sbin/md5/tests/1.sha512-p.chk1
-rw-r--r--sbin/md5/tests/1.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/2.inp1
-rw-r--r--sbin/md5/tests/2.sha512-p.chk1
-rw-r--r--sbin/md5/tests/2.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/3.inp1
-rw-r--r--sbin/md5/tests/3.sha512-p.chk1
-rw-r--r--sbin/md5/tests/3.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/4.inp1
-rw-r--r--sbin/md5/tests/4.sha512-p.chk1
-rw-r--r--sbin/md5/tests/4.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/5.inp1
-rw-r--r--sbin/md5/tests/5.sha512-p.chk1
-rw-r--r--sbin/md5/tests/5.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/6.inp1
-rw-r--r--sbin/md5/tests/6.sha512-p.chk1
-rw-r--r--sbin/md5/tests/6.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/7.inp1
-rw-r--r--sbin/md5/tests/7.sha512-p.chk1
-rw-r--r--sbin/md5/tests/7.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/8.inp1
-rw-r--r--sbin/md5/tests/8.sha512-p.chk1
-rw-r--r--sbin/md5/tests/8.sha512sum-p.chk1
-rw-r--r--sbin/md5/tests/Makefile37
-rw-r--r--sbin/md5/tests/Makefile.depend10
-rw-r--r--sbin/md5/tests/algorithms.txt1
-rw-r--r--sbin/md5/tests/bsd-c-test.SH23
-rw-r--r--sbin/md5/tests/bsd-p-test.SH24
-rw-r--r--sbin/md5/tests/bsd-s-test.SH30
-rw-r--r--sbin/md5/tests/coreutils-c-test.SH21
-rw-r--r--sbin/md5/tests/md5.digest8
-rw-r--r--sbin/md5/tests/md5_test.sh409
-rw-r--r--sbin/md5/tests/md5sum.digest8
-rw-r--r--sbin/md5/tests/rmd160.digest8
-rw-r--r--sbin/md5/tests/rmd160sum.digest8
-rw-r--r--sbin/md5/tests/self-test.SH8
-rw-r--r--sbin/md5/tests/self-test.md5.chk9
-rw-r--r--sbin/md5/tests/self-test.rmd160.chk9
-rw-r--r--sbin/md5/tests/self-test.sh_inp8
-rw-r--r--sbin/md5/tests/self-test.sha1.chk9
-rw-r--r--sbin/md5/tests/self-test.sha224.chk9
-rw-r--r--sbin/md5/tests/self-test.sha256.chk9
-rw-r--r--sbin/md5/tests/self-test.sha384.chk9
-rw-r--r--sbin/md5/tests/self-test.sha512.chk9
-rw-r--r--sbin/md5/tests/self-test.sha512t256.chk9
-rw-r--r--sbin/md5/tests/self-test.skein1024.chk9
-rw-r--r--sbin/md5/tests/self-test.skein256.chk9
-rw-r--r--sbin/md5/tests/self-test.skein512.chk9
-rw-r--r--sbin/md5/tests/sha1.digest8
-rw-r--r--sbin/md5/tests/sha1sum.digest8
-rw-r--r--sbin/md5/tests/sha224.digest8
-rw-r--r--sbin/md5/tests/sha224sum.digest8
-rw-r--r--sbin/md5/tests/sha256.digest8
-rw-r--r--sbin/md5/tests/sha256sum.digest8
-rw-r--r--sbin/md5/tests/sha384.digest8
-rw-r--r--sbin/md5/tests/sha384sum.digest8
-rw-r--r--sbin/md5/tests/sha512.digest8
-rw-r--r--sbin/md5/tests/sha512sum.digest8
-rw-r--r--sbin/md5/tests/sha512t256.digest8
-rw-r--r--sbin/md5/tests/sha512t256sum.digest8
-rw-r--r--sbin/md5/tests/skein1024.digest8
-rw-r--r--sbin/md5/tests/skein1024sum.digest8
-rw-r--r--sbin/md5/tests/skein256.digest8
-rw-r--r--sbin/md5/tests/skein256sum.digest8
-rw-r--r--sbin/md5/tests/skein512.digest8
-rw-r--r--sbin/md5/tests/skein512sum.digest8
-rw-r--r--sbin/mdconfig/Makefile2
-rw-r--r--sbin/mdconfig/Makefile.depend4
-rw-r--r--sbin/mdconfig/mdconfig.812
-rw-r--r--sbin/mdconfig/mdconfig.c117
-rw-r--r--sbin/mdconfig/tests/Makefile2
-rw-r--r--sbin/mdconfig/tests/Makefile.depend1
-rwxr-xr-xsbin/mdconfig/tests/mdconfig_test.sh38
-rw-r--r--sbin/mdmfs/Makefile2
-rw-r--r--sbin/mdmfs/Makefile.depend2
-rw-r--r--sbin/mdmfs/mdmfs.826
-rw-r--r--sbin/mdmfs/mdmfs.c14
-rw-r--r--sbin/mknod/Makefile3
-rw-r--r--sbin/mknod/Makefile.depend2
-rw-r--r--sbin/mknod/mknod.89
-rw-r--r--sbin/mknod/mknod.c14
-rw-r--r--sbin/mksnap_ffs/Makefile7
-rw-r--r--sbin/mksnap_ffs/Makefile.depend2
-rw-r--r--sbin/mksnap_ffs/mksnap_ffs.832
-rw-r--r--sbin/mksnap_ffs/mksnap_ffs.c4
-rw-r--r--sbin/mount/Makefile6
-rw-r--r--sbin/mount/Makefile.depend3
-rw-r--r--sbin/mount/extern.h4
-rw-r--r--sbin/mount/getmntopts.3181
-rw-r--r--sbin/mount/getmntopts.c199
-rw-r--r--sbin/mount/mntopts.h109
-rw-r--r--sbin/mount/mount.865
-rw-r--r--sbin/mount/mount.c96
-rw-r--r--sbin/mount/mount_fs.c16
-rw-r--r--sbin/mount/pathnames.h3
-rw-r--r--sbin/mount/vfslist.c8
-rw-r--r--sbin/mount_cd9660/Makefile11
-rw-r--r--sbin/mount_cd9660/Makefile.depend2
-rw-r--r--sbin/mount_cd9660/mount_cd9660.843
-rw-r--r--sbin/mount_cd9660/mount_cd9660.c98
-rw-r--r--sbin/mount_fusefs/Makefile11
-rw-r--r--sbin/mount_fusefs/Makefile.depend2
-rw-r--r--sbin/mount_fusefs/mount_fusefs.810
-rw-r--r--sbin/mount_fusefs/mount_fusefs.c8
-rw-r--r--sbin/mount_msdosfs/Makefile12
-rw-r--r--sbin/mount_msdosfs/Makefile.depend2
-rw-r--r--sbin/mount_msdosfs/mount_msdosfs.86
-rw-r--r--sbin/mount_msdosfs/mount_msdosfs.c8
-rw-r--r--sbin/mount_nfs/Makefile14
-rw-r--r--sbin/mount_nfs/Makefile.depend2
-rw-r--r--sbin/mount_nfs/mount_nfs.8122
-rw-r--r--sbin/mount_nfs/mount_nfs.c131
-rw-r--r--sbin/mount_nullfs/Makefile10
-rw-r--r--sbin/mount_nullfs/Makefile.depend2
-rw-r--r--sbin/mount_nullfs/mount_nullfs.854
-rw-r--r--sbin/mount_nullfs/mount_nullfs.c40
-rw-r--r--sbin/mount_udf/Makefile9
-rw-r--r--sbin/mount_udf/Makefile.depend2
-rw-r--r--sbin/mount_udf/mount_udf.82
-rw-r--r--sbin/mount_udf/mount_udf.c5
-rw-r--r--sbin/mount_unionfs/Makefile10
-rw-r--r--sbin/mount_unionfs/Makefile.depend2
-rw-r--r--sbin/mount_unionfs/mount_unionfs.89
-rw-r--r--sbin/mount_unionfs/mount_unionfs.c18
-rw-r--r--sbin/natd/Makefile2
-rw-r--r--sbin/natd/Makefile.depend2
-rw-r--r--sbin/natd/README1
-rw-r--r--sbin/natd/icmp.c2
-rw-r--r--sbin/natd/natd.824
-rw-r--r--sbin/natd/natd.c18
-rw-r--r--sbin/natd/natd.h2
-rw-r--r--sbin/natd/samples/natd.cf.sample1
-rw-r--r--sbin/newfs/Makefile4
-rw-r--r--sbin/newfs/Makefile.depend2
-rw-r--r--sbin/newfs/mkfs.c96
-rw-r--r--sbin/newfs/newfs.848
-rw-r--r--sbin/newfs/newfs.c39
-rw-r--r--sbin/newfs/newfs.h2
-rw-r--r--sbin/newfs/ref.test1
-rw-r--r--sbin/newfs/runtest00.sh1
-rw-r--r--sbin/newfs/runtest01.sh1
-rw-r--r--sbin/newfs_msdos/Makefile3
-rw-r--r--sbin/newfs_msdos/Makefile.depend2
-rw-r--r--sbin/newfs_msdos/mkfs_msdos.c30
-rw-r--r--sbin/newfs_msdos/mkfs_msdos.h1
-rw-r--r--sbin/newfs_msdos/newfs_msdos.823
-rw-r--r--sbin/newfs_msdos/newfs_msdos.c9
-rw-r--r--sbin/nfsiod/Makefile3
-rw-r--r--sbin/nfsiod/Makefile.depend2
-rw-r--r--sbin/nfsiod/nfsiod.83
-rw-r--r--sbin/nfsiod/nfsiod.c14
-rw-r--r--sbin/nos-tun/Makefile2
-rw-r--r--sbin/nos-tun/Makefile.depend2
-rw-r--r--sbin/nos-tun/nos-tun.82
-rw-r--r--sbin/nos-tun/nos-tun.c17
-rw-r--r--sbin/nvmecontrol/Makefile34
-rw-r--r--sbin/nvmecontrol/Makefile.depend4
-rw-r--r--sbin/nvmecontrol/comnd.c5
-rw-r--r--sbin/nvmecontrol/comnd.h4
-rw-r--r--sbin/nvmecontrol/connect.c313
-rw-r--r--sbin/nvmecontrol/devlist.c209
-rw-r--r--sbin/nvmecontrol/disconnect.c82
-rw-r--r--sbin/nvmecontrol/discover.c300
-rw-r--r--sbin/nvmecontrol/fabrics.c559
-rw-r--r--sbin/nvmecontrol/fabrics.h50
-rw-r--r--sbin/nvmecontrol/firmware.c19
-rw-r--r--sbin/nvmecontrol/format.c34
-rw-r--r--sbin/nvmecontrol/identify.c116
-rw-r--r--sbin/nvmecontrol/identify_ext.c219
-rw-r--r--sbin/nvmecontrol/logpage.c279
-rw-r--r--sbin/nvmecontrol/modules/Makefile7
-rw-r--r--sbin/nvmecontrol/modules/Makefile.inc5
-rw-r--r--sbin/nvmecontrol/modules/intel/Makefile2
-rw-r--r--sbin/nvmecontrol/modules/intel/intel.c57
-rw-r--r--sbin/nvmecontrol/modules/micron/Makefile6
-rw-r--r--sbin/nvmecontrol/modules/micron/micron.c129
-rw-r--r--sbin/nvmecontrol/modules/samsung/Makefile4
-rw-r--r--sbin/nvmecontrol/modules/samsung/samsung.c162
-rw-r--r--sbin/nvmecontrol/modules/wdc/Makefile2
-rw-r--r--sbin/nvmecontrol/modules/wdc/wdc.c15
-rw-r--r--sbin/nvmecontrol/nc_util.c4
-rw-r--r--sbin/nvmecontrol/ns.c109
-rw-r--r--sbin/nvmecontrol/nsid.c5
-rw-r--r--sbin/nvmecontrol/nvmecontrol.8384
-rw-r--r--sbin/nvmecontrol/nvmecontrol.c36
-rw-r--r--sbin/nvmecontrol/nvmecontrol.h49
-rw-r--r--sbin/nvmecontrol/nvmecontrol_ext.h4
-rw-r--r--sbin/nvmecontrol/passthru.c7
-rw-r--r--sbin/nvmecontrol/perftest.c5
-rw-r--r--sbin/nvmecontrol/power.c22
-rw-r--r--sbin/nvmecontrol/reconnect.c333
-rw-r--r--sbin/nvmecontrol/reset.c5
-rw-r--r--sbin/nvmecontrol/resv.c9
-rw-r--r--sbin/nvmecontrol/sanitize.c25
-rw-r--r--sbin/nvmecontrol/selftest.c8
-rw-r--r--sbin/nvmecontrol/telemetry.c182
-rw-r--r--sbin/nvmecontrol/tests/Makefile2
-rw-r--r--sbin/nvmecontrol/tests/Makefile.depend10
-rwxr-xr-xsbin/nvmecontrol/tests/basic.sh15
-rw-r--r--sbin/pfctl/Makefile2
-rw-r--r--sbin/pfctl/Makefile.depend4
-rw-r--r--sbin/pfctl/parse.y2226
-rw-r--r--sbin/pfctl/pf.os1
-rw-r--r--sbin/pfctl/pf_print_state.c233
-rw-r--r--sbin/pfctl/pf_ruleset.c3
-rw-r--r--sbin/pfctl/pfctl.8243
-rw-r--r--sbin/pfctl/pfctl.c1806
-rw-r--r--sbin/pfctl/pfctl.h82
-rw-r--r--sbin/pfctl/pfctl_altq.c4
-rw-r--r--sbin/pfctl/pfctl_optimize.c182
-rw-r--r--sbin/pfctl/pfctl_osfp.c35
-rw-r--r--sbin/pfctl/pfctl_parser.c715
-rw-r--r--sbin/pfctl/pfctl_parser.h97
-rw-r--r--sbin/pfctl/pfctl_qstats.c2
-rw-r--r--sbin/pfctl/pfctl_radix.c189
-rw-r--r--sbin/pfctl/pfctl_table.c371
-rw-r--r--sbin/pfctl/tests/Makefile4
-rw-r--r--sbin/pfctl/tests/Makefile.depend6
-rw-r--r--sbin/pfctl/tests/files/Makefile4
-rw-r--r--sbin/pfctl/tests/files/Makefile.depend1
-rw-r--r--sbin/pfctl/tests/files/pf0004.ok24
-rw-r--r--sbin/pfctl/tests/files/pf0016.in6
-rw-r--r--sbin/pfctl/tests/files/pf0016.ok4
-rw-r--r--sbin/pfctl/tests/files/pf0018.in18
-rw-r--r--sbin/pfctl/tests/files/pf0018.ok19
-rw-r--r--sbin/pfctl/tests/files/pf0019.in4
-rw-r--r--sbin/pfctl/tests/files/pf0019.ok9
-rw-r--r--sbin/pfctl/tests/files/pf0020.in4
-rw-r--r--sbin/pfctl/tests/files/pf0020.ok12
-rw-r--r--sbin/pfctl/tests/files/pf0048.in12
-rw-r--r--sbin/pfctl/tests/files/pf0048.ok8
-rw-r--r--sbin/pfctl/tests/files/pf0069.in3
-rw-r--r--sbin/pfctl/tests/files/pf0069.ok1
-rw-r--r--sbin/pfctl/tests/files/pf0070.in3
-rw-r--r--sbin/pfctl/tests/files/pf0070.ok1
-rw-r--r--sbin/pfctl/tests/files/pf0071.in3
-rw-r--r--sbin/pfctl/tests/files/pf0071.ok1
-rw-r--r--sbin/pfctl/tests/files/pf0072.in3
-rw-r--r--sbin/pfctl/tests/files/pf0072.ok2
-rw-r--r--sbin/pfctl/tests/files/pf0084.in12
-rw-r--r--sbin/pfctl/tests/files/pf0084.ok3
-rw-r--r--sbin/pfctl/tests/files/pf0088.in2
-rw-r--r--sbin/pfctl/tests/files/pf0088.ok2
-rw-r--r--sbin/pfctl/tests/files/pf0098.in3
-rw-r--r--sbin/pfctl/tests/files/pf0098.ok1
-rw-r--r--sbin/pfctl/tests/files/pf0100.ok10
-rw-r--r--sbin/pfctl/tests/files/pf0102.ok4
-rw-r--r--sbin/pfctl/tests/files/pf1002.in5
-rw-r--r--sbin/pfctl/tests/files/pf1002.ok5
-rw-r--r--sbin/pfctl/tests/files/pf1010.in2
-rw-r--r--sbin/pfctl/tests/files/pf1010.ok2
-rw-r--r--sbin/pfctl/tests/files/pf1011.in1
-rw-r--r--sbin/pfctl/tests/files/pf1011.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1012.in1
-rw-r--r--sbin/pfctl/tests/files/pf1012.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1013.in1
-rw-r--r--sbin/pfctl/tests/files/pf1013.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1014.in1
-rw-r--r--sbin/pfctl/tests/files/pf1014.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1015.in1
-rw-r--r--sbin/pfctl/tests/files/pf1015.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1016.in1
-rw-r--r--sbin/pfctl/tests/files/pf1016.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1017.in1
-rw-r--r--sbin/pfctl/tests/files/pf1017.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1018.in1
-rw-r--r--sbin/pfctl/tests/files/pf1018.ok2
-rw-r--r--sbin/pfctl/tests/files/pf1019.in1
-rw-r--r--sbin/pfctl/tests/files/pf1019.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1020.in3
-rw-r--r--sbin/pfctl/tests/files/pf1020.include4
-rw-r--r--sbin/pfctl/tests/files/pf1020.ok2
-rw-r--r--sbin/pfctl/tests/files/pf1021.in1
-rw-r--r--sbin/pfctl/tests/files/pf1021.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1022.in1
-rw-r--r--sbin/pfctl/tests/files/pf1022.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1023.in3
-rw-r--r--sbin/pfctl/tests/files/pf1023.ok3
-rw-r--r--sbin/pfctl/tests/files/pf1024.in1
-rw-r--r--sbin/pfctl/tests/files/pf1024.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1025.in1
-rw-r--r--sbin/pfctl/tests/files/pf1025.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1026.in1
-rw-r--r--sbin/pfctl/tests/files/pf1026.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1027.in1
-rw-r--r--sbin/pfctl/tests/files/pf1027.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1028.in1
-rw-r--r--sbin/pfctl/tests/files/pf1028.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1029.in1
-rw-r--r--sbin/pfctl/tests/files/pf1029.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1030.in1
-rw-r--r--sbin/pfctl/tests/files/pf1030.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1031.in1
-rw-r--r--sbin/pfctl/tests/files/pf1031.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1032.in1
-rw-r--r--sbin/pfctl/tests/files/pf1032.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1033.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1033.in1
-rw-r--r--sbin/pfctl/tests/files/pf1034.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1034.in1
-rw-r--r--sbin/pfctl/tests/files/pf1035.in1
-rw-r--r--sbin/pfctl/tests/files/pf1035.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1036.in1
-rw-r--r--sbin/pfctl/tests/files/pf1036.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1037.in1
-rw-r--r--sbin/pfctl/tests/files/pf1037.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1038.in1
-rw-r--r--sbin/pfctl/tests/files/pf1038.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1039.in1
-rw-r--r--sbin/pfctl/tests/files/pf1039.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1040.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1040.in1
-rw-r--r--sbin/pfctl/tests/files/pf1040.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1041.in1
-rw-r--r--sbin/pfctl/tests/files/pf1041.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1042.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1042.in1
-rw-r--r--sbin/pfctl/tests/files/pf1043.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1043.in1
-rw-r--r--sbin/pfctl/tests/files/pf1044.in1
-rw-r--r--sbin/pfctl/tests/files/pf1044.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1045.in1
-rw-r--r--sbin/pfctl/tests/files/pf1045.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1046.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1046.in1
-rw-r--r--sbin/pfctl/tests/files/pf1047.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1047.in1
-rw-r--r--sbin/pfctl/tests/files/pf1048.in1
-rw-r--r--sbin/pfctl/tests/files/pf1048.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1049.in1
-rw-r--r--sbin/pfctl/tests/files/pf1049.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1050.in1
-rw-r--r--sbin/pfctl/tests/files/pf1050.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1051.in1
-rw-r--r--sbin/pfctl/tests/files/pf1051.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1052.in1
-rw-r--r--sbin/pfctl/tests/files/pf1052.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1053.in1
-rw-r--r--sbin/pfctl/tests/files/pf1053.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1054.in3
-rw-r--r--sbin/pfctl/tests/files/pf1054.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1055.in1
-rw-r--r--sbin/pfctl/tests/files/pf1055.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1056.in1
-rw-r--r--sbin/pfctl/tests/files/pf1056.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1057.in1
-rw-r--r--sbin/pfctl/tests/files/pf1057.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1058.in1
-rw-r--r--sbin/pfctl/tests/files/pf1058.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1059.in1
-rw-r--r--sbin/pfctl/tests/files/pf1059.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1060.in1
-rw-r--r--sbin/pfctl/tests/files/pf1060.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1061.in1
-rw-r--r--sbin/pfctl/tests/files/pf1061.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1062.in1
-rw-r--r--sbin/pfctl/tests/files/pf1062.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1063.in1
-rw-r--r--sbin/pfctl/tests/files/pf1063.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1064.in1
-rw-r--r--sbin/pfctl/tests/files/pf1064.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1065.in1
-rw-r--r--sbin/pfctl/tests/files/pf1065.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1066.in1
-rw-r--r--sbin/pfctl/tests/files/pf1066.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1067.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1067.in1
-rw-r--r--sbin/pfctl/tests/files/pf1068.in1
-rw-r--r--sbin/pfctl/tests/files/pf1068.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1069.in1
-rw-r--r--sbin/pfctl/tests/files/pf1069.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1070.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1070.in2
-rw-r--r--sbin/pfctl/tests/files/pf1070.include2
-rw-r--r--sbin/pfctl/tests/files/pf1071.in1
-rw-r--r--sbin/pfctl/tests/files/pf1071.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1072.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1072.in1
-rw-r--r--sbin/pfctl/tests/files/pf1073.in1
-rw-r--r--sbin/pfctl/tests/files/pf1073.ok1
-rw-r--r--sbin/pfctl/tests/files/pf1074.fail1
-rw-r--r--sbin/pfctl/tests/files/pf1074.in1
-rw-r--r--sbin/pfctl/tests/files/pf1075.in1
-rw-r--r--sbin/pfctl/tests/files/pf1075.ok1
-rwxr-xr-xsbin/pfctl/tests/macro.sh2
-rw-r--r--sbin/pfctl/tests/pfctl_test.c209
-rw-r--r--sbin/pfctl/tests/pfctl_test_list.inc68
-rw-r--r--sbin/pfilctl/Makefile2
-rw-r--r--sbin/pfilctl/pfilctl.82
-rw-r--r--sbin/pfilctl/pfilctl.c9
-rw-r--r--sbin/pflogd/Makefile2
-rw-r--r--sbin/pflogd/Makefile.depend3
-rw-r--r--sbin/pflowctl/Makefile9
-rw-r--r--sbin/pflowctl/Makefile.depend (renamed from sbin/sconfig/Makefile.depend)2
-rw-r--r--sbin/pflowctl/pflowctl.897
-rw-r--r--sbin/pflowctl/pflowctl.c602
-rw-r--r--sbin/ping/Makefile4
-rw-r--r--sbin/ping/Makefile.depend3
-rw-r--r--sbin/ping/Makefile.depend.options1
-rw-r--r--sbin/ping/main.c255
-rw-r--r--sbin/ping/main.h29
-rw-r--r--sbin/ping/ping.8150
-rw-r--r--sbin/ping/ping.c380
-rw-r--r--sbin/ping/ping.h4
-rw-r--r--sbin/ping/ping6.c153
-rw-r--r--sbin/ping/ping6.h4
-rw-r--r--sbin/ping/tests/Makefile10
-rw-r--r--sbin/ping/tests/Makefile.depend (renamed from sbin/gbde/Makefile.depend)11
-rw-r--r--sbin/ping/tests/in_cksum_test.c5
-rw-r--r--sbin/ping/tests/injection.py83
-rw-r--r--sbin/ping/tests/ping_6_c1_s8_t1.out6
-rw-r--r--sbin/ping/tests/ping_c1_s8_t1_S1.out6
-rw-r--r--sbin/ping/tests/ping_test.sh304
-rw-r--r--sbin/ping/tests/test_ping.py1458
-rw-r--r--sbin/ping/utils.c14
-rw-r--r--sbin/ping/utils.h4
-rw-r--r--sbin/ping6/Makefile.depend.options8
-rw-r--r--sbin/quotacheck/Makefile3
-rw-r--r--sbin/quotacheck/Makefile.depend3
-rw-r--r--sbin/quotacheck/preen.c11
-rw-r--r--sbin/quotacheck/quotacheck.83
-rw-r--r--sbin/quotacheck/quotacheck.c20
-rw-r--r--sbin/quotacheck/quotacheck.h2
-rw-r--r--sbin/rcorder/Makefile1
-rw-r--r--sbin/rcorder/Makefile.depend2
-rw-r--r--sbin/rcorder/ealloc.c1
-rw-r--r--sbin/rcorder/ealloc.h1
-rw-r--r--sbin/rcorder/hash.c14
-rw-r--r--sbin/rcorder/hash.h3
-rwxr-xr-xsbin/rcorder/rcorder-visualize.sh1
-rw-r--r--sbin/rcorder/rcorder.812
-rw-r--r--sbin/rcorder/rcorder.c12
-rw-r--r--sbin/rcorder/sprite.h3
-rw-r--r--sbin/reboot/Makefile11
-rw-r--r--sbin/reboot/Makefile.depend2
-rw-r--r--sbin/reboot/boot_i386.812
-rw-r--r--sbin/reboot/nextboot.82
-rw-r--r--sbin/reboot/nextboot.sh133
-rw-r--r--sbin/reboot/reboot.878
-rw-r--r--sbin/reboot/reboot.c306
-rw-r--r--sbin/recoverdisk/Makefile2
-rw-r--r--sbin/recoverdisk/Makefile.depend3
-rw-r--r--sbin/recoverdisk/recoverdisk.1267
-rw-r--r--sbin/recoverdisk/recoverdisk.c798
-rw-r--r--sbin/resolvconf/Makefile4
-rw-r--r--sbin/resolvconf/Makefile.depend1
-rw-r--r--sbin/restore/Makefile5
-rw-r--r--sbin/restore/Makefile.depend2
-rw-r--r--sbin/restore/dirs.c18
-rw-r--r--sbin/restore/extern.h3
-rw-r--r--sbin/restore/interactive.c9
-rw-r--r--sbin/restore/main.c15
-rw-r--r--sbin/restore/restore.83
-rw-r--r--sbin/restore/restore.c9
-rw-r--r--sbin/restore/restore.h7
-rw-r--r--sbin/restore/symtab.c8
-rw-r--r--sbin/restore/tape.c26
-rw-r--r--sbin/restore/utilities.c8
-rw-r--r--sbin/route/Makefile14
-rw-r--r--sbin/route/Makefile.depend3
-rw-r--r--sbin/route/keywords2
-rw-r--r--sbin/route/route.8109
-rw-r--r--sbin/route/route.c208
-rw-r--r--sbin/route/route_netlink.c914
-rw-r--r--sbin/route/tests/Makefile10
-rw-r--r--sbin/route/tests/Makefile.depend10
-rw-r--r--sbin/route/tests/basic.sh61
-rw-r--r--sbin/route/tests/utils.subr3
-rw-r--r--sbin/routed/Makefile3
-rw-r--r--sbin/routed/Makefile.depend2
-rw-r--r--sbin/routed/Makefile.inc2
-rw-r--r--sbin/routed/defs.h7
-rw-r--r--sbin/routed/if.c5
-rw-r--r--sbin/routed/input.c5
-rw-r--r--sbin/routed/main.c7
-rw-r--r--sbin/routed/output.c5
-rw-r--r--sbin/routed/parms.c5
-rw-r--r--sbin/routed/pathnames.h4
-rw-r--r--sbin/routed/radix.c7
-rw-r--r--sbin/routed/radix.h4
-rw-r--r--sbin/routed/rdisc.c5
-rw-r--r--sbin/routed/routed.812
-rw-r--r--sbin/routed/rtquery/Makefile1
-rw-r--r--sbin/routed/rtquery/Makefile.depend2
-rw-r--r--sbin/routed/rtquery/rtquery.88
-rw-r--r--sbin/routed/rtquery/rtquery.c23
-rw-r--r--sbin/routed/table.c5
-rw-r--r--sbin/routed/trace.c5
-rw-r--r--sbin/rtsol/Makefile1
-rw-r--r--sbin/rtsol/Makefile.depend1
-rw-r--r--sbin/rtsol/Makefile.depend.options1
-rw-r--r--sbin/savecore/Makefile5
-rw-r--r--sbin/savecore/Makefile.depend6
-rw-r--r--sbin/savecore/Makefile.depend.options1
-rw-r--r--sbin/savecore/savecore.89
-rw-r--r--sbin/savecore/savecore.c59
-rw-r--r--sbin/savecore/tests/Makefile6
-rw-r--r--sbin/savecore/tests/livedump_test.sh54
-rw-r--r--sbin/savecore/tests/log_test.sh25
-rw-r--r--sbin/sconfig/Makefile10
-rw-r--r--sbin/sconfig/sconfig.8608
-rw-r--r--sbin/sconfig/sconfig.c1212
-rw-r--r--sbin/setkey/Makefile1
-rw-r--r--sbin/setkey/Makefile.depend4
-rw-r--r--sbin/setkey/parse.y254
-rw-r--r--sbin/setkey/sample.cf1
-rw-r--r--sbin/setkey/scriptdump.pl1
-rw-r--r--sbin/setkey/setkey.897
-rw-r--r--sbin/setkey/setkey.c20
-rw-r--r--sbin/setkey/test-pfkey.c1
-rw-r--r--sbin/setkey/test-policy.c2
-rw-r--r--sbin/setkey/token.l16
-rw-r--r--sbin/setkey/vchar.h1
-rw-r--r--sbin/shutdown/Makefile3
-rw-r--r--sbin/shutdown/Makefile.depend2
-rw-r--r--sbin/shutdown/shutdown.839
-rw-r--r--sbin/shutdown/shutdown.c51
-rw-r--r--sbin/swapon/Makefile8
-rw-r--r--sbin/swapon/Makefile.depend2
-rw-r--r--sbin/swapon/swapon.83
-rw-r--r--sbin/swapon/swapon.c126
-rw-r--r--sbin/swapon/tests/Makefile5
-rwxr-xr-xsbin/swapon/tests/swapon_test.sh225
-rw-r--r--sbin/sysctl/Makefile11
-rw-r--r--sbin/sysctl/Makefile.depend2
-rw-r--r--sbin/sysctl/sysctl.8202
-rw-r--r--sbin/sysctl/sysctl.c197
-rw-r--r--sbin/sysctl/sysctl.conf1
-rw-r--r--sbin/sysctl/tests/Makefile3
-rw-r--r--sbin/sysctl/tests/Makefile.depend10
-rw-r--r--sbin/sysctl/tests/sysctl_test.sh174
-rw-r--r--sbin/tests/Makefile2
-rw-r--r--sbin/tests/Makefile.depend1
-rw-r--r--sbin/tunefs/Makefile12
-rw-r--r--sbin/tunefs/Makefile.depend2
-rw-r--r--sbin/tunefs/tunefs.842
-rw-r--r--sbin/tunefs/tunefs.c50
-rw-r--r--sbin/umbctl/Makefile8
-rw-r--r--sbin/umbctl/umbctl.8161
-rw-r--r--sbin/umbctl/umbctl.c557
-rw-r--r--sbin/umount/Makefile4
-rw-r--r--sbin/umount/Makefile.depend2
-rw-r--r--sbin/umount/umount.813
-rw-r--r--sbin/umount/umount.c86
-rw-r--r--sbin/veriexec/Makefile2
-rw-r--r--sbin/veriexec/Makefile.depend3
-rw-r--r--sbin/veriexec/manifest_lexer.l2
-rw-r--r--sbin/veriexec/manifest_parser.y6
-rw-r--r--sbin/veriexec/veriexec.8107
-rw-r--r--sbin/veriexec/veriexec.c71
-rw-r--r--sbin/veriexec/veriexec.h4
-rw-r--r--sbin/zfsbootcfg/Makefile16
-rw-r--r--sbin/zfsbootcfg/Makefile.depend17
-rw-r--r--sbin/zfsbootcfg/zfsbootcfg.810
-rw-r--r--sbin/zfsbootcfg/zfsbootcfg.c3
1166 files changed, 28800 insertions, 22475 deletions
diff --git a/sbin/Makefile b/sbin/Makefile
index 69cf51a83e26..ef953e80ba1e 100644
--- a/sbin/Makefile
+++ b/sbin/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.5 (Berkeley) 3/31/94
-# $FreeBSD$
-
.include <src.opts.mk>
SUBDIR=adjkerntz \
@@ -9,6 +6,7 @@ SUBDIR=adjkerntz \
comcontrol \
conscontrol \
ddb \
+ devd \
devfs \
devmatch \
dhclient \
@@ -23,11 +21,9 @@ SUBDIR=adjkerntz \
fsck_msdosfs \
fsdb \
fsirand \
- gbde \
geom \
ggate \
growfs \
- gvinum \
ifconfig \
init \
kldconfig \
@@ -52,6 +48,7 @@ SUBDIR=adjkerntz \
newfs_msdos \
nfsiod \
nos-tun \
+ nvmecontrol \
pfilctl \
rcorder \
reboot \
@@ -65,6 +62,7 @@ SUBDIR=adjkerntz \
swapon \
sysctl \
tunefs \
+ umbctl \
umount
.if ${MK_INET} != "no" || ${MK_INET6} != "no"
@@ -72,17 +70,16 @@ SUBDIR+= ping
.endif
SUBDIR.${MK_CCD}+= ccdconfig
-SUBDIR.${MK_CXX}+= devd
SUBDIR.${MK_HAST}+= hastctl
SUBDIR.${MK_HAST}+= hastd
SUBDIR.${MK_INET6}+= rtsol
SUBDIR.${MK_IPFILTER}+= ipf
SUBDIR.${MK_IPFW}+= ipfw
SUBDIR.${MK_IPFW}+= natd
-SUBDIR.${MK_NVME}+= nvmecontrol
SUBDIR.${MK_OPENSSL}+= decryptcore
SUBDIR.${MK_PF}+= pfctl
SUBDIR.${MK_PF}+= pflogd
+SUBDIR.${MK_PF}+= pflowctl
SUBDIR.${MK_QUOTAS}+= quotacheck
SUBDIR.${MK_ROUTED}+= routed
SUBDIR.${MK_VERIEXEC}+= veriexec
diff --git a/sbin/Makefile.amd64 b/sbin/Makefile.amd64
index 4135c44082c9..a7cb39976324 100644
--- a/sbin/Makefile.amd64
+++ b/sbin/Makefile.amd64
@@ -1,5 +1,2 @@
-# $FreeBSD$
-
SUBDIR += bsdlabel
SUBDIR += fdisk
-SUBDIR += sconfig
diff --git a/sbin/Makefile.arm b/sbin/Makefile.arm
index 2d231b0cb2b0..a7cb39976324 100644
--- a/sbin/Makefile.arm
+++ b/sbin/Makefile.arm
@@ -1,4 +1,2 @@
-# $FreeBSD$
-
SUBDIR += bsdlabel
SUBDIR += fdisk
diff --git a/sbin/Makefile.i386 b/sbin/Makefile.i386
index 4135c44082c9..a7cb39976324 100644
--- a/sbin/Makefile.i386
+++ b/sbin/Makefile.i386
@@ -1,5 +1,2 @@
-# $FreeBSD$
-
SUBDIR += bsdlabel
SUBDIR += fdisk
-SUBDIR += sconfig
diff --git a/sbin/Makefile.inc b/sbin/Makefile.inc
index 401e2a8e3491..7034747d22e7 100644
--- a/sbin/Makefile.inc
+++ b/sbin/Makefile.inc
@@ -1,6 +1,3 @@
-# @(#)Makefile.inc 8.1 (Berkeley) 6/8/93
-# $FreeBSD$
-
.include <src.opts.mk>
BINDIR?= /sbin
diff --git a/sbin/Makefile.powerpc64 b/sbin/Makefile.powerpc64
index 2d231b0cb2b0..a7cb39976324 100644
--- a/sbin/Makefile.powerpc64
+++ b/sbin/Makefile.powerpc64
@@ -1,4 +1,2 @@
-# $FreeBSD$
-
SUBDIR += bsdlabel
SUBDIR += fdisk
diff --git a/sbin/adjkerntz/Makefile b/sbin/adjkerntz/Makefile
index e30841e3ae2d..54980c3a57fb 100644
--- a/sbin/adjkerntz/Makefile
+++ b/sbin/adjkerntz/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=runtime
PROG= adjkerntz
MAN= adjkerntz.8
diff --git a/sbin/adjkerntz/Makefile.depend b/sbin/adjkerntz/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/adjkerntz/Makefile.depend
+++ b/sbin/adjkerntz/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/adjkerntz/adjkerntz.8 b/sbin/adjkerntz/adjkerntz.8
index 1bd1391b8ccb..b87981fd19f4 100644
--- a/sbin/adjkerntz/adjkerntz.8
+++ b/sbin/adjkerntz/adjkerntz.8
@@ -1,4 +1,7 @@
-.\" Copyright (C) 1993-1998 by Andrey A. Chernov, Moscow, Russia.
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 1993-1998 by Andrey A. Chernov, Moscow, Russia.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -22,14 +25,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd March 8, 2012
+.Dd July 29, 2024
.Dt ADJKERNTZ 8
.Os
.Sh NAME
.Nm adjkerntz
-.Nd adjust the local time CMOS clock to reflect time zone changes and keep the current timezone offset for the kernel
+.Nd adjust real-time clock (rtc) and kernel timezone offset
.Sh SYNOPSIS
.Nm
.Fl i
@@ -39,7 +40,7 @@
The
.Nm
utility maintains the proper relationship between the kernel clock, which
-is always set to UTC and the CMOS clock, which may be set to local time.
+is always set to UTC and the real-time clock, which may be set to local time.
The
.Nm
utility also informs the kernel about machine timezone shifts in order to
@@ -53,13 +54,13 @@ installed on the same system rather than fixing broken MS-DOS file
timestamps.
If the file
.Pa /etc/wall_cmos_clock
-exists, it means that the CMOS clock keeps local time (MS-DOS and MS-Windows
-compatible mode).
-If that file does not exist, it means that the CMOS clock keeps UTC time.
+exists, it means that the real-time clock keeps local time
+.Pq MS-DOS and MS-Windows compatible mode .
+If that file does not exist, it means that the real-time clock keeps UTC time.
The
.Nm
utility passes this state to the
-.Pa machdep.wall_cmos_clock
+.Va machdep.wall_cmos_clock
kernel variable.
.Pp
Adjustments may be needed at system startup and shutdown, and
@@ -67,7 +68,7 @@ whenever a time zone change occurs.
To handle these different situations,
.Nm
is invoked in two ways:
-.Bl -tag -width 4n
+.Bl -tag -width "-a [-s]"
.It Fl i
This form handles system startups and shutdowns.
The
@@ -78,51 +79,51 @@ on entry to multi-user mode, before any other daemons have been started.
The
.Nm
utility puts itself into the background.
-Then, for a local time CMOS clock,
+Then, for a local time real-time clock,
.Nm
reads the local time from it
and sets the kernel clock to the corresponding UTC time.
The
.Nm
utility also stores the local time zone offset in the
-.Pa machdep.adjkerntz
+.Va machdep.adjkerntz
kernel variable, for use by subsequent invocations of
-.Em "'adjkerntz -a'"
+.Ql adjkerntz -a
and by local time file systems.
.Pp
-For a local time CMOS clock
-.Em "'adjkerntz -i'"
+For a local time real-time clock
+.Ql adjkerntz -i
pauses and remains inactive as a background daemon until it
receives a SIGTERM.
The SIGTERM will normally be sent by
.Xr init 8
-when the system leaves multi-user mode (usually, because the system
-is being shut down).
+when the system leaves multi-user mode
+.Pq usually, because the system is being shut down .
After receiving the SIGTERM,
.Nm
-reads the UTC kernel clock and updates the CMOS clock, if necessary,
+reads the UTC kernel clock and updates the real-time clock, if necessary,
to ensure that it reflects the current local time zone.
Then
.Nm
exits.
.It Fl a Op Fl s
-This form is used to update the local time CMOS clock and kernel
-.Pa machdep.adjkerntz
-variable when time zone changes occur,
+This form is used to update the local time real-time clock and
+.Va machdep.adjkerntz
+kernel variable when time zone changes occur,
e.g., when entering or leaving daylight savings time.
The
.Nm
utility uses the kernel clock's UTC time,
-the previously stored
-time zone offset, and the changed time zone rule to
-calculate a new time zone offset.
+the previously stored time zone offset,
+and the changed time zone rule to calculate a new time zone offset.
It stores the new offset into the
-.Pa machdep.adjkerntz
-kernel variable and updates the wall CMOS clock to the new local time.
+.Va machdep.adjkerntz
+kernel variable and updates the wall real-time clock to the new local time.
If
-.Em "'adjkerntz -a'"
-was started at a nonexistent time (during a timezone change), it exits
-with a warning diagnostic unless the
+.Ql adjkerntz -a
+was started at a nonexistent time
+.Pq during a timezone change ,
+it exits with a warning diagnostic unless the
.Fl s
option was used, in which case
.Nm
@@ -130,14 +131,14 @@ sleeps 30 minutes and tries again.
.Pp
This form should be invoked from root's
.Xr crontab 5
-every half hour between midnight and 5am, when most modern time
-zone changes occur.
+every half hour between midnight and 5am,
+when most modern time zone changes occur.
Warning: do not use the
.Fl s
option in a
.Xr crontab 5
command line, or multiple
-.Em "'adjkerntz -a'"
+.Ql adjkerntz -a
instances could conflict with each other.
.El
.Pp
@@ -147,7 +148,7 @@ utility clears the kernel timezone structure and makes the kernel clock run
in the UTC time zone.
Super-user privileges are required for all operations.
.Sh ENVIRONMENT
-.Bl -tag -width Fl
+.Bl -tag -width /etc/wall_cmos_clock
.It Ev TZ
Time zone change rule, see
.Xr tzset 3 ;
@@ -166,8 +167,8 @@ and
.Xr zic 8 .
.It Pa /etc/wall_cmos_clock
Empty file.
-Its presence indicates that the machine's CMOS clock is set to local
-time, while its absence indicates a UTC CMOS clock.
+Its presence indicates that the machine's real-time clock is set to local
+time, while its absence indicates a UTC real-time clock.
.El
.Sh DIAGNOSTICS
No diagnostics.
@@ -180,6 +181,7 @@ and exits with a nonzero return code.
.Xr tzset 3 ,
.Xr crontab 5 ,
.Xr mount_msdosfs 8 ,
+.Xr ntpd 8 ,
.Xr rc 8 ,
.Xr sysctl 8 ,
.Xr tzsetup 8 ,
diff --git a/sbin/adjkerntz/adjkerntz.c b/sbin/adjkerntz/adjkerntz.c
index e6cadcf7f189..b231e1647b33 100644
--- a/sbin/adjkerntz/adjkerntz.c
+++ b/sbin/adjkerntz/adjkerntz.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 1993-1998 by Andrey A. Chernov, Moscow, Russia.
* All rights reserved.
@@ -26,16 +26,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#)Copyright (C) 1993-1996 by Andrey A. Chernov, Moscow, Russia.\n\
- All rights reserved.\n";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* Andrey A. Chernov <ache@astral.msk.su> Dec 20 1993
*
@@ -67,7 +57,7 @@ __FBSDID("$FreeBSD$");
#define REPORT_PERIOD (30*60)
static void fake(int);
-static void usage(void);
+static void usage(void) __dead2;
static void
fake(int unused __unused)
diff --git a/sbin/adjkerntz/pathnames.h b/sbin/adjkerntz/pathnames.h
index 43356cd357a9..3b6fa96149a5 100644
--- a/sbin/adjkerntz/pathnames.h
+++ b/sbin/adjkerntz/pathnames.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 1993 by Andrew A. Chernov, Moscow, Russia.
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 <paths.h>
diff --git a/sbin/bectl/Makefile b/sbin/bectl/Makefile
index 46d43306b9ca..c11426c57e45 100644
--- a/sbin/bectl/Makefile
+++ b/sbin/bectl/Makefile
@@ -1,8 +1,6 @@
-# $FreeBSD$
-
.include <src.opts.mk>
-PACKAGE=runtime
+PACKAGE=zfs
PROG= bectl
MAN= bectl.8
@@ -23,7 +21,7 @@ CFLAGS+= -I${SRCTOP}/sys
CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include
CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/module/icp/include
CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h
-CFLAGS+= -DHAVE_ISSETUGID
+CFLAGS+= -DHAVE_ISSETUGID -DHAVE_STRLCAT -DHAVE_STRLCPY
CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h
HAS_TESTS= yes
diff --git a/sbin/bectl/Makefile.depend b/sbin/bectl/Makefile.depend
index 125289c3cdc7..bcc4f32f88da 100644
--- a/sbin/bectl/Makefile.depend
+++ b/sbin/bectl/Makefile.depend
@@ -1,29 +1,17 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- cddl/lib/libavl \
cddl/lib/libnvpair \
cddl/lib/libspl \
- cddl/lib/libumem \
- cddl/lib/libuutil \
- cddl/lib/libzfs \
- cddl/lib/libzfs_core \
+ cddl/lib/libzfsbootenv \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libbe \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
- lib/libgeom \
lib/libjail \
- lib/libmd \
- lib/libsbuf \
- lib/libthr \
lib/libutil \
- lib/libz \
- lib/msun \
.include <dirdeps.mk>
diff --git a/sbin/bectl/bectl.8 b/sbin/bectl/bectl.8
index 79bdec751a86..0e08b3383e9a 100644
--- a/sbin/bectl/bectl.8
+++ b/sbin/bectl/bectl.8
@@ -1,97 +1,110 @@
.\"
-.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD
-.\"
.\" Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
.\"
-.\" 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.
-.\"
-.\"
-.\" @(#)be.1
+.\" SPDX-License-Identifier: BSD-2-Clause
.\"
-.\" $FreeBSD$
-.\"
-.Dd March 31, 2022
+.Dd June 13, 2025
.Dt BECTL 8
.Os
.Sh NAME
.Nm bectl
-.Nd Utility to manage boot environments on ZFS
+.Nd manage ZFS boot environments
.Sh SYNOPSIS
.Nm
+.Op Fl h
+.Nm
+.Op Fl r Ar beroot
.Cm activate
.Op Fl t | Fl T
.Ar beName
.Nm
+.Op Fl r Ar beroot
.Cm check
.Nm
+.Op Fl r Ar beroot
.Cm create
.Op Fl r
.Op Fl e Brq Ar nonActiveBe | Ar beName Ns Cm @ Ns Ar snapshot
.Ar newBeName
.Nm
+.Op Fl r Ar beroot
.Cm create
.Op Fl r
.Ar beName@snapshot
.Nm
+.Op Fl r Ar beroot
.Cm destroy
.Op Fl \&Fo
.Ar beName Ns Op Cm @ Ns Ar snapshot
.Nm
+.Op Fl r Ar beroot
.Cm export
.Ar sourceBe
.Nm
+.Op Fl r Ar beroot
.Cm import
.Ar targetBe
.Nm
+.Op Fl r Ar beroot
.Cm jail
.Op Fl bU
.Oo Bro Fl o Ar key Ns Cm = Ns Ar value | Fl u Ar key Brc Oc Ns ...
.Ar beName
.Op Ar utility Op Ar argument ...
.Nm
+.Op Fl r Ar beroot
.Cm list
.Op Fl aDHs
.Op Fl c Ar property
.Op Fl C Ar property
.Oo Bro Fl c Ar property | Fl C Ar property Brc Oc
.Nm
+.Op Fl r Ar beroot
.Cm mount
.Ar beName
.Op Ar mountpoint
.Nm
+.Op Fl r Ar beroot
.Cm rename
.Ar origBeName
.Ar newBeName
.Nm
+.Op Fl r Ar beroot
.Brq Cm ujail | unjail
.Brq Ar jailId | jailName | beName
.Nm
+.Op Fl r Ar beroot
.Brq Cm umount | unmount
.Op Fl f
.Ar beName
-.Pp
-.Nm
-.Op Fl h\&?
.Sh DESCRIPTION
The
.Nm
-command is used to setup and interact with ZFS boot environments, which are
-bootable clones of datasets.
-.Pp
-Boot environments
-allow the system to be upgraded, while preserving the old system environment in
-a separate ZFS dataset.
-.Pp
-The following commands are supported by
-.Nm :
-.Bl -tag -width activate
+utility manages bootable ZFS clones called boot environments.
+Boot envionments allow system changes to be tested safely,
+as they are selectable directly from the boot
+.Xr loader 8 .
+This utility can
+.Cm create ,
+.Cm list ,
+.Cm mount ,
+or
+.Cm jail
+boot environments.
+Once the changes have been tested, the boot environment can be
+.Cm unmount Ns ed ,
+.Cm activate Ns d ,
+.Cm rename Ns d ,
+and
+.Cm destroy Ns ed .
+.Ss Supported Subcommands and Flags
+.Bl -tag -width indent
+.It Fl h
+Print usage information and exit.
+.It Fl r Ar beroot Sy Ar subcommand
+Specify a parent dataset for the boot environment to use for
+.Ar subcommand
+for operation on manually imported pools or unusual layouts.
.It Xo
.Cm activate
.Op Fl t | Fl T
@@ -106,19 +119,19 @@ flag is given, this takes effect only for the next boot.
Flag
.Fl T
removes temporary boot once configuration.
-Without temporary configuration, the next boot will use zfs dataset specified
-in boot pool
+Without temporary configuration,
+the next boot will use zfs dataset specified in boot pool
.Ar bootfs
property.
.It Xo
.Cm check
.Xc
-Performs a silent sanity check on the current system.
+Perform a check to see if the current system can use boot environments.
If boot environments are supported and used,
.Nm
will exit with a status code of 0.
-Any other status code is not currently defined and may, in the future, grow
-special meaning for different degrees of sanity check failures.
+Any other status code is not currently defined and may, in the future,
+grow special meaning for different degrees of sanity check failures.
.It Xo
.Cm create
.Op Fl r
@@ -141,11 +154,13 @@ flag is specified, the new environment will be cloned from the given
.Ar nonActiveBe
or
.Ar beName Ns Cm @ Ns Ar snapshot .
-Otherwise, the new environment will be created from the currently booted environment.
+Otherwise, the new environment will be created from the currently booted
+environment.
.Pp
If
.Nm
-is creating from another boot environment, a snapshot of that boot environment will be created to clone from.
+is creating from another boot environment,
+a snapshot of that boot environment will be created to clone from.
.It Xo
.Cm create
.Op Fl r
@@ -156,13 +171,15 @@ Create a snapshot of the boot environment named
.Pp
If the
.Fl r
-flag is given, a recursive snapshot of the boot environment will be created.
-A snapshot is created for each descendant dataset of the boot environment.
+flag is given,
+a recursive snapshot of the boot environment will be created.
+A snapshot is created for each descendant dataset
+of the boot environment.
See
.Sx Boot Environment Structures
for a discussion on different layouts.
.Pp
-No new boot environment is created with this command.
+No new boot environment is created with this subcommand.
.It Xo
.Cm destroy
.Op Fl \&Fo
@@ -173,7 +190,7 @@ Destroy the given
boot environment or
.Ar beName Ns Cm @ Ns Ar snapshot
snapshot without confirmation, unlike in
-.Xr beadm 1 .
+.Xr beadm 8 .
Specifying
.Fl F
will automatically unmount without confirmation.
@@ -223,8 +240,8 @@ If
.Ar utility
is specified, it will be executed instead of
.Pa /bin/sh .
-The jail will be destroyed and the boot environment unmounted when the command
-finishes executing, unless the
+The jail will be destroyed and the boot environment unmounted
+when the command finishes executing, unless the
.Fl U
argument is specified.
.Pp
@@ -251,11 +268,11 @@ The following default parameters are provided:
.It Va allow.mount Ta Cm true
.It Va allow.mount.devfs Ta Cm true
.It Va enforce_statfs Ta Cm 1
-.It Va name Ta Set to jail ID.
+.It Va name Ta set to jail ID
.It Va host.hostname Ta Va bootenv
-.It Va path Ta Set to a path in Pa /tmp
+.It Va path Ta set to a path in Pa /tmp
generated by
-.Xr libbe 3 .
+.Xr libbe 3
.El
.Pp
All default parameters may be overwritten.
@@ -276,13 +293,12 @@ is used on next boot once
.Pq Em \&T ;
or combination of
.Pq Em \&NRT .
-.Pp
.Bl -tag -width indent
.It Fl a
Display all datasets.
.It Fl D
-Display the full space usage for each boot environment, assuming all
-other boot environments were destroyed.
+Display the full space usage for each boot environment,
+assuming all other boot environments were destroyed.
.It Fl H
Used for scripting.
Do not print headers and separate fields by a single tab instead of
@@ -290,18 +306,20 @@ arbitrary white space.
.It Fl s
Display all snapshots as well.
.It Fl c Ar property
-Sort boot environments by given property name.
+Sort boot environments by the given ZFS dataset property.
The following properties are supported:
.Pp
.Bl -tag -width 4n -offset indent -compact
-.It name (default output)
+.It name (the default)
.It creation
.It origin
.It used
-.It usedds
-.It usedsnap
-.It usedrefreserv
+.It usedbydataset
+.It usedbyrefreservation
+.It usedbysnapshots
.El
+.Pp
+Short forms usedds, usedrefreserv and usedsnap are also supported.
.It Fl C Ar property
Same as the
.Fl c
@@ -316,16 +334,34 @@ or
.Fl a
option is used.
.It Cm mount Ar beName Op Ar mountpoint
-Temporarily mount the boot environment.
-Mount at the specified
+Mount the given boot environment.
+.Pp
+If a nonexistent
.Ar mountpoint
-if provided.
+is given:
+.Nm
+will make the directory, including intermediate directories as required.
+.Pp
+If no
+.Ar mountpoint
+is given:
+.Nm
+will make a directory such as
+.Pa be_mount.c6Sf
+in
+.Pa /tmp .
+Randomness in the last four characters of the directory name
+will prevent mount point conflicts.
+Unmount of an environment, followed by mount of the same environment
+without giving a
+.Ar mountpoint ,
+will result in a different randomly-named mountpoint.
.It Cm rename Ar origBeName newBeName
Rename the given
.Ar origBeName
to the given
.Ar newBeName .
-The boot environment will not be unmounted in order for this rename to occur.
+The boot environment will not be unmounted for this rename to occur.
.It Cm ujail Brq Ar jailId | jailName | beName
.It Cm unjail Brq Ar jailId | jailName | beName
Destroy the jail created from the given boot environment.
@@ -343,14 +379,9 @@ Unmount the given boot environment, if it is mounted.
Specifying
.Fl f
will force the unmount if busy.
-.El
.Pp
-.Nm
-prints usage information if
-.Fl h
-or
-.Fl \&?
-is specified.
+Unmount will not remove the mount point.
+.El
.Ss Boot Environment Structures
The traditional
.Fx
@@ -358,8 +389,8 @@ boot environment layout, as created by the Auto ZFS option to
.Xr bsdinstall 8 ,
is a
.Dq shallow
-boot environment structure, where boot environment datasets do not have any
-directly subordinate datasets.
+boot environment structure, where boot environment datasets
+do not have any directly subordinate datasets.
Instead, they're organized off in
.Pa zroot/ROOT ,
and they rely on datasets elsewhere in the pool having
@@ -373,9 +404,10 @@ NAME CANMOUNT MOUNTPOINT
zroot
zroot/ROOT noauto none
zroot/ROOT/default noauto none
+zroot/home on /home
zroot/usr off /usr
-zroot/usr/home on /usr/home
-zroot/var on /var
+zroot/usr/src on /usr/src
+zroot/var off /var
.Ed
.Pp
In that example,
@@ -386,10 +418,11 @@ set to
.Dv off ,
thus files in
.Pa /usr
-typically fall into the boot environment because this dataset is not mounted.
-.Pa zroot/usr/home
+typically fall into the boot environment
+because this dataset is not mounted.
+.Pa zroot/usr/src
is mounted, thus files in
-.Pa /usr/home
+.Pa /usr/src
are not in the boot environment.
.Pp
The other style of boot environments in use, frequently called
@@ -412,8 +445,8 @@ Note that the subordinate datasets now have
.Dv canmount
set to
.Dv noauto .
-These are more obviously a part of the boot environment, as indicated by their
-positioning in the layout.
+These are more obviously a part of the boot environment,
+as indicated by their positioning in the layout.
These subordinate datasets will be mounted by the
.Dv zfsbe
.Xr rc 8
@@ -423,7 +456,7 @@ In this example,
is excluded from the boot environment.
.Pp
.Nm
-commands that have their own
+subcommands that have their own
.Fl r
operate on this second,
.Dq deep
@@ -435,33 +468,50 @@ A future version of
may default to handling both styles and deprecate the various
.Fl r
flags.
-\" .Sh EXAMPLES
-\" .Bl -bullet
-\" .It
-\" To fill in with jail upgrade example when behavior is firm.
-\" .El
+.Sh EXAMPLES
+Create a boot environment, named with today's date,
+containing snapshots of the root dataset and of all child datasets:
+.Pp
+.Dl bectl create -r `date +%Y%m%d`
+.Pp
+Mount a previous boot environment,
+.Ar yesterdaysbe ,
+to
+.Pa /mnt :
+.Pp
+.Dl bectl mount yesterdaysbe /mnt
+.\" To fill in with jail upgrade example when behavior is firm.
.Sh SEE ALSO
.Xr libbe 3 ,
+.Xr zfsprops 7 ,
.Xr beinstall.sh 8 ,
.Xr jail 8 ,
+.Xr loader 8 ,
.Xr zfs 8 ,
.Xr zpool 8
.Sh HISTORY
.Nm
-is based on
-.Xr beadm 1
-and was implemented as a project for the 2017 Summer of Code, along with
-.Xr libbe 3 .
-.Sh AUTHORS
-.Nm
-was written by
-.An Kyle Kneitinger (kneitinger) Aq Mt kyle@kneit.in .
-.Pp
-.Xr beadm 1
-was written and is maintained by
-.An Slawomir Wojciech Wojtczak (vermaden) Aq Mt vermaden@interia.pl .
+and
+.Xr libbe 3
+were written by
+.An Kyle Kneitinger (kneitinger) Aq Mt kyle@kneit.in
+as a 2017 Google Summer of Code project, with
+.An Allan Jude (allanjude) Aq Mt allanjude@freebsd.org
+as mentor.
.Pp
+.Nm
+and this manual page were derived from
+.Xr beadm 8 .
+.Sh AUTHORS
+.An Slawomir Wojciech Wojtczak (vermaden) Aq Mt vermaden@interia.pl
+is the creator and maintainer of
+.Xr beadm 8 .
.An Bryan Drewery (bdrewery) Aq Mt bryan@shatow.net
-wrote the original
-.Xr beadm 1
-manual page that this one is derived from.
+contributed child dataset fixes, and wrote the
+.Xr beadm 8
+manual page.
+.Pp
+Most later changes to
+.Nm ,
+and to this page, were written by
+.An Kyle Evans (kevans) Aq Mt kevans@freebsd.org .
diff --git a/sbin/bectl/bectl.c b/sbin/bectl/bectl.c
index 2b7af4e55419..95715b34336b 100644
--- a/sbin/bectl/bectl.c
+++ b/sbin/bectl/bectl.c
@@ -1,33 +1,9 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
+/*
* Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
*
- * 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 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.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <errno.h>
@@ -67,25 +43,25 @@ usage(bool explicit)
fp = explicit ? stdout : stderr;
fprintf(fp, "%s",
- "Usage:\tbectl {-h | -? | subcommand [args...]}\n"
+ "Usage:\tbectl {-h | subcommand [args...]}\n"
#if SOON
- "\tbectl add (path)*\n"
+ "\tbectl [-r beroot] add (path)*\n"
#endif
- "\tbectl activate [-t] beName\n"
- "\tbectl activate [-T]\n"
- "\tbectl check\n"
- "\tbectl create [-r] [-e {nonActiveBe | beName@snapshot}] beName\n"
- "\tbectl create [-r] beName@snapshot\n"
- "\tbectl destroy [-Fo] {beName | beName@snapshot}\n"
- "\tbectl export sourceBe\n"
- "\tbectl import targetBe\n"
- "\tbectl jail [-bU] [{-o key=value | -u key}]... beName\n"
+ "\tbectl [-r beroot] activate [-t] beName\n"
+ "\tbectl [-r beroot] activate [-T]\n"
+ "\tbectl [-r beroot] check\n"
+ "\tbectl [-r beroot] create [-r] [-e {nonActiveBe | beName@snapshot}] beName\n"
+ "\tbectl [-r beroot] create [-r] beName@snapshot\n"
+ "\tbectl [-r beroot] destroy [-Fo] {beName | beName@snapshot}\n"
+ "\tbectl [-r beroot] export sourceBe\n"
+ "\tbectl [-r beroot] import targetBe\n"
+ "\tbectl [-r beroot] jail [-bU] [{-o key=value | -u key}]... beName\n"
"\t [utility [argument ...]]\n"
- "\tbectl list [-aDHs] [{-c property | -C property}]\n"
- "\tbectl mount beName [mountpoint]\n"
- "\tbectl rename origBeName newBeName\n"
- "\tbectl {ujail | unjail} {jailID | jailName | beName}\n"
- "\tbectl {umount | unmount} [-f] beName\n");
+ "\tbectl [-r beroot] list [-aDHs] [{-c property | -C property}]\n"
+ "\tbectl [-r beroot] mount beName [mountpoint]\n"
+ "\tbectl [-r beroot] rename origBeName newBeName\n"
+ "\tbectl [-r beroot] {ujail | unjail} {jailID | jailName | beName}\n"
+ "\tbectl [-r beroot] {umount | unmount} [-f] beName\n");
return (explicit ? 0 : EX_USAGE);
}
@@ -117,7 +93,9 @@ static struct command_map_entry command_map[] =
{ "mount", bectl_cmd_mount, false },
{ "rename", bectl_cmd_rename, false },
{ "unjail", bectl_cmd_unjail, false },
+ { "ujail", bectl_cmd_unjail, false },
{ "unmount", bectl_cmd_unmount, false },
+ { "umount", bectl_cmd_unmount, false },
{ "check", bectl_cmd_check, true },
};
@@ -180,13 +158,15 @@ bectl_cmd_activate(int argc, char *argv[])
/* activate logic goes here */
if ((err = be_activate(be, argv[0], temp)) != 0)
/* XXX TODO: more specific error msg based on err */
- printf("Did not successfully activate boot environment %s\n",
+ printf("Did not successfully activate boot environment %s",
argv[0]);
else
- printf("Successfully activated boot environment %s\n", argv[0]);
+ printf("Successfully activated boot environment %s", argv[0]);
if (temp)
- printf("for next boot\n");
+ printf(" for next boot");
+
+ printf("\n");
return (err);
}
@@ -362,7 +342,8 @@ static int
bectl_cmd_destroy(int argc, char *argv[])
{
nvlist_t *props;
- char *origin, *target, targetds[BE_MAXPATHLEN];
+ char *target, targetds[BE_MAXPATHLEN];
+ const char *origin;
int err, flags, opt;
flags = 0;
@@ -441,7 +422,7 @@ bectl_cmd_mount(int argc, char *argv[])
switch (err) {
case BE_ERR_SUCCESS:
- printf("Successfully mounted %s at %s\n", bootenv, result_loc);
+ printf("%s\n", result_loc);
break;
default:
fprintf(stderr,
@@ -547,36 +528,30 @@ main(int argc, char *argv[])
{
struct command_map_entry *cmd;
const char *command;
- char *root;
- int rc;
-
- cmd = NULL;
- root = NULL;
- if (argc < 2)
- return (usage(false));
+ char *root = NULL;
+ int opt, rc;
- if (strcmp(argv[1], "-r") == 0) {
- if (argc < 4)
- return (usage(false));
- root = strdup(argv[2]);
- command = argv[3];
- argc -= 3;
- argv += 3;
- } else {
- command = argv[1];
- argc -= 1;
- argv += 1;
+ while ((opt = getopt(argc, argv, "hr:")) != -1) {
+ switch (opt) {
+ case 'h':
+ exit(usage(true));
+ case 'r':
+ root = strdup(optarg);
+ break;
+ default:
+ exit(usage(false));
+ }
}
- /* Handle command aliases */
- if (strcmp(command, "umount") == 0)
- command = "unmount";
+ argc -= optind;
+ argv += optind;
- if (strcmp(command, "ujail") == 0)
- command = "unjail";
+ if (argc == 0)
+ exit(usage(false));
- if ((strcmp(command, "-?") == 0) || (strcmp(command, "-h") == 0))
- return (usage(true));
+ command = *argv;
+ optreset = 1;
+ optind = 1;
if ((cmd = get_cmd_info(command)) == NULL) {
fprintf(stderr, "Unknown command: %s\n", command);
diff --git a/sbin/bectl/bectl.h b/sbin/bectl/bectl.h
index 878af24f0cbb..355110bcd6d3 100644
--- a/sbin/bectl/bectl.h
+++ b/sbin/bectl/bectl.h
@@ -1,30 +1,7 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
+/*
* Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
*
- * 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 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$
+ * SPDX-License-Identifier: BSD-2-Clause
*/
int usage(bool explicit);
diff --git a/sbin/bectl/bectl_jail.c b/sbin/bectl/bectl_jail.c
index 1d7d4a1496a2..050d46b627b4 100644
--- a/sbin/bectl/bectl_jail.c
+++ b/sbin/bectl/bectl_jail.c
@@ -1,33 +1,9 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
+/*
* Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
*
- * 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 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.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/jail.h>
#include <sys/mount.h>
@@ -133,7 +109,8 @@ jailparam_delarg(char *arg)
static int
build_jailcmd(char ***argvp, bool interactive, int argc, char *argv[])
{
- char *cmd, **jargv, *name, *val;
+ char *cmd, **jargv;
+ const char *name, *val;
nvpair_t *nvp;
size_t i, iarg, nargv;
@@ -404,7 +381,7 @@ static int
bectl_locate_jail(const char *ident)
{
nvlist_t *belist, *props;
- char *mnt;
+ const char *mnt;
int jid;
/* Try the easy-match first */
diff --git a/sbin/bectl/bectl_list.c b/sbin/bectl/bectl_list.c
index e43c3000d8f2..bd724b7bf012 100644
--- a/sbin/bectl/bectl_list.c
+++ b/sbin/bectl/bectl_list.c
@@ -1,33 +1,9 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
+/*
* Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
*
- * 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 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.
+ * SPDX-License-Identifier: BSD-2-Clause
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <stdbool.h>
#include <stdio.h>
@@ -39,8 +15,8 @@ __FBSDID("$FreeBSD$");
#include "bectl.h"
struct sort_column {
- char *name;
- char *val;
+ const char *name;
+ const char *val;
nvlist_t *nvl;
};
@@ -80,7 +56,7 @@ static unsigned long long dataset_space(const char *oname);
static const char *
get_origin_props(nvlist_t *dsprops, nvlist_t **originprops)
{
- char *propstr;
+ const char *propstr;
if (nvlist_lookup_string(dsprops, "origin", &propstr) == 0) {
if (be_prop_list_alloc(originprops) != 0) {
@@ -119,7 +95,8 @@ static unsigned long long
dataset_space(const char *oname)
{
unsigned long long space;
- char *dsname, *propstr, *sep;
+ char *dsname, *sep;
+ const char *propstr;
nvlist_t *dsprops;
space = 0;
@@ -179,8 +156,7 @@ print_info(const char *name, nvlist_t *dsprops, struct printc *pc)
char buf[BUFSZ];
unsigned long long ctimenum, space;
nvlist_t *originprops;
- const char *oname;
- char *dsname, *propstr;
+ const char *oname, *dsname, *propstr;
int active_colsz;
boolean_t active_now, active_reboot, bootonce;
@@ -293,10 +269,9 @@ print_info(const char *name, nvlist_t *dsprops, struct printc *pc)
static void
print_headers(nvlist_t *props, struct printc *pc)
{
- const char *chosen_be_header;
+ const char *chosen_be_header, *propstr;
nvpair_t *cur;
nvlist_t *dsprops;
- char *propstr;
size_t be_maxcol, mount_colsz;
if (pc->show_all_datasets || pc->show_snaps)
diff --git a/sbin/bectl/tests/Makefile b/sbin/bectl/tests/Makefile
index 10e23336d345..3a35a5263a69 100644
--- a/sbin/bectl/tests/Makefile
+++ b/sbin/bectl/tests/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= tests
ATF_TESTS_SH+= bectl_test
diff --git a/sbin/bectl/tests/Makefile.depend b/sbin/bectl/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/sbin/bectl/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/bectl/tests/bectl_test.sh b/sbin/bectl/tests/bectl_test.sh
index b101591c3ee9..8084b0a173f4 100755
--- a/sbin/bectl/tests/bectl_test.sh
+++ b/sbin/bectl/tests/bectl_test.sh
@@ -1,30 +1,8 @@
#
-# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
-#
# Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
#
-# 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.
+# SPDX-License-Identifier: BSD-2-Clause
#
-# $FreeBSD$
ZPOOL_NAME_FILE=zpool_name
get_zpool_name()
@@ -94,7 +72,6 @@ bectl_cleanup()
atf_test_case bectl_create cleanup
bectl_create_head()
{
-
atf_set "descr" "Check the various forms of bectl create"
atf_set "require.user" root
}
@@ -158,7 +135,6 @@ bectl_create_cleanup()
atf_test_case bectl_destroy cleanup
bectl_destroy_head()
{
-
atf_set "descr" "Check bectl destroy"
atf_set "require.user" root
}
@@ -241,14 +217,12 @@ bectl_destroy_body()
}
bectl_destroy_cleanup()
{
-
bectl_cleanup $(get_zpool_name)
}
atf_test_case bectl_export_import cleanup
bectl_export_import_head()
{
-
atf_set "descr" "Check bectl export and import"
atf_set "require.user" root
}
@@ -279,14 +253,12 @@ bectl_export_import_body()
}
bectl_export_import_cleanup()
{
-
bectl_cleanup $(get_zpool_name)
}
atf_test_case bectl_list cleanup
bectl_list_head()
{
-
atf_set "descr" "Check bectl list"
atf_set "require.user" root
}
@@ -324,14 +296,12 @@ bectl_list_body()
}
bectl_list_cleanup()
{
-
bectl_cleanup $(get_zpool_name)
}
atf_test_case bectl_mount cleanup
bectl_mount_head()
{
-
atf_set "descr" "Check bectl mount/unmount"
atf_set "require.user" root
}
@@ -368,14 +338,12 @@ bectl_mount_body()
}
bectl_mount_cleanup()
{
-
bectl_cleanup $(get_zpool_name)
}
atf_test_case bectl_rename cleanup
bectl_rename_head()
{
-
atf_set "descr" "Check bectl rename"
atf_set "require.user" root
}
@@ -404,14 +372,12 @@ bectl_rename_body()
}
bectl_rename_cleanup()
{
-
bectl_cleanup $(get_zpool_name)
}
atf_test_case bectl_jail cleanup
bectl_jail_head()
{
-
atf_set "descr" "Check bectl rename"
atf_set "require.user" root
atf_set "require.progs" jail
@@ -525,6 +491,147 @@ bectl_jail_cleanup()
bectl_cleanup ${zpool}
}
+atf_test_case bectl_promotion cleanup
+bectl_promotion_head()
+{
+ atf_set "descr" "Check bectl promotion upon activation"
+ atf_set "require.user" root
+}
+bectl_promotion_body()
+{
+ if [ "$(atf_config_get ci false)" = "true" ] && \
+ [ "$(uname -p)" = "i386" ]; then
+ atf_skip "https://bugs.freebsd.org/249055"
+ fi
+
+ if [ "$(atf_config_get ci false)" = "true" ] && \
+ [ "$(uname -p)" = "armv7" ]; then
+ atf_skip "https://bugs.freebsd.org/249229"
+ fi
+
+ cwd=$(realpath .)
+ zpool=$(make_zpool_name)
+ disk=${cwd}/disk.img
+ mount=${cwd}/mnt
+ root=${mount}/root
+
+ bectl_create_deep_setup ${zpool} ${disk} ${mount}
+ atf_check mkdir -p ${root}
+
+ # Sleeps interspersed to workaround some naming quirks; notably,
+ # bectl will append a serial if two snapshots were created within
+ # the same second, but it can only do that for the one root it's
+ # operating on. It won't check that other roots don't have a snapshot
+ # with the same name, and the promotion will fail.
+ atf_check bectl -r ${zpool}/ROOT rename default A
+ sleep 1
+ atf_check bectl -r ${zpool}/ROOT create -r -e A B
+ sleep 1
+ atf_check bectl -r ${zpool}/ROOT create -r -e B C
+
+ # C should be a clone of B to start with
+ atf_check -o not-inline:"-" zfs list -Hr -o origin ${zpool}/ROOT/C
+
+ # Activating it should then promote it all the way out of clone-hood.
+ # This entails two promotes internally, as the first would promote it to
+ # a snapshot of A before finally promoting it the second time out of
+ # clone status.
+ atf_check -o not-empty bectl -r ${zpool}/ROOT activate C
+ atf_check -o inline:"-\n-\n" zfs list -Hr -o origin ${zpool}/ROOT/C
+}
+bectl_promotion_cleanup()
+{
+ bectl_cleanup $(get_zpool_name)
+}
+
+atf_test_case bectl_destroy_bootonce cleanup
+bectl_destroy_bootonce_head()
+{
+ atf_set "descr" "Check bectl destroy (bootonce)"
+ atf_set "require.user" root
+}
+bectl_destroy_bootonce_body()
+{
+ if [ "$(atf_config_get ci false)" = "true" ] && \
+ [ "$(uname -p)" = "i386" ]; then
+ atf_skip "https://bugs.freebsd.org/249055"
+ fi
+
+ if [ "$(atf_config_get ci false)" = "true" ] && \
+ [ "$(uname -p)" = "armv7" ]; then
+ atf_skip "https://bugs.freebsd.org/249229"
+ fi
+
+ cwd=$(realpath .)
+ zpool=$(make_zpool_name)
+ disk=${cwd}/disk.img
+ mount=${cwd}/mnt
+ root=${mount}/root
+
+ be=default2
+
+ bectl_create_setup ${zpool} ${disk} ${mount}
+ atf_check -s exit:0 -o empty bectl -r ${zpool}/ROOT create -e default ${be}
+
+ # Create boot environment and bootonce activate it
+ atf_check -s exit:0 -o ignore bectl -r ${zpool}/ROOT activate -t ${be}
+ atf_check -s exit:0 -o inline:"zfs:${zpool}/ROOT/${be}:\n" zfsbootcfg -z ${zpool}
+
+ # Destroy it
+ atf_check -s exit:0 -o ignore bectl -r ${zpool}/ROOT destroy ${be}
+
+ # Should be empty
+ atf_check -s exit:0 -o empty zfsbootcfg -z ${zpool}
+}
+bectl_destroy_bootonce_cleanup()
+{
+ bectl_cleanup $(get_zpool_name)
+}
+
+atf_test_case bectl_rename_bootonce cleanup
+bectl_rename_bootonce_head()
+{
+ atf_set "descr" "Check bectl destroy (bootonce)"
+ atf_set "require.user" root
+}
+bectl_rename_bootonce_body()
+{
+ if [ "$(atf_config_get ci false)" = "true" ] && \
+ [ "$(uname -p)" = "i386" ]; then
+ atf_skip "https://bugs.freebsd.org/249055"
+ fi
+
+ if [ "$(atf_config_get ci false)" = "true" ] && \
+ [ "$(uname -p)" = "armv7" ]; then
+ atf_skip "https://bugs.freebsd.org/249229"
+ fi
+
+ cwd=$(realpath .)
+ zpool=$(make_zpool_name)
+ disk=${cwd}/disk.img
+ mount=${cwd}/mnt
+ root=${mount}/root
+
+ be=default2
+
+ bectl_create_setup ${zpool} ${disk} ${mount}
+ atf_check -s exit:0 -o empty bectl -r ${zpool}/ROOT create -e default ${be}
+
+ # Create boot environment and bootonce activate it
+ atf_check -s exit:0 -o ignore bectl -r ${zpool}/ROOT activate -t ${be}
+ atf_check -s exit:0 -o inline:"zfs:${zpool}/ROOT/${be}:\n" zfsbootcfg -z ${zpool}
+
+ # Rename it
+ atf_check -s exit:0 -o ignore bectl -r ${zpool}/ROOT rename ${be} ${be}_renamed
+
+ # Should be renamed
+ atf_check -s exit:0 -o inline:"zfs:${zpool}/ROOT/${be}_renamed:\n" zfsbootcfg -z ${zpool}
+}
+bectl_rename_bootonce_cleanup()
+{
+ bectl_cleanup $(get_zpool_name)
+}
+
atf_init_test_cases()
{
atf_add_test_case bectl_create
@@ -534,4 +641,7 @@ atf_init_test_cases()
atf_add_test_case bectl_mount
atf_add_test_case bectl_rename
atf_add_test_case bectl_jail
+ atf_add_test_case bectl_promotion
+ atf_add_test_case bectl_destroy_bootonce
+ atf_add_test_case bectl_rename_bootonce
}
diff --git a/sbin/bsdlabel/Makefile b/sbin/bsdlabel/Makefile
index 6921a655af10..d2be16efa544 100644
--- a/sbin/bsdlabel/Makefile
+++ b/sbin/bsdlabel/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.2 (Berkeley) 3/17/94
-# $FreeBSD$
-
.PATH: ${SRCTOP}/sys/geom
CONFS= disktab
diff --git a/sbin/bsdlabel/Makefile.depend b/sbin/bsdlabel/Makefile.depend
index 0220673c9076..0dd05cace3c0 100644
--- a/sbin/bsdlabel/Makefile.depend
+++ b/sbin/bsdlabel/Makefile.depend
@@ -1,16 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
lib/libgeom \
- lib/libsbuf \
.include <dirdeps.mk>
diff --git a/sbin/bsdlabel/bsdlabel.8 b/sbin/bsdlabel/bsdlabel.8
index fe2e6825de03..abea59756aea 100644
--- a/sbin/bsdlabel/bsdlabel.8
+++ b/sbin/bsdlabel/bsdlabel.8
@@ -28,10 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)disklabel.8 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD$
-.\"
-.Dd October 5, 2016
+.Dd January 23, 2025
.Dt BSDLABEL 8
.Os
.Sh NAME
@@ -62,6 +59,22 @@
.Op Fl f
.Ar disk | Fl f Ar file
.Ar protofile
+.Sh DEPRECATION NOTICE
+.Nm
+is deprecated and is not available in
+.Fx 15.0
+or later.
+Use
+.Xr gpart 8
+instead
+.Po
+with the
+.Cm BSD
+partitioning scheme
+.Pc ,
+or install the
+.Pa freebsd-bsdlabel
+port or package.
.Sh DESCRIPTION
The
.Nm
@@ -311,8 +324,6 @@ file systems and
.Xr ccd 4
partitions, use type
.Cm 4.2BSD .
-For Vinum drives, use type
-.Cm vinum .
Other common types are
.Cm swap
and
@@ -505,3 +516,8 @@ The
.Nm disklabel
utility appeared in
.Bx 4.3 Tahoe .
+.Sh BUGS
+.\" PR276517
+The disklabel scheme supports up to 20 partitions, but
+.Nm
+supports only 8 partitions.
diff --git a/sbin/bsdlabel/bsdlabel.c b/sbin/bsdlabel/bsdlabel.c
index 943f37207fc2..a68ee377a97c 100644
--- a/sbin/bsdlabel/bsdlabel.c
+++ b/sbin/bsdlabel/bsdlabel.c
@@ -42,21 +42,6 @@
* from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1987, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94";
-/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <stdint.h>
#include <sys/file.h>
@@ -65,7 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/disk.h>
#define DKTYPENAMES
#define FSTYPENAMES
-#define MAXPARTITIONS 20
+#define MAXPARTITIONS 8 /* XXX should be 20, but see PR276517 */
#include <sys/disklabel.h>
#include <unistd.h>
@@ -146,10 +131,14 @@ main(int argc, char *argv[])
FILE *t;
int ch, error, fd;
const char *name;
-
+
error = 0;
name = NULL;
+ fprintf(stderr,
+ "WARNING: bsdlabel is deprecated and is not available in FreeBSD 15 or later.\n"
+ "Please use gpart instead.\n\n");
+
while ((ch = getopt(argc, argv, "ABb:efm:nRrw")) != -1)
switch (ch) {
case 'A':
@@ -1094,7 +1083,7 @@ checklabel(struct disklabel *lp)
struct partition *pp;
int i, errors = 0;
char part;
- u_long base_offset, needed, total_size, total_percent, current_offset;
+ u_long base_offset, needed, total_percent, current_offset;
long free_space;
int seen_default_offset;
int hog_part;
@@ -1173,7 +1162,6 @@ checklabel(struct disklabel *lp)
/* first allocate space to the partitions, then offsets */
- total_size = 0; /* in sectors */
total_percent = 0; /* in percent */
hog_part = -1;
/* find all fixed partitions */
@@ -1234,9 +1222,6 @@ checklabel(struct disklabel *lp)
size /= lp->d_secsize;
pp->p_size = size;
}
- /* else already in sectors */
- if (i != RAW_PART)
- total_size += size;
}
}
}
@@ -1272,7 +1257,6 @@ checklabel(struct disklabel *lp)
if (part_set[i] && part_size_type[i] == '%') {
/* careful of overflows! and integer roundoff */
pp->p_size = ((double)pp->p_size/100) * free_space;
- total_size += pp->p_size;
/* FIX we can lose a sector or so due to roundoff per
partition. A more complex algorithm could avoid that */
@@ -1328,7 +1312,6 @@ checklabel(struct disklabel *lp)
} else {
lp->d_partitions[hog_part].p_size = current_offset -
base_offset - needed;
- total_size += lp->d_partitions[hog_part].p_size;
}
}
diff --git a/sbin/bsdlabel/disktab b/sbin/bsdlabel/disktab
index cb0fba033699..72ff689c82ff 100644
--- a/sbin/bsdlabel/disktab
+++ b/sbin/bsdlabel/disktab
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# Disk geometry and partition layout tables.
# See disktab(5) for format of this file.
diff --git a/sbin/bsdlabel/pathnames.h b/sbin/bsdlabel/pathnames.h
index 77ee59e0279e..4d215eb72e33 100644
--- a/sbin/bsdlabel/pathnames.h
+++ b/sbin/bsdlabel/pathnames.h
@@ -27,9 +27,6 @@
* 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.
- *
- * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
- * $FreeBSD$
*/
#include <paths.h>
diff --git a/sbin/camcontrol/Makefile b/sbin/camcontrol/Makefile
index 958f37714662..2b0c2c9dbc14 100644
--- a/sbin/camcontrol/Makefile
+++ b/sbin/camcontrol/Makefile
@@ -1,23 +1,30 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=runtime
PROG= camcontrol
-SRCS= camcontrol.c util.c
-SRCS+= attrib.c depop.c epc.c fwdownload.c modeedit.c persist.c progress.c timestamp.c zone.c
-.if ${MK_NVME} != "no"
+SRCS= camcontrol.c
+SRCS+= attrib.c
+SRCS+= depop.c
+SRCS+= epc.c
+SRCS+= fwdownload.c
+SRCS+= modeedit.c
+SRCS+= persist.c
+SRCS+= progress.c
+SRCS+= timestamp.c
+SRCS+= util.c
+SRCS+= zone.c
.PATH: ${SRCTOP}/sbin/nvmecontrol
-CFLAGS+= -I${SRCTOP}/sbin/nvmecontrol -DWITH_NVME
-SRCS+= identify_ext.c nc_util.c
+CFLAGS+= -I${SRCTOP}/sbin/nvmecontrol
+SRCS+= identify_ext.c
+SRCS+= nc_util.c
.PATH: ${SRCTOP}/sys/dev/nvme
SRCS+= nvme_util.c
-.endif
# This is verboten
.if ${MACHINE_CPUARCH} == "arm"
WARNS?= 3
.endif
-LIBADD= cam sbuf util
+CFLAGS+= -I${SRCTOP}/lib/libnvmf
+LIBADD= cam nvmf sbuf util
MAN= camcontrol.8
.include <bsd.prog.mk>
diff --git a/sbin/camcontrol/Makefile.depend b/sbin/camcontrol/Makefile.depend
index ee06e1c20939..bef65a3c03d5 100644
--- a/sbin/camcontrol/Makefile.depend
+++ b/sbin/camcontrol/Makefile.depend
@@ -1,14 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcam \
lib/libcompiler_rt \
+ lib/libnvmf \
lib/libsbuf \
lib/libutil \
diff --git a/sbin/camcontrol/attrib.c b/sbin/camcontrol/attrib.c
index 05cabb1b8145..4cf9832756b4 100644
--- a/sbin/camcontrol/attrib.c
+++ b/sbin/camcontrol/attrib.c
@@ -34,11 +34,9 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/ioctl.h>
#include <sys/stdint.h>
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/endian.h>
#include <sys/sbuf.h>
#include <sys/queue.h>
@@ -267,7 +265,7 @@ scsiattrib(struct cam_device *device, int argc, char **argv, char *combinedopt,
int entry_num = 0;
status = scsi_get_nv(elem_type_map,
- sizeof(elem_type_map) / sizeof(elem_type_map[0]),
+ nitems(elem_type_map),
optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
if (status == SCSI_NV_FOUND)
element_type = elem_type_map[entry_num].value;
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
index 3d65487cc60e..bdda1828abf5 100644
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -25,9 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd October 20, 2021
+.Dd December 28, 2023
.Dt CAMCONTROL 8
.Os
.Sh NAME
@@ -53,6 +51,12 @@
.Op device id
.Op generic args
.Nm
+.Ic sense
+.Op device id
+.Op generic args
+.Op Fl D
+.Op Fl x
+.Nm
.Ic inquiry
.Op device id
.Op generic args
@@ -377,9 +381,10 @@
.Sh DESCRIPTION
The
.Nm
-utility is designed to provide a way for users to access and control the
+utility allows users to access and control the
.Fx
-CAM subsystem.
+CAM subsystem described in
+.Xr cam 4 .
.Pp
The
.Nm
@@ -489,6 +494,15 @@ Send the SCSI test unit ready (0x00) command to the given device.
The
.Nm
utility will report whether the device is ready or not.
+.It Ic sense
+Send a SCSI REQUEST SENSE command (0x03) to a device.
+The decoded sense (or hexdump) is printed to stdout.
+.Bl -tag -width 4n
+.It Fl D
+Request descriptor sense instead of fixed sense.
+.It Fl x
+Do a hexdump of the returned sense data.
+.El
.It Ic inquiry
Send a SCSI inquiry command (0x12) to a device.
By default,
@@ -510,7 +524,7 @@ This is to aid in script writing.
Print out transfer rate information.
.El
.It Ic identify
-Send a ATA identify command (0xec) to a device.
+Send an ATA identify command (0xec) to a device.
.It Ic reportluns
Send the SCSI REPORT LUNS (0xA0) command to the given device.
By default,
@@ -746,7 +760,7 @@ Disable block descriptors for mode sense.
Display/edit block descriptors instead of mode page.
.It Fl L
Use long LBA block descriptors.
-Allows number of LBAs bigger then 2^^32.
+Allows number of LBAs bigger than 2^^32.
.It Fl b
Displays mode page data in binary format.
.It Fl e
@@ -763,7 +777,7 @@ The editor will be invoked if
detects that standard input is terminal.
.It Fl l
Lists all available mode pages.
-If specified more then once, also lists subpages.
+If specified more than once, also lists subpages.
.It Fl m Ar page[,subpage]
This specifies the number of the mode page and optionally subpage the user
would like to view and/or edit.
@@ -1686,6 +1700,8 @@ Tested with Constellation ES (ST32000444SS), ES.2 (ST33000651SS) and
ES.3 (ST1000NM0023) drives.
.It SmrtStor
Tested with 400GB Optimus SSDs (TXA2D20400GA6001).
+.It TOSHIBA
+Tested with 22TB MG10SFA22TE SAS drives.
.El
.Pp
.Em WARNING! WARNING! WARNING!
@@ -2314,7 +2330,7 @@ For the Report Zones command, specify a subset of zones to report.
.It all
Report all zones.
This is the default.
-.It emtpy
+.It empty
Report only empty zones.
.It imp_open
Report zones that are implicitly open.
@@ -2971,6 +2987,7 @@ that was created using this format string.
.Xr cam 4 ,
.Xr pass 4 ,
.Xr xpt 4 ,
+.Xr diskinfo 8 ,
.Xr trim 8 ,
.Xr zonectl 8
.Sh HISTORY
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index 489c3026537a..15a5d42a2ba5 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -27,8 +27,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/ioctl.h>
#include <sys/stdint.h>
#include <sys/types.h>
@@ -36,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/sbuf.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -45,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <ctype.h>
#include <err.h>
+#include <libnvmf.h>
#include <libutil.h>
#include <limits.h>
#include <inttypes.h>
@@ -61,9 +61,7 @@ __FBSDID("$FreeBSD$");
#include <cam/mmc/mmc_all.h>
#include <camlib.h>
#include "camcontrol.h"
-#ifdef WITH_NVME
#include "nvmecontrol_ext.h"
-#endif
typedef enum {
CAM_CMD_NONE,
@@ -112,6 +110,7 @@ typedef enum {
CAM_CMD_DEVTYPE,
CAM_CMD_AMA,
CAM_CMD_DEPOP,
+ CAM_CMD_REQSENSE
} cam_cmd;
typedef enum {
@@ -123,18 +122,21 @@ typedef enum {
CAM_ARG_LUN = 0x00000010,
CAM_ARG_EJECT = 0x00000020,
CAM_ARG_UNIT = 0x00000040,
- CAM_ARG_FORMAT_BLOCK = 0x00000080,
- CAM_ARG_FORMAT_BFI = 0x00000100,
- CAM_ARG_FORMAT_PHYS = 0x00000200,
- CAM_ARG_PLIST = 0x00000400,
- CAM_ARG_GLIST = 0x00000800,
+ /* unused 0x00000080 */
+ /* unused 0x00000100 */
+ /* unused 0x00000200 */
+ /* unused 0x00000400 */
+ /* unused 0x00000800 */
CAM_ARG_GET_SERIAL = 0x00001000,
CAM_ARG_GET_STDINQ = 0x00002000,
CAM_ARG_GET_XFERRATE = 0x00004000,
CAM_ARG_INQ_MASK = 0x00007000,
+ /* unused 0x00008000 */
+ /* unused 0x00010000 */
CAM_ARG_TIMEOUT = 0x00020000,
CAM_ARG_CMD_IN = 0x00040000,
CAM_ARG_CMD_OUT = 0x00080000,
+ /* unused 0x00100000 */
CAM_ARG_ERR_RECOVER = 0x00200000,
CAM_ARG_RETRIES = 0x00400000,
CAM_ARG_START_UNIT = 0x00800000,
@@ -145,6 +147,7 @@ typedef enum {
CAM_ARG_DEBUG_XPT = 0x10000000,
CAM_ARG_DEBUG_PERIPH = 0x20000000,
CAM_ARG_DEBUG_PROBE = 0x40000000,
+ /* unused 0x80000000 */
} cam_argmask;
struct camcontrol_opts {
@@ -156,9 +159,9 @@ struct camcontrol_opts {
struct ata_set_max_pwd
{
- u_int16_t reserved1;
- u_int8_t password[32];
- u_int16_t reserved2[239];
+ uint16_t reserved1;
+ uint8_t password[32];
+ uint16_t reserved2[239];
};
static struct scsi_nv task_attrs[] = {
@@ -230,6 +233,7 @@ static struct camcontrol_opts option_table[] = {
{"epc", CAM_CMD_EPC, CAM_ARG_NONE, "c:dDeHp:Pr:sS:T:"},
{"timestamp", CAM_CMD_TIMESTAMP, CAM_ARG_NONE, "f:mrsUT:"},
{"depop", CAM_CMD_DEPOP, CAM_ARG_NONE, "ac:de:ls"},
+ {"sense", CAM_CMD_REQSENSE, CAM_ARG_NONE, "Dx"},
{"help", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
{"-?", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
{"-h", CAM_CMD_USAGE, CAM_ARG_NONE, NULL},
@@ -273,9 +277,10 @@ static int print_dev_ata(struct device_match_result *dev_result, char *tmpstr);
static int print_dev_semb(struct device_match_result *dev_result, char *tmpstr);
static int print_dev_mmcsd(struct device_match_result *dev_result,
char *tmpstr);
-#ifdef WITH_NVME
static int print_dev_nvme(struct device_match_result *dev_result, char *tmpstr);
-#endif
+static int requestsense(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int task_attr, int retry_count,
+ int timeout);
static int testunitready(struct cam_device *device, int task_attr,
int retry_count, int timeout, int quiet);
static int scsistart(struct cam_device *device, int startstop, int loadeject,
@@ -592,14 +597,12 @@ getdevtree(int argc, char **argv, char *combinedopt)
skip_device = 1;
break;
}
-#ifdef WITH_NVME
} else if (dev_result->protocol == PROTO_NVME) {
if (print_dev_nvme(dev_result,
&tmpstr[0]) != 0) {
skip_device = 1;
break;
}
-#endif
} else {
sprintf(tmpstr, "<>");
}
@@ -650,6 +653,7 @@ getdevtree(int argc, char **argv, char *combinedopt)
if (need_close)
fprintf(stdout, ")\n");
+ free(ccb.cdm.matches);
close(fd);
return (error);
@@ -773,7 +777,6 @@ print_dev_mmcsd(struct device_match_result *dev_result, char *tmpstr)
return (0);
}
-#ifdef WITH_NVME
static int
nvme_get_cdata(struct cam_device *dev, struct nvme_controller_data *cdata)
{
@@ -835,7 +838,114 @@ print_dev_nvme(struct device_match_result *dev_result, char *tmpstr)
cam_close_device(dev);
return (0);
}
-#endif
+
+static int
+requestsense(struct cam_device *device, int argc, char **argv,
+ char *combinedopt, int task_attr, int retry_count, int timeout)
+{
+ int c;
+ int descriptor_sense = 0;
+ int do_hexdump = 0;
+ struct scsi_sense_data sense;
+ union ccb *ccb = NULL;
+ int error = 0;
+ size_t returned_bytes;
+
+ while ((c = getopt(argc, argv, combinedopt)) != -1) {
+ switch (c) {
+ case 'D':
+ descriptor_sense = 1;
+ break;
+ case 'x':
+ do_hexdump = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ccb = cam_getccb(device);
+ if (ccb == NULL) {
+ warnx("couldn't allocate CCB");
+ return (1);
+ }
+
+ /* cam_getccb cleans up the header, caller has to zero the payload */
+ CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio);
+
+ bzero(&sense, sizeof(sense));
+
+ scsi_request_sense(&ccb->csio,
+ /*retries*/ retry_count,
+ /*cbfcnp*/ NULL,
+ /*data_ptr*/ (void *)&sense,
+ /*dxfer_len*/ sizeof(sense),
+ /*tag_action*/ task_attr,
+ /*sense_len*/ SSD_FULL_SIZE,
+ /*timeout*/ timeout ? timeout : 60000);
+
+ if (descriptor_sense != 0) {
+ struct scsi_request_sense *cdb;
+
+ cdb = (struct scsi_request_sense *)&ccb->csio.cdb_io.cdb_bytes;
+ cdb->byte2 |= SRS_DESC;
+ }
+
+ ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
+
+ if (arglist & CAM_ARG_ERR_RECOVER)
+ ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ warn("error sending REQUEST SENSE command");
+ cam_freeccb(ccb);
+ error = 1;
+ goto bailout;
+ }
+
+ /*
+ * REQUEST SENSE is not generally supposed to fail. But there can
+ * be transport or other errors that might cause it to fail. It
+ * may also fail if the user asks for descriptor sense and the
+ * device doesn't support it. So we check the CCB status here to see.
+ */
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ warnx("REQUEST SENSE failed");
+ cam_error_print(device, ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+ error = 1;
+ goto bailout;
+ }
+
+ returned_bytes = ccb->csio.dxfer_len - ccb->csio.resid;
+
+ if (do_hexdump != 0) {
+ hexdump(&sense, returned_bytes, NULL, 0);
+ } else {
+ char path_str[80];
+ struct sbuf *sb;
+
+ cam_path_string(device, path_str, sizeof(path_str));
+ sb = sbuf_new_auto();
+ if (sb == NULL) {
+ warnx("%s: cannot allocate sbuf", __func__);
+ error = 1;
+ goto bailout;
+ }
+
+ scsi_sense_only_sbuf(&sense, returned_bytes, sb, path_str,
+ &device->inq_data, scsiio_cdb_ptr(&ccb->csio),
+ ccb->csio.cdb_len);
+
+ sbuf_finish(sb);
+ printf("%s", sbuf_data(sb));
+ sbuf_delete(sb);
+ }
+bailout:
+ if (ccb != NULL)
+ cam_freeccb(ccb);
+
+ return (error);
+}
static int
testunitready(struct cam_device *device, int task_attr, int retry_count,
@@ -1042,7 +1152,7 @@ scsiinquiry(struct cam_device *device, int task_attr, int retry_count,
* - The SCSI spec says that when a length field is only 1 byte,
* a value of 0 will be interpreted as 256. Therefore
* scsi_inquiry() will convert an inq_len (which is passed in as
- * a u_int32_t, but the field in the CDB is only 1 byte) of 256
+ * a uint32_t, but the field in the CDB is only 1 byte) of 256
* to 0. Evidently, very few devices meet the spec in that
* regard. Some devices, like many Seagate disks, take the 0 as
* 0, and don't return any data. One Pioneer DVD-R drive
@@ -1070,7 +1180,7 @@ scsiinquiry(struct cam_device *device, int task_attr, int retry_count,
/* retries */ retry_count,
/* cbfcnp */ NULL,
/* tag_action */ task_attr,
- /* inq_buf */ (u_int8_t *)inq_buf,
+ /* inq_buf */ (uint8_t *)inq_buf,
/* inq_len */ SHORT_INQUIRY_LENGTH,
/* evpd */ 0,
/* page_code */ 0,
@@ -1143,7 +1253,7 @@ scsiserial(struct cam_device *device, int task_attr, int retry_count,
/*retries*/ retry_count,
/*cbfcnp*/ NULL,
/* tag_action */ task_attr,
- /* inq_buf */ (u_int8_t *)serial_buf,
+ /* inq_buf */ (uint8_t *)serial_buf,
/* inq_len */ sizeof(*serial_buf),
/* evpd */ 1,
/* page_code */ SVPD_UNIT_SERIAL_NUMBER,
@@ -1198,8 +1308,8 @@ int
camxferrate(struct cam_device *device)
{
struct ccb_pathinq cpi;
- u_int32_t freq = 0;
- u_int32_t speed = 0;
+ uint32_t freq = 0;
+ uint32_t speed = 0;
union ccb *ccb;
u_int mb;
int retval = 0;
@@ -1360,8 +1470,8 @@ xferrate_bailout:
static void
atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
{
- u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
- ((u_int32_t)parm->lba_size_2 << 16);
+ uint32_t lbasize = (uint32_t)parm->lba_size_1 |
+ ((uint32_t)parm->lba_size_2 << 16);
u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
((u_int64_t)parm->lba_size48_2 << 16) |
@@ -1393,8 +1503,8 @@ atahpa_print(struct ata_params *parm, u_int64_t hpasize, int header)
static void
ataama_print(struct ata_params *parm, u_int64_t nativesize, int header)
{
- u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
- ((u_int32_t)parm->lba_size_2 << 16);
+ uint32_t lbasize = (uint32_t)parm->lba_size_1 |
+ ((uint32_t)parm->lba_size_2 << 16);
u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
((u_int64_t)parm->lba_size48_2 << 16) |
@@ -1432,8 +1542,8 @@ static void
atacapprint(struct ata_params *parm)
{
const char *proto;
- u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
- ((u_int32_t)parm->lba_size_2 << 16);
+ uint32_t lbasize = (uint32_t)parm->lba_size_1 |
+ ((uint32_t)parm->lba_size_2 << 16);
u_int64_t lbasize48 = ((u_int64_t)parm->lba_size48_1) |
((u_int64_t)parm->lba_size48_2 << 16) |
@@ -1750,7 +1860,7 @@ scsi_cam_pass_16_send(struct cam_device *device, union ccb *ccb)
/*
* Consider any non-CAM_REQ_CMP status as error and report it here,
- * unless caller set AP_FLAG_CHK_COND, in which case it is reponsible.
+ * unless caller set AP_FLAG_CHK_COND, in which case it is responsible.
*/
if (!(ata_pass_16->flags & AP_FLAG_CHK_COND) &&
(ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
@@ -1788,7 +1898,7 @@ ata_cam_send(struct cam_device *device, union ccb *ccb)
/*
* Consider any non-CAM_REQ_CMP status as error and report it here,
- * unless caller set AP_FLAG_CHK_COND, in which case it is reponsible.
+ * unless caller set AP_FLAG_CHK_COND, in which case it is responsible.
*/
if (!(ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT) &&
(ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
@@ -1805,10 +1915,10 @@ ata_cam_send(struct cam_device *device, union ccb *ccb)
static int
ata_do_pass_16(struct cam_device *device, union ccb *ccb, int retries,
- u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
- u_int8_t tag_action, u_int8_t command, u_int16_t features,
- u_int64_t lba, u_int16_t sector_count, u_int8_t *data_ptr,
- u_int16_t dxfer_len, int timeout)
+ uint32_t flags, uint8_t protocol, uint8_t ata_flags,
+ uint8_t tag_action, uint8_t command, uint16_t features,
+ u_int64_t lba, uint16_t sector_count, uint8_t *data_ptr,
+ uint16_t dxfer_len, int timeout)
{
if (data_ptr != NULL) {
if (flags & CAM_DIR_OUT)
@@ -1862,10 +1972,10 @@ ata_try_pass_16(struct cam_device *device)
static int
ata_do_cmd(struct cam_device *device, union ccb *ccb, int retries,
- u_int32_t flags, u_int8_t protocol, u_int8_t ata_flags,
- u_int8_t tag_action, u_int8_t command, u_int16_t features,
- u_int64_t lba, u_int16_t sector_count, u_int8_t *data_ptr,
- u_int16_t dxfer_len, int timeout, int force48bit)
+ uint32_t flags, uint8_t protocol, uint8_t ata_flags,
+ uint8_t tag_action, uint8_t command, uint16_t features,
+ u_int64_t lba, uint16_t sector_count, uint8_t *data_ptr,
+ uint16_t dxfer_len, int timeout, int force48bit)
{
int retval;
@@ -1962,12 +2072,12 @@ atahpa_proc_resp(struct cam_device *device, union ccb *ccb, u_int64_t *hpasize)
static int
ata_read_native_max(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb,
+ uint32_t timeout, union ccb *ccb,
struct ata_params *parm, u_int64_t *hpasize)
{
int error;
u_int cmd, is48bit;
- u_int8_t protocol;
+ uint8_t protocol;
is48bit = parm->support.command2 & ATA_SUPPORT_ADDRESS48;
protocol = AP_PROTO_NON_DATA;
@@ -1992,7 +2102,7 @@ ata_read_native_max(struct cam_device *device, int retry_count,
/*sector_count*/0,
/*data_ptr*/NULL,
/*dxfer_len*/0,
- timeout ? timeout : 5000,
+ timeout ? timeout : 10 * 1000,
is48bit);
if (error)
@@ -2003,12 +2113,12 @@ ata_read_native_max(struct cam_device *device, int retry_count,
static int
atahpa_set_max(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb,
+ uint32_t timeout, union ccb *ccb,
int is48bit, u_int64_t maxsize, int persist)
{
int error;
u_int cmd;
- u_int8_t protocol;
+ uint8_t protocol;
protocol = AP_PROTO_NON_DATA;
@@ -2047,11 +2157,11 @@ atahpa_set_max(struct cam_device *device, int retry_count,
static int
atahpa_password(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb,
+ uint32_t timeout, union ccb *ccb,
int is48bit, struct ata_set_max_pwd *pwd)
{
u_int cmd;
- u_int8_t protocol;
+ uint8_t protocol;
protocol = AP_PROTO_PIO_OUT;
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
@@ -2068,7 +2178,7 @@ atahpa_password(struct cam_device *device, int retry_count,
/*features*/ATA_HPA_FEAT_SET_PWD,
/*lba*/0,
/*sector_count*/sizeof(*pwd) / 512,
- /*data_ptr*/(u_int8_t*)pwd,
+ /*data_ptr*/(uint8_t*)pwd,
/*dxfer_len*/sizeof(*pwd),
timeout ? timeout : 1000,
is48bit));
@@ -2076,10 +2186,10 @@ atahpa_password(struct cam_device *device, int retry_count,
static int
atahpa_lock(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb, int is48bit)
+ uint32_t timeout, union ccb *ccb, int is48bit)
{
u_int cmd;
- u_int8_t protocol;
+ uint8_t protocol;
protocol = AP_PROTO_NON_DATA;
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
@@ -2103,11 +2213,11 @@ atahpa_lock(struct cam_device *device, int retry_count,
static int
atahpa_unlock(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb,
+ uint32_t timeout, union ccb *ccb,
int is48bit, struct ata_set_max_pwd *pwd)
{
u_int cmd;
- u_int8_t protocol;
+ uint8_t protocol;
protocol = AP_PROTO_PIO_OUT;
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
@@ -2124,7 +2234,7 @@ atahpa_unlock(struct cam_device *device, int retry_count,
/*features*/ATA_HPA_FEAT_UNLOCK,
/*lba*/0,
/*sector_count*/sizeof(*pwd) / 512,
- /*data_ptr*/(u_int8_t*)pwd,
+ /*data_ptr*/(uint8_t*)pwd,
/*dxfer_len*/sizeof(*pwd),
timeout ? timeout : 1000,
is48bit));
@@ -2132,10 +2242,10 @@ atahpa_unlock(struct cam_device *device, int retry_count,
static int
atahpa_freeze_lock(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb, int is48bit)
+ uint32_t timeout, union ccb *ccb, int is48bit)
{
u_int cmd;
- u_int8_t protocol;
+ uint8_t protocol;
protocol = AP_PROTO_NON_DATA;
cmd = (is48bit) ? ATA_SET_MAX_ADDRESS48 : ATA_SET_MAX_ADDRESS;
@@ -2159,7 +2269,7 @@ atahpa_freeze_lock(struct cam_device *device, int retry_count,
static int
ata_get_native_max(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb,
+ uint32_t timeout, union ccb *ccb,
u_int64_t *nativesize)
{
int error;
@@ -2188,7 +2298,7 @@ ata_get_native_max(struct cam_device *device, int retry_count,
static int
ataama_set(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb, u_int64_t maxsize)
+ uint32_t timeout, union ccb *ccb, u_int64_t maxsize)
{
int error;
@@ -2220,7 +2330,7 @@ ataama_set(struct cam_device *device, int retry_count,
static int
ataama_freeze(struct cam_device *device, int retry_count,
- u_int32_t timeout, union ccb *ccb)
+ uint32_t timeout, union ccb *ccb)
{
return (ata_do_cmd(device,
@@ -2249,7 +2359,7 @@ ata_do_identify(struct cam_device *device, int retry_count, int timeout,
struct ccb_getdev cgd;
u_int i, error;
int16_t *ptr;
- u_int8_t command, retry_command;
+ uint8_t command, retry_command;
if (get_cpi(device, &cpi) != 0) {
warnx("couldn't get CPI");
@@ -2291,7 +2401,7 @@ retry:
/*features*/0,
/*lba*/0,
/*sector_count*/sizeof(struct ata_params) / 512,
- /*data_ptr*/(u_int8_t *)ptr,
+ /*data_ptr*/(uint8_t *)ptr,
/*dxfer_len*/sizeof(struct ata_params),
/*timeout*/timeout ? timeout : 30 * 1000,
/*force48bit*/0);
@@ -2373,7 +2483,6 @@ ataidentify(struct cam_device *device, int retry_count, int timeout)
return (0);
}
-#ifdef WITH_NVME
static int
nvmeidentify(struct cam_device *device, int retry_count __unused, int timeout __unused)
{
@@ -2385,12 +2494,10 @@ nvmeidentify(struct cam_device *device, int retry_count __unused, int timeout __
return (0);
}
-#endif
static int
identify(struct cam_device *device, int retry_count, int timeout)
{
-#ifdef WITH_NVME
struct ccb_pathinq cpi;
if (get_cpi(device, &cpi) != 0) {
@@ -2401,7 +2508,6 @@ identify(struct cam_device *device, int retry_count, int timeout)
if (cpi.protocol == PROTO_NVME) {
return (nvmeidentify(device, retry_count, timeout));
}
-#endif
return (ataidentify(device, retry_count, timeout));
}
@@ -2417,7 +2523,7 @@ enum {
};
static void
-atasecurity_print_time(u_int16_t tw)
+atasecurity_print_time(uint16_t tw)
{
if (tw == 0)
@@ -2428,8 +2534,8 @@ atasecurity_print_time(u_int16_t tw)
printf("%i min", 2 * tw);
}
-static u_int32_t
-atasecurity_erase_timeout_msecs(u_int16_t timeout)
+static uint32_t
+atasecurity_erase_timeout_msecs(uint16_t timeout)
{
if (timeout == 0)
@@ -2442,7 +2548,7 @@ atasecurity_erase_timeout_msecs(u_int16_t timeout)
static void
-atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
+atasecurity_notify(uint8_t command, struct ata_security_password *pwd)
{
struct ata_cmd cmd;
@@ -2472,7 +2578,7 @@ atasecurity_notify(u_int8_t command, struct ata_security_password *pwd)
static int
atasecurity_freeze(struct cam_device *device, union ccb *ccb,
- int retry_count, u_int32_t timeout, int quiet)
+ int retry_count, uint32_t timeout, int quiet)
{
if (quiet == 0)
@@ -2497,7 +2603,7 @@ atasecurity_freeze(struct cam_device *device, union ccb *ccb,
static int
atasecurity_unlock(struct cam_device *device, union ccb *ccb,
- int retry_count, u_int32_t timeout,
+ int retry_count, uint32_t timeout,
struct ata_security_password *pwd, int quiet)
{
@@ -2516,7 +2622,7 @@ atasecurity_unlock(struct cam_device *device, union ccb *ccb,
/*features*/0,
/*lba*/0,
/*sector_count*/sizeof(*pwd) / 512,
- /*data_ptr*/(u_int8_t *)pwd,
+ /*data_ptr*/(uint8_t *)pwd,
/*dxfer_len*/sizeof(*pwd),
/*timeout*/timeout,
/*force48bit*/0);
@@ -2524,7 +2630,7 @@ atasecurity_unlock(struct cam_device *device, union ccb *ccb,
static int
atasecurity_disable(struct cam_device *device, union ccb *ccb,
- int retry_count, u_int32_t timeout,
+ int retry_count, uint32_t timeout,
struct ata_security_password *pwd, int quiet)
{
@@ -2542,7 +2648,7 @@ atasecurity_disable(struct cam_device *device, union ccb *ccb,
/*features*/0,
/*lba*/0,
/*sector_count*/sizeof(*pwd) / 512,
- /*data_ptr*/(u_int8_t *)pwd,
+ /*data_ptr*/(uint8_t *)pwd,
/*dxfer_len*/sizeof(*pwd),
/*timeout*/timeout,
/*force48bit*/0);
@@ -2582,8 +2688,8 @@ atasecurity_erase_confirm(struct cam_device *device,
static int
atasecurity_erase(struct cam_device *device, union ccb *ccb,
- int retry_count, u_int32_t timeout,
- u_int32_t erase_timeout,
+ int retry_count, uint32_t timeout,
+ uint32_t erase_timeout,
struct ata_security_password *pwd, int quiet)
{
int error;
@@ -2625,7 +2731,7 @@ atasecurity_erase(struct cam_device *device, union ccb *ccb,
/*features*/0,
/*lba*/0,
/*sector_count*/sizeof(*pwd) / 512,
- /*data_ptr*/(u_int8_t *)pwd,
+ /*data_ptr*/(uint8_t *)pwd,
/*dxfer_len*/sizeof(*pwd),
/*timeout*/erase_timeout,
/*force48bit*/0);
@@ -2638,7 +2744,7 @@ atasecurity_erase(struct cam_device *device, union ccb *ccb,
static int
atasecurity_set_password(struct cam_device *device, union ccb *ccb,
- int retry_count, u_int32_t timeout,
+ int retry_count, uint32_t timeout,
struct ata_security_password *pwd, int quiet)
{
@@ -2657,7 +2763,7 @@ atasecurity_set_password(struct cam_device *device, union ccb *ccb,
/*features*/0,
/*lba*/0,
/*sector_count*/sizeof(*pwd) / 512,
- /*data_ptr*/(u_int8_t *)pwd,
+ /*data_ptr*/(uint8_t *)pwd,
/*dxfer_len*/sizeof(*pwd),
/*timeout*/timeout,
/*force48bit*/0);
@@ -2706,7 +2812,7 @@ atasecurity_print(struct ata_params *parm)
* the data will still be copied but no null termination will occur.
*/
static int
-ata_getpwd(u_int8_t *passwd, int max, char opt)
+ata_getpwd(uint8_t *passwd, int max, char opt)
{
int len;
@@ -3823,23 +3929,20 @@ readdefects(struct cam_device *device, int argc, char **argv,
struct scsi_read_defect_data_hdr_10 *hdr10 = NULL;
struct scsi_read_defect_data_hdr_12 *hdr12 = NULL;
size_t hdr_size = 0, entry_size = 0;
- int use_12byte = 0;
- int hex_format = 0;
- u_int8_t *defect_list = NULL;
- u_int8_t list_format = 0;
- int list_type_set = 0;
- u_int32_t dlist_length = 0;
- u_int32_t returned_length = 0, valid_len = 0;
- u_int32_t num_returned = 0, num_valid = 0;
- u_int32_t max_possible_size = 0, hdr_max = 0;
- u_int32_t starting_offset = 0;
- u_int8_t returned_format, returned_type;
+ uint8_t *defect_list = NULL;
+ uint8_t list_format = 0;
+ uint32_t dlist_length = 0;
+ uint32_t returned_length = 0, valid_len = 0;
+ uint32_t num_returned = 0, num_valid = 0;
+ uint32_t max_possible_size = 0, hdr_max = 0;
+ uint32_t starting_offset = 0;
+ uint8_t returned_format, returned_type;
unsigned int i;
- int summary = 0, quiet = 0;
int c, error = 0;
- int lists_specified = 0;
- int get_length = 1, first_pass = 1;
int mads = 0;
+ bool summary = false, quiet = false, list_type_set = false;
+ bool get_length = true, use_12byte = false, first_pass = true;
+ bool hex_format = false;
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch(c){
@@ -3848,15 +3951,21 @@ readdefects(struct cam_device *device, int argc, char **argv,
scsi_nv_status status;
int entry_num = 0;
+ if (list_type_set) {
+ warnx("%s: -f specified twice", __func__);
+ error = 1;
+ goto defect_bailout;
+ }
+
status = scsi_get_nv(defect_list_type_map,
sizeof(defect_list_type_map) /
sizeof(defect_list_type_map[0]), optarg,
&entry_num, SCSI_NV_FLAG_IG_CASE);
if (status == SCSI_NV_FOUND) {
- list_format = defect_list_type_map[
+ list_format |= defect_list_type_map[
entry_num].value;
- list_type_set = 1;
+ list_type_set = true;
} else {
warnx("%s: %s %s option %s", __func__,
(status == SCSI_NV_AMBIGUOUS) ?
@@ -3868,16 +3977,16 @@ readdefects(struct cam_device *device, int argc, char **argv,
break;
}
case 'G':
- arglist |= CAM_ARG_GLIST;
+ list_format |= SRDD10_GLIST;
break;
case 'P':
- arglist |= CAM_ARG_PLIST;
+ list_format |= SRDD10_PLIST;
break;
case 'q':
- quiet = 1;
+ quiet = true;
break;
case 's':
- summary = 1;
+ summary = true;
break;
case 'S': {
char *endptr;
@@ -3888,52 +3997,48 @@ readdefects(struct cam_device *device, int argc, char **argv,
warnx("invalid starting offset %s", optarg);
goto defect_bailout;
}
+ use_12byte = true;
break;
}
case 'X':
- hex_format = 1;
+ hex_format = true;
break;
default:
break;
}
}
- if (list_type_set == 0) {
+ if (!list_type_set) {
error = 1;
warnx("no defect list format specified");
goto defect_bailout;
}
- if (arglist & CAM_ARG_PLIST) {
- list_format |= SRDD10_PLIST;
- lists_specified++;
- }
-
- if (arglist & CAM_ARG_GLIST) {
- list_format |= SRDD10_GLIST;
- lists_specified++;
- }
-
/*
* This implies a summary, and was the previous behavior.
*/
- if (lists_specified == 0)
- summary = 1;
+ if ((list_format & ~SRDD10_DLIST_FORMAT_MASK) == 0)
+ summary = true;
ccb = cam_getccb(device);
-retry_12byte:
-
/*
- * We start off asking for just the header to determine how much
- * defect data is available. Some Hitachi drives return an error
- * if you ask for more data than the drive has. Once we know the
- * length, we retry the command with the returned length.
+ * We start off asking for just the header to determine how much defect
+ * data is available. Some Hitachi drives return an error if you ask
+ * for more data than the drive has. Once we know the length, we retry
+ * the command with the returned length. When we're retrying the with
+ * 12-byte command, we're always changing to the 12-byte command and
+ * need to get the length. Simplify the logic below by always setting
+ * use_12byte in this case with this slightly more complex logic here.
*/
- if (use_12byte == 0)
+ if (!use_12byte) {
dlist_length = sizeof(*hdr10);
- else
+ } else {
+retry_12byte:
+ get_length = true;
+ use_12byte = true;
dlist_length = sizeof(*hdr12);
+ }
retry:
if (defect_list != NULL) {
@@ -3979,7 +4084,7 @@ next_batch:
valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
- if (use_12byte == 0) {
+ if (!use_12byte) {
hdr10 = (struct scsi_read_defect_data_hdr_10 *)defect_list;
hdr_size = sizeof(*hdr10);
hdr_max = SRDDH10_MAX_LENGTH;
@@ -4033,8 +4138,8 @@ next_batch:
num_valid = min(returned_length, valid_len - hdr_size);
num_valid /= entry_size;
- if (get_length != 0) {
- get_length = 0;
+ if (get_length) {
+ get_length = false;
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR) {
@@ -4055,10 +4160,8 @@ next_batch:
if ((sense_key == SSD_KEY_RECOVERED_ERROR)
&& (asc == 0x1c) && (ascq == 0x00)
&& (returned_length > 0)) {
- if ((use_12byte == 0)
+ if (!use_12byte
&& (returned_length >= max_possible_size)) {
- get_length = 1;
- use_12byte = 1;
goto retry_12byte;
}
dlist_length = returned_length + hdr_size;
@@ -4073,9 +4176,7 @@ next_batch:
* command can support. Retry with the 12
* byte command.
*/
- if (use_12byte == 0) {
- get_length = 1;
- use_12byte = 1;
+ if (!use_12byte) {
goto retry_12byte;
}
dlist_length = returned_length + hdr_size;
@@ -4089,9 +4190,7 @@ next_batch:
* error and no data. Retry with the 12
* byte command.
*/
- if (use_12byte == 0) {
- get_length = 1;
- use_12byte = 1;
+ if (!use_12byte) {
goto retry_12byte;
}
dlist_length = returned_length + hdr_size;
@@ -4104,11 +4203,9 @@ next_batch:
if (returned_length == 0)
dlist_length = SRDD10_MAX_LENGTH;
else {
- if ((use_12byte == 0)
+ if (!use_12byte
&& (returned_length >=
max_possible_size)) {
- get_length = 1;
- use_12byte = 1;
goto retry_12byte;
}
dlist_length = returned_length +
@@ -4124,17 +4221,15 @@ next_batch:
CAM_EPF_ALL, stderr);
goto defect_bailout;
} else {
- if ((use_12byte == 0)
+ if (!use_12byte
&& (returned_length >= max_possible_size)) {
- get_length = 1;
- use_12byte = 1;
goto retry_12byte;
}
dlist_length = returned_length + hdr_size;
}
- if (summary != 0) {
+ if (summary) {
fprintf(stdout, "%u", num_returned);
- if (quiet == 0) {
+ if (!quiet) {
fprintf(stdout, " defect%s",
(num_returned != 1) ? "s" : "");
}
@@ -4218,10 +4313,10 @@ next_batch:
goto defect_bailout;
}
- if (first_pass != 0) {
+ if (first_pass) {
fprintf(stderr, "Got %d defect", num_returned);
- if ((lists_specified == 0) || (num_returned == 0)) {
+ if (!summary || (num_returned == 0)) {
fprintf(stderr, "s.\n");
goto defect_bailout;
} else if (num_returned == 1)
@@ -4229,7 +4324,7 @@ next_batch:
else
fprintf(stderr, "s:\n");
- first_pass = 0;
+ first_pass = false;
}
/*
@@ -4254,7 +4349,7 @@ next_batch:
0 : 1;
sector &= ~SDD_EXT_PHYS_FLAG_MASK;
}
- if (hex_format == 0)
+ if (!hex_format)
fprintf(stdout, "%d:%d:%d%s",
scsi_3btoul(dlist[i].cylinder),
dlist[i].head,
@@ -4290,7 +4385,7 @@ next_batch:
mads = (bfi & SDD_EXT_BFI_MADS) ? 1 : 0;
bfi &= ~SDD_EXT_BFI_FLAG_MASK;
}
- if (hex_format == 0)
+ if (!hex_format)
fprintf(stdout, "%d:%d:%d%s",
scsi_3btoul(dlist[i].cylinder),
dlist[i].head,
@@ -4319,7 +4414,7 @@ next_batch:
(defect_list + hdr_size);
for (i = 0; i < num_valid; i++) {
- if (hex_format == 0)
+ if (!hex_format)
fprintf(stdout, "%u\n",
scsi_4btoul(dlist[i].address));
else
@@ -4342,7 +4437,7 @@ next_batch:
(defect_list + hdr_size);
for (i = 0; i < num_valid; i++) {
- if (hex_format == 0)
+ if (!hex_format)
fprintf(stdout, "%ju\n",
(uintmax_t)scsi_8btou64(
dlist[i].address));
@@ -4377,7 +4472,7 @@ defect_bailout:
#if 0
void
-reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
+reassignblocks(struct cam_device *device, uint32_t *blocks, int num_blocks)
{
union ccb *ccb;
@@ -4390,7 +4485,7 @@ reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks)
void
mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa, int pc,
int page, int subpage, int task_attr, int retry_count, int timeout,
- u_int8_t *data, int datalen)
+ uint8_t *data, int datalen)
{
union ccb *ccb;
int error_code, sense_key, asc, ascq;
@@ -4402,7 +4497,7 @@ mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa, int pc,
retry:
/*
* MODE SENSE(6) can't handle more then 255 bytes. If there are more,
- * device must return error, so we should not get trucated data.
+ * device must return error, so we should not get truncated data.
*/
if (*cdb_len == 6 && datalen > 255)
datalen = 255;
@@ -4464,7 +4559,7 @@ retry:
void
mode_select(struct cam_device *device, int cdb_len, int save_pages,
- int task_attr, int retry_count, int timeout, u_int8_t *data, int datalen)
+ int task_attr, int retry_count, int timeout, uint8_t *data, int datalen)
{
union ccb *ccb;
int retval;
@@ -4589,10 +4684,10 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
int task_attr, int retry_count, int timeout)
{
union ccb *ccb;
- u_int32_t flags = CAM_DIR_NONE;
- u_int8_t *data_ptr = NULL;
- u_int8_t cdb[20];
- u_int8_t atacmd[12];
+ uint32_t flags = CAM_DIR_NONE;
+ uint8_t *data_ptr = NULL;
+ uint8_t cdb[20];
+ uint8_t atacmd[12];
struct get_hook hook;
int c, data_bytes = 0, valid_bytes;
int cdb_len = 0;
@@ -4693,7 +4788,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
&& (datastr[0] == '-'))
fd_data = 1;
- data_ptr = (u_int8_t *)malloc(data_bytes);
+ data_ptr = (uint8_t *)malloc(data_bytes);
if (data_ptr == NULL) {
warnx("can't malloc memory for data_ptr");
error = 1;
@@ -4720,7 +4815,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
hook.argv = argv + optind;
hook.got = 0;
datastr = cget(&hook, NULL);
- data_ptr = (u_int8_t *)malloc(data_bytes);
+ data_ptr = (uint8_t *)malloc(data_bytes);
if (data_ptr == NULL) {
warnx("can't malloc memory for data_ptr");
error = 1;
@@ -4761,7 +4856,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
if ((fd_data == 1) && (arglist & CAM_ARG_CMD_OUT)) {
ssize_t amt_read;
int amt_to_read = data_bytes;
- u_int8_t *buf_ptr = data_ptr;
+ uint8_t *buf_ptr = data_ptr;
for (amt_read = 0; amt_to_read > 0;
amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
@@ -4910,7 +5005,7 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
} else {
ssize_t amt_written;
int amt_to_write = valid_bytes;
- u_int8_t *buf_ptr = data_ptr;
+ uint8_t *buf_ptr = data_ptr;
for (amt_written = 0; (amt_to_write > 0) &&
(amt_written =write(1, buf_ptr,amt_to_write))> 0;){
@@ -5285,6 +5380,39 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
sata->caps);
}
}
+ if (cts->transport == XPORT_NVME) {
+ struct ccb_trans_settings_nvme *nvme =
+ &cts->xport_specific.nvme;
+
+ if (nvme->valid & CTS_NVME_VALID_LINK) {
+ fprintf(stdout, "%sPCIe lanes: %d (%d max)\n", pathstr,
+ nvme->lanes, nvme->max_lanes);
+ fprintf(stdout, "%sPCIe Generation: %d (%d max)\n", pathstr,
+ nvme->speed, nvme->max_speed);
+ }
+ }
+ if (cts->transport == XPORT_NVMF) {
+ struct ccb_trans_settings_nvmf *nvmf =
+ &cts->xport_specific.nvmf;
+
+ if (nvmf->valid & CTS_NVMF_VALID_TRTYPE) {
+ fprintf(stdout, "%sTransport: %s\n", pathstr,
+ nvmf_transport_type(nvmf->trtype));
+ }
+ }
+ if (cts->transport == XPORT_UFSHCI) {
+ struct ccb_trans_settings_ufshci *ufshci =
+ &cts->xport_specific.ufshci;
+
+ if (ufshci->valid & CTS_UFSHCI_VALID_LINK) {
+ fprintf(stdout, "%sHigh Speed Gear: %d (%d max)\n",
+ pathstr, ufshci->hs_gear, ufshci->max_hs_gear);
+ fprintf(stdout, "%sUnipro TX lanes: %d (%d max)\n", pathstr,
+ ufshci->tx_lanes, ufshci->max_tx_lanes);
+ fprintf(stdout, "%sUnipro RX lanes: %d (%d max)\n", pathstr,
+ ufshci->rx_lanes, ufshci->max_rx_lanes);
+ }
+ }
if (cts->protocol == PROTO_ATA) {
struct ccb_trans_settings_ata *ata=
&cts->proto_specific.ata;
@@ -5305,24 +5433,16 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
"enabled" : "disabled");
}
}
-#ifdef WITH_NVME
if (cts->protocol == PROTO_NVME) {
- struct ccb_trans_settings_nvme *nvmex =
- &cts->xport_specific.nvme;
+ struct ccb_trans_settings_nvme *nvme =
+ &cts->proto_specific.nvme;
- if (nvmex->valid & CTS_NVME_VALID_SPEC) {
+ if (nvme->valid & CTS_NVME_VALID_SPEC) {
fprintf(stdout, "%sNVMe Spec: %d.%d\n", pathstr,
- NVME_MAJOR(nvmex->spec),
- NVME_MINOR(nvmex->spec));
- }
- if (nvmex->valid & CTS_NVME_VALID_LINK) {
- fprintf(stdout, "%sPCIe lanes: %d (%d max)\n", pathstr,
- nvmex->lanes, nvmex->max_lanes);
- fprintf(stdout, "%sPCIe Generation: %d (%d max)\n", pathstr,
- nvmex->speed, nvmex->max_speed);
+ NVME_MAJOR(nvme->spec),
+ NVME_MINOR(nvme->spec));
}
}
-#endif
}
/*
@@ -5419,7 +5539,7 @@ dev_has_vpd_page(struct cam_device *dev, uint8_t page_id, int retry_count,
/*retries*/ retry_count,
/*cbfcnp*/ NULL,
/* tag_action */ MSG_SIMPLE_Q_TAG,
- /* inq_buf */ (u_int8_t *)&sup_pages,
+ /* inq_buf */ (uint8_t *)&sup_pages,
/* inq_len */ sizeof(sup_pages),
/* evpd */ 1,
/* page_code */ SVPD_SUPPORTED_PAGE_LIST,
@@ -6324,9 +6444,9 @@ scsiformat(struct cam_device *device, int argc, char **argv,
int use_timeout = 10800 * 1000;
int immediate = 1;
struct format_defect_list_header fh;
- u_int8_t *data_ptr = NULL;
- u_int32_t dxfer_len = 0;
- u_int8_t byte2 = 0;
+ uint8_t *data_ptr = NULL;
+ uint32_t dxfer_len = 0;
+ uint8_t byte2 = 0;
int num_warnings = 0;
int reportonly = 0;
@@ -6423,7 +6543,7 @@ scsiformat(struct cam_device *device, int argc, char **argv,
*/
if (immediate != 0) {
fh.byte2 = FU_DLH_IMMED;
- data_ptr = (u_int8_t *)&fh;
+ data_ptr = (uint8_t *)&fh;
dxfer_len = sizeof(fh);
byte2 = FU_FMT_DATA;
} else if (quiet == 0) {
@@ -6795,7 +6915,7 @@ sanitize(struct cam_device *device, int argc, char **argv,
char *combinedopt, int task_attr, int retry_count, int timeout)
{
union ccb *ccb;
- u_int8_t action = 0;
+ uint8_t action = 0;
int c;
int ycount = 0, quiet = 0;
int error = 0;
@@ -6806,8 +6926,8 @@ sanitize(struct cam_device *device, int argc, char **argv,
int ause = 0;
int fd = -1;
const char *pattern = NULL;
- u_int8_t *data_ptr = NULL;
- u_int32_t dxfer_len = 0;
+ uint8_t *data_ptr = NULL;
+ uint32_t dxfer_len = 0;
uint8_t byte2;
uint16_t feature, count;
uint64_t lba;
@@ -7651,7 +7771,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
&& (datastr[0] == '-'))
fd_response = 1;
- smp_response = (u_int8_t *)malloc(response_size);
+ smp_response = (uint8_t *)malloc(response_size);
if (smp_response == NULL) {
warn("can't malloc memory for SMP response");
error = 1;
@@ -7671,7 +7791,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
hook.argv = argv + optind;
hook.got = 0;
datastr = cget(&hook, NULL);
- smp_request = (u_int8_t *)malloc(request_size);
+ smp_request = (uint8_t *)malloc(request_size);
if (smp_request == NULL) {
warn("can't malloc memory for SMP request");
error = 1;
@@ -7703,7 +7823,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
if ((fd_request == 1) && (arglist & CAM_ARG_CMD_OUT)) {
ssize_t amt_read;
int amt_to_read = request_size;
- u_int8_t *buf_ptr = smp_request;
+ uint8_t *buf_ptr = smp_request;
for (amt_read = 0; amt_to_read > 0;
amt_read = read(STDIN_FILENO, buf_ptr, amt_to_read)) {
@@ -7763,7 +7883,7 @@ smpcmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
} else {
ssize_t amt_written;
int amt_to_write = response_size;
- u_int8_t *buf_ptr = smp_response;
+ uint8_t *buf_ptr = smp_response;
for (amt_written = 0; (amt_to_write > 0) &&
(amt_written = write(STDOUT_FILENO, buf_ptr,
@@ -9246,7 +9366,7 @@ atapm(struct cam_device *device, int argc, char **argv,
int retval = 0;
int t = -1;
int c;
- u_int8_t ata_flags = 0;
+ uint8_t ata_flags = 0;
u_char cmd, sc;
ccb = cam_getccb(device);
@@ -9312,12 +9432,11 @@ atapm(struct cam_device *device, int argc, char **argv,
/*timeout*/timeout ? timeout : 30 * 1000,
/*force48bit*/0);
- cam_freeccb(ccb);
-
- if (retval || cmd != ATA_CHECK_POWER_MODE)
- return (retval);
+ if (retval == 0 && cmd == ATA_CHECK_POWER_MODE)
+ retval = atapm_proc_resp(device, ccb);
- return (atapm_proc_resp(device, ccb));
+ cam_freeccb(ccb);
+ return (retval);
}
static int
@@ -9878,6 +9997,7 @@ usage(int printlong)
" camcontrol devlist [-b] [-v]\n"
" camcontrol periphlist [dev_id][-n dev_name] [-u unit]\n"
" camcontrol tur [dev_id][generic args]\n"
+" camcontrol sense [dev_id][generic args][-D][-x]\n"
" camcontrol inquiry [dev_id][generic args] [-D] [-S] [-R]\n"
" camcontrol identify [dev_id][generic args] [-v]\n"
" camcontrol reportluns [dev_id][generic args] [-c] [-l] [-r report]\n"
@@ -9966,6 +10086,7 @@ usage(int printlong)
"Specify one of the following options:\n"
"devlist list all CAM devices\n"
"periphlist list all CAM peripheral drivers attached to a device\n"
+"sense send a request sense command to the named device\n"
"tur send a test unit ready to the named device\n"
"inquiry send a SCSI inquiry command to the named device\n"
"identify send a ATA identify command to the named device\n"
@@ -10030,6 +10151,9 @@ usage(int printlong)
"-f format specify defect list format (block, bfi or phys)\n"
"-G get the grown defect list\n"
"-P get the permanent defect list\n"
+"sense arguments:\n"
+"-D request descriptor sense data\n"
+"-x do a hexdump of the sense data\n"
"inquiry arguments:\n"
"-D get the standard inquiry data\n"
"-S get the serial number\n"
@@ -10500,6 +10624,10 @@ main(int argc, char **argv)
case CAM_CMD_DEVTYPE:
error = getdevtype(cam_dev);
break;
+ case CAM_CMD_REQSENSE:
+ error = requestsense(cam_dev, argc, argv, combinedopt,
+ task_attr, retry_count, timeout);
+ break;
case CAM_CMD_TUR:
error = testunitready(cam_dev, task_attr, retry_count,
timeout, 0);
diff --git a/sbin/camcontrol/camcontrol.h b/sbin/camcontrol/camcontrol.h
index b84587df7a3e..ebc6d4039f8f 100644
--- a/sbin/camcontrol/camcontrol.h
+++ b/sbin/camcontrol/camcontrol.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-NetBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1998 Kenneth D. Merry.
* All rights reserved.
@@ -26,8 +26,6 @@
* 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 _CAMCONTROL_H
@@ -95,7 +93,7 @@ void mode_sense(struct cam_device *device, int *cdb_len, int dbd, int llbaa,
int pc, int page, int subpage, int task_attr, int retry_count,
int timeout, uint8_t *data, int datalen);
void mode_select(struct cam_device *device, int cdb_len, int save_pages,
- int task_attr, int retry_count, int timeout, u_int8_t *data,
+ int task_attr, int retry_count, int timeout, uint8_t *data,
int datalen);
void mode_edit(struct cam_device *device, int cdb_len, int desc, int dbd,
int llbaa, int pc, int page, int subpage, int edit, int binary,
diff --git a/sbin/camcontrol/depop.c b/sbin/camcontrol/depop.c
index cf205ab6b471..4aff0284abe1 100644
--- a/sbin/camcontrol/depop.c
+++ b/sbin/camcontrol/depop.c
@@ -50,9 +50,6 @@
* 'depop' provides a wrapper around all these functions.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <err.h>
diff --git a/sbin/camcontrol/epc.c b/sbin/camcontrol/epc.c
index aac94ccaa4e5..4273ad19047c 100644
--- a/sbin/camcontrol/epc.c
+++ b/sbin/camcontrol/epc.c
@@ -33,12 +33,9 @@
* ATA Extended Power Conditions (EPC) support
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/stdint.h>
-#include <sys/types.h>
#include <sys/endian.h>
#include <sys/sbuf.h>
#include <sys/queue.h>
@@ -153,7 +150,7 @@ epc_print_pcl_desc(struct ata_power_cond_log_desc *desc, const char *prefix)
max_chars = 75;
num_printed = printf("%sFlags: ", prefix);
- for (i = 0; i < (sizeof(epc_flags) / sizeof(epc_flags[0])); i++) {
+ for (i = 0; i < nitems(epc_flags); i++) {
if ((desc->flags & epc_flags[i].value) == 0)
continue;
if (first == 0) {
@@ -468,7 +465,7 @@ check_power_mode:
}
mode_name = scsi_nv_to_str(epc_power_cond_map,
- sizeof(epc_power_cond_map) / sizeof(epc_power_cond_map[0]), count);
+ nitems(epc_power_cond_map), count);
printf("Current power state: ");
/* Note: ident can be null in power_only mode */
if ((ident == NULL)
@@ -640,7 +637,7 @@ epc(struct cam_device *device, int argc, char **argv, char *combinedopt,
int entry_num;
status = scsi_get_nv(epc_cmd_map,
- (sizeof(epc_cmd_map) / sizeof(epc_cmd_map[0])),
+ nitems(epc_cmd_map),
optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
if (status == SCSI_NV_FOUND)
action = epc_cmd_map[entry_num].value;
@@ -717,7 +714,7 @@ epc(struct cam_device *device, int argc, char **argv, char *combinedopt,
int entry_num;
status = scsi_get_nv(epc_ps_map,
- (sizeof(epc_ps_map) / sizeof(epc_ps_map[0])),
+ nitems(epc_ps_map),
optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
if (status == SCSI_NV_FOUND)
power_src = epc_ps_map[entry_num].value;
diff --git a/sbin/camcontrol/fwdownload.c b/sbin/camcontrol/fwdownload.c
index 02b60f25df04..569021c2bfc1 100644
--- a/sbin/camcontrol/fwdownload.c
+++ b/sbin/camcontrol/fwdownload.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2011 Sandvine Incorporated. All rights reserved.
* Copyright (c) 2002-2011 Andre Albsmeier <andre@albsmeier.net>
@@ -49,9 +49,6 @@
* specified device.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/stat.h>
@@ -86,6 +83,7 @@ typedef enum {
VENDOR_SAMSUNG,
VENDOR_SEAGATE,
VENDOR_SMART,
+ VENDOR_TOSHIBA,
VENDOR_ATA,
VENDOR_UNKNOWN
} fw_vendor_t;
@@ -167,8 +165,8 @@ struct fw_vendor {
const char *pattern;
int dev_type;
int max_pkt_size;
- u_int8_t cdb_byte2;
- u_int8_t cdb_byte2_last;
+ uint8_t cdb_byte2;
+ uint8_t cdb_byte2_last;
int inc_cdb_buffer_id;
int inc_cdb_offset;
fw_tur_status tur_status;
@@ -215,6 +213,8 @@ static struct fw_vendor vendors_list[] = {
0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT},
{VENDOR_SMART, "SmrtStor", T_DIRECT,
0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT},
+ {VENDOR_TOSHIBA, "TOSHIBA", T_DIRECT,
+ 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT},
{VENDOR_HGST, "WD", T_DIRECT,
0x1000, 0x07, 0x07, 1, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT},
{VENDOR_HGST, "WDC", T_DIRECT,
@@ -474,7 +474,7 @@ fw_validate_ibm(struct cam_device *dev, int retry_count, int timeout, int fd,
/*retries*/ retry_count,
/*cbfcnp*/ NULL,
/* tag_action */ MSG_SIMPLE_Q_TAG,
- /* inq_buf */ (u_int8_t *)&vpd_page,
+ /* inq_buf */ (uint8_t *)&vpd_page,
/* inq_len */ sizeof(vpd_page),
/* evpd */ 1,
/* page_code */ SVPD_IBM_FW_DESIGNATION,
@@ -832,9 +832,9 @@ fw_download_img(struct cam_device *cam_dev, struct fw_vendor *vp,
union ccb *ccb = NULL;
int pkt_count = 0;
int max_pkt_size;
- u_int32_t pkt_size = 0;
+ uint32_t pkt_size = 0;
char *pkt_ptr = buf;
- u_int32_t offset;
+ uint32_t offset;
int last_pkt = 0;
int retval = 0;
diff --git a/sbin/camcontrol/modeedit.c b/sbin/camcontrol/modeedit.c
index 15e5c6608f47..46accea0da43 100644
--- a/sbin/camcontrol/modeedit.c
+++ b/sbin/camcontrol/modeedit.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2000 Kelly Yancey <kbyanc@posi.net>
* Derived from work done by Julian Elischer <julian@tfs.com,
@@ -29,8 +29,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/sbuf.h>
@@ -595,8 +593,8 @@ static void
editlist_populate(struct cam_device *device, int cdb_len, int dbd, int pc,
int page, int subpage, int task_attr, int retries, int timeout)
{
- u_int8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
- u_int8_t *mode_pars; /* Pointer to modepage params. */
+ uint8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
+ uint8_t *mode_pars; /* Pointer to modepage params. */
struct scsi_mode_page_header *mph;
struct scsi_mode_page_header_sp *mphsp;
size_t len;
@@ -700,8 +698,8 @@ static void
editlist_save(struct cam_device *device, int cdb_len, int dbd, int pc,
int page, int subpage, int task_attr, int retries, int timeout)
{
- u_int8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
- u_int8_t *mode_pars; /* Pointer to modepage params. */
+ uint8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
+ uint8_t *mode_pars; /* Pointer to modepage params. */
struct scsi_mode_page_header *mph;
struct scsi_mode_page_header_sp *mphsp;
size_t len, hlen, mphlen;
@@ -1003,8 +1001,8 @@ static void
modepage_dump(struct cam_device *device, int cdb_len, int dbd, int pc,
int page, int subpage, int task_attr, int retries, int timeout)
{
- u_int8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
- u_int8_t *mode_pars; /* Pointer to modepage params. */
+ uint8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
+ uint8_t *mode_pars; /* Pointer to modepage params. */
struct scsi_mode_page_header *mph;
struct scsi_mode_page_header_sp *mphsp;
size_t indx, len;
@@ -1153,7 +1151,7 @@ void
mode_list(struct cam_device *device, int cdb_len, int dbd, int pc, int subpages,
int task_attr, int retry_count, int timeout)
{
- u_int8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
+ uint8_t data[MAX_DATA_SIZE]; /* Buffer to hold mode parameters. */
struct scsi_mode_page_header *mph;
struct scsi_mode_page_header_sp *mphsp;
struct pagename *nameentry;
diff --git a/sbin/camcontrol/persist.c b/sbin/camcontrol/persist.c
index f7ef30e06ede..d6fb9c6a5f2c 100644
--- a/sbin/camcontrol/persist.c
+++ b/sbin/camcontrol/persist.c
@@ -34,8 +34,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/ioctl.h>
#include <sys/stdint.h>
#include <sys/types.h>
diff --git a/sbin/camcontrol/progress.c b/sbin/camcontrol/progress.c
index 054b3f5391e7..c3c23fba428a 100644
--- a/sbin/camcontrol/progress.c
+++ b/sbin/camcontrol/progress.c
@@ -1,7 +1,7 @@
/* $NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp $ */
/*-
- * SPDX-License-Identifier: BSD-2-Clause-NetBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -44,8 +44,6 @@
#include <unistd.h>
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "progress.h"
static const char * const suffixes[] = {
diff --git a/sbin/camcontrol/progress.h b/sbin/camcontrol/progress.h
index 1234c1136eaf..b3b0453a93a9 100644
--- a/sbin/camcontrol/progress.h
+++ b/sbin/camcontrol/progress.h
@@ -1,7 +1,7 @@
/* $NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp $ */
/*-
- * SPDX-License-Identifier: BSD-2-Clause-NetBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997-2012 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -29,8 +29,6 @@
* 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 PROGRESS_H_
diff --git a/sbin/camcontrol/timestamp.c b/sbin/camcontrol/timestamp.c
index 9667db832298..3130dec188dc 100644
--- a/sbin/camcontrol/timestamp.c
+++ b/sbin/camcontrol/timestamp.c
@@ -35,9 +35,6 @@
* SCSI tape drive timestamp support
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <assert.h>
diff --git a/sbin/camcontrol/util.c b/sbin/camcontrol/util.c
index 58fc93746fc7..08b4cb7630ca 100644
--- a/sbin/camcontrol/util.c
+++ b/sbin/camcontrol/util.c
@@ -46,8 +46,6 @@
* from: scsi.c,v 1.17 1998/01/12 07:57:57 charnier Exp $";
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/stdint.h>
#include <sys/types.h>
diff --git a/sbin/camcontrol/zone.c b/sbin/camcontrol/zone.c
index 3f7dfcec4f35..dc87cd9a9570 100644
--- a/sbin/camcontrol/zone.c
+++ b/sbin/camcontrol/zone.c
@@ -34,12 +34,9 @@
* This is an implementation of the SCSI ZBC and ATA ZAC specs.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
+#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/stdint.h>
-#include <sys/types.h>
#include <sys/endian.h>
#include <sys/sbuf.h>
#include <sys/queue.h>
@@ -138,7 +135,6 @@ zone_rz_print(uint8_t *data_ptr, uint32_t valid_len, int ata_format,
struct scsi_report_zones_desc *desc = NULL;
uint32_t hdr_len, len;
uint64_t max_lba, next_lba = 0;
- int more_data = 0;
zone_print_status status = ZONE_PRINT_OK;
char tmpstr[80];
int field_widths[ZONE_NUM_FIELDS];
@@ -168,7 +164,6 @@ zone_rz_print(uint8_t *data_ptr, uint32_t valid_len, int ata_format,
}
if (hdr_len > (valid_len + sizeof(*hdr))) {
- more_data = 1;
status = ZONE_PRINT_MORE_DATA;
}
@@ -357,7 +352,7 @@ zone(struct cam_device *device, int argc, char **argv, char *combinedopt,
int entry_num;
status = scsi_get_nv(zone_cmd_map,
- (sizeof(zone_cmd_map) / sizeof(zone_cmd_map[0])),
+ nitems(zone_cmd_map),
optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
if (status == SCSI_NV_FOUND)
action = zone_cmd_map[entry_num].value;
@@ -391,7 +386,7 @@ zone(struct cam_device *device, int argc, char **argv, char *combinedopt,
int entry_num;
status = scsi_get_nv(zone_rep_opts,
- (sizeof(zone_rep_opts) /sizeof(zone_rep_opts[0])),
+ nitems(zone_rep_opts),
optarg, &entry_num, SCSI_NV_FLAG_IG_CASE);
if (status == SCSI_NV_FOUND)
rep_option = zone_rep_opts[entry_num].value;
@@ -592,7 +587,7 @@ restart_report:
/*retry_count*/ retry_count,
/*flags*/ CAM_DIR_NONE | CAM_DEV_QFRZDIS,
/*tag_action*/ task_attr,
- /*protocol*/ AP_PROTO_NON_DATA,
+ /*protocol*/ protocol,
/*ata_flags*/ AP_FLAG_BYT_BLOK_BYTES |
AP_FLAG_TLEN_NO_DATA,
/*features*/ features,
diff --git a/sbin/ccdconfig/Makefile b/sbin/ccdconfig/Makefile
index c01b0c55b178..8972945ed072 100644
--- a/sbin/ccdconfig/Makefile
+++ b/sbin/ccdconfig/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=ccdconfig
PROG= ccdconfig
MAN= ccdconfig.8
diff --git a/sbin/ccdconfig/Makefile.depend b/sbin/ccdconfig/Makefile.depend
index 0220673c9076..0dd05cace3c0 100644
--- a/sbin/ccdconfig/Makefile.depend
+++ b/sbin/ccdconfig/Makefile.depend
@@ -1,16 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
lib/libgeom \
- lib/libsbuf \
.include <dirdeps.mk>
diff --git a/sbin/ccdconfig/ccdconfig.8 b/sbin/ccdconfig/ccdconfig.8
index e73864bc1fef..52bbfef20af6 100644
--- a/sbin/ccdconfig/ccdconfig.8
+++ b/sbin/ccdconfig/ccdconfig.8
@@ -26,9 +26,8 @@
.\" SUCH DAMAGE.
.\"
.\" $NetBSD: ccdconfig.8,v 1.4 1996/02/28 01:01:17 thorpej Exp $
-.\" $FreeBSD$
.\"
-.Dd March 17, 2022
+.Dd January 23, 2025
.Dt CCDCONFIG 8
.Os
.Sh NAME
@@ -123,13 +122,6 @@ argument is optional.
ccd0 16 none /dev/da2s1 /dev/da3s1
.Ed
.Pp
-The component devices need to name partitions of type
-.Li FS_BSDFFS
-(or
-.Dq 4.2BSD
-as shown by
-.Xr disklabel 8 ) .
-.Pp
If you want to use the
.Tn Linux
.Xr md 4
@@ -153,7 +145,7 @@ are exactly the same as you might place in the
configuration file.
The first example creates a 4-disk stripe out of
four scsi disk partitions.
-The stripe uses a 64 sector interleave.
+The stripe uses a 64-sector interleave.
The second example is an example of a complex stripe/mirror combination.
It reads as a two disk stripe of da4 and da5 which is mirrored
to a two disk stripe of da6 and da7.
@@ -184,34 +176,9 @@ ccdconfig -c /dev/ccd0 32 linux /dev/ada0s1 /dev/ada0s2
.Ed
.Pp
When you create a new ccd disk you generally want to
-.Xr fdisk 8
-and
-.Xr disklabel 8
+partition it using
+.Xr gpart 8
it before doing anything else.
-Once you create the initial label you can
-edit it, adding additional partitions.
-The label itself takes up the first
-16 sectors of the ccd disk.
-If all you are doing is creating file systems
-with newfs, you do not have to worry about this as newfs will skip the
-label area.
-However, if you intend to
-.Xr dd 1
-to or from a ccd partition it is usually a good idea to construct the
-partition such that it does not overlap the label area.
-For example, if
-you have A ccd disk with 10000 sectors you might create a 'd' partition
-with offset 16 and size 9984.
-.Bd -literal
-# disklabel ccd0 > /tmp/disklabel.ccd0
-# disklabel -R ccd0 /tmp/disklabel.ccd0
-# disklabel -e ccd0
-.Ed
-.Pp
-The disklabeling of a ccd disk is usually a one-time affair.
-If you reboot the machine and reconfigure the ccd disk,
-the disklabel you
-had created before will still be there and not require reinitialization.
Beware that changing any ccd parameters: interleave, flags, or the
device list making up the ccd disk, will usually destroy any prior
data on that ccd disk.
@@ -232,27 +199,18 @@ If you need
more than this you should look into external hardware RAID SCSI boxes,
RAID controllers (see GENERIC),
or software RAID systems such as
-.Xr geom 8
-and
-.Xr gvinum 8 .
+.Xr graid 8
+or
+.Xr zfs 8 .
.Sh SEE ALSO
.Xr dd 1 ,
.Xr ccd 4 ,
-.Xr disklabel 8 ,
-.Xr fdisk 8 ,
-.Xr gvinum 8 ,
-.Xr rc 8
+.Xr gpart 8 ,
+.Xr graid 8 ,
+.Xr rc 8 ,
+.Xr zfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Nx 1.1 .
-.Sh BUGS
-The initial disklabel returned by
-.Xr ccd 4
-specifies only 3 partitions.
-One needs to change the number of partitions to 8 using
-.Dq Nm disklabel Fl e
-to get the usual
-.Bx
-expectations.
diff --git a/sbin/ccdconfig/ccdconfig.c b/sbin/ccdconfig/ccdconfig.c
index 1429426e8638..6b8086ef0213 100644
--- a/sbin/ccdconfig/ccdconfig.c
+++ b/sbin/ccdconfig/ccdconfig.c
@@ -32,9 +32,6 @@
* NetBSD: ccdconfig.c,v 1.6 1996/05/16 07:11:18 thorpej Exp $
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/module.h>
diff --git a/sbin/ccdconfig/pathnames.h b/sbin/ccdconfig/pathnames.h
index 85791ddbfcff..4924323e5a8e 100644
--- a/sbin/ccdconfig/pathnames.h
+++ b/sbin/ccdconfig/pathnames.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-NetBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1996 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -29,7 +29,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*
* $NetBSD: pathnames.h,v 1.4 2008/04/28 20:23:07 martin Exp $
- * $FreeBSD$
*/
#define _PATH_CCDCONF "/etc/ccd.conf"
diff --git a/sbin/clri/Makefile b/sbin/clri/Makefile
index 5f8777f30391..51f4e9a914dc 100644
--- a/sbin/clri/Makefile
+++ b/sbin/clri/Makefile
@@ -1,7 +1,4 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
-PACKAGE=runtime
+PACKAGE=ufs
PROG= clri
MAN= clri.8
LIBADD= ufs
diff --git a/sbin/clri/Makefile.depend b/sbin/clri/Makefile.depend
index 6cfaab1c3644..910688a678fa 100644
--- a/sbin/clri/Makefile.depend
+++ b/sbin/clri/Makefile.depend
@@ -1,13 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libufs \
.include <dirdeps.mk>
diff --git a/sbin/clri/clri.8 b/sbin/clri/clri.8
index 61bdde7feb6a..9d1fb92e22ba 100644
--- a/sbin/clri/clri.8
+++ b/sbin/clri/clri.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)clri.8 8.2 (Berkeley) 4/19/94
-.\" $FreeBSD$
-.\"
.Dd October 5, 2016
.Dt CLRI 8
.Os
diff --git a/sbin/clri/clri.c b/sbin/clri/clri.c
index 7f9a4f09bfe0..331975b4cdce 100644
--- a/sbin/clri/clri.c
+++ b/sbin/clri/clri.c
@@ -32,21 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1990, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)clri.c 8.2 (Berkeley) 9/23/93";
-#endif /* not lint */
-#endif
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/disklabel.h>
diff --git a/sbin/comcontrol/Makefile b/sbin/comcontrol/Makefile
index 9bfc4684dd6a..6c868dcfb1ae 100644
--- a/sbin/comcontrol/Makefile
+++ b/sbin/comcontrol/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 5.4 (Berkeley) 6/5/91
-# $FreeBSD$
-
PACKAGE=runtime
PROG= comcontrol
MAN= comcontrol.8
diff --git a/sbin/comcontrol/Makefile.depend b/sbin/comcontrol/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/comcontrol/Makefile.depend
+++ b/sbin/comcontrol/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/comcontrol/comcontrol.8 b/sbin/comcontrol/comcontrol.8
index 84309a04960f..f51a1f011167 100644
--- a/sbin/comcontrol/comcontrol.8
+++ b/sbin/comcontrol/comcontrol.8
@@ -1,14 +1,17 @@
-.\" $FreeBSD$
-.Dd May 15, 1994
+.Dd August 31, 2025
.Dt COMCONTROL 8
.Os
.Sh NAME
.Nm comcontrol
.Nd control a special tty device
+.Sh DEPRECATION NOTICE
+The
+.Nm
+utility is deprecated and will be removed in
+.Fx 16.0 .
.Sh SYNOPSIS
.Nm
.Ar special_device
-.Op dtrwait Ar number
.Op drainwait Ar number
.Sh DESCRIPTION
The
@@ -23,20 +26,13 @@ Only the superuser can change the settings.
.Pp
The following options are available:
.Bl -tag -width indent
-.It Cm dtrwait Ar number
-Set the time to wait after dropping DTR
-to the given number.
-The units are hundredths of a second.
-The default is 300 hundredths, i.e., 3 seconds.
-This option needed mainly to set proper recover time after
-modem reset.
.It Cm drainwait Ar number
Set the time to wait for output drain
to the given number.
The units are seconds.
The default is 5 minutes, 0 means
waiting forever.
-This option needed mainly to specify upper limit of minutes
+This option is needed mainly to specify an upper limit of minutes
to prevent modem hanging.
.El
.Pp
@@ -53,12 +49,11 @@ dialin devices, hardwired terminals
dialout devices
.El
.Sh SEE ALSO
-.Xr stty 1 ,
+.Xr stty 1
.Sh HISTORY
Originally part of cgd's com package patches, version 0.2.1, to
.Bx 386 0.1 .
Once controlled bidirectional capabilities.
-Little is left to control now
-that these capabilities are standard.
+Little is left to control now that these capabilities are standard.
.Sh AUTHORS
.An Christopher G. Demetriou
diff --git a/sbin/comcontrol/comcontrol.c b/sbin/comcontrol/comcontrol.c
index 6bfb47b74c2d..d6d24e8acab8 100644
--- a/sbin/comcontrol/comcontrol.c
+++ b/sbin/comcontrol/comcontrol.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1992 Christopher G. Demetriou
* All rights reserved.
@@ -29,8 +29,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -42,13 +40,13 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/ioctl.h>
-static void usage(void);
+static void usage(void) __dead2;
static void
usage(void)
{
fprintf(stderr,
- "usage: comcontrol <filename> [dtrwait <n>] [drainwait <n>]\n");
+ "usage: comcontrol <filename> [drainwait <n>]\n");
exit(1);
}
@@ -57,8 +55,8 @@ main(int argc, char *argv[])
{
int fd;
int res = 0;
- int print_dtrwait = 1, print_drainwait = 1;
- int dtrwait = -1, drainwait = -1;
+ int print_drainwait = 1;
+ int drainwait = -1;
if (argc < 2)
usage();
@@ -73,13 +71,6 @@ main(int argc, char *argv[])
}
}
if (argc == 2) {
- if (ioctl(fd, TIOCMGDTRWAIT, &dtrwait) < 0) {
- print_dtrwait = 0;
- if (errno != ENOTTY) {
- res = 1;
- warn("TIOCMGDTRWAIT");
- }
- }
if (ioctl(fd, TIOCGDRAINWAIT, &drainwait) < 0) {
print_drainwait = 0;
if (errno != ENOTTY) {
@@ -87,21 +78,12 @@ main(int argc, char *argv[])
warn("TIOCGDRAINWAIT");
}
}
- if (print_dtrwait)
- printf("dtrwait %d ", dtrwait);
if (print_drainwait)
printf("drainwait %d ", drainwait);
printf("\n");
} else {
while (argv[2] != NULL) {
- if (!strcmp(argv[2],"dtrwait")) {
- if (dtrwait >= 0)
- usage();
- if (argv[3] == NULL || !isdigit(argv[3][0]))
- usage();
- dtrwait = atoi(argv[3]);
- argv += 2;
- } else if (!strcmp(argv[2],"drainwait")) {
+ if (!strcmp(argv[2],"drainwait")) {
if (drainwait >= 0)
usage();
if (argv[3] == NULL || !isdigit(argv[3][0]))
@@ -111,12 +93,6 @@ main(int argc, char *argv[])
} else
usage();
}
- if (dtrwait >= 0) {
- if (ioctl(fd, TIOCMSDTRWAIT, &dtrwait) < 0) {
- res = 1;
- warn("TIOCMSDTRWAIT");
- }
- }
if (drainwait >= 0) {
if (ioctl(fd, TIOCSDRAINWAIT, &drainwait) < 0) {
res = 1;
diff --git a/sbin/conscontrol/Makefile b/sbin/conscontrol/Makefile
index 0bd82e695c31..33665536167c 100644
--- a/sbin/conscontrol/Makefile
+++ b/sbin/conscontrol/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=runtime
PROG= conscontrol
MAN= conscontrol.8
diff --git a/sbin/conscontrol/Makefile.depend b/sbin/conscontrol/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/conscontrol/Makefile.depend
+++ b/sbin/conscontrol/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/conscontrol/conscontrol.8 b/sbin/conscontrol/conscontrol.8
index eb9b4dfdbc0f..c11a1f7db5d9 100644
--- a/sbin/conscontrol/conscontrol.8
+++ b/sbin/conscontrol/conscontrol.8
@@ -1,3 +1,5 @@
+.\"-
+.\" SPDX-License-Identifer: BSD-2-Clause
.\"
.\" Copyright (c) 2001 Jonathan Lemon <jlemon@FreeBSD.org>
.\" All rights reserved.
@@ -23,14 +25,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd April 14, 2011
+.Dd July 7, 2024
.Dt CONSCONTROL 8
.Os
.Sh NAME
.Nm conscontrol
-.Nd control physical console devices
+.Nd control physical system video console devices
.Sh SYNOPSIS
.Nm
.Op Cm list
diff --git a/sbin/conscontrol/conscontrol.c b/sbin/conscontrol/conscontrol.c
index f4298eb8a2cc..9c7ec9175910 100644
--- a/sbin/conscontrol/conscontrol.c
+++ b/sbin/conscontrol/conscontrol.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2001 Jonathan Lemon <jlemon@FreeBSD.org>
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/ioctl.h>
diff --git a/sbin/ddb/Makefile b/sbin/ddb/Makefile
index f1bf75e41b36..8d527ad5259a 100644
--- a/sbin/ddb/Makefile
+++ b/sbin/ddb/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
CONFS= ddb.conf
PACKAGE=runtime
PROG= ddb
diff --git a/sbin/ddb/Makefile.depend b/sbin/ddb/Makefile.depend
index 4a0ebeceed6f..124f2f93f8a6 100644
--- a/sbin/ddb/Makefile.depend
+++ b/sbin/ddb/Makefile.depend
@@ -1,14 +1,11 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
diff --git a/sbin/ddb/ddb.8 b/sbin/ddb/ddb.8
index 0fb9687991e5..562251e0b448 100644
--- a/sbin/ddb/ddb.8
+++ b/sbin/ddb/ddb.8
@@ -23,8 +23,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd December 24, 2008
.Dt DDB 8
.Os
@@ -150,6 +148,7 @@ and
manual pages.
.Sh SEE ALSO
.Xr ddb 4 ,
+.Xr mac_ddb 4 ,
.Xr textdump 4 ,
.Xr sysctl 8
.Sh HISTORY
diff --git a/sbin/ddb/ddb.c b/sbin/ddb/ddb.c
index a90a693e1b03..885921d7c51f 100644
--- a/sbin/ddb/ddb.c
+++ b/sbin/ddb/ddb.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
@@ -27,8 +27,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/sbin/ddb/ddb.conf b/sbin/ddb/ddb.conf
index 1246c0effdf4..7572a7a91915 100644
--- a/sbin/ddb/ddb.conf
+++ b/sbin/ddb/ddb.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# This file is read when going to multi-user and its contents piped thru
# ``ddb'' to define debugging scripts.
diff --git a/sbin/ddb/ddb.h b/sbin/ddb/ddb.h
index 6f9a6f99f04b..bd33b24c92cb 100644
--- a/sbin/ddb/ddb.h
+++ b/sbin/ddb/ddb.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 DDB_H
diff --git a/sbin/ddb/ddb_capture.c b/sbin/ddb/ddb_capture.c
index 1bb27b5b7e93..ab8b2c1ed0bb 100644
--- a/sbin/ddb/ddb_capture.c
+++ b/sbin/ddb/ddb_capture.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2008 Robert N. M. Watson
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/sysctl.h>
diff --git a/sbin/ddb/ddb_script.c b/sbin/ddb/ddb_script.c
index e36cb6606380..76724df8d772 100644
--- a/sbin/ddb/ddb_script.c
+++ b/sbin/ddb/ddb_script.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2007 Robert N. M. Watson
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/sysctl.h>
diff --git a/sbin/decryptcore/Makefile b/sbin/decryptcore/Makefile
index 3a3a6a029f87..97421fe5cd3c 100644
--- a/sbin/decryptcore/Makefile
+++ b/sbin/decryptcore/Makefile
@@ -1,7 +1,6 @@
-# $FreeBSD$
-
PROG= decryptcore
+CFLAGS+=-DOPENSSL_API_COMPAT=0x10100000L
LIBADD= crypto pjdlog
MAN= decryptcore.8
diff --git a/sbin/decryptcore/Makefile.depend b/sbin/decryptcore/Makefile.depend
index d718b860472f..fa1f7fd358f0 100644
--- a/sbin/decryptcore/Makefile.depend
+++ b/sbin/decryptcore/Makefile.depend
@@ -1,15 +1,14 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
+ lib/libcapsicum \
+ lib/libcasper/libcasper \
lib/libcompiler_rt \
lib/libpjdlog \
- lib/libutil \
secure/lib/libcrypto \
diff --git a/sbin/decryptcore/decryptcore.8 b/sbin/decryptcore/decryptcore.8
index fc6a1dadc7b5..057d3a0ed7ea 100644
--- a/sbin/decryptcore/decryptcore.8
+++ b/sbin/decryptcore/decryptcore.8
@@ -22,8 +22,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd January 29, 2018
.Dt DECRYPTCORE 8
.Os
@@ -110,7 +108,7 @@ Specify a number of a crash dump to be decrypted.
.Sh EXIT STATUS
.Ex -std
.Sh SEE ALSO
-.Xr kgdb 1 ,
+.Xr kgdb 1 Pq Pa ports/devel/gdb ,
.Xr capsicum 4 ,
.Xr dumpon 8 ,
.Xr savecore 8 ,
diff --git a/sbin/decryptcore/decryptcore.c b/sbin/decryptcore/decryptcore.c
index fc6599fb0ecc..1e7cf4070e51 100644
--- a/sbin/decryptcore/decryptcore.c
+++ b/sbin/decryptcore/decryptcore.c
@@ -24,9 +24,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/capsicum.h>
#include <sys/endian.h>
@@ -41,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
+#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
@@ -179,8 +177,10 @@ decrypt(int ofd, const char *privkeyfile, const char *keyfile,
unsigned char c[1];
RAND_bytes(c, 1);
}
-#endif
ERR_load_crypto_strings();
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
+#endif
caph_cache_catpages();
if (caph_enter() < 0) {
diff --git a/sbin/devd/Makefile b/sbin/devd/Makefile
index 0bda9e1ecf95..553aecf4ee88 100644
--- a/sbin/devd/Makefile
+++ b/sbin/devd/Makefile
@@ -1,9 +1,7 @@
-# $FreeBSD$
-
.include <src.opts.mk>
-WARNS?= 3
-PACKAGE=runtime
+WARNS?= 6
+PACKAGE=devd
CONFGROUPS= CONFS DEVD
CONFS= devd.conf
DEVD= devmatch.conf
@@ -12,6 +10,40 @@ DEVDDIR= /etc/devd
DEVD+= asus.conf
.endif
+.if ${MK_AUTOFS} != "no"
+CONFGROUPS+= AUTOFS
+AUTOFSDIR= ${DEVDDIR}
+AUTOFS+= autofs.conf
+AUTOFSPACKAGE= autofs
+.endif
+
+CONFGROUPS+= DHCLIENT
+DHCLIENTDIR= ${DEVDDIR}
+DHCLIENT+= dhclient.conf
+DHCLIENTPACKAGE= dhclient
+
+CONFGROUPS+= POWERPROFILE
+POWERPROFILEDIR= ${DEVDDIR}
+POWERPROFILE+= power_profile.conf
+POWERPROFILEPACKAGE= acpi
+
+CONFGROUPS+= CONSOLE
+CONSOLEDIR= ${DEVDDIR}
+CONSOLE+= moused.conf syscons.conf
+CONSOLEPACKAGE= console-tools
+
+CONFGROUPS+= SND
+SNDDIR= ${DEVDDIR}
+SND= snd.conf
+SNDPACKAGE= sound
+
+.if ${MK_BLUETOOTH} != "no"
+CONFGROUPS+= BLUETOOTH
+BLUETOOTHDIR= ${DEVDDIR}
+BLUETOOTH+= bluetooth.conf
+BLUETOOTHPACKAGE= bluetooth
+.endif
+
.if ${MK_HYPERV} != "no"
CONFGROUPS+= HYPERV
HYPERVDIR=${DEVDDIR}
@@ -19,6 +51,11 @@ HYPERV+= hyperv.conf
HYPERVPACKAGE= hyperv-tools
.endif
+CONFGROUPS+= NVME
+NVMEDIR= ${DEVDDIR}
+NVME+= nvmf.conf
+NVMEPACKAGE= nvme-tools
+
.if ${MK_USB} != "no"
DEVD+= uath.conf ulpt.conf
.endif
@@ -35,8 +72,6 @@ PROG_CXX=devd
SRCS= devd.cc token.l parse.y y.tab.h
MAN= devd.8 devd.conf.5
-NO_SHARED?=YES
-
LIBADD= util
YFLAGS+=-v
diff --git a/sbin/devd/Makefile.depend b/sbin/devd/Makefile.depend
index 8c3f699ac991..a5009d89b087 100644
--- a/sbin/devd/Makefile.depend
+++ b/sbin/devd/Makefile.depend
@@ -1,17 +1,15 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libc++ \
lib/libcompiler_rt \
+ lib/libcxxrt \
lib/libutil \
lib/msun \
- usr.bin/lex/lib \
usr.bin/yacc.host \
diff --git a/sbin/devd/apple.conf b/sbin/devd/apple.conf
index 0a9143f7b5a5..7a164c0ebfc7 100644
--- a/sbin/devd/apple.conf
+++ b/sbin/devd/apple.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# PowerPC Apple specific devd events
diff --git a/sbin/devd/asus.conf b/sbin/devd/asus.conf
index 0074e7a7c55f..0962af7df2e0 100644
--- a/sbin/devd/asus.conf
+++ b/sbin/devd/asus.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# ASUS specific devd events
diff --git a/sbin/devd/autofs.conf b/sbin/devd/autofs.conf
new file mode 100644
index 000000000000..2671687ecd83
--- /dev/null
+++ b/sbin/devd/autofs.conf
@@ -0,0 +1,9 @@
+#
+# autofs(4) specific devd events
+
+# Discard autofs caches, useful for the -media special map.
+notify 100 {
+ match "system" "GEOM";
+ match "subsystem" "DEV";
+ action "/usr/sbin/automount -c";
+};
diff --git a/sbin/devd/bluetooth.conf b/sbin/devd/bluetooth.conf
new file mode 100644
index 000000000000..29bd51e36fca
--- /dev/null
+++ b/sbin/devd/bluetooth.conf
@@ -0,0 +1,9 @@
+# When a USB Bluetooth dongle appears, activate it
+attach 100 {
+ device-name "ubt[0-9]+";
+ action "service bluetooth quietstart $device-name";
+};
+detach 100 {
+ device-name "ubt[0-9]+";
+ action "service bluetooth quietstop $device-name";
+};
diff --git a/sbin/devd/devd.8 b/sbin/devd/devd.8
index 77c8e4aac2fb..f4e8e173399c 100644
--- a/sbin/devd/devd.8
+++ b/sbin/devd/devd.8
@@ -22,9 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd October 19, 2021
+.Dd May 7, 2025
.Dt DEVD 8
.Os
.Sh NAME
@@ -156,6 +154,12 @@ to communicate with its clients.
.It Pa /var/run/devd.pipe
A deprecated socket retained for use with old clients.
.El
+.Sh EXAMPLES
+Use
+.Xr cat 1
+to monitor kernel events:
+.Pp
+.Dl cat /var/run/devd.seqpacket.pipe
.Sh SEE ALSO
.Xr devctl 4 ,
.Xr devd.conf 5
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc
index a1b6ee479921..ee38fbb2ccee 100644
--- a/sbin/devd/devd.cc
+++ b/sbin/devd/devd.cc
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause
*
* Copyright (c) 2002-2010 M. Warner Losh <imp@FreeBSD.org>
*
@@ -63,9 +63,6 @@
// - devd needs to document the unix domain socket
// - devd.conf needs more details on the supported statements.
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -156,6 +153,8 @@ static volatile sig_atomic_t romeo_must_die = 0;
static const char *configfile = CF;
+static char vm_guest[80];
+
static void devdlog(int priority, const char* message, ...)
__printflike(2, 3);
static void event_loop(void);
@@ -173,6 +172,8 @@ delete_and_clear(vector<T *> &v)
static config cfg;
+static const char *curr_cf = NULL;
+
event_proc::event_proc() : _prio(-1)
{
_epsvec.reserve(4);
@@ -452,17 +453,28 @@ config::reset(void)
delete_and_clear(_notify_list);
}
+/*
+ * Called recursively as new files are included, so current stack of old names
+ * saved in each instance of 'old' on the call stack. Called single threaded
+ * so global varaibles curr_cf and lineno (and all of yacc's parser state)
+ * are safe to access w/o a lock.
+ */
void
config::parse_one_file(const char *fn)
{
+ const char *old;
+
devdlog(LOG_DEBUG, "Parsing %s\n", fn);
yyin = fopen(fn, "r");
+ old = curr_cf;
+ curr_cf = fn;
if (yyin == NULL)
err(1, "Cannot open config file %s", fn);
lineno = 1;
if (yyparse() != 0)
errx(1, "Cannot parse %s at line %d", fn, lineno);
fclose(yyin);
+ curr_cf = old;
}
void
@@ -857,6 +869,8 @@ process_event(char *buffer)
cfg.set_variable("timestamp", timestr);
free(timestr);
+ cfg.set_variable("vm_guest", vm_guest);
+
// Match doesn't have a device, and the format is a little
// different, so handle it separately.
switch (type) {
@@ -928,7 +942,7 @@ create_socket(const char *name, int socktype)
return (fd);
}
-static unsigned int max_clients = 10; /* Default, can be overridden on cmdline. */
+static unsigned int max_clients = 50; /* Default, can be overridden on cmdline. */
static unsigned int num_clients;
static list<client_t> clients;
@@ -1097,6 +1111,14 @@ event_loop(void)
err(1, "select");
} else if (rv == 0)
check_clients();
+ /*
+ * Aside from the socket type, both sockets use the same
+ * protocol, so we can process clients the same way.
+ */
+ if (FD_ISSET(stream_fd, &fds))
+ new_client(stream_fd, SOCK_STREAM);
+ if (FD_ISSET(seqpacket_fd, &fds))
+ new_client(seqpacket_fd, SOCK_SEQPACKET);
if (FD_ISSET(fd, &fds)) {
rv = read(fd, buffer, sizeof(buffer) - 1);
if (rv > 0) {
@@ -1125,14 +1147,6 @@ event_loop(void)
break;
}
}
- if (FD_ISSET(stream_fd, &fds))
- new_client(stream_fd, SOCK_STREAM);
- /*
- * Aside from the socket type, both sockets use the same
- * protocol, so we can process clients the same way.
- */
- if (FD_ISSET(seqpacket_fd, &fds))
- new_client(seqpacket_fd, SOCK_SEQPACKET);
}
cfg.remove_pidfile();
close(seqpacket_fd);
@@ -1291,6 +1305,7 @@ int
main(int argc, char **argv)
{
int ch;
+ size_t len;
check_devd_enabled();
while ((ch = getopt(argc, argv, "df:l:nq")) != -1) {
@@ -1315,6 +1330,12 @@ main(int argc, char **argv)
}
}
+ len = sizeof(vm_guest);
+ if (sysctlbyname("kern.vm_guest", vm_guest, &len, NULL, 0) < 0) {
+ devdlog(LOG_ERR,
+ "sysctlbyname(kern.vm_guest) failed: %d\n", errno);
+ }
+
cfg.parse();
if (!no_daemon && daemonize_quick) {
cfg.open_pidfile();
diff --git a/sbin/devd/devd.conf b/sbin/devd/devd.conf
index 15b37ee8fd90..86faf2f30722 100644
--- a/sbin/devd/devd.conf
+++ b/sbin/devd/devd.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# Refer to devd.conf(5) and devd(8) man pages for the details on how to
# run and configure devd.
@@ -19,8 +18,8 @@ options {
# Setup some shorthand for regex that we use later in the file.
#XXX Yes, this is gross -- imp
set wifi-driver-regex
- "(ath|bwi|bwn|ipw|iwlwifi|iwi|iwm|iwn|malo|mwl|otus|ral|rsu|rtw|rtwn|rum|\
- run|uath|upgt|ural|urtw|wpi|wtap|zyd)[0-9]+";
+ "(ath|ath[0-9]+k|bwi|bwn|ipw|iwlwifi|iwi|iwm|iwn|malo|mwl|mt79|mtw|otus|\
+ ral|rsu|rtw|rtwn|rum|run|uath|upgt|ural|urtw|wpi|wtap|zyd)[0-9]+";
};
# Note that the attach/detach with the highest value wins, so that one can
@@ -45,19 +44,6 @@ notify 0 {
};
#
-# Try to start dhclient on Ethernet-like interfaces when the link comes
-# up. Only devices that are configured to support DHCP will actually
-# run it. No link down rule exists because dhclient automatically exits
-# when the link goes down.
-#
-notify 0 {
- match "system" "IFNET";
- match "type" "LINK_UP";
- media-type "ethernet";
- action "service dhclient quietstart $subsystem";
-};
-
-#
# Like Ethernet devices, but separate because 802.11 require spawning
# wlan(4) interface.
#
@@ -69,12 +55,6 @@ detach 0 {
device-name "$wifi-driver-regex";
action "/etc/pccard_ether $device-name stopchildren";
};
-notify 0 {
- match "system" "IFNET";
- match "type" "LINK_UP";
- media-type "802.11";
- action "service dhclient quietstart $subsystem";
-};
# An entry like this might be in a different file, but is included here
# as an example of how to override things. Normally 'ed50' would match
@@ -88,16 +68,6 @@ detach 100 {
device-name "ed50";
};
-# When a USB Bluetooth dongle appears, activate it
-attach 100 {
- device-name "ubt[0-9]+";
- action "service bluetooth quietstart $device-name";
-};
-detach 100 {
- device-name "ubt[0-9]+";
- action "service bluetooth quietstop $device-name";
-};
-
# Firmware downloader for Atheros AR3011 based USB Bluetooth devices
#attach 100 {
# match "vendor" "0x0cf3";
@@ -105,82 +75,6 @@ detach 100 {
# action "sleep 2 && /usr/sbin/ath3kfw -d $device-name -f /usr/local/etc/ath3k-1.fw";
#};
-# When a USB keyboard arrives, attach it as the console keyboard.
-attach 100 {
- device-name "ukbd0";
- action "service syscons setkeyboard /dev/ukbd0";
-};
-detach 100 {
- device-name "ukbd0";
- action "service syscons setkeyboard /dev/kbd0";
-};
-
-notify 100 {
- match "system" "DEVFS";
- match "subsystem" "CDEV";
- match "type" "CREATE";
- match "cdev" "atp[0-9]+";
-
- action "service moused quietstart $cdev";
-};
-
-notify 100 {
- match "system" "DEVFS";
- match "subsystem" "CDEV";
- match "type" "CREATE";
- match "cdev" "ums[0-9]+";
-
- action "service moused quietstart $cdev";
-};
-
-notify 100 {
- match "system" "DEVFS";
- match "subsystem" "CDEV";
- match "type" "CREATE";
- match "cdev" "wsp[0-9]+";
-
- action "service moused quietstart $cdev";
-};
-
-notify 100 {
- match "system" "DEVFS";
- match "subsystem" "CDEV";
- match "type" "DESTROY";
- match "cdev" "ums[0-9]+";
-
- action "service moused stop $cdev";
-};
-
-# Don't even try to second guess what to do about drivers that don't
-# match here. Instead, pass it off to syslog. Commented out for the
-# moment, as the pnpinfo variable isn't set in devd yet. Individual
-# variables within the bus supplied pnpinfo are set.
-nomatch 0 {
-# action "logger Unknown device: $pnpinfo $location $bus";
-};
-
-# Various logging of unknown devices.
-nomatch 10 {
- match "bus" "uhub[0-9]+";
- action "logger Unknown USB device: vendor $vendor product $product \
- bus $bus";
-};
-
-# Some Cardbus cards don't offer numerical manufacturer/product IDs, just
-# show the CIS info there.
-nomatch 10 {
- match "bus" "cardbus[0-9]+";
- action "logger Unknown Cardbus device: device $device class $class \
- vendor $vendor bus $bus";
-};
-
-# Switch power profiles when the AC line state changes.
-notify 10 {
- match "system" "ACPI";
- match "subsystem" "ACAD";
- action "service power_profile $notify";
-};
-
# Notify all users before beginning emergency shutdown when we get
# a _CRT or _HOT thermal event and we're going to power down the system
# very soon.
@@ -242,13 +136,6 @@ notify 0 {
action "service postgresql restart";
};
-# Discard autofs caches, useful for the -media special map.
-notify 100 {
- match "system" "GEOM";
- match "subsystem" "DEV";
- action "/usr/sbin/automount -c";
-};
-
# Handle userland coredumps.
# This commented out handler makes it possible to run an
# automated debugging session after the core dump is generated.
diff --git a/sbin/devd/devd.conf.5 b/sbin/devd/devd.conf.5
index dd9faa05c869..8df3e910e076 100644
--- a/sbin/devd/devd.conf.5
+++ b/sbin/devd/devd.conf.5
@@ -21,8 +21,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.\" The section on comments was taken from named.conf.5, which has the
.\" following copyright:
.\" Copyright (c) 1999-2000 by Internet Software Consortium
@@ -40,12 +38,12 @@
.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
.\" SOFTWARE.
.\"
-.Dd November 3, 2021
+.Dd July 9, 2025
.Dt DEVD.CONF 5
.Os
.Sh NAME
.Nm devd.conf
-.Nd configuration file for
+.Nd configuration file format for
.Xr devd 8
.Sh DESCRIPTION
.Ss General Syntax
@@ -177,8 +175,6 @@ For network devices,
will match devices that have the given media type.
Valid media types are:
.Dq Li Ethernet ,
-.Dq Li Tokenring ,
-.Dq Li FDDI ,
.Dq Li 802.11 ,
and
.Dq Li ATM .
@@ -326,7 +322,7 @@ mechanism.
.\" for each of the tables so that things line up in columns nicely.
.\" Please do not omit the type column for notifiers that omit it.
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li ACPI Ta Ta Ta
Events related to the ACPI Subsystem.
@@ -350,13 +346,13 @@ Suspend notification.
Thermal zone events.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li AEON Ta Li power Ta Li press Ta
The power button on an Amiga has been pressed.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li CAM Ta Ta Ta
Events related to the
@@ -370,24 +366,24 @@ Generic errors.
Command timeouts.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li CARP Ta Ta Ta
Events related to the
.Xr carp 4
protocol.
-.It CARP Ta Ar vhid@inet Ta Ta
+.It Li CARP Ta Ar vhid@inet Ta Ta
The
.Dq subsystem
contains the actual CARP vhid and the name of the network interface
on which the event took place.
-.It CARP Ta Ar vhid@inet Ta MASTER Ta
+.It Li CARP Ta Ar vhid@inet Ta Li MASTER Ta
Node become the master for a virtual host.
-.It CARP Ta Ar vhid@inet Ta BACKUP Ta
+.It Li CARP Ta Ar vhid@inet Ta Li BACKUP Ta
Node become the backup for a virtual host.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "CORETEMP" "SUBSYSTEM" "TEMPERATURE" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li coretemp Ta Ta Ta
Events related to the
@@ -399,7 +395,7 @@ Notification that the CPU core has reached critical temperature.
String containing the temperature of the core that has become too hot.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li DEVFS
.It Li DEVFS Ta Li CDEV Ta Li CREATE Ta
@@ -412,7 +408,7 @@ The
node is destroyed.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li ETHERNET Ta Ar inet Ta IFATTACH Ta
Notification when the default VNET instance of the
@@ -420,7 +416,7 @@ Notification when the default VNET instance of the
interface is attached.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "GEOM::ROTATION_RATE" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li GEOM Ta Ta Ta
Events related to the
@@ -451,7 +447,7 @@ A
provider size has changed.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "LINK_DOWN" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li IFNET
.It Li IFNET Ta Em inet Ta Ta
@@ -475,15 +471,7 @@ The network interface address added.
The network interface address removed.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
-.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
-.It Li kern Ta Li power Ta Li resume Ta
-Notification that the system has woken from the suspended state.
-Note: this notification is deprecated and will be removed in
-.Fx 14.0 .
-.El
-.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li kernel Ta Li signal Ta Li coredump Ta
Notification that a process has crashed and dumped core.
@@ -491,7 +479,49 @@ Notification that a process has crashed and dumped core.
Notification that the system has woken from the suspended state.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "SMART_ERROR" -compact
+.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
+.It Li nvme Ta Li controller Ta Ta
+Controller events provide the controller name
+.Pq for example, Li nvme0
+in $name.
+.It Li nvme Ta Li controller Ta Li SMART_ERROR Ta
+A SMART Critical Warning State change has happened.
+$state has a hex bitmask of the bits that changed, as defined
+in the NVMe Standard for Critical Warning field of log page 2
+.Dq SMART / Health Information Log :
+.Pp
+.Bl -tag -width "Bit Value" -compact
+.It Sy "Bit Value"
+.Sy Meaning
+.It 0x1
+Spare capacity below threshold
+.It 0x2
+Temperature outside acceptable range
+.It 0x4
+Reliability of media degraded
+.It 0x8
+Media placed into read-only mode
+.It 0x10
+Volatime memory backup failure
+.It 0x20
+Persistent memory read-only or degraded
+.El
+.It Li nvme Ta Li controller Ta Li RESET Ta
+A controller reset event has happened.
+$event is one of
+.Dq start ,
+.Dq success ,
+and
+.Dq timed_out
+representing the start of a controller reset, the successful completion of a
+controller reset, or a timeout while waiting for the controller to reset,
+respectively.
+.It Li nvme Ta Li controller Ta Li RECONNECT Ta
+An NVMe over Fabrics host has disconnected and is requesting a reconnect.
+.El
+.Pp
+.Bl -column "SYSTEM" "SUBSYSTEM" "SHUTDOWN-THRESHOLD" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li PMU Ta Ta Ta
Notification of events from various types of Power Management Units.
@@ -504,25 +534,25 @@ Power has been applied to the AC power line.
.It Li PMU Ta Li "AC" Ta Li unplugged Ta
Power has been removed from the AC power line.
.It Li PMU Ta Li Battery Ta Ta
-.It Li PMU Ta Li Battery Ta absent Ta
+.It Li PMU Ta Li Battery Ta Li absent Ta
Battery is no longer absent.
-.It Li PMU Ta Li Battery Ta charged Ta
+.It Li PMU Ta Li Battery Ta Li charged Ta
The battery has become charged.
-.It Li PMU Ta Li Battery Ta charging Ta
+.It Li PMU Ta Li Battery Ta Li charging Ta
The battery has started charging.
-.It Li PMU Ta Li Battery Ta disconnected Ta
+.It Li PMU Ta Li Battery Ta Li disconnected Ta
The battery has been disconnected.
-.It Li PMU Ta Li Battery Ta high-temp Ta
+.It Li PMU Ta Li Battery Ta Li high-temp Ta
The battery reported a temperature over the limit.
-.It Li PMU Ta Li Battery Ta low-temp Ta
+.It Li PMU Ta Li Battery Ta Li low-temp Ta
The battery reported a temperature under the limit.
-.It Li PMU Ta Li Battery Ta plugged Ta
+.It Li PMU Ta Li Battery Ta Li plugged Ta
The battery has become plugged (eg connected).
-.It Li PMU Ta Li Battery Ta shutdown-threshold Ta
+.It Li PMU Ta Li Battery Ta Li shutdown-threshold Ta
The power in the battery has fallen below the shutdown threshold.
-.It Li PMU Ta Li Battery Ta warning-threshold Ta
+.It Li PMU Ta Li Battery Ta Li warning-threshold Ta
The power in the battery has fallen below the warn the user threshold.
-.It Li PMU Ta Li Button Ta pressed Ta
+.It Li PMU Ta Li Button Ta Li pressed Ta
A button on a
.Xr adb 4
or
@@ -532,39 +562,39 @@ has been pressed.
One of the keys on the
.Xr adb 4
keyboard has been pressed.
-.It Li PMU Ta Li keys Ta brightness Ta
+.It Li PMU Ta Li keys Ta Li brightness Ta
A brightness level change has been requested.
Direction is in the $notify variable.
-.It Li PMU Ta Li keys Ta mute Ta
+.It Li PMU Ta Li keys Ta Li mute Ta
The mute key
-.It Li PMU Ta Li keys Ta volume Ta
+.It Li PMU Ta Li keys Ta Li volume Ta
A volume level change has been requested.
Direction is in the $notify variable.
-.It Li PMU Ta Li keys Ta eject Ta
+.It Li PMU Ta Li keys Ta Li eject Ta
An ejection has been requested.
-.It Li PMU Ta Li lid Ta close Ta
+.It Li PMU Ta Li lid Ta Li close Ta
The
.Xr pmc 4
device has detected the lid closing.
-.It Li PMU Ta Li lid Ta open Ta
+.It Li PMU Ta Li lid Ta Li open Ta
The
.Xr pmc 4
device has detected the lid openinging.
-.It Li PMU Ta Li POWER Ta ACLINE Ta
+.It Li PMU Ta Li POWER Ta Li ACLINE Ta
The
.Xr pmc 4
-device has deteted an AC line state ($notify=0x00 is offline, 0x01 is online).
-.It Li PMU Ta Li USB Ta overvoltage Ta
+device has detected an AC line state ($notify=0x00 is offline, 0x01 is online).
+.It Li PMU Ta Li USB Ta Li overvoltage Ta
An over-voltage condition on the power lines for the USB power pins.
-.It Li PMU Ta Li USB Ta plugged Ta
+.It Li PMU Ta Li USB Ta Li plugged Ta
A device has been plugged into a USB device.
-.It Li PMU Ta Li USB Ta undervoltage Ta
+.It Li PMU Ta Li USB Ta Li undervoltage Ta
An under-voltage condition on the power lines for the USB power pins.
-.It Li PMU Ta Li USB Ta unplugged Ta
-A device has been unplugged into a USB device.
+.It Li PMU Ta Li USB Ta Li unplugged Ta
+A device has been unplugged from a USB device.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li RCTL Ta Ta Ta
Events related to the
@@ -574,7 +604,7 @@ framework.
A rule with action specified as "devctl" was triggered.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li USB Ta Ta Ta
Events related to the USB subsystem.
@@ -588,7 +618,7 @@ USB interface is attached to a device.
USB interface is detached from a device.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
.It Li VFS Ta Ta Ta
Events from the vfs system.
@@ -602,18 +632,18 @@ Notification of a filesystem is remounted (whether or not the options actually c
Notification of a filesystem being unmounted.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
-.It Li VT Ta BELL Ta RING Ta
+.It Li VT Ta Li BELL Ta Li RING Ta
Notification that the console bell has rung.
See
.Xr vt 4
for details.
.El
.Pp
-.Bl -column "System" "Subsystem" "1234567" -compact
+.Bl -column "SYSTEM" "SUBSYSTEM" "12345678" -compact
.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
-.It Li ZFS Ta ZFS Ta Ta
+.It Li ZFS Ta Li ZFS Ta Ta
Events about the ZFS subsystem.
See
.Xr zfsd 8
@@ -622,6 +652,22 @@ and
for details.
.El
.Pp
+.Bl -column "System" "Subsystem" "1234567" -compact
+.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description"
+.It Li SND Ta Ta Ta
+Events related to the
+.Xr sound 4
+driver.
+.It Li SND Ta Li CONN Ta Li IN Ta
+Connected input device specified in
+.Pa cdev
+variable.
+.It Li SND Ta Li CONN Ta Li OUT Ta
+Connected output device specified in
+.Pa cdev
+variable.
+.El
+.Pp
.\"
.\" End of tables
.\"
@@ -678,6 +724,26 @@ For example:
// part of the previous comment.
.Ed
.Ss Notes on Variable Expansion
+Variables are expanded by preceding them by a
+.Dq $
+sign.
+Any text immediately following that sign, starting with a letter, a minus sign
+.Dq - ,
+an underscore
+.Dq _ ,
+or an asterisk
+.Dq *
+is considered an internal variable, and expanded accordingly.
+If that variable does not exist, it silently expands to an empty string.
+Consequently, if the intention is to pass a
+.Xr sh 1
+variable, it must be surrounded by braces to prevent it from being
+considered an internal variable.
+.Pp
+See
+.Sx EXAMPLES
+for a detailed example.
+.Pp
To prevent issues with special shell characters, the following happens for each
variable
.Ic $foo .
@@ -695,6 +761,10 @@ The value of the
.Ic foo
variable is inserted into the buffer with all single quote characters
prefixed by a backslash.
+.It
+A final
+.Dq '
+is inserted.
.El
.Pp
See
@@ -736,6 +806,14 @@ regardless of the value of the variable.
The
.Xr devd 8
configuration file.
+.It Pa /etc/devd
+A directory that
+.Nm devd
+searches for additional configuration files.
+.It Pa /usr/local/etc/devd
+A directory that
+.Nm devd
+searches for additional configuration files.
.El
.Sh EXAMPLES
.Bd -literal
@@ -798,6 +876,37 @@ detach 0 {
};
.Ed
.Pp
+The following example illustrates the difference betwen internal and shell variables:
+.Bd -literal
+attach 20 {
+ device-name "umodem[0-9]+";
+ match "vendor" "0x2047";
+ match "product" "0x001(0|3|4)";
+ match "interface" "0";
+ action "cd /dev; p=$product; dn=$device-name; \\
+ un=$(sysctl -n dev.umodem.${dn#umodem}.ttyname); \\
+ chmod 666 cua${un}; ln -sf cua${un} mspfet${p#0x}";
+};
+.Ed
+.Pp
+.Dq product ,
+and
+.Dq device-name
+are internal variables.
+Their contents are initially assigned to shell variables
+.Dq p ,
+and
+.Dq dn ,
+respectively.
+Then, variable
+.Dq dn
+is used inside a shell command substitution, assigning to shell variable
+.Dq un .
+Finally, this shell variable is used in two other shell statements, where
+it needs to be wrapped in braces in order to prevent it from being
+considered in internal variable to
+.Nm devd .
+.Pp
The installed
.Pa /etc/devd.conf
has many additional examples.
diff --git a/sbin/devd/devd.h b/sbin/devd/devd.h
index a291e8141298..6d6495c915de 100644
--- a/sbin/devd/devd.h
+++ b/sbin/devd/devd.h
@@ -1,7 +1,7 @@
/*-
* DEVD (Device action daemon)
*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 M. Warner Losh <imp@FreeBSD.org>
*
@@ -25,8 +25,6 @@
* 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 DEVD_H
diff --git a/sbin/devd/devd.hh b/sbin/devd/devd.hh
index 62511d8ec3a5..5ab7a190c0e5 100644
--- a/sbin/devd/devd.hh
+++ b/sbin/devd/devd.hh
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002-2003 M. Warner Losh <imp@FreeBSD.org>
*
@@ -23,8 +23,6 @@
* 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 DEVD_HH
diff --git a/sbin/devd/devmatch.conf b/sbin/devd/devmatch.conf
index 902c96f33664..a7c27857c0bd 100644
--- a/sbin/devd/devmatch.conf
+++ b/sbin/devd/devmatch.conf
@@ -1,15 +1,32 @@
+# Implement the run-time component of devmatch by reacting to nomatch events.
+
#
-# $FreeBSD$
+# Ignore those devices that can't possibly match. When there's neither a
+# location, nor a pnpinfo string, we know that there's nothing devmatch can
+# match on. When it's only a location, it'd debateable, but for nomatch
+# events, we can't disambiguate between the two reliably.
#
+nomatch 101 {
+ match "_" " +at +on .*";
+};
#
-# Example devd configuration file for automatically
-# loading what modules we can based on nomatch
-# events.
+# Ignore ACPI devices whose _HID is none. These cannot tell us what to load,
+# since 'none' is not a valid id. There's no need to call devvmatch for these either.
+#
+nomatch 101 {
+ match "_HID" "none";
+ match "bus" "acpi[0-9]+";
+};
+
#
# Generic NOMATCH event
+#
+# Note: It would be better to have some internal-to-devd action that will do
+# what devmatch does without re-parsing loader.hints for each invocation
+#
nomatch 100 {
- action "service devmatch quietstart '?'$_";
+ action "service devmatch quietstart $*";
};
# Add the following to devd.conf to prevent this from running:
diff --git a/sbin/devd/dhclient.conf b/sbin/devd/dhclient.conf
new file mode 100644
index 000000000000..e90558295e1a
--- /dev/null
+++ b/sbin/devd/dhclient.conf
@@ -0,0 +1,19 @@
+#
+# Try to start dhclient on Ethernet-like interfaces when the link comes
+# up. Only devices that are configured to support DHCP will actually
+# run it. No link down rule exists because dhclient automatically exits
+# when the link goes down.
+#
+notify 0 {
+ match "system" "IFNET";
+ match "type" "LINK_UP";
+ media-type "ethernet";
+ action "service dhclient quietstart $subsystem";
+};
+
+notify 0 {
+ match "system" "IFNET";
+ match "type" "LINK_UP";
+ media-type "802.11";
+ action "service dhclient quietstart $subsystem";
+};
diff --git a/sbin/devd/hyperv.conf b/sbin/devd/hyperv.conf
index 7c3e92ed099f..70108ac36e54 100644
--- a/sbin/devd/hyperv.conf
+++ b/sbin/devd/hyperv.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# Hyper-V specific events
@@ -104,5 +103,6 @@ notify 10 {
notify 10 {
match "system" "ETHERNET";
match "type" "IFATTACH";
+ match "vm_guest" "hv";
action "/usr/libexec/hyperv/hyperv_vfattach $subsystem 0";
};
diff --git a/sbin/devd/moused.conf b/sbin/devd/moused.conf
new file mode 100644
index 000000000000..8821c2bb8375
--- /dev/null
+++ b/sbin/devd/moused.conf
@@ -0,0 +1,44 @@
+notify 100 {
+ match "system" "DEVFS";
+ match "subsystem" "CDEV";
+ match "type" "CREATE";
+ match "cdev" "atp[0-9]+";
+
+ action "service moused quietstart $cdev";
+};
+
+notify 100 {
+ match "system" "DEVFS";
+ match "subsystem" "CDEV";
+ match "type" "CREATE";
+ match "cdev" "ums[0-9]+";
+
+ action "service moused quietstart $cdev";
+};
+
+notify 100 {
+ match "system" "DEVFS";
+ match "subsystem" "CDEV";
+ match "type" "CREATE";
+ match "cdev" "wsp[0-9]+";
+
+ action "service moused quietstart $cdev";
+};
+
+notify 100 {
+ match "system" "DEVFS";
+ match "subsystem" "CDEV";
+ match "type" "DESTROY";
+ match "cdev" "ums[0-9]+";
+
+ action "service moused quietstop $cdev";
+};
+
+notify 100 {
+ match "system" "DEVFS";
+ match "subsystem" "CDEV";
+ match "type" "CREATE";
+ match "cdev" "input/event[0-9]+";
+
+ action "service moused quietstart $cdev";
+};
diff --git a/sbin/devd/nvmf.conf b/sbin/devd/nvmf.conf
new file mode 100644
index 000000000000..eaf3ebe86cec
--- /dev/null
+++ b/sbin/devd/nvmf.conf
@@ -0,0 +1,7 @@
+# Attempt to reconnect NVMeoF host devices when requested
+notify 100 {
+ match "system" "nvme";
+ match "subsystem" "controller";
+ match "type" "RECONNECT";
+ action "nvmecontrol reconnect $name";
+};
diff --git a/sbin/devd/parse.y b/sbin/devd/parse.y
index 9b8fd592045a..1aa3c20b6b68 100644
--- a/sbin/devd/parse.y
+++ b/sbin/devd/parse.y
@@ -2,7 +2,7 @@
/*-
* DEVD (Device action daemon)
*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 M. Warner Losh <imp@FreeBSD.org>
*
@@ -26,8 +26,6 @@
* 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/cdefs.h>
diff --git a/sbin/devd/power_profile.conf b/sbin/devd/power_profile.conf
new file mode 100644
index 000000000000..294856071f00
--- /dev/null
+++ b/sbin/devd/power_profile.conf
@@ -0,0 +1,6 @@
+# Switch power profiles when the AC line state changes.
+notify 10 {
+ match "system" "ACPI";
+ match "subsystem" "ACAD";
+ action "service power_profile $notify";
+};
diff --git a/sbin/devd/snd.conf b/sbin/devd/snd.conf
new file mode 100644
index 000000000000..a45f427f6c79
--- /dev/null
+++ b/sbin/devd/snd.conf
@@ -0,0 +1,26 @@
+# Audio redirection
+notify 0 {
+ match "system" "SND";
+ match "subsystem" "CONN";
+ match "type" "IN";
+ match "cdev" "dsp[0-9]+";
+
+ # Other audio servers or device switching commands can be used here
+ # instead of virtual_oss(8).
+ #
+ # FIXME: We are hardcoding /dev/vdsp.ctl here, simply because it is a
+ # common virtual_oss control device name. Until we find a proper way to
+ # define control devices here, /dev/vdsp.ctl can be changed to the
+ # control device of choice.
+ action "/usr/sbin/virtual_oss_cmd /dev/vdsp.ctl -R /dev/$cdev";
+};
+
+notify 0 {
+ match "system" "SND";
+ match "subsystem" "CONN";
+ match "type" "OUT";
+ match "cdev" "dsp[0-9]+";
+
+ # See comment above.
+ action "/usr/sbin/virtual_oss_cmd /dev/vdsp.ctl -P /dev/$cdev";
+};
diff --git a/sbin/devd/syscons.conf b/sbin/devd/syscons.conf
new file mode 100644
index 000000000000..cd0c744955b9
--- /dev/null
+++ b/sbin/devd/syscons.conf
@@ -0,0 +1,9 @@
+# When a USB keyboard arrives, attach it as the console keyboard.
+attach 100 {
+ device-name "ukbd0";
+ action "service syscons setkeyboard /dev/ukbd0";
+};
+detach 100 {
+ device-name "ukbd0";
+ action "service syscons setkeyboard /dev/kbd0";
+};
diff --git a/sbin/devd/tests/Makefile b/sbin/devd/tests/Makefile
index c0a346f94d33..fba7176d5ae1 100644
--- a/sbin/devd/tests/Makefile
+++ b/sbin/devd/tests/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
ATF_TESTS_C= client_test
TEST_METADATA.client_test= required_files="/var/run/devd.pid"
TEST_METADATA.client_test+= required_programs="devd"
diff --git a/sbin/devd/tests/Makefile.depend b/sbin/devd/tests/Makefile.depend
index c062f6026d94..1af0c88e099c 100644
--- a/sbin/devd/tests/Makefile.depend
+++ b/sbin/devd/tests/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/devd/tests/client_test.c b/sbin/devd/tests/client_test.c
index 90081d963f4b..fdac3c98b3c6 100644
--- a/sbin/devd/tests/client_test.c
+++ b/sbin/devd/tests/client_test.c
@@ -22,17 +22,14 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdbool.h>
-#include <stdio.h>
-
#include <sys/param.h>
-#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
#include <atf-c.h>
const char create_pat[] = "!system=DEVFS subsystem=CDEV type=CREATE cdev=md";
@@ -136,29 +133,37 @@ ATF_TC_BODY(seqpacket, tc)
ATF_TC_WITHOUT_HEAD(stream);
ATF_TC_BODY(stream, tc)
{
+ char *event;
int s;
bool got_create_event = false;
bool got_destroy_event = false;
- ssize_t len = 0;
+ size_t len = 0, sz;
s = common_setup(SOCK_STREAM, "/var/run/devd.pipe");
+
+ /*
+ * Use a large buffer: we're reading from a stream socket so can't rely
+ * on record boundaries. Instead, we just keep appending to the buffer.
+ */
+ sz = 1024 * 1024;
+ event = malloc(sz);
+ ATF_REQUIRE(event != NULL);
+
/*
* Loop until both events are detected on the same or different reads.
* There may be extra events due to unrelated system activity.
* If we never get both events, then the test will timeout.
*/
- while (!(got_create_event && got_destroy_event)) {
- char event[1024];
+ while (!(got_create_event && got_destroy_event) && len < sz - 1) {
ssize_t newlen;
char *create_pos, *destroy_pos;
/* Read 1 less than sizeof(event) to allow space for NULL */
- newlen = read(s, &event[len], sizeof(event) - len - 1);
- ATF_REQUIRE(newlen != -1);
+ newlen = read(s, &event[len], sz - len - 1);
+ ATF_REQUIRE(newlen > 0);
len += newlen;
/* NULL terminate the result */
event[len] = '\0';
- printf("%s", event);
create_pos = strstr(event, create_pat);
if (create_pos != NULL)
@@ -168,7 +173,11 @@ ATF_TC_BODY(stream, tc)
if (destroy_pos != NULL)
got_destroy_event = true;
}
+ printf("%s", event);
+ if (len >= sz - 1)
+ atf_tc_fail("Event buffer overflowed");
+ free(event);
close(s);
}
diff --git a/sbin/devd/token.l b/sbin/devd/token.l
index 30e48e815fe3..f60ee40dedb2 100644
--- a/sbin/devd/token.l
+++ b/sbin/devd/token.l
@@ -2,7 +2,7 @@
/*-
* DEVD (Device action daemon)
*
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 M. Warner Losh <imp@FreeBSD.org>
*
@@ -26,8 +26,6 @@
* 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 <ctype.h>
diff --git a/sbin/devd/uath.conf b/sbin/devd/uath.conf
index 9f0cb939050b..13b50d44c739 100644
--- a/sbin/devd/uath.conf
+++ b/sbin/devd/uath.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# Atheros USB wireless network device specific devd events
diff --git a/sbin/devd/ulpt.conf b/sbin/devd/ulpt.conf
index 2082726cbf47..f38398574a09 100644
--- a/sbin/devd/ulpt.conf
+++ b/sbin/devd/ulpt.conf
@@ -1,5 +1,4 @@
#
-# $FreeBSD$
#
#
diff --git a/sbin/devd/zfs.conf b/sbin/devd/zfs.conf
index ef6a6c12b6a1..56e1e2b21acd 100644
--- a/sbin/devd/zfs.conf
+++ b/sbin/devd/zfs.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# Sample ZFS problem reports handling.
diff --git a/sbin/devfs/Makefile b/sbin/devfs/Makefile
index cf1fa812d3d6..0a20cee8241c 100644
--- a/sbin/devfs/Makefile
+++ b/sbin/devfs/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
CONFS= devfs.conf devfs.rules
CONFSDIR_devfs.rules= /etc/defaults
CONFSMODE_devfs.rules= 600
diff --git a/sbin/devfs/Makefile.depend b/sbin/devfs/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/devfs/Makefile.depend
+++ b/sbin/devfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/devfs/devfs.8 b/sbin/devfs/devfs.8
index 4a9c42b7ebc5..bbe4825b8bb2 100644
--- a/sbin/devfs/devfs.8
+++ b/sbin/devfs/devfs.8
@@ -23,9 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd December 1, 2020
+.Dd October 18, 2023
.Dt DEVFS 8
.Os
.Sh NAME
@@ -40,7 +38,7 @@
The
.Nm
utility provides an interface to manipulate properties of
-.Xr devfs 5
+.Xr devfs 4
mounts.
.Pp
The rules, by default as configured by
@@ -66,7 +64,7 @@ The following flags are common to all keywords:
Operate on
.Ar mount-point ,
which is expected to be a
-.Xr devfs 5
+.Xr devfs 4
mount.
If this option is not specified,
.Nm
@@ -75,7 +73,7 @@ operates on
.El
.Ss Rule Subsystem
The
-.Xr devfs 5
+.Xr devfs 4
rule subsystem provides a way for the administrator of a system to control
the attributes of DEVFS nodes.
.\" XXX devfs node? entry? what?
@@ -250,7 +248,7 @@ will return the same information regardless of the mount-point specified with
The mount-point is only relevant when changing what its current ruleset is
or when using one of the apply commands.
.Sh FILES
-.Bl -tag -width "Pa /usr/share/examples/etc/devfs.conf" -compact
+.Bl -tag -width "Pa /etc/defaults/devfs.rules" -compact
.It Pa /etc/defaults/devfs.rules
Default
.Nm
@@ -266,10 +264,6 @@ with the same ruleset number, otherwise the two files are effectively merged.
Boot-time
.Nm
configuration file.
-.It Pa /usr/share/examples/etc/devfs.conf
-Example boot-time
-.Nm
-configuration file.
.El
.Sh EXAMPLES
When the system boots,
@@ -378,7 +372,7 @@ this feature can be used to copy rulesets:
.Xr chmod 1 ,
.Xr jail 2 ,
.Xr glob 3 ,
-.Xr devfs 5 ,
+.Xr devfs 4 ,
.Xr devfs.conf 5 ,
.Xr devfs.rules 5 ,
.Xr chown 8 ,
diff --git a/sbin/devfs/devfs.c b/sbin/devfs/devfs.c
index b5a6bf4015a2..ae8954e9d88b 100644
--- a/sbin/devfs/devfs.c
+++ b/sbin/devfs/devfs.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2001, 2002 Dima Dorfman.
* All rights reserved.
@@ -30,9 +30,6 @@
* DEVFS control.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/queue.h>
diff --git a/sbin/devfs/devfs.conf b/sbin/devfs/devfs.conf
index d3d60752c0b1..d3430a2fe844 100644
--- a/sbin/devfs/devfs.conf
+++ b/sbin/devfs/devfs.conf
@@ -22,7 +22,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
# These are examples of how to configure devices using /etc/rc.d/devfs.
# The first parameter is always the action to take, the second is always the
diff --git a/sbin/devfs/devfs.rules b/sbin/devfs/devfs.rules
index a92cd03a019b..c51672815e64 100644
--- a/sbin/devfs/devfs.rules
+++ b/sbin/devfs/devfs.rules
@@ -1,5 +1,5 @@
#
-# The following are some default rules for devfs(5) mounts.
+# The following are some default rules for devfs(4) mounts.
# The format is very simple. Empty lines and lines beginning
# with a hash '#' are ignored. If the hash mark occurs anywhere
# other than the beginning of a line, it and any subsequent
@@ -13,7 +13,6 @@
# references must include a dollar sign '$' in front of the
# name to be expanded properly.
#
-# $FreeBSD$
#
# Very basic and secure ruleset: Hide everything.
diff --git a/sbin/devfs/extern.h b/sbin/devfs/extern.h
index c02a7afba30e..952bdafd44ea 100644
--- a/sbin/devfs/extern.h
+++ b/sbin/devfs/extern.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Dima Dorfman.
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 __DEVFS_H__
diff --git a/sbin/devfs/rule.c b/sbin/devfs/rule.c
index 0bfc7ffaf3c8..d07104d1de13 100644
--- a/sbin/devfs/rule.c
+++ b/sbin/devfs/rule.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Dima Dorfman.
* All rights reserved.
@@ -30,9 +30,6 @@
* Rule subsystem manipulation.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/ioctl.h>
diff --git a/sbin/devmatch/Makefile b/sbin/devmatch/Makefile
index 6622bdb284d1..20da7231206f 100644
--- a/sbin/devmatch/Makefile
+++ b/sbin/devmatch/Makefile
@@ -1,5 +1,4 @@
-# $FreeBSD$
-
+PACKAGE= devmatch
PROG= devmatch
MAN= devmatch.8
diff --git a/sbin/devmatch/Makefile.depend b/sbin/devmatch/Makefile.depend
index fe15dd35be95..a4d91ccfc657 100644
--- a/sbin/devmatch/Makefile.depend
+++ b/sbin/devmatch/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/devmatch/devmatch.8 b/sbin/devmatch/devmatch.8
index 11cf844bef9f..71bd7365d645 100644
--- a/sbin/devmatch/devmatch.8
+++ b/sbin/devmatch/devmatch.8
@@ -21,9 +21,7 @@
.\" (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 November 21, 2021
+.Dd August 13, 2023
.Dt DEVMATCH 8
.Os
.Sh NAME
@@ -31,13 +29,13 @@
.Nd print information about unattached devices
.Sh SYNOPSIS
.Nm
-.Op Fl adhpuv
-.Op Fl -all
-.Op Fl -dump
-.Op Fl -hints Ar file
-.Op Fl -nomatch Ar event
-.Op Fl -unbound
-.Op Fl -verbose
+.Op Fl a | -all
+.Op Fl d | -dump
+.Op Oo Fl h | -hints Oc Ar file
+.Op Oo Fl p | -nomatch Oc Ar event
+.Op Fl q | -quiet
+.Op Fl u | -unbound
+.Op Fl v | -verbose
.Sh DESCRIPTION
The
.Nm
@@ -60,9 +58,13 @@ guessed from the current module load path.
Parse and use a standard NOMATCH event from
.Xr devd 8
for matching instead of searching the device tree.
+.It Fl q Fl -quiet
+Suppress some error messages and simply return a non-zero exit code.
+This is helpful to avoid an endless list of warnings during bootup if
+no hints are available.
.It Fl u Fl -unbound
Attempt to produce a list of those drivers with PNP info whose driver
-tables with that PNP info can not be found.
+tables with that PNP info cannot be found.
.It Fl v Fl -verbose
Produce more verbose output.
.El
@@ -91,10 +93,11 @@ and will be reported twice.
The PNP string's attributes are evaluated once per PNP entry on that
bus rather than once.
.Pp
-The term PNP is overloaded in FreeBSD.
+The term PNP is overloaded in
+.Fx .
It means, generically, the identifying data the bus provides about a
device.
-While this include old ISA PNP identifiers, it also includes the
+While this includes old ISA PNP identifiers, it also includes the
logical equivalent in USB, PCI, and others.
.Pp
Many drivers currently lack proper PNP table decorations and need to
diff --git a/sbin/devmatch/devmatch.c b/sbin/devmatch/devmatch.c
index 20a57353ecf6..4a5a300ca313 100644
--- a/sbin/devmatch/devmatch.c
+++ b/sbin/devmatch/devmatch.c
@@ -23,9 +23,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <ctype.h>
#include <devinfo.h>
@@ -33,9 +30,11 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
#include <unistd.h>
#include <sys/linker.h>
#include <sys/module.h>
@@ -48,6 +47,7 @@ static struct option longopts[] = {
{ "dump", no_argument, NULL, 'd' },
{ "hints", required_argument, NULL, 'h' },
{ "nomatch", required_argument, NULL, 'p' },
+ { "quiet", no_argument, NULL, 'q' },
{ "unbound", no_argument, NULL, 'u' },
{ "verbose", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
@@ -55,12 +55,13 @@ static struct option longopts[] = {
#define DEVMATCH_MAX_HITS 256
-static int all_flag;
-static int dump_flag;
+static bool all_flag;
+static bool dump_flag;
static char *linker_hints;
static char *nomatch_str;
-static int unbound_flag;
-static int verbose_flag;
+static bool quiet_flag;
+static bool unbound_flag;
+static bool verbose_flag;
static void *hints;
static void *hints_end;
@@ -114,14 +115,24 @@ read_linker_hints(void)
continue;
break;
}
- if (q == NULL)
- errx(1, "Can't read linker hints file.");
+ if (q == NULL) {
+ if (quiet_flag)
+ exit(EX_UNAVAILABLE);
+ else
+ errx(EX_UNAVAILABLE, "Can't read linker hints file.");
+ }
} else {
hints = read_hints(linker_hints, &len);
if (hints == NULL)
err(1, "Can't open %s for reading", fn);
}
+ if (len < sizeof(int)) {
+ warnx("Linker hints file too short.");
+ free(hints);
+ hints = NULL;
+ return;
+ }
if (*(int *)(intptr_t)hints != LINKER_HINTS_VERSION) {
warnx("Linker hints version %d doesn't match expected %d.",
*(int *)(intptr_t)hints, LINKER_HINTS_VERSION);
@@ -402,7 +413,7 @@ search_hints(const char *bus, const char *dev, const char *pnpinfo)
else if (!notme) {
if (!unbound_flag) {
if (all_flag)
- printf("%s: %s", *dev ? dev : "unattached", lastmod);
+ printf("%s: %s\n", *dev ? dev : "unattached", lastmod);
else
printf("%s\n", lastmod);
if (verbose_flag)
@@ -441,7 +452,7 @@ find_unmatched(struct devinfo_dev *dev, void *arg)
break;
if (!(dev->dd_flags & DF_ENABLED))
break;
- if (dev->dd_flags & DF_ATTACHED_ONCE)
+ if (!all_flag && dev->dd_flags & DF_ATTACHED_ONCE)
break;
parent = devinfo_handle_to_device(dev->dd_parent);
bus = strdup(parent->dd_name);
@@ -565,14 +576,14 @@ main(int argc, char **argv)
{
int ch;
- while ((ch = getopt_long(argc, argv, "adh:p:uv",
+ while ((ch = getopt_long(argc, argv, "adh:p:quv",
longopts, NULL)) != -1) {
switch (ch) {
case 'a':
- all_flag++;
+ all_flag = true;
break;
case 'd':
- dump_flag++;
+ dump_flag = true;
break;
case 'h':
linker_hints = optarg;
@@ -580,11 +591,14 @@ main(int argc, char **argv)
case 'p':
nomatch_str = optarg;
break;
+ case 'q':
+ quiet_flag = true;
+ break;
case 'u':
- unbound_flag++;
+ unbound_flag = true;
break;
case 'v':
- verbose_flag++;
+ verbose_flag = true;
break;
default:
usage();
diff --git a/sbin/dhclient/Makefile b/sbin/dhclient/Makefile
index cdf93b8b8145..27c81d9d9e6c 100644
--- a/sbin/dhclient/Makefile
+++ b/sbin/dhclient/Makefile
@@ -1,5 +1,4 @@
# $OpenBSD: Makefile,v 1.9 2004/05/04 12:52:05 henning Exp $
-# $FreeBSD$
#
# Copyright (c) 1996, 1997 The Internet Software Consortium.
# All rights reserved.
@@ -34,7 +33,7 @@
.include <src.opts.mk>
CONFS= dhclient.conf
-PACKAGE=runtime
+PACKAGE=dhclient
SRCS= dhclient.c clparse.c alloc.c dispatch.c hash.c bpf.c options.c \
tree.c conflex.c errwarn.c inet.c packet.c convert.c tables.c \
parse.c privsep.c
diff --git a/sbin/dhclient/Makefile.depend b/sbin/dhclient/Makefile.depend
index 7d9bf2cd046a..2326fec704fd 100644
--- a/sbin/dhclient/Makefile.depend
+++ b/sbin/dhclient/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
@@ -9,7 +8,6 @@ DIRDEPS = \
lib/libc \
lib/libcapsicum \
lib/libcompiler_rt \
- lib/libnv \
lib/libutil \
diff --git a/sbin/dhclient/Makefile.depend.options b/sbin/dhclient/Makefile.depend.options
index f61d5cffc555..ec521958a588 100644
--- a/sbin/dhclient/Makefile.depend.options
+++ b/sbin/dhclient/Makefile.depend.options
@@ -1,4 +1,3 @@
-# $FreeBSD$
# This file is not autogenerated - take care!
DIRDEPS_OPTIONS= CASPER
diff --git a/sbin/dhclient/alloc.c b/sbin/dhclient/alloc.c
index c3ea309a5456..1926f7924170 100644
--- a/sbin/dhclient/alloc.c
+++ b/sbin/dhclient/alloc.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
struct string_list *
diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c
index d938b68c7c94..d4bbe56332c8 100644
--- a/sbin/dhclient/bpf.c
+++ b/sbin/dhclient/bpf.c
@@ -44,8 +44,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
#include "privsep.h"
#include <sys/capsicum.h>
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c
index c7b02a073aa3..c883e2a0ddb5 100644
--- a/sbin/dhclient/clparse.c
+++ b/sbin/dhclient/clparse.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
#include "dhctoken.h"
@@ -186,6 +184,7 @@ read_client_leases(void)
* hardware-declaration |
* REQUEST option-list |
* REQUIRE option-list |
+ * IGNORE option-list |
* TIMEOUT number |
* RETRY number |
* REBOOT number |
@@ -249,6 +248,9 @@ parse_client_statement(FILE *cfile, struct interface_info *ip,
sizeof(config->required_options));
parse_option_list(cfile, config->required_options);
return;
+ case IGNORE:
+ parse_option_list(cfile, config->ignored_options);
+ return;
case TIMEOUT:
parse_lease_time(cfile, &config->timeout);
return;
diff --git a/sbin/dhclient/conflex.c b/sbin/dhclient/conflex.c
index c11c9189527e..377f7a1d440a 100644
--- a/sbin/dhclient/conflex.c
+++ b/sbin/dhclient/conflex.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <ctype.h>
#include "dhcpd.h"
@@ -413,6 +411,8 @@ intern(char *atom, int dfv)
return (HOSTNAME);
break;
case 'i':
+ if (!strcasecmp(atom + 1, "gnore"))
+ return (IGNORE);
if (!strcasecmp(atom + 1, "nitial-interval"))
return (INITIAL_INTERVAL);
if (!strcasecmp(atom + 1, "nterface"))
diff --git a/sbin/dhclient/convert.c b/sbin/dhclient/convert.c
index c30195254d4b..8401615b5bf0 100644
--- a/sbin/dhclient/convert.c
+++ b/sbin/dhclient/convert.c
@@ -46,8 +46,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
u_int32_t
diff --git a/sbin/dhclient/dhclient-script b/sbin/dhclient/dhclient-script
index 3439fd960773..27c424e18118 100755
--- a/sbin/dhclient/dhclient-script
+++ b/sbin/dhclient/dhclient-script
@@ -1,7 +1,6 @@
#!/bin/sh
#
# $OpenBSD: dhclient-script,v 1.6 2004/05/06 18:22:41 claudio Exp $
-# $FreeBSD$
#
# Copyright (c) 2003 Kenneth R Westerback <krw@openbsd.org>
#
@@ -173,6 +172,10 @@ add_new_routes() {
if [ "$new_ip_address" = "$router" ]; then
route add default -iface $router >/dev/null 2>&1
else
+ if [ "$new_subnet_mask" = "255.255.255.255" ]; then
+ route add "$router" -iface "$interface" >/dev/null 2>&1
+ fi
+
route add default $router >/dev/null 2>&1
fi
fi
@@ -314,13 +317,12 @@ fi
case $reason in
MEDIUM)
eval "$IFCONFIG $interface $medium"
- eval "$IFCONFIG $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
sleep 1
;;
PREINIT)
delete_old_alias
- $IFCONFIG $interface inet alias 0.0.0.0 netmask 255.0.0.0 broadcast 255.255.255.255 up
+ eval "$IFCONFIG $interface up"
;;
ARPCHECK|ARPSEND)
diff --git a/sbin/dhclient/dhclient-script.8 b/sbin/dhclient/dhclient-script.8
index 2fae9f67cbe5..dd3efd3e8698 100644
--- a/sbin/dhclient/dhclient-script.8
+++ b/sbin/dhclient/dhclient-script.8
@@ -36,8 +36,6 @@
.\" see ``http://www.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 6, 2010
.Dt DHCLIENT-SCRIPT 8
.Os
diff --git a/sbin/dhclient/dhclient.8 b/sbin/dhclient/dhclient.8
index 3ea35e8eb472..7f0b418128ca 100644
--- a/sbin/dhclient/dhclient.8
+++ b/sbin/dhclient/dhclient.8
@@ -36,9 +36,7 @@
.\" see ``http://www.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
-.\" $FreeBSD$
-.\"
-.Dd August 4, 2018
+.Dd August 1, 2024
.Dt DHCLIENT 8
.Os
.Sh NAME
@@ -84,6 +82,10 @@ will revert to running in the background.
Specify an alternate location,
.Ar file ,
for the leases file.
+.It Fl n
+Make
+.Nm
+not wait for ARP resolution.
.It Fl p Ar file
Specify an alternate location for the PID file.
The default is
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index a1628f0ee22f..5d2a7453578b 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -56,8 +56,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
#include "privsep.h"
@@ -92,7 +90,8 @@ __FBSDID("$FreeBSD$");
cap_channel_t *capsyslog;
-time_t cur_time;
+time_t cur_time; /* Seconds since epoch. */
+struct timespec time_now; /* CLOCK_MONOTONIC. */
static time_t default_lease_time = 43200; /* 12 hours... */
const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
@@ -122,6 +121,8 @@ struct pidfh *pidfile;
*/
#define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
+static struct timespec arp_timeout = { .tv_sec = 0, .tv_nsec = 250 * 1000 * 1000 };
+static const struct timespec zero_timespec = { .tv_sec = 0, .tv_nsec = 0 };
int log_priority;
static int no_daemon;
static int unknown_ok = 1;
@@ -385,7 +386,7 @@ main(int argc, char *argv[])
cap_openlog(capsyslog, getprogname(), LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
- while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
+ while ((ch = getopt(argc, argv, "bc:dl:np:qu")) != -1)
switch (ch) {
case 'b':
immediate_daemon = 1;
@@ -399,6 +400,9 @@ main(int argc, char *argv[])
case 'l':
path_dhclient_db = optarg;
break;
+ case 'n':
+ arp_timeout = zero_timespec;
+ break;
case 'p':
path_dhclient_pidfile = optarg;
break;
@@ -445,7 +449,8 @@ main(int argc, char *argv[])
log_perror = 0;
tzset();
- time(&cur_time);
+ clock_gettime(CLOCK_MONOTONIC, &time_now);
+ cur_time = time(NULL);
inaddr_broadcast.s_addr = INADDR_BROADCAST;
inaddr_any.s_addr = INADDR_ANY;
@@ -534,7 +539,7 @@ main(int argc, char *argv[])
setproctitle("%s", ifi->name);
/* setgroups(2) is not permitted in capability mode. */
- if (setgroups(1, &pw->pw_gid) != 0)
+ if (setgroups(0, NULL) != 0)
error("can't restrict groups: %m");
if (caph_enter_casper() < 0)
@@ -574,7 +579,7 @@ void
usage(void)
{
- fprintf(stderr, "usage: %s [-bdqu] ", getprogname());
+ fprintf(stderr, "usage: %s [-bdnqu] ", getprogname());
fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
exit(1);
}
@@ -798,7 +803,7 @@ dhcpack(struct packet *packet)
ACTION_SUPERSEDE)
ip->client->new->expiry = getULong(
ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
- else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
+ else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].len >= 4)
ip->client->new->expiry = getULong(
ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
else
@@ -821,7 +826,7 @@ dhcpack(struct packet *packet)
ACTION_SUPERSEDE)
ip->client->new->renewal = getULong(
ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
- else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
+ else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len >= 4)
ip->client->new->renewal = getULong(
ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
else
@@ -835,7 +840,7 @@ dhcpack(struct packet *packet)
ACTION_SUPERSEDE)
ip->client->new->rebind = getULong(
ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
- else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
+ else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len >= 4)
ip->client->new->rebind = getULong(
ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
else
@@ -1024,10 +1029,14 @@ dhcpoffer(struct packet *packet)
struct interface_info *ip = packet->interface;
struct client_lease *lease, *lp;
int i;
- int arp_timeout_needed, stop_selecting;
+ struct timespec arp_timeout_needed;
+ time_t stop_selecting;
+ struct timespec stop_time;
const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
"DHCPOFFER" : "BOOTREPLY";
+ clock_gettime(CLOCK_MONOTONIC, &time_now);
+
/* If we're not receptive to an offer right now, or if the offer
has an unrecognizable transaction id, then just drop it. */
if (ip->client->state != S_SELECTING ||
@@ -1039,7 +1048,6 @@ dhcpoffer(struct packet *packet)
note("%s from %s", name, piaddr(packet->client_addr));
-
/* If this lease doesn't supply the minimum required parameters,
blow it off. */
for (i = 0; ip->client->config->required_options[i]; i++) {
@@ -1081,9 +1089,10 @@ dhcpoffer(struct packet *packet)
/* If the script can't send an ARP request without waiting,
we'll be waiting when we do the ARPCHECK, so don't wait now. */
if (script_go())
- arp_timeout_needed = 0;
+ arp_timeout_needed = zero_timespec;
+
else
- arp_timeout_needed = 2;
+ arp_timeout_needed = arp_timeout;
/* Figure out when we're supposed to stop selecting. */
stop_selecting =
@@ -1102,9 +1111,13 @@ dhcpoffer(struct packet *packet)
offer would take us past the selection timeout,
then don't extend the timeout - just hope for the
best. */
+
+ struct timespec interm_struct;
+ timespecadd(&time_now, &arp_timeout_needed, &interm_struct);
+
if (ip->client->offered_leases &&
- (cur_time + arp_timeout_needed) > stop_selecting)
- arp_timeout_needed = 0;
+ interm_struct.tv_sec >= stop_selecting)
+ arp_timeout_needed = zero_timespec;
/* Put the lease at the end of the list. */
lease->next = NULL;
@@ -1118,21 +1131,21 @@ dhcpoffer(struct packet *packet)
}
}
- /* If we're supposed to stop selecting before we've had time
- to wait for the ARPREPLY, add some delay to wait for
- the ARPREPLY. */
- if (stop_selecting - cur_time < arp_timeout_needed)
- stop_selecting = cur_time + arp_timeout_needed;
-
- /* If the selecting interval has expired, go immediately to
- state_selecting(). Otherwise, time out into
- state_selecting at the select interval. */
- if (stop_selecting <= 0)
- state_selecting(ip);
- else {
- add_timeout(stop_selecting, state_selecting, ip);
- cancel_timeout(send_discover, ip);
+ /*
+ * Wait until stop_selecting seconds past the epoch, or until
+ * arp_timeout_needed past now, whichever is longer. Note that
+ * the first case only occurs if select-timeout is set to nonzero
+ * in dhclient.conf.
+ */
+ struct timespec time_left =
+ {.tv_sec = stop_selecting - cur_time, .tv_nsec = 0};
+ if (timespeccmp(&time_left, &arp_timeout_needed, <)) {
+ timespecadd(&time_now, &arp_timeout_needed, &stop_time);
+ } else {
+ timespecadd(&time_now, &time_left, &stop_time);
}
+ add_timeout_timespec(stop_time, state_selecting, ip);
+ cancel_timeout(send_discover, ip);
}
/* Allocate a client_lease structure and initialize it from the parameters
@@ -1141,8 +1154,9 @@ dhcpoffer(struct packet *packet)
struct client_lease *
packet_to_lease(struct packet *packet)
{
+ struct interface_info *ip = packet->interface;
struct client_lease *lease;
- int i;
+ int i, j;
lease = malloc(sizeof(struct client_lease));
@@ -1156,6 +1170,15 @@ packet_to_lease(struct packet *packet)
/* Copy the lease options. */
for (i = 0; i < 256; i++) {
if (packet->options[i].len) {
+ int ignored = 0;
+ for (j = 0; ip->client->config->ignored_options[j]; j++)
+ if (i ==
+ ip->client->config->ignored_options[j]) {
+ ignored = 1;
+ break;
+ }
+ if (ignored)
+ continue;
lease->options[i].data =
malloc(packet->options[i].len + 1);
if (!lease->options[i].data) {
@@ -2611,6 +2634,9 @@ check_option(struct client_lease *l, int option)
case DHO_BOOTFILE_NAME:
case DHO_DHCP_USER_CLASS_ID:
case DHO_URL:
+ case DHO_SIP_SERVERS:
+ case DHO_V_I_VENDOR_CLASS:
+ case DHO_V_I_VENDOR_OPTS:
case DHO_END:
return (1);
case DHO_CLASSLESS_ROUTES:
diff --git a/sbin/dhclient/dhclient.conf b/sbin/dhclient/dhclient.conf
index a7639d904aad..4979cd470d5e 100644
--- a/sbin/dhclient/dhclient.conf
+++ b/sbin/dhclient/dhclient.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# This file is required by the ISC DHCP client.
# See ``man 5 dhclient.conf'' for details.
diff --git a/sbin/dhclient/dhclient.conf.5 b/sbin/dhclient/dhclient.conf.5
index 14a0de4111dd..b2190a8e076b 100644
--- a/sbin/dhclient/dhclient.conf.5
+++ b/sbin/dhclient/dhclient.conf.5
@@ -36,9 +36,7 @@
.\" see ``http://www.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
-.\" $FreeBSD$
-.\"
-.Dd July 21, 2021
+.Dd March 17, 2023
.Dt DHCLIENT.CONF 5
.Os
.Sh NAME
@@ -200,6 +198,11 @@ option other than the default requested lease time, which is two hours.
The other obvious use for this statement is to send information to the server
that will allow it to differentiate between this client and other
clients or kinds of clients.
+.It Ic ignore Oo Ar option Oc Oo , Ar ... option Oc ;
+The
+.Ic ignore
+statement causes the client to disregard the specified options in any offer
+received, as though the server had never sent them at all.
.El
.Sh OPTION MODIFIERS
In some cases, a client may receive option data from the server which
diff --git a/sbin/dhclient/dhclient.leases.5 b/sbin/dhclient/dhclient.leases.5
index 38c8edb969c5..5aca3f10d6ae 100644
--- a/sbin/dhclient/dhclient.leases.5
+++ b/sbin/dhclient/dhclient.leases.5
@@ -36,8 +36,6 @@
.\" see ``http://www.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
-.\" $FreeBSD$
-.\"
.Dd January 1, 1997
.Dt DHCLIENT.LEASES 5
.Os
diff --git a/sbin/dhclient/dhcp-options.5 b/sbin/dhclient/dhcp-options.5
index 29b2e7234422..24604514a016 100644
--- a/sbin/dhclient/dhcp-options.5
+++ b/sbin/dhclient/dhcp-options.5
@@ -36,8 +36,6 @@
.\" see ``http://www.isc.org/isc''. To learn more about Vixie
.\" Enterprises, see ``http://www.vix.com''.
.\"
-.\" $FreeBSD$
-.\"
.Dd January 1, 1995
.Dt DHCP-OPTIONS 5
.Os
diff --git a/sbin/dhclient/dhcp.h b/sbin/dhclient/dhcp.h
index 9183a9c82aec..02ea42a66079 100644
--- a/sbin/dhclient/dhcp.h
+++ b/sbin/dhclient/dhcp.h
@@ -1,5 +1,4 @@
/* $OpenBSD: dhcp.h,v 1.5 2004/05/04 15:49:49 deraadt Exp $ */
-/* $FreeBSD$ */
/* Protocol structures... */
@@ -173,7 +172,10 @@ struct dhcp_packet {
#define DHO_DHCP_USER_CLASS_ID 77
#define DHO_URL 114
#define DHO_DOMAIN_SEARCH 119
+#define DHO_SIP_SERVERS 120
#define DHO_CLASSLESS_ROUTES 121
+#define DHO_V_I_VENDOR_CLASS 124
+#define DHO_V_I_VENDOR_OPTS 125
#define DHO_END 255
/* DHCP message types. */
diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h
index b151daa90a1c..c61564067598 100644
--- a/sbin/dhclient/dhcpd.h
+++ b/sbin/dhclient/dhcpd.h
@@ -39,8 +39,6 @@
* Enterprises. To learn more about the Internet Software Consortium,
* see ``http://www.vix.com/isc''. To learn more about Vixie
* Enterprises, see ``http://www.vix.com''.
- *
- * $FreeBSD$
*/
#include <sys/param.h>
@@ -159,6 +157,7 @@ struct client_config {
u_int8_t required_options[256];
u_int8_t requested_options[256];
int requested_option_count;
+ u_int8_t ignored_options[256];
u_int vlan_pcp;
time_t timeout;
time_t initial_interval;
@@ -200,7 +199,6 @@ struct client_state {
struct interface_info {
struct interface_info *next;
struct hardware hw_address;
- struct in_addr primary_address;
char name[IFNAMSIZ];
int rfdesc;
int wfdesc;
@@ -220,7 +218,7 @@ struct interface_info {
struct timeout {
struct timeout *next;
- time_t when;
+ struct timespec when;
void (*func)(void *);
void *what;
};
@@ -322,6 +320,7 @@ void reinitialize_interfaces(void);
void dispatch(void);
void got_one(struct protocol *);
void add_timeout(time_t, void (*)(void *), void *);
+void add_timeout_timespec(struct timespec, void (*)(void *), void *);
void cancel_timeout(void (*)(void *), void *);
void add_protocol(const char *, int, void (*)(struct protocol *), void *);
void remove_protocol(struct protocol *);
@@ -362,7 +361,8 @@ char *piaddr(struct iaddr);
extern cap_channel_t *capsyslog;
extern const char *path_dhclient_conf;
extern char *path_dhclient_db;
-extern time_t cur_time;
+extern struct timespec time_now; /* CLOCK_MONOTONIC */
+extern time_t cur_time; /* Seconds since epoch */
extern int log_priority;
extern int log_perror;
diff --git a/sbin/dhclient/dhctoken.h b/sbin/dhclient/dhctoken.h
index c929307c7e06..20ea515a49ae 100644
--- a/sbin/dhclient/dhctoken.h
+++ b/sbin/dhclient/dhctoken.h
@@ -40,8 +40,6 @@
* Enterprises. To learn more about the Internet Software Consortium,
* see ``http://www.vix.com/isc''. To learn more about Vixie
* Enterprises, see ``http://www.vix.com''.
- *
- * $FreeBSD$
*/
#define SEMI ';'
@@ -134,6 +132,7 @@
#define TOKEN_NOT 334
#define ALWAYS_REPLY_RFC1048 335
#define VLAN_PCP 336
+#define IGNORE 337
#define is_identifier(x) ((x) >= FIRST_TOKEN && \
(x) != STRING && \
diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c
index 91f1694ec902..06bd31e5ec82 100644
--- a/sbin/dhclient/dispatch.c
+++ b/sbin/dhclient/dispatch.c
@@ -42,8 +42,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
#include "privsep.h"
@@ -58,6 +56,10 @@ __FBSDID("$FreeBSD$");
#define assert_aligned(p, align) assert((((uintptr_t)p) & ((align) - 1)) == 0)
static struct protocol *protocols;
+static const struct timespec timespec_intmax_ms = {
+ .tv_sec = INT_MAX / 1000,
+ .tv_nsec = (INT_MAX % 1000) * 1000000
+};
static struct timeout *timeouts;
static struct timeout *free_timeouts;
static int interfaces_invalidated;
@@ -118,26 +120,14 @@ discover_interfaces(struct interface_info *iface)
iface->hw_address.htype = HTYPE_ETHER; /* XXX */
memcpy(iface->hw_address.haddr,
LLADDR(foo), foo->sdl_alen);
- } else if (ifa->ifa_addr->sa_family == AF_INET) {
- struct sockaddr_in foo;
- struct iaddr addr;
-
- memcpy(&foo, ifa->ifa_addr, sizeof(foo));
- if (foo.sin_addr.s_addr == htonl(INADDR_LOOPBACK))
- continue;
- if (!iface->ifp) {
- if ((tif = calloc(1, sizeof(struct ifreq)))
- == NULL)
- error("no space to remember ifp");
- strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
- memcpy(&tif->ifr_addr, ifa->ifa_addr,
- ifa->ifa_addr->sa_len);
- iface->ifp = tif;
- iface->primary_address = foo.sin_addr;
- }
- addr.len = 4;
- memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len);
}
+ if (!iface->ifp) {
+ if ((tif = calloc(1, sizeof(struct ifreq))) == NULL)
+ error("no space to remember ifp");
+ strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
+ iface->ifp = tif;
+ }
+
}
if (!iface->ifp)
@@ -168,7 +158,9 @@ dispatch(void)
int count, live_interfaces, i, to_msec, nfds = 0;
struct protocol *l;
struct pollfd *fds;
- time_t howlong;
+ struct timespec howlong;
+
+ clock_gettime(CLOCK_MONOTONIC, &time_now);
for (l = protocols; l; l = l->next)
nfds++;
@@ -186,7 +178,7 @@ another:
if (timeouts) {
struct timeout *t;
- if (timeouts->when <= cur_time) {
+ if (timespeccmp(&timeouts->when, &time_now, <=)) {
t = timeouts;
timeouts = timeouts->next;
(*(t->func))(t->what);
@@ -201,10 +193,10 @@ another:
* int for poll, while not polling with a
* negative timeout and blocking indefinitely.
*/
- howlong = timeouts->when - cur_time;
- if (howlong > INT_MAX / 1000)
- howlong = INT_MAX / 1000;
- to_msec = howlong * 1000;
+ timespecsub(&timeouts->when, &time_now, &howlong);
+ if (timespeccmp(&howlong, &timespec_intmax_ms, >))
+ howlong = timespec_intmax_ms;
+ to_msec = howlong.tv_sec * 1000 + howlong.tv_nsec / 1000000;
} else
to_msec = -1;
@@ -231,14 +223,16 @@ another:
/* Not likely to be transitory... */
if (count == -1) {
if (errno == EAGAIN || errno == EINTR) {
- time(&cur_time);
+ clock_gettime(CLOCK_MONOTONIC, &time_now);
+ cur_time = time(NULL);
continue;
} else
error("poll: %m");
}
/* Get the current time... */
- time(&cur_time);
+ clock_gettime(CLOCK_MONOTONIC, &time_now);
+ cur_time = time(NULL);
i = 0;
for (l = protocols; l; l = l->next) {
@@ -369,7 +363,18 @@ active:
}
void
-add_timeout(time_t when, void (*where)(void *), void *what)
+add_timeout(time_t when_s, void (*where)(void *), void *what)
+{
+ struct timespec when;
+
+ cur_time = time(NULL);
+ clock_gettime(CLOCK_MONOTONIC, &when);
+ when.tv_sec += when_s - cur_time;
+ add_timeout_timespec(when, where, what);
+}
+
+void
+add_timeout_timespec(struct timespec when, void (*where)(void *), void *what)
{
struct timeout *t, *q;
@@ -408,7 +413,7 @@ add_timeout(time_t when, void (*where)(void *), void *what)
/* Now sort this timeout into the timeout list. */
/* Beginning of list? */
- if (!timeouts || timeouts->when > q->when) {
+ if (!timeouts || timespeccmp(&timeouts->when, &q->when, >)) {
q->next = timeouts;
timeouts = q;
return;
@@ -416,7 +421,7 @@ add_timeout(time_t when, void (*where)(void *), void *what)
/* Middle of list? */
for (t = timeouts; t->next; t = t->next) {
- if (t->next->when > q->when) {
+ if (timespeccmp(&t->next->when, &q->when, >)) {
q->next = t->next;
t->next = q;
return;
diff --git a/sbin/dhclient/errwarn.c b/sbin/dhclient/errwarn.c
index 824faafd75a3..c073d5997056 100644
--- a/sbin/dhclient/errwarn.c
+++ b/sbin/dhclient/errwarn.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <errno.h>
#include "dhcpd.h"
diff --git a/sbin/dhclient/hash.c b/sbin/dhclient/hash.c
index 5d797cc96964..b2d72a5a299a 100644
--- a/sbin/dhclient/hash.c
+++ b/sbin/dhclient/hash.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
static int do_hash(const unsigned char *, int, int);
diff --git a/sbin/dhclient/inet.c b/sbin/dhclient/inet.c
index c72a7f6b702e..1684994129b8 100644
--- a/sbin/dhclient/inet.c
+++ b/sbin/dhclient/inet.c
@@ -45,8 +45,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
/*
diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c
index afdb3985aa59..4bc26c007921 100644
--- a/sbin/dhclient/options.c
+++ b/sbin/dhclient/options.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <ctype.h>
#define DHCP_OPTION_DATA
diff --git a/sbin/dhclient/packet.c b/sbin/dhclient/packet.c
index 276bb5c2457f..fc0305a8cb0c 100644
--- a/sbin/dhclient/packet.c
+++ b/sbin/dhclient/packet.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
#include <netinet/in_systm.h>
@@ -137,11 +135,14 @@ assemble_udp_ip_header(unsigned char *buf, int *bufix, u_int32_t from,
udp.uh_ulen = htons(sizeof(udp) + len);
memset(&udp.uh_sum, 0, sizeof(udp.uh_sum));
- udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp),
- checksum(data, len, checksum((unsigned char *)&ip.ip_src,
+ udp.uh_sum = wrapsum(checksum(data, len, checksum((unsigned char *)&udp,
+ sizeof(udp), checksum((unsigned char *)&ip.ip_src,
2 * sizeof(ip.ip_src),
IPPROTO_UDP + (u_int32_t)ntohs(udp.uh_ulen)))));
+ if (udp.uh_sum == htons(0))
+ udp.uh_sum = htons(0xffff);
+
memcpy(&buf[*bufix], &udp, sizeof(udp));
*bufix += sizeof(udp);
}
@@ -168,7 +169,7 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
struct ip *ip;
struct udphdr *udp;
u_int32_t ip_len = (buf[bufix] & 0xf) << 2;
- u_int32_t sum, usum;
+ u_int32_t sum, usum, pseudo_sum;
static int ip_packets_seen;
static int ip_packets_bad_checksum;
static int udp_packets_seen;
@@ -226,23 +227,37 @@ decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
}
usum = udp->uh_sum;
- udp->uh_sum = 0;
-
- sum = wrapsum(checksum((unsigned char *)udp, sizeof(*udp),
- checksum(data, len, checksum((unsigned char *)&ip->ip_src,
- 2 * sizeof(ip->ip_src),
- IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen)))));
-
udp_packets_seen++;
- if (usum && usum != sum) {
- udp_packets_bad_checksum++;
- if (udp_packets_seen > 4 && udp_packets_bad_checksum != 0 &&
- (udp_packets_seen / udp_packets_bad_checksum) < 2) {
- note("%d bad udp checksums in %d packets",
- udp_packets_bad_checksum, udp_packets_seen);
- udp_packets_seen = udp_packets_bad_checksum = 0;
+
+ if (usum != htons(0)) {
+ udp->uh_sum = 0;
+
+ pseudo_sum = checksum((unsigned char *)&ip->ip_src,
+ 2 * sizeof(ip->ip_src),
+ IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen));
+ sum = wrapsum(checksum(data, len,
+ checksum((unsigned char *)udp, sizeof(*udp), pseudo_sum)));
+ if (sum == htons(0))
+ sum = htons(0xffff);
+
+ /*
+ * In addition to accepting UDP packets with the correct
+ * checksum in the checksum field, accept also the ones which
+ * have the correct pseudo header checksum in the checksum
+ * field. This allows to process UDP packets, which have been
+ * marked for transmit checksum offloading by the sender side.
+ */
+ if (usum != sum && usum != htons(pseudo_sum & 0x0000ffff)) {
+ udp_packets_bad_checksum++;
+ if (udp_packets_seen > 4 &&
+ udp_packets_bad_checksum != 0 &&
+ (udp_packets_seen / udp_packets_bad_checksum) < 2) {
+ note("%d bad udp checksums in %d packets",
+ udp_packets_bad_checksum, udp_packets_seen);
+ udp_packets_seen = udp_packets_bad_checksum = 0;
+ }
+ return (-1);
}
- return (-1);
}
memcpy(&from->sin_port, &udp->uh_sport, sizeof(udp->uh_sport));
diff --git a/sbin/dhclient/parse.c b/sbin/dhclient/parse.c
index 4018f70f3a5d..da0c4aa754e1 100644
--- a/sbin/dhclient/parse.c
+++ b/sbin/dhclient/parse.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <stdbool.h>
#include "dhcpd.h"
@@ -444,9 +442,7 @@ convert_num(unsigned char *buf, char *str, unsigned base, int size)
time_t
parse_date(FILE *cfile)
{
- static int months[11] = { 31, 59, 90, 120, 151, 181,
- 212, 243, 273, 304, 334 };
- int guess, token;
+ int token;
struct tm tm;
char *val;
@@ -570,27 +566,5 @@ parse_date(FILE *cfile)
return (0);
}
- /* Guess the time value... */
- guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */
- (tm.tm_year - 69) / 4 + /* Leap days since '70 */
- (tm.tm_mon /* Days in months this year */
- ? months[tm.tm_mon - 1]
- : 0) +
- (tm.tm_mon > 1 && /* Leap day this year */
- !((tm.tm_year - 72) & 3)) +
- tm.tm_mday - 1) * 24) + /* Day of month */
- tm.tm_hour) * 60) +
- tm.tm_min) * 60) + tm.tm_sec;
-
- /*
- * This guess could be wrong because of leap seconds or other
- * weirdness we don't know about that the system does. For
- * now, we're just going to accept the guess, but at some point
- * it might be nice to do a successive approximation here to get
- * an exact value. Even if the error is small, if the server
- * is restarted frequently (and thus the lease database is
- * reread), the error could accumulate into something
- * significant.
- */
- return (guess);
+ return (timegm(&tm));
}
diff --git a/sbin/dhclient/privsep.c b/sbin/dhclient/privsep.c
index a286b6900808..02d12a36a3d9 100644
--- a/sbin/dhclient/privsep.c
+++ b/sbin/dhclient/privsep.c
@@ -17,8 +17,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
#include "privsep.h"
diff --git a/sbin/dhclient/privsep.h b/sbin/dhclient/privsep.h
index db6ec9b4acea..1e26daa3d83d 100644
--- a/sbin/dhclient/privsep.h
+++ b/sbin/dhclient/privsep.h
@@ -14,8 +14,6 @@
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $FreeBSD$
*/
#include <sys/types.h>
diff --git a/sbin/dhclient/tables.c b/sbin/dhclient/tables.c
index 9225c4fe2051..134b54fa3b56 100644
--- a/sbin/dhclient/tables.c
+++ b/sbin/dhclient/tables.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
/*
diff --git a/sbin/dhclient/tests/Makefile b/sbin/dhclient/tests/Makefile
index ce4c7acb822e..2cca8635fa13 100644
--- a/sbin/dhclient/tests/Makefile
+++ b/sbin/dhclient/tests/Makefile
@@ -1,12 +1,14 @@
-# $FreeBSD$
-
.PATH: ${.CURDIR:H}
ATF_TESTS_SH= pcp
+# Tests assign a common IP address.
+TEST_METADATA.pcp+= is_exclusive=true
+
PLAIN_TESTS_C= option-domain-search_test
SRCS.option-domain-search_test= alloc.c convert.c hash.c options.c \
- tables.c fake.c option-domain-search.c
+ tables.c parse.c conflex.c tree.c fake.c \
+ option-domain-search.c
CFLAGS.option-domain-search_test+= -I${.CURDIR:H}
LIBADD.option-domain-search_test= util
diff --git a/sbin/dhclient/tests/Makefile.depend b/sbin/dhclient/tests/Makefile.depend
index 4fc5be2a35f0..28acae7b0d55 100644
--- a/sbin/dhclient/tests/Makefile.depend
+++ b/sbin/dhclient/tests/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/dhclient/tests/fake.c b/sbin/dhclient/tests/fake.c
index 6a170953beb0..15ed04dde077 100644
--- a/sbin/dhclient/tests/fake.c
+++ b/sbin/dhclient/tests/fake.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
#include <setjmp.h>
#include <stdarg.h>
@@ -7,6 +6,7 @@
#include "dhcpd.h"
extern jmp_buf env;
+int warnings_occurred;
void
error(const char *fmt, ...)
@@ -52,6 +52,20 @@ note(const char *fmt, ...)
return ret;
}
+int
+parse_warn(const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "\n");
+
+ return ret;
+}
+
void
bootp(struct packet *packet)
{
diff --git a/sbin/dhclient/tests/option-domain-search.c b/sbin/dhclient/tests/option-domain-search.c
index b79f9a560137..6a7f92c8775d 100644
--- a/sbin/dhclient/tests/option-domain-search.c
+++ b/sbin/dhclient/tests/option-domain-search.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
#include <setjmp.h>
#include <stdlib.h>
@@ -303,6 +302,51 @@ multiple_domains_valid()
free(option->data);
}
+static
+void
+parse_date_helper(const char *string, time_t timestamp)
+{
+ int ret = 0;
+ FILE *file = NULL;
+ time_t ts;
+
+ file = fopen("/tmp/dhclient.test", "w");
+ if (!file)
+ abort();
+
+ ret = fwrite(string, strlen(string), 1, file);
+ if (ret <= 0)
+ abort();
+
+ fclose(file);
+
+ file = fopen("/tmp/dhclient.test", "r");
+ if (!file)
+ abort();
+
+ new_parse("test");
+ ts = parse_date(file);
+ if (ts != timestamp)
+ abort();
+
+ fclose(file);
+}
+
+void
+parse_date_valid(void)
+{
+ int ret;
+
+ ret = setjmp(env);
+ if (ret != 0)
+ abort();
+
+ parse_date_helper(" 2 2024/7/2 20:25:50;\n", 1719951950);
+#ifndef __i386__
+ parse_date_helper(" 1 2091/7/2 20:25:50;\n", 3834246350);
+#endif
+}
+
int
main(int argc, char *argv[])
{
@@ -324,5 +368,7 @@ main(int argc, char *argv[])
multiple_domains_valid();
+ parse_date_valid();
+
return (0);
}
diff --git a/sbin/dhclient/tree.c b/sbin/dhclient/tree.c
index 9639cb87321b..0414129b2efb 100644
--- a/sbin/dhclient/tree.c
+++ b/sbin/dhclient/tree.c
@@ -43,8 +43,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include "dhcpd.h"
pair
diff --git a/sbin/dhclient/tree.h b/sbin/dhclient/tree.h
index 7bbd1e4c3226..f51b0a7bfdf4 100644
--- a/sbin/dhclient/tree.h
+++ b/sbin/dhclient/tree.h
@@ -39,8 +39,6 @@
* Enterprises. To learn more about the Internet Software Consortium,
* see ``http://www.vix.com/isc''. To learn more about Vixie
* Enterprises, see ``http://www.vix.com''.
- *
- * $FreeBSD$
*/
/* A pair of pointers, suitable for making a linked list. */
diff --git a/sbin/dmesg/Makefile b/sbin/dmesg/Makefile
index a443225242d8..b0bd864fd09d 100644
--- a/sbin/dmesg/Makefile
+++ b/sbin/dmesg/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
PACKAGE=runtime
PROG= dmesg
MAN= dmesg.8
diff --git a/sbin/dmesg/Makefile.depend b/sbin/dmesg/Makefile.depend
index 4a0ebeceed6f..124f2f93f8a6 100644
--- a/sbin/dmesg/Makefile.depend
+++ b/sbin/dmesg/Makefile.depend
@@ -1,14 +1,11 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
diff --git a/sbin/dmesg/dmesg.8 b/sbin/dmesg/dmesg.8
index 50b5e3e26404..0dca0ff5da89 100644
--- a/sbin/dmesg/dmesg.8
+++ b/sbin/dmesg/dmesg.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)dmesg.8 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
.Dd May 7, 2022
.Dt DMESG 8
.Os
@@ -77,7 +74,7 @@ variables control how the kernel timestamps entries in the message buffer:
The default value is shown next to each variable.
.Bl -tag -width indent
.It kern.msgbuf_show_timestamp : No 0
-If set to 0, no timetamps are added.
+If set to 0, no timestamps are added.
If set to 1, then a 1-second granularity timestamp will be added to most lines
in the message buffer.
If set to 2, then a microsecond granularity timestamp will be added.
diff --git a/sbin/dmesg/dmesg.c b/sbin/dmesg/dmesg.c
index f266e6b98b39..65005a903154 100644
--- a/sbin/dmesg/dmesg.c
+++ b/sbin/dmesg/dmesg.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1991, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static const char sccsid[] = "@(#)dmesg.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/msgbuf.h>
#include <sys/sysctl.h>
diff --git a/sbin/dump/Makefile b/sbin/dump/Makefile
index f611d6b1ab47..6f0dbf3f478f 100644
--- a/sbin/dump/Makefile
+++ b/sbin/dump/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
# dump.h header file
# itime.c reads /etc/dumpdates
# main.c driver
@@ -13,7 +10,7 @@
# DEBUG use local directory to find ddate and dumpdates
# TDEBUG trace out the process forking
-PACKAGE=runtime
+PACKAGE=ufs
PROG= dump
CONFS= /dev/null
CONFSGRP= operator
diff --git a/sbin/dump/Makefile.depend b/sbin/dump/Makefile.depend
index 4bd09984c29d..d26328b3bed1 100644
--- a/sbin/dump/Makefile.depend
+++ b/sbin/dump/Makefile.depend
@@ -1,14 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/protocols \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libufs \
.include <dirdeps.mk>
diff --git a/sbin/dump/cache.c b/sbin/dump/cache.c
index 906ac2716959..b0da1bcc1aa8 100644
--- a/sbin/dump/cache.c
+++ b/sbin/dump/cache.c
@@ -2,8 +2,6 @@
* CACHE.C
*
* Block cache for dump
- *
- * $FreeBSD$
*/
#include <sys/param.h>
diff --git a/sbin/dump/dump.8 b/sbin/dump/dump.8
index 80e8eae21d19..08b3c2e574d7 100644
--- a/sbin/dump/dump.8
+++ b/sbin/dump/dump.8
@@ -26,9 +26,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)dump.8 8.3 (Berkeley) 5/1/95
-.\" $FreeBSD$
-.\"
.Dd December 28, 2020
.Dt DUMP 8
.Os
diff --git a/sbin/dump/dump.h b/sbin/dump/dump.h
index fc8c845fc576..a776c8209d0b 100644
--- a/sbin/dump/dump.h
+++ b/sbin/dump/dump.h
@@ -27,10 +27,6 @@
* 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.
- *
- * @(#)dump.h 8.2 (Berkeley) 4/28/95
- *
- * $FreeBSD$
*/
/*
@@ -101,7 +97,7 @@ void quit(const char *fmt, ...) __printflike(1, 2);
void timeest(void);
time_t unctime(char *str);
-/* mapping rouintes */
+/* mapping routines */
union dinode;
int mapfiles(ino_t maxino, long *tapesize);
int mapdirs(ino_t maxino, long *tapesize);
diff --git a/sbin/dump/dumprmt.c b/sbin/dump/dumprmt.c
index d1769faa3daf..4f61905eb60e 100644
--- a/sbin/dump/dumprmt.c
+++ b/sbin/dump/dumprmt.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)dumprmt.c 8.3 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/mtio.h>
#include <sys/socket.h>
diff --git a/sbin/dump/itime.c b/sbin/dump/itime.c
index cb6d55625e6d..ba6ccaf47f04 100644
--- a/sbin/dump/itime.c
+++ b/sbin/dump/itime.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)itime.c 8.1 (Berkeley) 6/5/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/queue.h>
diff --git a/sbin/dump/main.c b/sbin/dump/main.c
index 8752f2c1bea5..0ff622125fdd 100644
--- a/sbin/dump/main.c
+++ b/sbin/dump/main.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1991, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/1/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/mount.h>
@@ -457,7 +443,7 @@ main(int argc, char *argv[])
msgtail("to %s\n", tape);
sync();
- if ((ret = sbget(diskfd, &sblock, STDSB)) != 0) {
+ if ((ret = sbget(diskfd, &sblock, UFS_STDSB, UFS_NOCSUM)) != 0) {
switch (ret) {
case ENOENT:
warn("Cannot find file system superblock");
diff --git a/sbin/dump/optr.c b/sbin/dump/optr.c
index 8eb163516c72..f263f48374ae 100644
--- a/sbin/dump/optr.c
+++ b/sbin/dump/optr.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)optr.c 8.2 (Berkeley) 1/6/94";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/wait.h>
diff --git a/sbin/dump/pathnames.h b/sbin/dump/pathnames.h
index 120bd72f5f11..e309643473a7 100644
--- a/sbin/dump/pathnames.h
+++ b/sbin/dump/pathnames.h
@@ -27,9 +27,6 @@
* 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.
- *
- * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
- * $FreeBSD$
*/
#include <paths.h>
diff --git a/sbin/dump/tape.c b/sbin/dump/tape.c
index 45ad0ee50487..e448bacf61b6 100644
--- a/sbin/dump/tape.c
+++ b/sbin/dump/tape.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)tape.c 8.4 (Berkeley) 5/1/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/wait.h>
@@ -74,7 +66,8 @@ static long blocksthisvol; /* number of blocks on current output file */
static char *nexttape;
static FILE *popenfp = NULL;
-static int atomic(ssize_t (*)(), int, char *, int);
+static int atomic_read(int, void *, int);
+static int atomic_write(int, const void *, int);
static void worker(int, int);
static void create_workers(void);
static void flushtape(void);
@@ -236,7 +229,7 @@ flushtape(void)
wp->req[trecno].count = 0; /* Sentinel */
- if (atomic(write, wp->fd, (char *)wp->req, siz) != siz)
+ if (atomic_write(wp->fd, (const void *)wp->req, siz) != siz)
quit("error writing command pipe: %s\n", strerror(errno));
wp->sent = 1; /* we sent a request, read the response later */
@@ -247,7 +240,7 @@ flushtape(void)
/* Read results back from next worker */
if (wp->sent) {
- if (atomic(read, wp->fd, (char *)&got, sizeof got)
+ if (atomic_read(wp->fd, (void *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
@@ -264,8 +257,8 @@ flushtape(void)
*/
for (i = 0; i < WORKERS; i++) {
if (workers[i].sent) {
- if (atomic(read, workers[i].fd,
- (char *)&got, sizeof got)
+ if (atomic_read(workers[i].fd,
+ (void *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
@@ -322,7 +315,7 @@ trewind(void)
* fixme: punt for now.
*/
if (workers[f].sent) {
- if (atomic(read, workers[f].fd, (char *)&got, sizeof got)
+ if (atomic_read(workers[f].fd, (void *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
@@ -446,7 +439,7 @@ rollforward(void)
lastspclrec = savedtapea - 1;
}
size = (char *)ntb - (char *)q;
- if (atomic(write, wp->fd, (char *)q, size) != size) {
+ if (atomic_write(wp->fd, (const void *)q, size) != size) {
perror(" DUMP: error writing command pipe");
dumpabort(0);
}
@@ -486,7 +479,7 @@ rollforward(void)
* worked ok, otherwise the tape is much too short!
*/
if (wp->sent) {
- if (atomic(read, wp->fd, (char *)&got, sizeof got)
+ if (atomic_read(wp->fd, (void *)&got, sizeof got)
!= sizeof got) {
perror(" DUMP: error reading command pipe in master");
dumpabort(0);
@@ -676,8 +669,7 @@ dumpabort(int signo __unused)
}
void
-Exit(status)
- int status;
+Exit(int status)
{
#ifdef TDEBUG
@@ -735,8 +727,8 @@ create_workers(void)
}
for (i = 0; i < WORKERS; i++)
- (void) atomic(write, workers[i].fd,
- (char *) &workers[(i + 1) % WORKERS].pid,
+ (void) atomic_write(workers[i].fd,
+ (const void *) &workers[(i + 1) % WORKERS].pid,
sizeof workers[0].pid);
master = 0;
@@ -777,7 +769,7 @@ worker(int cmd, int worker_number)
/*
* Need the pid of the next worker in the loop...
*/
- if ((nread = atomic(read, cmd, (char *)&nextworker, sizeof nextworker))
+ if ((nread = atomic_read(cmd, (void *)&nextworker, sizeof nextworker))
!= sizeof nextworker) {
quit("master/worker protocol botched - didn't get pid of next worker.\n");
}
@@ -785,7 +777,7 @@ worker(int cmd, int worker_number)
/*
* Get list of blocks to dump, read the blocks into tape buffer
*/
- while ((nread = atomic(read, cmd, (char *)wp->req, reqsiz)) == reqsiz) {
+ while ((nread = atomic_read(cmd, (void *)wp->req, reqsiz)) == reqsiz) {
struct req *p = wp->req;
for (trecno = 0; trecno < ntrec;
@@ -794,8 +786,8 @@ worker(int cmd, int worker_number)
blkread(p->dblk, wp->tblock[trecno],
p->count * TP_BSIZE);
} else {
- if (p->count != 1 || atomic(read, cmd,
- (char *)wp->tblock[trecno],
+ if (p->count != 1 || atomic_read(cmd,
+ (void *)wp->tblock[trecno],
TP_BSIZE) != TP_BSIZE)
quit("master/worker protocol botched.\n");
}
@@ -858,7 +850,8 @@ worker(int cmd, int worker_number)
* pass size of write back to master
* (for EOT handling)
*/
- (void) atomic(write, cmd, (char *)&size, sizeof size);
+ (void)atomic_write(cmd, (const void *)&size,
+ sizeof size);
}
/*
@@ -873,15 +866,28 @@ worker(int cmd, int worker_number)
/*
* Since a read from a pipe may not return all we asked for,
- * or a write may not write all we ask if we get a signal,
* loop until the count is satisfied (or error).
*/
static int
-atomic(ssize_t (*func)(), int fd, char *buf, int count)
+atomic_read(int fd, void *buf, int count)
+{
+ int got, need = count;
+
+ while ((got = read(fd, buf, need)) > 0 && (need -= got) > 0)
+ buf += got;
+ return (got < 0 ? got : count - need);
+}
+
+/*
+ * Since a write to a pipe may not write all we ask if we get a signal,
+ * loop until the count is satisfied (or error).
+ */
+static int
+atomic_write(int fd, const void *buf, int count)
{
int got, need = count;
- while ((got = (*func)(fd, buf, need)) > 0 && (need -= got) > 0)
+ while ((got = write(fd, buf, need)) > 0 && (need -= got) > 0)
buf += got;
return (got < 0 ? got : count - need);
}
diff --git a/sbin/dump/traverse.c b/sbin/dump/traverse.c
index 08e902667759..d3bb671644e3 100644
--- a/sbin/dump/traverse.c
+++ b/sbin/dump/traverse.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)traverse.c 8.7 (Berkeley) 6/15/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/stat.h>
@@ -59,10 +51,6 @@ static const char rcsid[] =
#include "dump.h"
-union dinode {
- struct ufs1_dinode dp1;
- struct ufs2_dinode dp2;
-};
#define DIP(dp, field) \
((sblock->fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
diff --git a/sbin/dump/unctime.c b/sbin/dump/unctime.c
index 3e03a65f1a7c..82ee12597c05 100644
--- a/sbin/dump/unctime.c
+++ b/sbin/dump/unctime.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)unctime.c 8.2 (Berkeley) 6/14/94";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <time.h>
/*
diff --git a/sbin/dumpfs/Makefile b/sbin/dumpfs/Makefile
index 03e1aae03b87..1e7fa4f150d3 100644
--- a/sbin/dumpfs/Makefile
+++ b/sbin/dumpfs/Makefile
@@ -1,7 +1,4 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
-PACKAGE=runtime
+PACKAGE=ufs
PROG= dumpfs
WARNS?= 2
LIBADD= ufs
diff --git a/sbin/dumpfs/Makefile.depend b/sbin/dumpfs/Makefile.depend
index 735bf03b75b6..910688a678fa 100644
--- a/sbin/dumpfs/Makefile.depend
+++ b/sbin/dumpfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/dumpfs/dumpfs.8 b/sbin/dumpfs/dumpfs.8
index ec5b12550447..768329315bc3 100644
--- a/sbin/dumpfs/dumpfs.8
+++ b/sbin/dumpfs/dumpfs.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)dumpfs.8 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
.Dd July 2, 2021
.Dt DUMPFS 8
.Os
@@ -89,7 +86,8 @@ and
are not handled and
.Fl p
is not useful in this case so is omitted.
-.Xr Newfs 8
+The
+.Xr newfs 8
options
.Fl n
and
diff --git a/sbin/dumpfs/dumpfs.c b/sbin/dumpfs/dumpfs.c
index 7c43cf4489a8..c4988ded88d8 100644
--- a/sbin/dumpfs/dumpfs.c
+++ b/sbin/dumpfs/dumpfs.c
@@ -44,20 +44,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1983, 1992, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)dumpfs.c 8.5 (Berkeley) 4/29/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/disklabel.h>
@@ -74,6 +60,7 @@ static const char rcsid[] =
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#define afs disk.d_fs
@@ -89,7 +76,7 @@ static void dumpfreespacecg(int);
static int marshal(const char *);
static void pbits(void *, int);
static void pblklist(void *, int, off_t, int);
-static void ufserr(const char *);
+static const char *ufserr(void);
static void usage(void) __dead2;
int
@@ -130,8 +117,9 @@ main(int argc, char *argv[])
usage();
while ((name = *argv++) != NULL) {
- if (ufs_disk_fillout(&disk, name) == -1) {
- ufserr(name);
+ if (ufs_disk_fillout_blank(&disk, name) == -1 ||
+ sbfind(&disk, 0) == -1) {
+ printf("\n%s: %s\n", name, ufserr());
eval |= 1;
continue;
}
@@ -162,7 +150,7 @@ dumpfs(const char *name, int dosb)
time_t fstime, fsmtime;
int64_t fssize;
int32_t fsflags;
- int i;
+ int i, ret;
switch (disk.d_ufs) {
case 2:
@@ -187,7 +175,8 @@ dumpfs(const char *name, int dosb)
afs.fs_ncg, (intmax_t)fssize, (intmax_t)afs.fs_dsize);
break;
default:
- goto err;
+ printf("Unknown filesystem type %d\n", disk.d_ufs);
+ return (1);
}
printf("bsize\t%d\tshift\t%d\tmask\t0x%08x\n",
afs.fs_bsize, afs.fs_bshift, afs.fs_bmask);
@@ -233,8 +222,8 @@ dumpfs(const char *name, int dosb)
printf("sbsize\t%d\tcgsize\t%d\tcgoffset %d\tcgmask\t0x%08x\n",
afs.fs_sbsize, afs.fs_cgsize, afs.fs_old_cgoffset,
afs.fs_old_cgmask);
- printf("csaddr\t%d\tcssize\t%d\n",
- afs.fs_old_csaddr, afs.fs_cssize);
+ printf("csaddr\t%jd\tcssize\t%d\n",
+ (intmax_t)afs.fs_csaddr, afs.fs_cssize);
printf("rotdelay %dms\trps\t%d\ttrackskew %d\tinterleave %d\n",
afs.fs_old_rotdelay, afs.fs_old_rps, afs.fs_old_trackskew,
afs.fs_old_interleave);
@@ -242,8 +231,11 @@ dumpfs(const char *name, int dosb)
afs.fs_old_nsect, afs.fs_old_npsect, afs.fs_old_spc);
break;
default:
- goto err;
+ printf("Unknown filesystem type %d\n", disk.d_ufs);
+ return (1);
}
+ printf("old_cpg\t%d\tsize_cg\t%zu\tCGSIZE\t%zu\n",
+ afs.fs_old_cpg, sizeof(struct cg), CGSIZE(&afs));
printf("sblkno\t%d\tcblkno\t%d\tiblkno\t%d\tdblkno\t%d\n",
afs.fs_sblkno, afs.fs_cblkno, afs.fs_iblkno, afs.fs_dblkno);
printf("cgrotor\t%d\tfmod\t%d\tronly\t%d\tclean\t%d\n",
@@ -308,9 +300,6 @@ dumpfs(const char *name, int dosb)
afs.fs_volname, (uintmax_t)afs.fs_swuid,
(uintmax_t)afs.fs_providersize);
printf("\ncs[].cs_(nbfree,ndir,nifree,nffree):\n\t");
- afs.fs_csp = calloc(1, afs.fs_cssize);
- if (bread(&disk, fsbtodb(&afs, afs.fs_csaddr), afs.fs_csp, afs.fs_cssize) == -1)
- goto err;
for (i = 0; i < afs.fs_ncg; i++) {
struct csum *cs = &afs.fs_cs(&afs, i);
if (i && i % 4 == 0)
@@ -329,14 +318,15 @@ dumpfs(const char *name, int dosb)
}
if (dosb)
return (0);
+ ret = 0;
while ((i = cgread(&disk)) != 0) {
- if (i == -1 || dumpcg())
- goto err;
+ if (i == -1) {
+ ret = 1;
+ printf("\ncg %d: %s\n", disk.d_lcg, ufserr());
+ } else if (dumpcg())
+ ret = 1;
}
- return (0);
-
-err: ufserr(name);
- return (1);
+ return (ret);
}
static int
@@ -402,17 +392,22 @@ dumpcg(void)
static int
dumpfreespace(const char *name, int fflag)
{
- int i;
+ intmax_t startblkno;
+ int i, ret;
+ ret = 0;
while ((i = cgread(&disk)) != 0) {
- if (i == -1)
- goto err;
- dumpfreespacecg(fflag);
+ if (i != -1) {
+ dumpfreespacecg(fflag);
+ } else {
+ startblkno = disk.d_lcg * afs.fs_fpg;
+ printf("\nBlocks %jd-%jd of cg %d skipped: %s\n",
+ startblkno, startblkno + afs.fs_fpg - 1,
+ disk.d_lcg, ufserr());
+ ret = 1;
+ }
}
- return (0);
-err:
- ufserr(name);
- return (1);
+ return (ret);
}
static void
@@ -521,13 +516,14 @@ pblklist(void *vp, int max, off_t offset, int fflag)
}
}
-static void
-ufserr(const char *name)
+static const char *
+ufserr(void)
{
if (disk.d_error != NULL)
- warnx("%s: %s", name, disk.d_error);
- else if (errno)
- warn("%s", name);
+ return(disk.d_error);
+ if (errno)
+ return (strerror(errno));
+ return ("unknown error");
}
static void
diff --git a/sbin/dumpon/Makefile b/sbin/dumpon/Makefile
index d0700ab16a89..03a72bcba41f 100644
--- a/sbin/dumpon/Makefile
+++ b/sbin/dumpon/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=runtime
@@ -8,6 +6,7 @@ PROG= dumpon
.if ${MK_OPENSSL} != "no"
LIBADD= crypto
CFLAGS+=-DHAVE_CRYPTO
+CFLAGS+=-DOPENSSL_API_COMPAT=0x10100000L
.endif
MAN= dumpon.8
diff --git a/sbin/dumpon/Makefile.depend b/sbin/dumpon/Makefile.depend
index 9a1f7bd0d413..72007d65f40b 100644
--- a/sbin/dumpon/Makefile.depend
+++ b/sbin/dumpon/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
@@ -10,7 +9,6 @@ DIRDEPS = \
lib/libcapsicum \
lib/libcasper/libcasper \
lib/libcompiler_rt \
- lib/libthr \
.include <dirdeps.mk>
diff --git a/sbin/dumpon/Makefile.depend.options b/sbin/dumpon/Makefile.depend.options
index fa96b2506b2c..b374d7a1fd52 100644
--- a/sbin/dumpon/Makefile.depend.options
+++ b/sbin/dumpon/Makefile.depend.options
@@ -1,4 +1,3 @@
-# $FreeBSD$
# This file is not autogenerated - take care!
DIRDEPS_OPTIONS= OPENSSL
diff --git a/sbin/dumpon/dumpon.8 b/sbin/dumpon/dumpon.8
index de9bd648e68b..a57dfef7096d 100644
--- a/sbin/dumpon/dumpon.8
+++ b/sbin/dumpon/dumpon.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" From: @(#)swapon.8 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
.Dd April 23, 2020
.Dt DUMPON 8
.Os
@@ -312,7 +309,7 @@ or shorter:
The
.Pa vmcore.#
can be now examined using
-.Xr kgdb 1 :
+.Xr kgdb 1 Pq Pa ports/devel/gdb :
.Pp
.Dl # kgdb /boot/kernel/kernel vmcore.#
.Pp
@@ -321,7 +318,7 @@ or shorter:
.Dl # kgdb -n #
.Pp
The core was decrypted properly if
-.Xr kgdb 1
+.Xr kgdb 1 Pq Pa ports/devel/gdb
does not print any errors.
Note that the live kernel might be at a different path
which can be examined by looking at the
@@ -368,7 +365,7 @@ Be sure to fill in the server IP address and change the interface name if
needed.
.Sh SEE ALSO
.Xr gzip 1 ,
-.Xr kgdb 1 ,
+.Xr kgdb 1 Pq Pa ports/devel/gdb ,
.Xr zstd 1 ,
.Xr ddb 4 ,
.Xr netdump 4 ,
diff --git a/sbin/dumpon/dumpon.c b/sbin/dumpon/dumpon.c
index 626350427595..e6c1634ff6fe 100644
--- a/sbin/dumpon/dumpon.c
+++ b/sbin/dumpon/dumpon.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "From: @(#)swapon.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/capsicum.h>
#include <sys/disk.h>
@@ -84,7 +70,7 @@ __FBSDID("$FreeBSD$");
static int verbose;
-static void _Noreturn
+static _Noreturn void
usage(void)
{
fprintf(stderr,
@@ -270,7 +256,8 @@ _genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap)
fclose(fp);
fp = NULL;
if (pubkey == NULL)
- errx(1, "Unable to read data from %s.", pubkeyfile);
+ errx(1, "Unable to read data from %s: %s", pubkeyfile,
+ ERR_error_string(ERR_get_error(), NULL));
/*
* RSA keys under ~1024 bits are trivially factorable (2018). OpenSSL
@@ -476,20 +463,23 @@ main(int argc, char *argv[])
struct diocskerneldump_arg ndconf, *kdap;
struct addrinfo hints, *res;
const char *dev, *pubkeyfile, *server, *client, *gateway;
- int ch, error, fd, cipher;
+ int ch, error, fd;
bool gzip, list, netdump, zstd, insert, rflag;
uint8_t ins_idx;
+#ifdef HAVE_CRYPTO
+ int cipher = KERNELDUMP_ENC_NONE;
+#endif
gzip = list = netdump = zstd = insert = rflag = false;
kdap = NULL;
pubkeyfile = NULL;
server = client = gateway = NULL;
ins_idx = KDA_APPEND;
- cipher = KERNELDUMP_ENC_NONE;
while ((ch = getopt(argc, argv, "C:c:g:i:k:lrs:vZz")) != -1)
switch ((char)ch) {
case 'C':
+#ifdef HAVE_CRYPTO
if (strcasecmp(optarg, "chacha") == 0 ||
strcasecmp(optarg, "chacha20") == 0)
cipher = KERNELDUMP_ENC_CHACHA20;
@@ -500,6 +490,11 @@ main(int argc, char *argv[])
errx(EX_USAGE, "Unrecognized cipher algorithm "
"'%s'", optarg);
break;
+#else
+ errx(EX_USAGE,
+ "Built without crypto support, -C is unhandled.");
+ break;
+#endif
case 'c':
client = optarg;
break;
@@ -565,7 +560,12 @@ main(int argc, char *argv[])
if (cipher != KERNELDUMP_ENC_NONE && pubkeyfile == NULL) {
errx(EX_USAGE, "-C option requires a public key file.");
} else if (pubkeyfile != NULL) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
ERR_load_crypto_strings();
+#else
+ if (!OPENSSL_init_crypto(0, NULL))
+ errx(EX_UNAVAILABLE, "Unable to initialize OpenSSL");
+#endif
}
#else
if (pubkeyfile != NULL)
diff --git a/sbin/etherswitchcfg/Makefile b/sbin/etherswitchcfg/Makefile
index 6ef9f5f8a2a0..00f9c3089323 100644
--- a/sbin/etherswitchcfg/Makefile
+++ b/sbin/etherswitchcfg/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 5.4 (Berkeley) 6/5/91
-# $FreeBSD$
-
PACKAGE=runtime
PROG= etherswitchcfg
MAN= etherswitchcfg.8
diff --git a/sbin/etherswitchcfg/Makefile.depend b/sbin/etherswitchcfg/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/etherswitchcfg/Makefile.depend
+++ b/sbin/etherswitchcfg/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/etherswitchcfg/etherswitchcfg.8 b/sbin/etherswitchcfg/etherswitchcfg.8
index 9380c1f4f055..f903975bd356 100644
--- a/sbin/etherswitchcfg/etherswitchcfg.8
+++ b/sbin/etherswitchcfg/etherswitchcfg.8
@@ -22,8 +22,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd June 23, 2021
.Dt ETHERSWITCHCFG 8
.Os
diff --git a/sbin/etherswitchcfg/etherswitchcfg.c b/sbin/etherswitchcfg/etherswitchcfg.c
index 7f3403918fad..f47dff1f0de2 100644
--- a/sbin/etherswitchcfg/etherswitchcfg.c
+++ b/sbin/etherswitchcfg/etherswitchcfg.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2011-2012 Stefan Bethke.
* All rights reserved.
@@ -24,13 +24,9 @@
* 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/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <ctype.h>
#include <err.h>
#include <errno.h>
diff --git a/sbin/etherswitchcfg/ifmedia.c b/sbin/etherswitchcfg/ifmedia.c
index 03ed4e56ab79..a54857ee2437 100644
--- a/sbin/etherswitchcfg/ifmedia.c
+++ b/sbin/etherswitchcfg/ifmedia.c
@@ -1,5 +1,4 @@
/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
-/* $FreeBSD$ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
diff --git a/sbin/fdisk/Makefile b/sbin/fdisk/Makefile
index eaed0aea04aa..85cea684a883 100644
--- a/sbin/fdisk/Makefile
+++ b/sbin/fdisk/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=runtime
PROG= fdisk
SRCS= fdisk.c fdisk_mbr_enc.c
diff --git a/sbin/fdisk/Makefile.depend b/sbin/fdisk/Makefile.depend
index 0220673c9076..0dd05cace3c0 100644
--- a/sbin/fdisk/Makefile.depend
+++ b/sbin/fdisk/Makefile.depend
@@ -1,16 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
lib/libgeom \
- lib/libsbuf \
.include <dirdeps.mk>
diff --git a/sbin/fdisk/fdisk.8 b/sbin/fdisk/fdisk.8
index 87862ec4949f..09933acf57df 100644
--- a/sbin/fdisk/fdisk.8
+++ b/sbin/fdisk/fdisk.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.Dd October 5, 2016
.Dt FDISK 8
@@ -16,6 +15,22 @@
.Fl f Ar configfile
.Op Fl itv
.Op Ar disk
+.Sh DEPRECATION NOTICE
+.Nm
+is deprecated and is not available in
+.Fx 15.0
+or later.
+Use
+.Xr gpart 8
+instead
+.Po
+with the
+.Cm MBR
+partitioning scheme
+.Pc ,
+or install the
+.Pa freebsd-fdisk
+port or package.
.Sh PROLOGUE
In order for the BIOS to boot the kernel,
certain conventions must be adhered to.
@@ -457,7 +472,7 @@ downwards to correspond to head and cylinder boundaries):
Example: to set slices 1, 2 and 4 to
.Fx
slices, the first being 2 Gigabytes, the second being 10 Gigabytes and the
-forth being the remainder of the disk (again, numbers will be rounded
+fourth being the remainder of the disk (again, numbers will be rounded
appropriately):
.Pp
.Dl "p 1 165 63 2G"
diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c
index a9afd50ed441..925cc68932d7 100644
--- a/sbin/fdisk/fdisk.c
+++ b/sbin/fdisk/fdisk.c
@@ -25,8 +25,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/disk.h>
#include <sys/disklabel.h>
#include <sys/diskmbr.h>
@@ -258,7 +256,7 @@ static int decimal(const char *str, int *num, int deflt, uint32_t maxval);
static int read_config(char *config_file);
static void reset_boot(void);
static int sanitize_partition(struct dos_partition *);
-static void usage(void);
+static void usage(void) __dead2;
int
main(int argc, char *argv[])
@@ -267,6 +265,10 @@ main(int argc, char *argv[])
int partition = -1;
struct dos_partition *partp;
+ fprintf(stderr,
+ "WARNING: fdisk is deprecated and is not available in FreeBSD 15 or later.\n"
+ "Please use gpart instead.\n\n");
+
while ((c = getopt(argc, argv, "BIab:f:ipqstuv1234")) != -1)
switch (c) {
case 'B':
@@ -382,7 +384,8 @@ main(int argc, char *argv[])
printf("******* Working on device %s *******\n",disk);
if (I_flag) {
- read_s0();
+ if (read_s0())
+ warnx("Ignoring bad existing MBR.");
reset_boot();
partp = &mboot.parts[0];
partp->dp_typ = DOSPTYP_386BSD;
@@ -412,8 +415,10 @@ main(int argc, char *argv[])
else
print_params();
- if (read_s0())
+ if (read_s0()) {
+ printf("Will replace existing bad MBR\n");
init_sector0(dos_sectors);
+ }
printf("Media sector size is %d\n", secsize);
printf("Warning: BIOS sector numbering starts with sector 1\n");
@@ -449,7 +454,7 @@ main(int argc, char *argv[])
}
static void
-usage()
+usage(void)
{
fprintf(stderr, "%s%s",
"usage: fdisk [-BIaipqstu] [-b bootcode] [-1234] [disk]\n",
@@ -610,7 +615,7 @@ change_part(int i)
}
static void
-print_params()
+print_params(void)
{
printf("parameters extracted from in-core disklabel are:\n");
printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
@@ -661,14 +666,14 @@ setactive:
}
static void
-change_code()
+change_code(void)
{
if (ok("Do you want to change the boot code?"))
init_boot();
}
void
-get_params_to_use()
+get_params_to_use(void)
{
int tmp;
print_params();
@@ -807,7 +812,7 @@ write_disk(off_t sector, void *buf)
}
static int
-get_params()
+get_params(void)
{
int error;
u_int u;
@@ -845,7 +850,7 @@ get_params()
}
static int
-read_s0()
+read_s0(void)
{
int i;
@@ -874,7 +879,7 @@ read_s0()
}
static int
-write_s0()
+write_s0(void)
{
int sector, i;
@@ -1467,7 +1472,6 @@ sanitize_partition(struct dos_partition *partp)
* The following choices are considered:
* /dev/ad0s1a => /dev/ad0
* /dev/da0a => /dev/da0
- * /dev/vinum/root => /dev/vinum/root
* A ".eli" part is removed if it exists (see geli(8)).
* A ".journal" ending is removed if it exists (see gjournal(8)).
*/
@@ -1484,7 +1488,7 @@ get_rootdisk(void)
if (statfs("/", &rootfs) == -1)
err(1, "statfs(\"/\")");
- if ((rv = regcomp(&re, "^(/dev/[a-z/]+[0-9]*)([sp][0-9]+)?[a-h]?(\\.journal)?$",
+ if ((rv = regcomp(&re, "^(/dev/[a-z/]+[0-9]+)([sp][0-9]+)?[a-h]?(\\.journal)?$",
REG_EXTENDED)) != 0)
errx(1, "regcomp() failed (%d)", rv);
strlcpy(dev, rootfs.f_mntfromname, sizeof (dev));
diff --git a/sbin/fdisk/fdisk_mbr_enc.c b/sbin/fdisk/fdisk_mbr_enc.c
index 1202896276c6..d621124c7a85 100644
--- a/sbin/fdisk/fdisk_mbr_enc.c
+++ b/sbin/fdisk/fdisk_mbr_enc.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2003 Poul-Henning Kamp
* All rights reserved.
@@ -33,9 +33,6 @@
* NB! This file must be usable both in kernel and userland.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/diskmbr.h>
#include <sys/endian.h>
diff --git a/sbin/fdisk/fdisk_mbr_enc.h b/sbin/fdisk/fdisk_mbr_enc.h
index 5a1a6bf70fce..f7b05b0ea1cc 100644
--- a/sbin/fdisk/fdisk_mbr_enc.h
+++ b/sbin/fdisk/fdisk_mbr_enc.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Conrad Meyer <cem@FreeBSD.org>
*
@@ -23,8 +23,6 @@
* 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$
*/
#pragma once
diff --git a/sbin/fdisk/runtest.sh b/sbin/fdisk/runtest.sh
index f25f4272bb0f..b89a59d18cd6 100644
--- a/sbin/fdisk/runtest.sh
+++ b/sbin/fdisk/runtest.sh
@@ -1,5 +1,4 @@
#!/bin/sh
-# $FreeBSD$
set -e
MD=`mdconfig -a -t malloc -s 4m -x 63 -y 16`
diff --git a/sbin/ffsinfo/Makefile b/sbin/ffsinfo/Makefile
index 19aa71ab89c4..cc03ac9d08ca 100644
--- a/sbin/ffsinfo/Makefile
+++ b/sbin/ffsinfo/Makefile
@@ -1,13 +1,10 @@
-# @(#)Makefile 8.8 (Berkeley) 6/21/2000
-#
# $TSHeader: src/sbin/ffsinfo/Makefile,v 1.3 2000/12/05 19:45:10 tomsoft Exp $
-# $FreeBSD$
#
GROWFS= ${.CURDIR:H}/growfs
.PATH: ${GROWFS}
-PACKAGE=runtime
+PACKAGE=ufs
PROG= ffsinfo
SRCS= ffsinfo.c debug.c
MAN= ffsinfo.8
diff --git a/sbin/ffsinfo/Makefile.depend b/sbin/ffsinfo/Makefile.depend
index 735bf03b75b6..910688a678fa 100644
--- a/sbin/ffsinfo/Makefile.depend
+++ b/sbin/ffsinfo/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/ffsinfo/ffsinfo.8 b/sbin/ffsinfo/ffsinfo.8
index 90580f5767d5..2221b2fb63b6 100644
--- a/sbin/ffsinfo/ffsinfo.8
+++ b/sbin/ffsinfo/ffsinfo.8
@@ -35,9 +35,8 @@
.\" SUCH DAMAGE.
.\"
.\" $TSHeader: src/sbin/ffsinfo/ffsinfo.8,v 1.3 2000/12/12 19:30:55 tomsoft Exp $
-.\" $FreeBSD$
.\"
-.Dd September 8, 2000
+.Dd January 23, 2025
.Dt FFSINFO 8
.Os
.Sh NAME
@@ -121,11 +120,11 @@ to
.Pa /var/tmp/ffsinfo
with all available information.
.Sh SEE ALSO
+.Xr ffs 4 ,
.Xr dumpfs 8 ,
.Xr fsck 8 ,
.Xr gpart 8 ,
.Xr growfs 8 ,
-.Xr gvinum 8 ,
.Xr newfs 8 ,
.Xr tunefs 8
.Sh HISTORY
diff --git a/sbin/ffsinfo/ffsinfo.c b/sbin/ffsinfo/ffsinfo.c
index 33ec5f175cbd..842d5c20bad0 100644
--- a/sbin/ffsinfo/ffsinfo.c
+++ b/sbin/ffsinfo/ffsinfo.c
@@ -41,18 +41,6 @@
*
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\
-Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\
-All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
/* ********************************************************** INCLUDES ***** */
#include <sys/param.h>
#include <sys/disklabel.h>
@@ -198,33 +186,25 @@ main(int argc, char **argv)
* No path prefix was given, so try in this order:
* /dev/r%s
* /dev/%s
- * /dev/vinum/r%s
- * /dev/vinum/%s.
*
- * FreeBSD now doesn't distinguish between raw and block
+ * FreeBSD now doesn't distinguish between raw and block
* devices any longer, but it should still work this way.
*/
- len = strlen(device) + strlen(_PATH_DEV) + 2 + strlen("vinum/");
+ len = strlen(device) + strlen(_PATH_DEV) + 2;
special = (char *)malloc(len);
if (special == NULL)
errx(1, "malloc failed");
snprintf(special, len, "%sr%s", _PATH_DEV, device);
if (stat(special, &st) == -1) {
+ /* For now this is the 'last resort' */
snprintf(special, len, "%s%s", _PATH_DEV, device);
- if (stat(special, &st) == -1) {
- snprintf(special, len, "%svinum/r%s",
- _PATH_DEV, device);
- if (stat(special, &st) == -1)
- /* For now this is the 'last resort' */
- snprintf(special, len, "%svinum/%s",
- _PATH_DEV, device);
- }
}
device = special;
}
- if (ufs_disk_fillout(&disk, device) == -1)
- err(1, "ufs_disk_fillout(%s) failed: %s", device, disk.d_error);
+ if (ufs_disk_fillout_blank(&disk, device) == -1 ||
+ sbfind(&disk, 0) == -1)
+ err(1, "superblock fetch(%s) failed: %s", device, disk.d_error);
DBG_OPEN(out_file); /* already here we need a superblock */
diff --git a/sbin/fsck/Makefile b/sbin/fsck/Makefile
index 8d3dd214857e..33ff4784a92b 100644
--- a/sbin/fsck/Makefile
+++ b/sbin/fsck/Makefile
@@ -1,9 +1,9 @@
# $NetBSD: Makefile,v 1.14 1996/09/27 22:38:37 christos Exp $
-# $FreeBSD$
PACKAGE=runtime
PROG= fsck
SRCS= fsck.c fsutil.c preen.c
MAN= fsck.8
+LIBADD= util
.include <bsd.prog.mk>
diff --git a/sbin/fsck/Makefile.depend b/sbin/fsck/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/fsck/Makefile.depend
+++ b/sbin/fsck/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/fsck/fsck.8 b/sbin/fsck/fsck.8
index 5ec0c02bbbfd..271ac2843cd3 100644
--- a/sbin/fsck/fsck.8
+++ b/sbin/fsck/fsck.8
@@ -27,8 +27,6 @@
.\" (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 5, 2019
.Dt FSCK 8
.Os
diff --git a/sbin/fsck/fsck.c b/sbin/fsck/fsck.c
index bb053fe56253..4c24cc9813e1 100644
--- a/sbin/fsck/fsck.c
+++ b/sbin/fsck/fsck.c
@@ -30,15 +30,10 @@
* 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: @(#)mount.c 8.19 (Berkeley) 4/19/94
* From: $NetBSD: mount.c,v 1.24 1995/11/18 03:34:29 cgd Exp
* $NetBSD: fsck.c,v 1.30 2003/08/07 10:04:15 agc Exp $
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/queue.h>
@@ -50,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <fstab.h>
#include <fcntl.h>
+#include <mntopts.h>
#include <paths.h>
#include <signal.h>
#include <stdio.h>
@@ -206,7 +202,7 @@ main(int argc, char *argv[])
_PATH_DEV, spec);
spec = device;
}
- mntp = getmntpt(spec);
+ mntp = getmntpoint(spec);
if (mntp != NULL) {
spec = mntp->f_mntfromname;
mntpt = mntp->f_mntonname;
@@ -269,7 +265,7 @@ isok(struct fstab *fs)
if (flags & DO_BACKGRD) {
if (!strcmp(fs->fs_type, FSTAB_RO))
return (0);
- if (getmntpt(fs->fs_spec) == NULL)
+ if (getmntpoint(fs->fs_spec) == NULL)
return (0);
if (checkfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, "-F", 0))
return (0);
diff --git a/sbin/fsck/fsutil.c b/sbin/fsck/fsutil.c
index 9644697e2530..9b011e0ed18e 100644
--- a/sbin/fsck/fsutil.c
+++ b/sbin/fsck/fsutil.c
@@ -35,8 +35,6 @@
#ifndef lint
__RCSID("$NetBSD: fsutil.c,v 1.15 2006/06/05 16:52:05 christos Exp $");
#endif /* not lint */
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/mount.h>
@@ -188,50 +186,6 @@ devcheck(const char *origname)
return (origname);
}
-/*
- * Get the mount point information for name.
- */
-struct statfs *
-getmntpt(const char *name)
-{
- struct stat devstat, mntdevstat;
- char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
- char *dev_name;
- struct statfs *mntbuf, *statfsp;
- int i, mntsize, isdev;
-
- if (stat(name, &devstat) != 0)
- return (NULL);
- if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
- isdev = 1;
- else
- isdev = 0;
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
- dev_name = statfsp->f_mntfromname;
- if (*dev_name != '/') {
- if (strlen(_PATH_DEV) + strlen(dev_name) + 1 >
- sizeof(statfsp->f_mntfromname))
- continue;
- strcpy(device, _PATH_DEV);
- strcat(device, dev_name);
- strcpy(statfsp->f_mntfromname, device);
- }
- if (isdev == 0) {
- if (strcmp(name, statfsp->f_mntonname))
- continue;
- return (statfsp);
- }
- if (stat(dev_name, &mntdevstat) == 0 &&
- mntdevstat.st_rdev == devstat.st_rdev)
- return (statfsp);
- }
- statfsp = NULL;
- return (statfsp);
-}
-
-
void *
emalloc(size_t s)
{
diff --git a/sbin/fsck/fsutil.h b/sbin/fsck/fsutil.h
index e65f5ddecb01..8d35d09678e2 100644
--- a/sbin/fsck/fsutil.h
+++ b/sbin/fsck/fsutil.h
@@ -24,8 +24,6 @@
* 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$
*/
struct fstab;
@@ -39,7 +37,6 @@ void panic(const char *, ...) __dead2 __printflike(1, 2);
const char *devcheck(const char *);
const char *cdevname(void);
void setcdevname(const char *, int);
-struct statfs *getmntpt(const char *);
void *emalloc(size_t);
void *erealloc(void *, size_t);
char *estrdup(const char *);
diff --git a/sbin/fsck/preen.c b/sbin/fsck/preen.c
index c8a36a608695..574826f4d8f0 100644
--- a/sbin/fsck/preen.c
+++ b/sbin/fsck/preen.c
@@ -29,18 +29,9 @@
* 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/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
-#else
-__RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $");
-#endif
-#endif /* not lint */
+/* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */
#include <sys/param.h>
#include <sys/stat.h>
diff --git a/sbin/fsck_ffs/Makefile b/sbin/fsck_ffs/Makefile
index ba8a39a87e1f..c6676007db2a 100644
--- a/sbin/fsck_ffs/Makefile
+++ b/sbin/fsck_ffs/Makefile
@@ -1,19 +1,16 @@
-# $FreeBSD$
-# @(#)Makefile 8.2 (Berkeley) 4/27/95
-
-PACKAGE=runtime
+PACKAGE=ufs
PROG= fsck_ffs
LINKS+= ${BINDIR}/fsck_ffs ${BINDIR}/fsck_ufs
LINKS+= ${BINDIR}/fsck_ffs ${BINDIR}/fsck_4.2bsd
MAN= fsck_ffs.8
MLINKS= fsck_ffs.8 fsck_ufs.8 fsck_ffs.8 fsck_4.2bsd.8
SRCS= dir.c ea.c fsutil.c inode.c main.c pass1.c pass1b.c pass2.c pass3.c \
- pass4.c pass5.c setup.c suj.c utilities.c gjournal.c getmntopts.c \
+ pass4.c pass5.c setup.c suj.c utilities.c gjournal.c \
globs.c
-LIBADD= ufs
+LIBADD= ufs util
WARNS?= 2
-CFLAGS+= -I${.CURDIR} -I${.CURDIR:H}/mount
+CFLAGS+= -I${.CURDIR}
-.PATH: ${SRCTOP}/sys/ufs/ffs ${.CURDIR:H}/mount
+.PATH: ${SRCTOP}/sys/ufs/ffs
.include <bsd.prog.mk>
diff --git a/sbin/fsck_ffs/Makefile.depend b/sbin/fsck_ffs/Makefile.depend
index 735bf03b75b6..910688a678fa 100644
--- a/sbin/fsck_ffs/Makefile.depend
+++ b/sbin/fsck_ffs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/fsck_ffs/dir.c b/sbin/fsck_ffs/dir.c
index 42ecf4112253..3eb0b63c0988 100644
--- a/sbin/fsck_ffs/dir.c
+++ b/sbin/fsck_ffs/dir.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)dir.c 8.8 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -63,7 +55,6 @@ static struct dirtemplate dirhead = {
static int chgino(struct inodesc *);
static int dircheck(struct inodesc *, struct bufarea *, struct direct *);
static int expanddir(struct inode *ip, char *name);
-static void freedir(ino_t ino, ino_t parent);
static struct direct *fsck_readdir(struct inodesc *);
static struct bufarea *getdirblk(ufs2_daddr_t blkno, long size);
static int lftempname(char *bufp, ino_t ino);
@@ -89,6 +80,7 @@ propagate(void)
if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
INO_IS_DUNFOUND(inp->i_number)) {
inoinfo(inp->i_number)->ino_state = DFOUND;
+ check_dirdepth(inp);
change++;
}
}
@@ -96,6 +88,105 @@ propagate(void)
}
/*
+ * Check that the recorded depth of the directory is correct.
+ */
+void
+check_dirdepth(struct inoinfo *inp)
+{
+ struct inoinfo *parentinp;
+ struct inode ip;
+ union dinode *dp;
+ int saveresolved;
+ size_t size;
+ static int updateasked, dirdepthupdate;
+
+ if ((parentinp = getinoinfo(inp->i_parent)) == NULL) {
+ pfatal("check_dirdepth: UNKNOWN PARENT DIR");
+ return;
+ }
+ /*
+ * If depth is correct, nothing to do.
+ */
+ if (parentinp->i_depth + 1 == inp->i_depth)
+ return;
+ /*
+ * Only the root inode should have depth of 0, so if any other
+ * directory has a depth of 0 then this is an old filesystem
+ * that has not been tracking directory depth. Ask just once
+ * whether it should start tracking directory depth.
+ */
+ if (inp->i_depth == 0 && updateasked == 0) {
+ updateasked = 1;
+ if (preen) {
+ pwarn("UPDATING FILESYSTEM TO TRACK DIRECTORY DEPTH\n");
+ dirdepthupdate = 1;
+ } else {
+ /*
+ * The file system can be marked clean even if
+ * a directory does not have the right depth.
+ * Hence, resolved should not be cleared when
+ * the filesystem does not update directory depths.
+ */
+ saveresolved = resolved;
+ dirdepthupdate =
+ reply("UPDATE FILESYSTEM TO TRACK DIRECTORY DEPTH");
+ resolved = saveresolved;
+ }
+ }
+ /*
+ * If we are not converting or we are running in no-write mode
+ * there is nothing more to do.
+ */
+ if ((inp->i_depth == 0 && dirdepthupdate == 0) ||
+ (fswritefd < 0 && bkgrdflag == 0))
+ return;
+ /*
+ * Individual directory at wrong depth. Report it and correct if
+ * in preen mode or ask if in interactive mode. Note that if a
+ * directory is renamed to a new location that is at a different
+ * level in the tree, its depth will be recalculated, but none of
+ * the directories that it contains will be updated. Thus it is
+ * not unexpected to find directories with incorrect depths. No
+ * operational harm will come from this though new directory
+ * placement in the subtree may not be as optimal until the depths
+ * of the affected directories are corrected.
+ *
+ * To avoid much spurious output on otherwise clean filesystems
+ * we only generate detailed output when the debug flag is given.
+ */
+ ginode(inp->i_number, &ip);
+ dp = ip.i_dp;
+ if (inp->i_depth != 0 && debug) {
+ pwarn("DIRECTORY");
+ prtinode(&ip);
+ printf(" DEPTH %d SHOULD BE %d", inp->i_depth,
+ parentinp->i_depth + 1);
+ if (preen == 0 && reply("ADJUST") == 0) {
+ irelse(&ip);
+ return;
+ }
+ if (preen)
+ printf(" (ADJUSTED)\n");
+ }
+ inp->i_depth = parentinp->i_depth + 1;
+ if (bkgrdflag == 0) {
+ DIP_SET(dp, di_dirdepth, inp->i_depth);
+ inodirty(&ip);
+ } else {
+ cmd.value = inp->i_number;
+ cmd.size = (int64_t)inp->i_depth - DIP(dp, di_dirdepth);
+ if (debug)
+ printf("adjdepth ino %ld amt %jd\n", (long)cmd.value,
+ (intmax_t)cmd.size);
+ size = MIBSIZE;
+ if (sysctlnametomib("vfs.ffs.adjdepth", adjdepth, &size) < 0 ||
+ sysctl(adjdepth, MIBSIZE, 0, 0, &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST INODE DEPTH", cmd.value);
+ }
+ irelse(&ip);
+}
+
+/*
* Scan each entry in a directory block.
*/
int
@@ -161,7 +252,7 @@ fsck_readdir(struct inodesc *idesc)
dp = (struct direct *)(bp->b_un.b_buf + idesc->id_loc);
/*
* Only need to check current entry if it is the first in the
- * the block, as later entries will have been checked in the
+ * block, as later entries will have been checked in the
* previous call to this function.
*/
if (idesc->id_loc % DIRBLKSIZ != 0 || dircheck(idesc, bp, dp) != 0) {
@@ -338,7 +429,7 @@ fileerror(ino_t cwd, ino_t ino, const char *errmesg)
char pathbuf[MAXPATHLEN + 1];
pwarn("%s ", errmesg);
- if (ino < UFS_ROOTINO || ino > maxino) {
+ if (ino < UFS_ROOTINO || ino >= maxino) {
pfatal("out-of-range inode number %ju", (uintmax_t)ino);
return;
}
@@ -422,7 +513,8 @@ adjust(struct inodesc *idesc, int lcnt)
(long long)cmd.size);
if (sysctl(adjrefcnt, MIBSIZE, 0, 0,
&cmd, sizeof cmd) == -1)
- rwerror("ADJUST INODE", cmd.value);
+ rwerror("ADJUST INODE LINK COUNT",
+ cmd.value);
}
}
}
@@ -472,8 +564,9 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
{
struct inode ip;
union dinode *dp;
- int lostdir;
+ int lostdir, depth;
ino_t oldlfdir;
+ struct inoinfo *inp;
struct inodesc idesc;
char tempname[BUFSIZ];
@@ -516,7 +609,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
if (preen)
printf(" (CREATED)\n");
} else {
- freedir(lfdir, UFS_ROOTINO);
+ freedirino(lfdir, UFS_ROOTINO);
lfdir = 0;
if (preen)
printf("\n");
@@ -525,6 +618,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
}
}
irelse(&ip);
+ free(idesc.id_name);
if (lfdir == 0) {
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY");
printf("\n\n");
@@ -545,7 +639,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
irelse(&ip);
return (0);
}
- if ((changeino(UFS_ROOTINO, lfname, lfdir) & ALTERED) == 0) {
+ if ((changeino(UFS_ROOTINO, lfname, lfdir, 1) & ALTERED) == 0) {
pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n");
irelse(&ip);
return (0);
@@ -574,23 +668,27 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
}
inoinfo(orphan)->ino_linkcnt--;
if (lostdir) {
- if ((changeino(orphan, "..", lfdir) & ALTERED) == 0 &&
+ depth = DIP(dp, di_dirdepth) + 1;
+ if ((changeino(orphan, "..", lfdir, depth) & ALTERED) == 0 &&
parentdir != (ino_t)-1)
(void)makeentry(orphan, lfdir, "..");
DIP_SET(dp, di_nlink, DIP(dp, di_nlink) + 1);
inodirty(&ip);
inoinfo(lfdir)->ino_linkcnt++;
pwarn("DIR I=%lu CONNECTED. ", (u_long)orphan);
- if (parentdir != (ino_t)-1) {
+ inp = getinoinfo(parentdir);
+ if (parentdir != (ino_t)-1 && inp != NULL) {
printf("PARENT WAS I=%lu\n", (u_long)parentdir);
/*
- * The parent directory, because of the ordering
+ * If the parent directory did not have to
+ * be replaced then because of the ordering
* guarantees, has had the link count incremented
* for the child, but no entry was made. This
* fixes the parent link count so that fsck does
* not need to be rerun.
*/
- inoinfo(parentdir)->ino_linkcnt++;
+ if ((inp->i_flags & INFO_NEW) != 0)
+ inoinfo(parentdir)->ino_linkcnt++;
}
if (preen == 0)
printf("\n");
@@ -603,7 +701,7 @@ linkup(ino_t orphan, ino_t parentdir, char *name)
* fix an entry in a directory.
*/
int
-changeino(ino_t dir, const char *name, ino_t newnum)
+changeino(ino_t dir, const char *name, ino_t newnum, int depth)
{
struct inodesc idesc;
struct inode ip;
@@ -617,7 +715,12 @@ changeino(ino_t dir, const char *name, ino_t newnum)
idesc.id_name = strdup(name);
idesc.id_parent = newnum; /* new value for name */
ginode(dir, &ip);
- error = ckinode(ip.i_dp, &idesc);
+ if (((error = ckinode(ip.i_dp, &idesc)) & ALTERED) && newnum != 0) {
+ DIP_SET(ip.i_dp, di_dirdepth, depth);
+ inodirty(&ip);
+ getinoinfo(dir)->i_depth = depth;
+ }
+ free(idesc.id_name);
irelse(&ip);
return (error);
}
@@ -652,15 +755,18 @@ makeentry(ino_t parent, ino_t ino, const char *name)
}
if ((ckinode(dp, &idesc) & ALTERED) != 0) {
irelse(&ip);
+ free(idesc.id_name);
return (1);
}
getpathname(pathbuf, parent, parent);
if (expanddir(&ip, pathbuf) == 0) {
irelse(&ip);
+ free(idesc.id_name);
return (0);
}
retval = ckinode(dp, &idesc) & ALTERED;
irelse(&ip);
+ free(idesc.id_name);
return (retval);
}
@@ -675,14 +781,17 @@ expanddir(struct inode *ip, char *name)
struct bufarea *bp, *nbp;
struct inodesc idesc;
union dinode *dp;
- int indiralloced;
+ long cg, indiralloced;
char *cp;
nbp = NULL;
indiralloced = newblk = indirblk = 0;
+ memset(&idesc, 0, sizeof(struct inodesc));
+ idesc.id_type = ADDR;
pwarn("NO SPACE LEFT IN %s", name);
if (!preen && reply("EXPAND") == 0)
return (0);
+ cg = ino_to_cg(&sblock, ip->i_number);
dp = ip->i_dp;
filesize = DIP(dp, di_size);
lastlbn = lblkno(&sblock, filesize);
@@ -701,7 +810,8 @@ expanddir(struct inode *ip, char *name)
bp = getdirblk(oldblk, lastlbnsize);
if (bp->b_errs)
goto bad;
- if ((newblk = allocblk(sblock.fs_frag)) == 0)
+ newblk = allocblk(cg, sblock.fs_frag, std_checkblkavail);
+ if (newblk == 0)
goto bad;
nbp = getdatablk(newblk, sblock.fs_bsize, BT_DIRDATA);
if (nbp->b_errs)
@@ -720,6 +830,7 @@ expanddir(struct inode *ip, char *name)
memmove(cp, &emptydir, sizeof emptydir);
dirty(nbp);
brelse(nbp);
+ binval(bp);
idesc.id_blkno = oldblk;
idesc.id_numfrags = numfrags(&sblock, lastlbnsize);
(void)freeblock(&idesc);
@@ -727,7 +838,7 @@ expanddir(struct inode *ip, char *name)
printf(" (EXPANDED)\n");
return (1);
}
- if ((newblk = allocblk(sblock.fs_frag)) == 0)
+ if ((newblk = allocblk(cg, sblock.fs_frag, std_checkblkavail)) == 0)
goto bad;
bp = getdirblk(newblk, sblock.fs_bsize);
if (bp->b_errs)
@@ -745,8 +856,12 @@ expanddir(struct inode *ip, char *name)
* Allocate indirect block if needed.
*/
if ((indirblk = DIP(dp, di_ib[0])) == 0) {
- if ((indirblk = allocblk(sblock.fs_frag)) == 0)
+ indirblk = allocblk(cg, sblock.fs_frag,
+ std_checkblkavail);
+ if (indirblk == 0) {
+ binval(bp);
goto bad;
+ }
indiralloced = 1;
}
nbp = getdatablk(indirblk, sblock.fs_bsize, BT_LEVEL1);
@@ -757,6 +872,7 @@ expanddir(struct inode *ip, char *name)
DIP_SET(dp, di_ib[0], indirblk);
DIP_SET(dp, di_blocks,
DIP(dp, di_blocks) + btodb(sblock.fs_bsize));
+ inodirty(ip);
}
IBLK_SET(nbp, lastlbn - UFS_NDADDR, newblk);
dirty(nbp);
@@ -770,8 +886,10 @@ expanddir(struct inode *ip, char *name)
return (1);
bad:
pfatal(" (EXPANSION FAILED)\n");
- if (nbp != NULL)
+ if (nbp != NULL) {
+ binval(bp);
brelse(nbp);
+ }
if (newblk != 0) {
idesc.id_blkno = newblk;
idesc.id_numfrags = sblock.fs_frag;
@@ -796,8 +914,8 @@ allocdir(ino_t parent, ino_t request, int mode)
struct inode ip;
union dinode *dp;
struct bufarea *bp;
- struct inoinfo *inp;
struct dirtemplate *dirp;
+ struct inoinfo *inp, *parentinp;
ino = allocino(request, IFDIR|mode);
if (ino == 0)
@@ -822,8 +940,12 @@ allocdir(ino_t parent, ino_t request, int mode)
DIP_SET(dp, di_nlink, 2);
inodirty(&ip);
if (ino == UFS_ROOTINO) {
+ inp = cacheino(dp, ino);
+ inp->i_parent = parent;
+ inp->i_dotdot = parent;
+ inp->i_flags |= INFO_NEW;
+ inoinfo(ino)->ino_type = DT_DIR;
inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink);
- cacheino(dp, ino);
irelse(&ip);
return(ino);
}
@@ -832,10 +954,18 @@ allocdir(ino_t parent, ino_t request, int mode)
irelse(&ip);
return (0);
}
- cacheino(dp, ino);
- inp = getinoinfo(ino);
+ inp = cacheino(dp, ino);
inp->i_parent = parent;
inp->i_dotdot = parent;
+ inp->i_flags |= INFO_NEW;
+ if ((parentinp = getinoinfo(inp->i_parent)) == NULL) {
+ pfatal("allocdir: UNKNOWN PARENT DIR");
+ } else {
+ inp->i_depth = parentinp->i_depth + 1;
+ DIP_SET(dp, di_dirdepth, inp->i_depth);
+ inodirty(&ip);
+ }
+ inoinfo(ino)->ino_type = DT_DIR;
inoinfo(ino)->ino_state = inoinfo(parent)->ino_state;
if (inoinfo(ino)->ino_state == DSTATE) {
inoinfo(ino)->ino_linkcnt = DIP(dp, di_nlink);
@@ -853,8 +983,8 @@ allocdir(ino_t parent, ino_t request, int mode)
/*
* free a directory inode
*/
-static void
-freedir(ino_t ino, ino_t parent)
+void
+freedirino(ino_t ino, ino_t parent)
{
struct inode ip;
union dinode *dp;
@@ -866,6 +996,7 @@ freedir(ino_t ino, ino_t parent)
inodirty(&ip);
irelse(&ip);
}
+ removecachedino(ino);
freeino(ino);
}
diff --git a/sbin/fsck_ffs/ea.c b/sbin/fsck_ffs/ea.c
index 54353005bdc0..f6ebc5c072fc 100644
--- a/sbin/fsck_ffs/ea.c
+++ b/sbin/fsck_ffs/ea.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-3-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2002 Poul-Henning Kamp
* Copyright (c) 2002 Networks Associates Technology, Inc.
@@ -35,9 +35,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/stdint.h>
@@ -61,10 +58,9 @@ eascan(struct inodesc *idesc, struct ufs2_dinode *dp)
return (0);
#else
struct bufarea *bp;
- u_int dsize, n;
+ u_int n;
u_char *cp;
long blksiz;
- char dbuf[DIRBLKSIZ];
printf("Inode %ju extsize %ju\n",
(intmax_t)idesc->id_number, (uintmax_t)dp->di_extsize);
@@ -74,8 +70,10 @@ eascan(struct inodesc *idesc, struct ufs2_dinode *dp)
blksiz = sblock.fs_fsize;
else
blksiz = sblock.fs_bsize;
- printf("blksiz = %ju\n", (intmax_t)blksiz);
bp = getdatablk(dp->di_extb[0], blksiz, BT_EXTATTR);
+ if (bp->b_errs)
+ return (STOP);
+ printf("blksiz = %ju\n", (intmax_t)blksiz);
cp = (u_char *)bp->b_un.b_buf;
for (n = 0; n < blksiz; n++) {
printf("%02x", cp[n]);
diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h
index 1fb0df0c5124..aaf02850f29a 100644
--- a/sbin/fsck_ffs/fsck.h
+++ b/sbin/fsck_ffs/fsck.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-3-Clause and BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-3-Clause and BSD-2-Clause
*
* Copyright (c) 2002 Networks Associates Technology, Inc.
* All rights reserved.
@@ -57,9 +57,6 @@
* 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.
- *
- * @(#)fsck.h 8.4 (Berkeley) 5/9/95
- * $FreeBSD$
*/
#ifndef _FSCK_H_
@@ -68,6 +65,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
+#include <libufs.h>
#include <sys/queue.h>
@@ -77,10 +75,6 @@
#define INOBUFSIZE 64*1024 /* size of buffer to read inodes in pass1 */
#define ZEROBUFSIZE (dev_bsize * 128) /* size of zero buffer used by -Z */
-union dinode {
- struct ufs1_dinode dp1;
- struct ufs2_dinode dp2;
-};
#define DIP(dp, field) \
((sblock.fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
@@ -112,7 +106,7 @@ struct inostat {
#define FSTATE 0x2 /* inode is file */
#define FZLINK 0x3 /* inode is file with a link count of zero */
#define DSTATE 0x4 /* inode is directory */
-#define DZLINK 0x5 /* inode is directory with a zero link count */
+#define DZLINK 0x5 /* inode is directory with a zero link count */
#define DFOUND 0x6 /* directory found during descent */
/* 0x7 UNUSED - see S_IS_DVALID() definition */
#define DCLEAR 0x8 /* directory is to be cleared */
@@ -159,7 +153,7 @@ struct bufarea {
int b_flags; /* B_ flags below */
int b_type; /* BT_ type below */
int b_refcnt; /* ref count of users */
- int b_index; /* for BT_LEVEL, ptr index */
+ uint64_t b_index; /* for BT_LEVEL, ptr index */
/* for BT_INODES, first inum */
union {
char *b_buf; /* buffer space */
@@ -200,8 +194,7 @@ struct bufarea {
#define BT_INODES 7 /* Buffer holds inodes */
#define BT_DIRDATA 8 /* Buffer holds directory data */
#define BT_DATA 9 /* Buffer holds user data */
-#define BT_EMPTY 10 /* Buffer allocated but not filled */
-#define BT_NUMBUFTYPES 11
+#define BT_NUMBUFTYPES 10
#define BT_NAMES { \
"unknown", \
"Superblock", \
@@ -212,8 +205,7 @@ struct bufarea {
"External Attribute", \
"Inode Block", \
"Directory Contents", \
- "User Data", \
- "Allocated but not filled" }
+ "User Data" }
extern char *buftype[];
#define BT_BUFTYPE(type) \
type < BT_NUMBUFTYPES ? buftype[type] : buftype[BT_UNKNOWN]
@@ -234,7 +226,7 @@ extern struct bufarea *pdirbp; /* current directory contents */
(bp)->b_flags |= B_DIRTY; \
} while (0)
#define initbarea(bp, type) do { \
- (bp)->b_bno = (ufs2_daddr_t)-1; \
+ (bp)->b_bno = (ufs2_daddr_t)-4; \
(bp)->b_size = 0; \
(bp)->b_errs = 0; \
(bp)->b_flags = 0; \
@@ -299,21 +291,30 @@ struct dups {
struct dups *next;
ufs2_daddr_t dup;
};
-extern struct dups *duplist; /* head of dup list */
-extern struct dups *muldup; /* end of unique duplicate dup block numbers */
+extern struct dups *duplist; /* head of dup list */
+extern struct dups *muldup; /* end of unique duplicate dup block numbers */
/*
* Inode cache data structures.
*/
-extern struct inoinfo {
- struct inoinfo *i_nexthash; /* next entry in hash chain */
+struct inoinfo {
+ SLIST_ENTRY(inoinfo) i_hash; /* hash list */
ino_t i_number; /* inode number of this entry */
ino_t i_parent; /* inode number of parent */
ino_t i_dotdot; /* inode number of `..' */
size_t i_isize; /* size of inode */
+ u_int i_depth; /* depth of directory from root */
+ u_int i_flags; /* flags, see below */
u_int i_numblks; /* size of block array in bytes */
ufs2_daddr_t i_blks[1]; /* actually longer */
-} **inphead, **inpsort;
+};
+extern SLIST_HEAD(inohash, inoinfo) *inphash;
+extern struct inoinfo **inpsort;
+/*
+ * flags for struct inoinfo
+ */
+#define INFO_NEW 0x0000001 /* replaced broken directory */
+
extern long dirhash, inplast;
extern unsigned long numdirs, listmax;
extern long countdirs; /* number of directories we actually found */
@@ -326,6 +327,7 @@ extern int adjnbfree[MIBSIZE]; /* MIB cmd to adjust number of free blocks */
extern int adjnifree[MIBSIZE]; /* MIB cmd to adjust number of free inodes */
extern int adjnffree[MIBSIZE]; /* MIB cmd to adjust number of free frags */
extern int adjnumclusters[MIBSIZE]; /* MIB cmd adjust number of free clusters */
+extern int adjdepth[MIBSIZE]; /* MIB cmd to adjust directory depth count */
extern int freefiles[MIBSIZE]; /* MIB cmd to free a set of files */
extern int freedirs[MIBSIZE]; /* MIB cmd to free a set of directories */
extern int freeblks[MIBSIZE]; /* MIB cmd to free a set of data blocks */
@@ -339,8 +341,10 @@ extern off_t bflag; /* location of alternate super block */
extern int bkgrdflag; /* use a snapshot to run on an active system */
extern char *blockmap; /* ptr to primary blk allocation map */
extern char *cdevname; /* name of device being checked */
+extern int cgheader_corrupt; /* one or more CG headers are corrupt */
extern char ckclean; /* only do work if not cleanly unmounted */
extern int ckhashadd; /* check hashes to be added */
+extern char *copybuf; /* buffer to copy snapshot blocks */
extern int cvtlevel; /* convert to newer file system format */
extern long dev_bsize; /* computed value of DEV_BSIZE */
extern u_int real_dev_bsize; /* actual disk sector size, not overridden */
@@ -363,10 +367,10 @@ extern char preen; /* just fix normal inconsistencies */
extern char rerun; /* rerun fsck. Only used in non-preen mode */
extern char resolved; /* cleared if unresolved changes => not clean */
extern int returntosingle; /* 1 => return to single user mode on exit */
-extern int sbhashfailed; /* when reading superblock check hash failed */
extern long secsize; /* actual disk sector size */
extern char skipclean; /* skip clean file systems if preening */
-extern char snapname[BUFSIZ]; /* when doing snapshots, the name of the file */
+extern int snapcnt; /* number of active snapshots */
+extern struct inode snaplist[FSMAXSNAP + 1]; /* list of active snapshots */
extern int sujrecovery; /* 1 => doing check using the journal */
extern int surrender; /* Give up if reads fail */
extern char usedsoftdep; /* just fix soft dependency inconsistencies */
@@ -415,6 +419,20 @@ Malloc(size_t size)
break;
return (retval);
}
+/*
+ * Allocate a block of memory to be used as an I/O buffer.
+ * Ensure that the buffer is aligned to the I/O subsystem requirements.
+ */
+static inline void*
+Balloc(size_t size)
+{
+ void *retval;
+
+ while ((retval = aligned_alloc(LIBUFS_BUFALIGN, size)) == NULL)
+ if (flushentry() == 0)
+ break;
+ return (retval);
+}
/*
* Wrapper for calloc() that flushes the cylinder group cache to try
@@ -436,9 +454,11 @@ struct fstab;
void adjust(struct inodesc *, int lcnt);
void alarmhandler(int sig);
-ufs2_daddr_t allocblk(long frags);
+ufs2_daddr_t allocblk(long cg, long frags, ufs2_daddr_t (*checkblkavail)
+ (ufs2_daddr_t blkno, long frags));
ino_t allocdir(ino_t parent, ino_t request, int mode);
ino_t allocino(ino_t request, int type);
+void binval(struct bufarea *);
void blkerror(ino_t ino, const char *type, ufs2_daddr_t blk);
char *blockcheck(char *name);
int blread(int fd, char *buf, ufs2_daddr_t blk, long size);
@@ -447,18 +467,24 @@ void blwrite(int fd, char *buf, ufs2_daddr_t blk, ssize_t size);
void blerase(int fd, ufs2_daddr_t blk, long size);
void blzero(int fd, ufs2_daddr_t blk, long size);
void brelse(struct bufarea *);
-void cacheino(union dinode *dp, ino_t inumber);
+struct inoinfo *cacheino(union dinode *dp, ino_t inumber);
void catch(int);
void catchquit(int);
void cgdirty(struct bufarea *);
struct bufarea *cglookup(int cg);
-int changeino(ino_t dir, const char *name, ino_t newnum);
-int check_cgmagic(int cg, struct bufarea *cgbp, int requestrebuild);
+int changeino(ino_t dir, const char *name, ino_t newnum, int depth);
+void check_blkcnt(struct inode *ip);
+int check_cgmagic(int cg, struct bufarea *cgbp);
+void rebuild_cg(int cg, struct bufarea *cgbp);
+void check_dirdepth(struct inoinfo *inp);
+int chkfilesize(mode_t mode, u_int64_t filesize);
int chkrange(ufs2_daddr_t blk, int cnt);
void ckfini(int markclean);
int ckinode(union dinode *dp, struct inodesc *);
void clri(struct inodesc *, const char *type, int flag);
int clearentry(struct inodesc *);
+void copyonwrite(struct fs *, struct bufarea *,
+ ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t, long));
void direrror(ino_t ino, const char *errmesg);
int dirscan(struct inodesc *);
int dofix(struct inodesc *, const char *msg);
@@ -469,16 +495,19 @@ int findino(struct inodesc *);
int findname(struct inodesc *);
void flush(int fd, struct bufarea *bp);
int freeblock(struct inodesc *);
+void freedirino(ino_t ino, ino_t parent);
void freeino(ino_t ino);
void freeinodebuf(void);
+void fsckinit(void);
void fsutilinit(void);
int ftypeok(union dinode *dp);
void getblk(struct bufarea *bp, ufs2_daddr_t blk, long size);
struct bufarea *getdatablk(ufs2_daddr_t blkno, long size, int type);
struct inoinfo *getinoinfo(ino_t inumber);
-union dinode *getnextinode(ino_t inumber, int rebuildcg);
+union dinode *getnextinode(ino_t inumber, int rebuiltcg);
void getpathname(char *namebuf, ino_t curdir, ino_t ino);
void ginode(ino_t, struct inode *);
+void gjournal_check(const char *filesys);
void infohandler(int sig);
void irelse(struct inode *);
ufs2_daddr_t ino_blkatoff(union dinode *, ino_t, ufs_lbn_t, int *,
@@ -500,17 +529,23 @@ void pass4(void);
void pass5(void);
void pfatal(const char *fmt, ...) __printflike(1, 2);
void propagate(void);
+void prtbuf(struct bufarea *, const char *, ...) __printflike(2, 3);
void prtinode(struct inode *);
void pwarn(const char *fmt, ...) __printflike(1, 2);
-int readsb(int listerr);
+int readsb(void);
+int removecachedino(ino_t);
int reply(const char *question);
void rwerror(const char *mesg, ufs2_daddr_t blk);
void sblock_init(void);
void setinodebuf(int, ino_t);
int setup(char *dev);
-void gjournal_check(const char *filesys);
+int snapblkfree(struct fs *, ufs2_daddr_t, long, ino_t,
+ ufs2_daddr_t (*)(ufs2_daddr_t, long));
+void snapremove(ino_t);
+void snapflush(ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t, long));
+ufs2_daddr_t std_checkblkavail(ufs2_daddr_t blkno, long frags);
+ufs2_daddr_t suj_checkblkavail(ufs2_daddr_t, long);
int suj_check(const char *filesys);
void update_maps(struct cg *, struct cg*, int);
-void fsckinit(void);
#endif /* !_FSCK_H_ */
diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8
index 35f3e112007b..8df5e684b963 100644
--- a/sbin/fsck_ffs/fsck_ffs.8
+++ b/sbin/fsck_ffs/fsck_ffs.8
@@ -26,10 +26,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)fsck.8 8.4 (Berkeley) 5/9/95
-.\" $FreeBSD$
-.\"
-.Dd May 3, 2019
+.Dd November 17, 2023
.Dt FSCK_FFS 8
.Os
.Sh NAME
@@ -424,6 +421,7 @@ are fully enumerated and explained in Appendix A of
.%T "Fsck \- The UNIX File System Check Program"
.Re
.Sh SEE ALSO
+.Xr ffs 4 ,
.Xr fs 5 ,
.Xr fstab 5 ,
.Xr fsck 8 ,
diff --git a/sbin/fsck_ffs/fsutil.c b/sbin/fsck_ffs/fsutil.c
index 711c9bb63549..2acf825b159f 100644
--- a/sbin/fsck_ffs/fsutil.c
+++ b/sbin/fsck_ffs/fsutil.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -60,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
-#include <libufs.h>
#include "fsck.h"
@@ -71,7 +62,6 @@ static void cg_write(struct bufarea *);
static void slowio_start(void);
static void slowio_end(void);
static void printIOstats(void);
-static void prtbuf(const char *, struct bufarea *);
static long diskreads, totaldiskreads, totalreads; /* Disk cache statistics */
static struct timespec startpass, finishpass;
@@ -79,11 +69,13 @@ struct timeval slowio_starttime;
int slowio_delay_usec = 10000; /* Initial IO delay for background fsck */
int slowio_pollcnt;
static struct bufarea cgblk; /* backup buffer for cylinder group blocks */
+static struct bufarea failedbuf; /* returned by failed getdatablk() */
static TAILQ_HEAD(bufqueue, bufarea) bufqueuehd; /* head of buffer cache LRU */
static LIST_HEAD(bufhash, bufarea) bufhashhd[HASHSIZE]; /* buffer hash list */
-static int numbufs; /* size of buffer cache */
-static int cachelookups; /* number of cache lookups */
-static int cachereads; /* number of cache reads */
+static struct bufhash freebufs; /* unused buffers */
+static int numbufs; /* size of buffer cache */
+static int cachelookups; /* number of cache lookups */
+static int cachereads; /* number of cache reads */
static int flushtries; /* number of tries to reclaim memory */
char *buftype[BT_NUMBUFTYPES] = BT_NAMES;
@@ -129,7 +121,8 @@ reply(const char *question)
if (preen)
pfatal("INTERNAL ERROR: GOT TO reply()");
- persevere = !strcmp(question, "CONTINUE");
+ persevere = strcmp(question, "CONTINUE") == 0 ||
+ strcmp(question, "LOOK FOR ALTERNATE SUPERBLOCKS") == 0;
printf("\n");
if (!persevere && (nflag || (fswritefd < 0 && bkgrdflag == 0))) {
printf("%s? no\n\n", question);
@@ -164,11 +157,11 @@ reply(const char *question)
struct inostat *
inoinfo(ino_t inum)
{
- static struct inostat unallocated = { USTATE, 0, 0 };
+ static struct inostat unallocated = { USTATE, 0, 0, 0 };
struct inostatlist *ilp;
int iloff;
- if (inum > maxino)
+ if (inum >= maxino)
errx(EEXIT, "inoinfo: inumber %ju out of range",
(uintmax_t)inum);
ilp = &inostathead[inum / sblock.fs_ipg];
@@ -186,11 +179,15 @@ bufinit(void)
{
int i;
- if ((cgblk.b_un.b_buf = Malloc((unsigned int)sblock.fs_bsize)) == NULL)
+ initbarea(&failedbuf, BT_UNKNOWN);
+ failedbuf.b_errs = -1;
+ failedbuf.b_un.b_buf = NULL;
+ if ((cgblk.b_un.b_buf = Balloc((unsigned int)sblock.fs_bsize)) == NULL)
errx(EEXIT, "Initial malloc(%d) failed", sblock.fs_bsize);
initbarea(&cgblk, BT_CYLGRP);
numbufs = cachelookups = cachereads = 0;
TAILQ_INIT(&bufqueuehd);
+ LIST_INIT(&freebufs);
for (i = 0; i < HASHSIZE; i++)
LIST_INIT(&bufhashhd[i]);
for (i = 0; i < BT_NUMBUFTYPES; i++) {
@@ -207,7 +204,7 @@ allocbuf(const char *failreason)
char *bufp;
bp = (struct bufarea *)Malloc(sizeof(struct bufarea));
- bufp = Malloc((unsigned int)sblock.fs_bsize);
+ bufp = Balloc((unsigned int)sblock.fs_bsize);
if (bp == NULL || bufp == NULL) {
errx(EEXIT, "%s", failreason);
/* NOTREACHED */
@@ -237,7 +234,7 @@ cglookup(int cg)
if ((unsigned) cg >= sblock.fs_ncg)
errx(EEXIT, "cglookup: out of range cylinder group %d", cg);
if (cgbufs == NULL) {
- cgbufs = calloc(sblock.fs_ncg, sizeof(struct bufarea));
+ cgbufs = Calloc(sblock.fs_ncg, sizeof(struct bufarea));
if (cgbufs == NULL)
errx(EEXIT, "Cannot allocate cylinder group buffers");
}
@@ -246,7 +243,7 @@ cglookup(int cg)
return (cgbp);
cgp = NULL;
if (flushtries == 0)
- cgp = Malloc((unsigned int)sblock.fs_cgsize);
+ cgp = Balloc((unsigned int)sblock.fs_cgsize);
if (cgp == NULL) {
if (sujrecovery)
errx(EEXIT,"Ran out of memory during journal recovery");
@@ -299,7 +296,7 @@ flushentry(void)
}
/*
- * Manage a cache of directory blocks.
+ * Manage a cache of filesystem disk blocks.
*/
struct bufarea *
getdatablk(ufs2_daddr_t blkno, long size, int type)
@@ -308,19 +305,25 @@ getdatablk(ufs2_daddr_t blkno, long size, int type)
struct bufhash *bhdp;
cachelookups++;
- /* If out of range, return empty buffer with b_err == -1 */
+ /*
+ * If out of range, return empty buffer with b_err == -1
+ *
+ * Skip check for inodes because chkrange() considers
+ * metadata areas invalid to write data.
+ */
if (type != BT_INODES && chkrange(blkno, size / sblock.fs_fsize)) {
- blkno = -1;
- type = BT_EMPTY;
+ failedbuf.b_refcnt++;
+ return (&failedbuf);
}
bhdp = &bufhashhd[HASH(blkno)];
LIST_FOREACH(bp, bhdp, b_hash)
if (bp->b_bno == fsbtodb(&sblock, blkno)) {
if (debug && bp->b_size != size) {
- prtbuf("getdatablk: size mismatch", bp);
+ prtbuf(bp, "getdatablk: size mismatch");
pfatal("getdatablk: b_size %d != size %ld\n",
bp->b_size, size);
}
+ TAILQ_REMOVE(&bufqueuehd, bp, b_list);
goto foundit;
}
/*
@@ -339,7 +342,9 @@ getdatablk(ufs2_daddr_t blkno, long size, int type)
if (size > sblock.fs_bsize)
errx(EEXIT, "Excessive buffer size %ld > %d\n", size,
sblock.fs_bsize);
- if (numbufs < MINBUFS) {
+ if ((bp = LIST_FIRST(&freebufs)) != NULL) {
+ LIST_REMOVE(bp, b_hash);
+ } else if (numbufs < MINBUFS) {
bp = allocbuf("cannot create minimal buffer pool");
} else if (sujrecovery) {
/*
@@ -367,6 +372,7 @@ getdatablk(ufs2_daddr_t blkno, long size, int type)
else
LIST_REMOVE(bp, b_hash);
}
+ TAILQ_REMOVE(&bufqueuehd, bp, b_list);
flush(fswritefd, bp);
bp->b_type = type;
LIST_INSERT_HEAD(bhdp, bp, b_hash);
@@ -374,13 +380,12 @@ getdatablk(ufs2_daddr_t blkno, long size, int type)
cachereads++;
/* fall through */
foundit:
+ TAILQ_INSERT_HEAD(&bufqueuehd, bp, b_list);
if (debug && bp->b_type != type) {
printf("getdatablk: buffer type changed to %s",
BT_BUFTYPE(type));
- prtbuf("", bp);
+ prtbuf(bp, "");
}
- TAILQ_REMOVE(&bufqueuehd, bp, b_list);
- TAILQ_INSERT_HEAD(&bufqueuehd, bp, b_list);
if (bp->b_errs == 0)
bp->b_refcnt++;
return (bp);
@@ -400,11 +405,7 @@ getblk(struct bufarea *bp, ufs2_daddr_t blk, long size)
readcnt[bp->b_type]++;
clock_gettime(CLOCK_REALTIME_PRECISE, &start);
}
- if (bp->b_type != BT_EMPTY)
- bp->b_errs =
- blread(fsreadfd, bp->b_un.b_buf, dblk, size);
- else
- bp->b_errs = -1;
+ bp->b_errs = blread(fsreadfd, bp->b_un.b_buf, dblk, size);
if (debug) {
clock_gettime(CLOCK_REALTIME_PRECISE, &finish);
timespecsub(&finish, &start, &finish);
@@ -421,11 +422,20 @@ brelse(struct bufarea *bp)
{
if (bp->b_refcnt <= 0)
- prtbuf("brelse: buffer with negative reference count", bp);
+ prtbuf(bp, "brelse: buffer with negative reference count");
bp->b_refcnt--;
}
void
+binval(struct bufarea *bp)
+{
+
+ bp->b_flags &= ~B_DIRTY;
+ LIST_REMOVE(bp, b_hash);
+ LIST_INSERT_HEAD(&freebufs, bp, b_hash);
+}
+
+void
flush(int fd, struct bufarea *bp)
{
struct inode ip;
@@ -450,10 +460,18 @@ flush(int fd, struct bufarea *bp)
if (bp != &sblk)
pfatal("BUFFER %p DOES NOT MATCH SBLK %p\n",
bp, &sblk);
+ /*
+ * Superblocks are always pre-copied so we do not need
+ * to check them for copy-on-write.
+ */
if (sbput(fd, bp->b_un.b_fs, 0) == 0)
fsmodified = 1;
break;
case BT_CYLGRP:
+ /*
+ * Cylinder groups are always pre-copied so we do not
+ * need to check them for copy-on-write.
+ */
if (sujrecovery)
cg_write(bp);
if (cgput(fswritefd, &sblock, bp->b_un.b_cg) == 0)
@@ -464,13 +482,13 @@ flush(int fd, struct bufarea *bp)
struct ufs2_dinode *dp = bp->b_un.b_dinode2;
int i;
- for (i = 0; i < INOPB(&sblock); dp++, i++) {
+ for (i = 0; i < bp->b_size; dp++, i += sizeof(*dp)) {
if (ffs_verify_dinode_ckhash(&sblock, dp) == 0)
continue;
pwarn("flush: INODE CHECK-HASH FAILED");
ip.i_bp = bp;
ip.i_dp = (union dinode *)dp;
- ip.i_number = bp->b_index + i;
+ ip.i_number = bp->b_index + (i / sizeof(*dp));
prtinode(&ip);
if (preen || reply("FIX") != 0) {
if (preen)
@@ -482,12 +500,39 @@ flush(int fd, struct bufarea *bp)
}
/* FALLTHROUGH */
default:
+ copyonwrite(&sblock, bp, std_checkblkavail);
blwrite(fd, bp->b_un.b_buf, bp->b_bno, bp->b_size);
break;
}
}
/*
+ * If there are any snapshots, ensure that all the blocks that they
+ * care about have been copied, then release the snapshot inodes.
+ * These operations need to be done before we rebuild the cylinder
+ * groups so that any block allocations are properly recorded.
+ * Since all the cylinder group maps have already been copied in
+ * the snapshots, no further snapshot copies will need to be done.
+ */
+void
+snapflush(ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t, long))
+{
+ struct bufarea *bp;
+ int cnt;
+
+ if (snapcnt > 0) {
+ if (debug)
+ printf("Check for snapshot copies\n");
+ TAILQ_FOREACH_REVERSE(bp, &bufqueuehd, bufqueue, b_list)
+ if ((bp->b_flags & B_DIRTY) != 0)
+ copyonwrite(&sblock, bp, checkblkavail);
+ for (cnt = 0; cnt < snapcnt; cnt++)
+ irelse(&snaplist[cnt]);
+ snapcnt = 0;
+ }
+}
+
+/*
* Journaled soft updates does not maintain cylinder group summary
* information during cleanup, so this routine recalculates the summary
* information and updates the superblock summary in preparation for
@@ -498,6 +543,7 @@ cg_write(struct bufarea *bp)
{
ufs1_daddr_t fragno, cgbno, maxbno;
u_int8_t *blksfree;
+ struct csum *csp;
struct cg *cgp;
int blk;
int i;
@@ -535,6 +581,11 @@ cg_write(struct bufarea *bp)
* Update the superblock cg summary from our now correct values
* before writing the block.
*/
+ csp = &sblock.fs_cs(&sblock, cgp->cg_cgx);
+ sblock.fs_cstotal.cs_ndir += cgp->cg_cs.cs_ndir - csp->cs_ndir;
+ sblock.fs_cstotal.cs_nbfree += cgp->cg_cs.cs_nbfree - csp->cs_nbfree;
+ sblock.fs_cstotal.cs_nifree += cgp->cg_cs.cs_nifree - csp->cs_nifree;
+ sblock.fs_cstotal.cs_nffree += cgp->cg_cs.cs_nffree - csp->cs_nffree;
sblock.fs_cs(&sblock, cgp->cg_cgx) = cgp->cg_cs;
}
@@ -555,11 +606,9 @@ void
ckfini(int markclean)
{
struct bufarea *bp, *nbp;
- struct inoinfo *inp, *ninp;
- int ofsmodified, cnt, cg, i;
+ int ofsmodified, cnt, cg;
if (bkgrdflag) {
- unlink(snapname);
if ((!(sblock.fs_flags & FS_UNCLEAN)) != markclean) {
cmd.value = FS_UNCLEAN;
cmd.size = markclean ? -1 : 1;
@@ -586,6 +635,7 @@ ckfini(int markclean)
(void)close(fsreadfd);
return;
}
+
/*
* To remain idempotent with partial truncations the buffers
* must be flushed in this order:
@@ -628,14 +678,9 @@ ckfini(int markclean)
case BT_SUPERBLK:
case BT_CYLGRP:
default:
- prtbuf("ckfini: improper buffer type on cache list",bp);
+ prtbuf(bp,"ckfini: improper buffer type on cache list");
continue;
/* These are the ones to flush in this step */
- case BT_EMPTY:
- if (bp->b_bno >= 0)
- pfatal("Unused BT_EMPTY buffer for block %jd\n",
- (intmax_t)bp->b_bno);
- /* FALLTHROUGH */
case BT_LEVEL1:
case BT_LEVEL2:
case BT_LEVEL3:
@@ -647,11 +692,10 @@ ckfini(int markclean)
case BT_INODES:
continue;
}
- if (debug && bp->b_refcnt != 0) {
- prtbuf("ckfini: clearing in-use buffer", bp);
- pfatal("ckfini: clearing in-use buffer\n");
- }
+ if (debug && bp->b_refcnt != 0)
+ prtbuf(bp, "ckfini: clearing in-use buffer");
TAILQ_REMOVE(&bufqueuehd, bp, b_list);
+ LIST_REMOVE(bp, b_hash);
cnt++;
flush(fswritefd, bp);
free(bp->b_un.b_buf);
@@ -665,11 +709,10 @@ ckfini(int markclean)
icachebp = NULL;
}
TAILQ_FOREACH_REVERSE_SAFE(bp, &bufqueuehd, bufqueue, b_list, nbp) {
- if (debug && bp->b_refcnt != 0) {
- prtbuf("ckfini: clearing in-use buffer", bp);
- pfatal("ckfini: clearing in-use buffer\n");
- }
+ if (debug && bp->b_refcnt != 0)
+ prtbuf(bp, "ckfini: clearing in-use buffer");
TAILQ_REMOVE(&bufqueuehd, bp, b_list);
+ LIST_REMOVE(bp, b_hash);
cnt++;
flush(fswritefd, bp);
free(bp->b_un.b_buf);
@@ -681,14 +724,17 @@ ckfini(int markclean)
if (debug)
printf("Flush the superblock\n");
flush(fswritefd, &sblk);
- if (havesb && cursnapshot == 0 && sblock.fs_magic == FS_UFS2_MAGIC &&
- sblk.b_bno != sblock.fs_sblockloc / dev_bsize &&
- !preen && reply("UPDATE STANDARD SUPERBLOCK")) {
- /* Change the write destination to standard superblock */
- sblock.fs_sblockactualloc = sblock.fs_sblockloc;
- sblk.b_bno = sblock.fs_sblockloc / dev_bsize;
- sbdirty();
- flush(fswritefd, &sblk);
+ if (havesb && cursnapshot == 0 &&
+ sblk.b_bno != sblock.fs_sblockloc / dev_bsize) {
+ if (preen || reply("UPDATE STANDARD SUPERBLOCK")) {
+ /* Change write destination to standard superblock */
+ sblock.fs_sblockactualloc = sblock.fs_sblockloc;
+ sblk.b_bno = sblock.fs_sblockloc / dev_bsize;
+ sbdirty();
+ flush(fswritefd, &sblk);
+ } else {
+ markclean = 0;
+ }
}
if (cursnapshot == 0 && sblock.fs_clean != markclean) {
if ((sblock.fs_clean = markclean) != 0) {
@@ -727,19 +773,7 @@ ckfini(int markclean)
free(inostathead);
}
inostathead = NULL;
- if (inpsort != NULL)
- free(inpsort);
- inpsort = NULL;
- if (inphead != NULL) {
- for (i = 0; i < dirhash; i++) {
- for (inp = inphead[i]; inp != NULL; inp = ninp) {
- ninp = inp->i_nexthash;
- free(inp);
- }
- }
- free(inphead);
- }
- inphead = NULL;
+ inocleanup();
finalIOstats();
(void)close(fsreadfd);
(void)close(fswritefd);
@@ -925,7 +959,7 @@ blzero(int fd, ufs2_daddr_t blk, long size)
if (fd < 0)
return;
if (zero == NULL) {
- zero = calloc(ZEROBUFSIZE, 1);
+ zero = Balloc(ZEROBUFSIZE);
if (zero == NULL)
errx(EEXIT, "cannot allocate buffer pool");
}
@@ -944,13 +978,26 @@ blzero(int fd, ufs2_daddr_t blk, long size)
/*
* Verify cylinder group's magic number and other parameters. If the
* test fails, offer an option to rebuild the whole cylinder group.
+ *
+ * Return 1 if the cylinder group is good or return 0 if it is bad.
*/
+#undef CHK
+#define CHK(lhs, op, rhs, fmt) \
+ if (lhs op rhs) { \
+ pwarn("UFS%d cylinder group %d failed: " \
+ "%s (" #fmt ") %s %s (" #fmt ")\n", \
+ sblock.fs_magic == FS_UFS1_MAGIC ? 1 : 2, cg, \
+ #lhs, (intmax_t)lhs, #op, #rhs, (intmax_t)rhs); \
+ error = 1; \
+ }
int
-check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
+check_cgmagic(int cg, struct bufarea *cgbp)
{
struct cg *cgp = cgbp->b_un.b_cg;
uint32_t cghash, calchash;
static int prevfailcg = -1;
+ long start;
+ int error;
/*
* Extended cylinder group checks.
@@ -963,32 +1010,69 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
calchash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
cgp->cg_ckhash = cghash;
}
- if (cgp->cg_ckhash == calchash &&
- cg_chkmagic(cgp) &&
- cgp->cg_cgx == cg &&
- ((sblock.fs_magic == FS_UFS1_MAGIC &&
- cgp->cg_old_niblk == sblock.fs_ipg &&
- cgp->cg_ndblk <= sblock.fs_fpg &&
- cgp->cg_old_ncyl <= sblock.fs_old_cpg) ||
- (sblock.fs_magic == FS_UFS2_MAGIC &&
- cgp->cg_niblk == sblock.fs_ipg &&
- cgp->cg_ndblk <= sblock.fs_fpg &&
- cgp->cg_initediblk <= sblock.fs_ipg))) {
- return (1);
+ error = 0;
+ CHK(cgp->cg_ckhash, !=, calchash, "%jd");
+ CHK(cg_chkmagic(cgp), ==, 0, "%jd");
+ CHK(cgp->cg_cgx, !=, cg, "%jd");
+ CHK(cgp->cg_ndblk, >, sblock.fs_fpg, "%jd");
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ CHK(cgp->cg_old_niblk, !=, sblock.fs_ipg, "%jd");
+ } else if (sblock.fs_magic == FS_UFS2_MAGIC) {
+ CHK(cgp->cg_niblk, !=, sblock.fs_ipg, "%jd");
+ CHK(cgp->cg_initediblk, >, sblock.fs_ipg, "%jd");
+ }
+ if (cgbase(&sblock, cg) + sblock.fs_fpg < sblock.fs_size) {
+ CHK(cgp->cg_ndblk, !=, sblock.fs_fpg, "%jd");
+ } else {
+ CHK(cgp->cg_ndblk, !=, sblock.fs_size - cgbase(&sblock, cg),
+ "%jd");
+ }
+ start = sizeof(*cgp);
+ if (sblock.fs_magic == FS_UFS2_MAGIC) {
+ CHK(cgp->cg_iusedoff, !=, start, "%jd");
+ } else if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ CHK(cgp->cg_niblk, !=, 0, "%jd");
+ CHK(cgp->cg_initediblk, !=, 0, "%jd");
+ CHK(cgp->cg_old_niblk, !=, sblock.fs_ipg, "%jd");
+ CHK(cgp->cg_old_btotoff, !=, start, "%jd");
+ CHK(cgp->cg_old_boff, !=, cgp->cg_old_btotoff +
+ sblock.fs_old_cpg * sizeof(int32_t), "%jd");
+ CHK(cgp->cg_iusedoff, !=, cgp->cg_old_boff +
+ sblock.fs_old_cpg * sizeof(u_int16_t), "%jd");
}
+ CHK(cgp->cg_freeoff, !=,
+ cgp->cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT), "%jd");
+ if (sblock.fs_contigsumsize == 0) {
+ CHK(cgp->cg_nextfreeoff, !=,
+ cgp->cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT), "%jd");
+ } else {
+ CHK(cgp->cg_nclusterblks, !=, cgp->cg_ndblk / sblock.fs_frag,
+ "%jd");
+ CHK(cgp->cg_clustersumoff, !=,
+ roundup(cgp->cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT),
+ sizeof(u_int32_t)) - sizeof(u_int32_t), "%jd");
+ CHK(cgp->cg_clusteroff, !=, cgp->cg_clustersumoff +
+ (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t), "%jd");
+ CHK(cgp->cg_nextfreeoff, !=, cgp->cg_clusteroff +
+ howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT),
+ "%jd");
+ }
+ if (error == 0)
+ return (1);
if (prevfailcg == cg)
return (0);
prevfailcg = cg;
pfatal("CYLINDER GROUP %d: INTEGRITY CHECK FAILED", cg);
- if (!request_rebuild) {
- printf("\n");
- return (0);
- }
- if (!reply("REBUILD CYLINDER GROUP")) {
- printf("YOU WILL NEED TO RERUN FSCK.\n");
- rerun = 1;
- return (1);
- }
+ printf("\n");
+ return (0);
+}
+
+void
+rebuild_cg(int cg, struct bufarea *cgbp)
+{
+ struct cg *cgp = cgbp->b_un.b_cg;
+ long start;
+
/*
* Zero out the cylinder group and then initialize critical fields.
* Bit maps and summaries will be recalculated by later passes.
@@ -1002,13 +1086,15 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
cgp->cg_ndblk = sblock.fs_fpg;
else
cgp->cg_ndblk = sblock.fs_size - cgbase(&sblock, cg);
- cgp->cg_iusedoff = &cgp->cg_space[0] - (u_char *)(&cgp->cg_firstfield);
- if (sblock.fs_magic == FS_UFS1_MAGIC) {
+ start = sizeof(*cgp);
+ if (sblock.fs_magic == FS_UFS2_MAGIC) {
+ cgp->cg_iusedoff = start;
+ } else if (sblock.fs_magic == FS_UFS1_MAGIC) {
cgp->cg_niblk = 0;
cgp->cg_initediblk = 0;
cgp->cg_old_ncyl = sblock.fs_old_cpg;
cgp->cg_old_niblk = sblock.fs_ipg;
- cgp->cg_old_btotoff = cgp->cg_iusedoff;
+ cgp->cg_old_btotoff = start;
cgp->cg_old_boff = cgp->cg_old_btotoff +
sblock.fs_old_cpg * sizeof(int32_t);
cgp->cg_iusedoff = cgp->cg_old_boff +
@@ -1026,58 +1112,115 @@ check_cgmagic(int cg, struct bufarea *cgbp, int request_rebuild)
cgp->cg_nextfreeoff = cgp->cg_clusteroff +
howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
}
+ cgp->cg_ckhash = calculate_crc32c(~0L, (void *)cgp, sblock.fs_cgsize);
cgdirty(cgbp);
- return (0);
}
/*
* allocate a data block with the specified number of fragments
*/
ufs2_daddr_t
-allocblk(long frags)
+allocblk(long startcg, long frags,
+ ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t blkno, long frags))
+{
+ ufs2_daddr_t blkno, newblk;
+
+ if (sujrecovery && checkblkavail == std_checkblkavail) {
+ pfatal("allocblk: std_checkblkavail used for SUJ recovery\n");
+ return (0);
+ }
+ if (frags <= 0 || frags > sblock.fs_frag)
+ return (0);
+ for (blkno = MAX(cgdata(&sblock, startcg), 0);
+ blkno < maxfsblock - sblock.fs_frag;
+ blkno += sblock.fs_frag) {
+ if ((newblk = (*checkblkavail)(blkno, frags)) == 0)
+ continue;
+ if (newblk > 0)
+ return (newblk);
+ if (newblk < 0)
+ blkno = -newblk;
+ }
+ for (blkno = MAX(cgdata(&sblock, 0), 0);
+ blkno < cgbase(&sblock, startcg) - sblock.fs_frag;
+ blkno += sblock.fs_frag) {
+ if ((newblk = (*checkblkavail)(blkno, frags)) == 0)
+ continue;
+ if (newblk > 0)
+ return (newblk);
+ if (newblk < 0)
+ blkno = -newblk;
+ }
+ return (0);
+}
+
+ufs2_daddr_t
+std_checkblkavail(ufs2_daddr_t blkno, long frags)
{
- int i, j, k, cg, baseblk;
struct bufarea *cgbp;
struct cg *cgp;
+ ufs2_daddr_t j, k, baseblk;
+ long cg;
- if (frags <= 0 || frags > sblock.fs_frag)
+ if ((u_int64_t)blkno > sblock.fs_size)
return (0);
- for (i = 0; i < maxfsblock - sblock.fs_frag; i += sblock.fs_frag) {
- for (j = 0; j <= sblock.fs_frag - frags; j++) {
- if (testbmap(i + j))
- continue;
- for (k = 1; k < frags; k++)
- if (testbmap(i + j + k))
- break;
- if (k < frags) {
- j += k;
- continue;
- }
- cg = dtog(&sblock, i + j);
- cgbp = cglookup(cg);
- cgp = cgbp->b_un.b_cg;
- if (!check_cgmagic(cg, cgbp, 0)) {
- i = (cg + 1) * sblock.fs_fpg - sblock.fs_frag;
- continue;
- }
- baseblk = dtogd(&sblock, i + j);
- for (k = 0; k < frags; k++) {
- setbmap(i + j + k);
- clrbit(cg_blksfree(cgp), baseblk + k);
- }
- n_blks += frags;
- if (frags == sblock.fs_frag)
- cgp->cg_cs.cs_nbfree--;
- else
- cgp->cg_cs.cs_nffree -= frags;
- cgdirty(cgbp);
- return (i + j);
+ for (j = 0; j <= sblock.fs_frag - frags; j++) {
+ if (testbmap(blkno + j))
+ continue;
+ for (k = 1; k < frags; k++)
+ if (testbmap(blkno + j + k))
+ break;
+ if (k < frags) {
+ j += k;
+ continue;
+ }
+ cg = dtog(&sblock, blkno + j);
+ cgbp = cglookup(cg);
+ cgp = cgbp->b_un.b_cg;
+ if (!check_cgmagic(cg, cgbp))
+ return (-((cg + 1) * sblock.fs_fpg - sblock.fs_frag));
+ baseblk = dtogd(&sblock, blkno + j);
+ for (k = 0; k < frags; k++) {
+ setbmap(blkno + j + k);
+ clrbit(cg_blksfree(cgp), baseblk + k);
}
+ n_blks += frags;
+ if (frags == sblock.fs_frag)
+ cgp->cg_cs.cs_nbfree--;
+ else
+ cgp->cg_cs.cs_nffree -= frags;
+ cgdirty(cgbp);
+ return (blkno + j);
}
return (0);
}
/*
+ * Check whether a file size is within the limits for the filesystem.
+ * Return 1 when valid and 0 when too big.
+ *
+ * This should match the file size limit in ffs_mountfs().
+ */
+int
+chkfilesize(mode_t mode, u_int64_t filesize)
+{
+ u_int64_t kernmaxfilesize;
+
+ if (sblock.fs_magic == FS_UFS1_MAGIC)
+ kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1;
+ else
+ kernmaxfilesize = sblock.fs_maxfilesize;
+ if (filesize > kernmaxfilesize ||
+ filesize > sblock.fs_maxfilesize ||
+ (mode == IFDIR && filesize > MAXDIRSIZE)) {
+ if (debug)
+ printf("bad file size %ju:", (uintmax_t)filesize);
+ return (0);
+ }
+ return (1);
+}
+
+/*
* Slow down IO so as to leave some disk bandwidth for other processes
*/
void
@@ -1151,9 +1294,11 @@ getpathname(char *namebuf, ino_t curdir, ino_t ino)
ginode(ino, &ip);
if ((ckinode(ip.i_dp, &idesc) & FOUND) == 0) {
irelse(&ip);
+ free(idesc.id_name);
break;
}
irelse(&ip);
+ free(idesc.id_name);
namelookup:
idesc.id_number = idesc.id_parent;
idesc.id_parent = ino;
@@ -1245,12 +1390,17 @@ dofix(struct inodesc *idesc, const char *msg)
/*
* Print details about a buffer.
*/
-static void
-prtbuf(const char *msg, struct bufarea *bp)
+void
+prtbuf(struct bufarea *bp, const char *fmt, ...)
{
-
- printf("%s: bp %p, type %s, bno %jd, size %d, refcnt %d, flags %s, "
- "index %jd\n", msg, bp, BT_BUFTYPE(bp->b_type), (intmax_t) bp->b_bno,
+ va_list ap;
+ va_start(ap, fmt);
+ if (preen)
+ (void)fprintf(stdout, "%s: ", cdevname);
+ (void)vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ printf(": bp %p, type %s, bno %jd, size %d, refcnt %d, flags %s, "
+ "index %jd\n", bp, BT_BUFTYPE(bp->b_type), (intmax_t) bp->b_bno,
bp->b_size, bp->b_refcnt, bp->b_flags & B_DIRTY ? "dirty" : "clean",
(intmax_t) bp->b_index);
}
diff --git a/sbin/fsck_ffs/gjournal.c b/sbin/fsck_ffs/gjournal.c
index b65589b5bd08..b94f27758315 100644
--- a/sbin/fsck_ffs/gjournal.c
+++ b/sbin/fsck_ffs/gjournal.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-3-Clause AND BSD-2-Clause
*
* Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -54,8 +54,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <string.h>
#include <sys/stat.h>
#include <ufs/ffs/fs.h>
@@ -77,7 +75,6 @@ gjournal_check(const char *filesys)
fs = &sblock;
/* Are there any unreferenced inodes in this file system? */
if (fs->fs_unrefs == 0) {
- //printf("No unreferenced inodes.\n");
sbdirty();
ckfini(1);
return;
@@ -97,7 +94,7 @@ gjournal_check(const char *filesys)
}
cgbp = cglookup(cg);
cgp = cgbp->b_un.b_cg;
- if (!check_cgmagic(cg, cgbp, 0)) {
+ if (!check_cgmagic(cg, cgbp)) {
rerun = 1;
ckfini(0);
return;
@@ -105,7 +102,6 @@ gjournal_check(const char *filesys)
/* Are there any unreferenced inodes in this cylinder group? */
if (cgp->cg_unrefs == 0)
continue;
- //printf("Analizing cylinder group %d (count=%d)\n", cg, cgp->cg_unrefs);
/*
* Now go through the list of all inodes in this cylinder group
* to find unreferenced ones.
@@ -150,20 +146,15 @@ gjournal_check(const char *filesys)
inodirty(&ip);
irelse(&ip);
cgdirty(cgbp);
- if (cgp->cg_unrefs == 0) {
- //printf("No more unreferenced inodes in cg=%d.\n", cg);
+ if (cgp->cg_unrefs == 0)
break;
- }
}
/*
- * If there are no more unreferenced inodes, there is no need to
- * check other cylinder groups.
+ * If there are no more unreferenced inodes, there is no
+ * need to check other cylinder groups.
*/
- if (fs->fs_unrefs == 0) {
- //printf("No more unreferenced inodes (cg=%d/%d).\n", cg,
- // fs->fs_ncg);
+ if (fs->fs_unrefs == 0)
break;
- }
}
/* Write back updated statistics and super-block. */
sbdirty();
diff --git a/sbin/fsck_ffs/globs.c b/sbin/fsck_ffs/globs.c
index 09dbcc6694a2..1f04311e2e5c 100644
--- a/sbin/fsck_ffs/globs.c
+++ b/sbin/fsck_ffs/globs.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1986, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
@@ -60,19 +46,19 @@ ino_t cursnapshot;
long dirhash, inplast;
unsigned long numdirs, listmax;
long countdirs; /* number of directories we actually found */
-int adjrefcnt[MIBSIZE]; /* MIB command to adjust inode reference cnt */
-int adjblkcnt[MIBSIZE]; /* MIB command to adjust inode block count */
-int setsize[MIBSIZE]; /* MIB command to set inode size */
-int adjndir[MIBSIZE]; /* MIB command to adjust number of directories */
-int adjnbfree[MIBSIZE]; /* MIB command to adjust number of free blocks */
-int adjnifree[MIBSIZE]; /* MIB command to adjust number of free inodes */
-int adjnffree[MIBSIZE]; /* MIB command to adjust number of free frags */
-int adjnumclusters[MIBSIZE]; /* MIB command to adjust number of free clusters */
-int freefiles[MIBSIZE]; /* MIB command to free a set of files */
-int freedirs[MIBSIZE]; /* MIB command to free a set of directories */
-int freeblks[MIBSIZE]; /* MIB command to free a set of data blocks */
+int adjrefcnt[MIBSIZE]; /* MIB cmd to adjust inode reference cnt */
+int adjblkcnt[MIBSIZE]; /* MIB cmd to adjust inode block count */
+int setsize[MIBSIZE]; /* MIB cmd to set inode size */
+int adjndir[MIBSIZE]; /* MIB cmd to adjust number of directories */
+int adjnbfree[MIBSIZE]; /* MIB cmd to adjust number of free blocks */
+int adjnifree[MIBSIZE]; /* MIB cmd to adjust number of free inodes */
+int adjnffree[MIBSIZE]; /* MIB cmd to adjust number of free frags */
+int adjnumclusters[MIBSIZE]; /* MIB cmd to adjust number of free clusters */
+int adjdepth[MIBSIZE]; /* MIB cmd to adjust directory depth count */
+int freefiles[MIBSIZE]; /* MIB cmd to free a set of files */
+int freedirs[MIBSIZE]; /* MIB cmd to free a set of directories */
+int freeblks[MIBSIZE]; /* MIB cmd to free a set of data blocks */
struct fsck_cmd cmd; /* sysctl file system update commands */
-char snapname[BUFSIZ]; /* when doing snapshots, the name of the file */
char *cdevname; /* name of device being checked */
long dev_bsize; /* computed value of DEV_BSIZE */
long secsize; /* actual disk sector size */
@@ -90,13 +76,12 @@ char ckclean; /* only do work if not cleanly unmounted */
int cvtlevel; /* convert to newer file system format */
int ckhashadd; /* check hashes to be added */
int bkgrdcheck; /* determine if background check is possible */
-int bkgrdsumadj; /* whether the kernel have ability to adjust superblock summary */
+int bkgrdsumadj; /* kernel able to adjust superblock summary */
char usedsoftdep; /* just fix soft dependency inconsistencies */
char preen; /* just fix normal inconsistencies */
char rerun; /* rerun fsck. Only used in non-preen mode */
int returntosingle; /* 1 => return to single user mode on exit */
char resolved; /* cleared if unresolved changes => not clean */
-int sbhashfailed; /* when reading superblock check hash failed */
char havesb; /* superblock has been read */
char skipclean; /* skip clean file systems if preening */
int fsmodified; /* 1 => write done to file system */
@@ -111,6 +96,7 @@ ino_t lfdir; /* lost & found directory inode number */
const char *lfname; /* lost & found directory name */
int lfmode; /* lost & found directory creation mode */
ufs2_daddr_t n_blks; /* number of blocks in use */
+int cgheader_corrupt; /* one or more CG headers are corrupt */
ino_t n_files; /* number of files in use */
volatile sig_atomic_t got_siginfo; /* received a SIGINFO */
volatile sig_atomic_t got_sigalarm; /* received a SIGALRM */
@@ -140,11 +126,11 @@ fsckinit(void)
bzero(adjnifree, sizeof(int) * MIBSIZE);
bzero(adjnffree, sizeof(int) * MIBSIZE);
bzero(adjnumclusters, sizeof(int) * MIBSIZE);
+ bzero(adjdepth, sizeof(int) * MIBSIZE);
bzero(freefiles, sizeof(int) * MIBSIZE);
bzero(freedirs, sizeof(int) * MIBSIZE);
bzero(freeblks, sizeof(int) * MIBSIZE);
bzero(&cmd, sizeof(struct fsck_cmd));
- bzero(snapname, sizeof(char) * BUFSIZ);
cdevname = NULL;
dev_bsize = 0;
secsize = 0;
@@ -156,7 +142,6 @@ fsckinit(void)
resolved = 0;
havesb = 0;
fsmodified = 0;
- sbhashfailed = 0;
fsreadfd = -1;
fswritefd = -1;
maxfsblock = 0;
@@ -166,6 +151,7 @@ fsckinit(void)
lfmode = 0700;
n_blks = 0;
n_files = 0;
+ cgheader_corrupt = 0;
got_siginfo = 0;
got_sigalarm = 0;
bzero(&zino.dp1, sizeof(struct ufs1_dinode));
diff --git a/sbin/fsck_ffs/inode.c b/sbin/fsck_ffs/inode.c
index 47f72c84a1f2..b30e3aa5068b 100644
--- a/sbin/fsck_ffs/inode.c
+++ b/sbin/fsck_ffs/inode.c
@@ -29,15 +29,8 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)inode.c 8.8 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
+#include <sys/stat.h>
#include <sys/stdint.h>
#include <sys/sysctl.h>
@@ -49,15 +42,18 @@ __FBSDID("$FreeBSD$");
#include <pwd.h>
#include <string.h>
#include <time.h>
-#include <libufs.h>
#include "fsck.h"
struct bufarea *icachebp; /* inode cache buffer */
+static time_t now; /* current time of day */
static int iblock(struct inodesc *, off_t isize, int type);
static ufs2_daddr_t indir_blkatoff(ufs2_daddr_t, ino_t, ufs_lbn_t, ufs_lbn_t,
struct bufarea **);
+static int snapclean(struct inodesc *idesc);
+static void chkcopyonwrite(struct fs *, ufs2_daddr_t,
+ ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t, long));
int
ckinode(union dinode *dp, struct inodesc *idesc)
@@ -86,6 +82,10 @@ ckinode(union dinode *dp, struct inodesc *idesc)
dino.dp1 = dp->dp1;
else
dino.dp2 = dp->dp2;
+ if (DIP(&dino, di_size) < 0) {
+ pfatal("NEGATIVE INODE SIZE %jd\n", DIP(&dino, di_size));
+ return (STOP);
+ }
ndb = howmany(DIP(&dino, di_size), sblock.fs_bsize);
for (i = 0; i < UFS_NDADDR; i++) {
idesc->id_lbn++;
@@ -112,6 +112,7 @@ ckinode(union dinode *dp, struct inodesc *idesc)
inodirty(&ip);
irelse(&ip);
}
+ return (STOP);
}
continue;
}
@@ -377,9 +378,13 @@ chkrange(ufs2_daddr_t blk, int cnt)
{
int c;
- if (cnt <= 0 || blk <= 0 || blk > maxfsblock ||
- cnt - 1 > maxfsblock - blk)
+ if (cnt <= 0 || blk <= 0 || blk >= maxfsblock ||
+ cnt > maxfsblock - blk) {
+ if (debug)
+ printf("out of range: blk %ld, offset %i, size %d\n",
+ (long)blk, (int)fragnum(&sblock, blk), cnt);
return (1);
+ }
if (cnt > sblock.fs_frag ||
fragnum(&sblock, blk) + cnt > sblock.fs_frag) {
if (debug)
@@ -415,21 +420,34 @@ chkrange(ufs2_daddr_t blk, int cnt)
/*
* General purpose interface for reading inodes.
+ *
+ * firstinum and lastinum track contents of getnextino() cache (below).
*/
+static ino_t firstinum, lastinum;
+static struct bufarea inobuf;
+
void
ginode(ino_t inumber, struct inode *ip)
{
ufs2_daddr_t iblk;
+ union dinodep dpp;
+ struct ufs2_dinode *dp;
- if (inumber < UFS_ROOTINO || inumber > maxino)
+ if (inumber < UFS_ROOTINO || inumber >= maxino)
errx(EEXIT, "bad inode number %ju to ginode",
(uintmax_t)inumber);
ip->i_number = inumber;
- if (icachebp != NULL &&
+ if (inumber >= firstinum && inumber < lastinum) {
+ /* contents in getnextino() cache */
+ ip->i_bp = &inobuf;
+ inobuf.b_refcnt++;
+ inobuf.b_index = firstinum;
+ } else if (icachebp != NULL &&
inumber >= icachebp->b_index &&
inumber < icachebp->b_index + INOPB(&sblock)) {
/* take an additional reference for the returned inode */
icachebp->b_refcnt++;
+ ip->i_bp = icachebp;
} else {
iblk = ino_to_fsba(&sblock, inumber);
/* release our cache-hold reference on old icachebp */
@@ -445,26 +463,32 @@ ginode(ino_t inumber, struct inode *ip)
/* take a cache-hold reference on new icachebp */
icachebp->b_refcnt++;
icachebp->b_index = rounddown(inumber, INOPB(&sblock));
+ ip->i_bp = icachebp;
}
- ip->i_bp = icachebp;
if (sblock.fs_magic == FS_UFS1_MAGIC) {
ip->i_dp = (union dinode *)
- &icachebp->b_un.b_dinode1[inumber % INOPB(&sblock)];
+ &ip->i_bp->b_un.b_dinode1[inumber - ip->i_bp->b_index];
+ dpp.dp1 = (struct ufs1_dinode *)ip->i_dp;
+ if (ffs_oldfscompat_inode_read(&sblock, dpp, now))
+ inodirty(ip);
return;
}
ip->i_dp = (union dinode *)
- &icachebp->b_un.b_dinode2[inumber % INOPB(&sblock)];
- if (ffs_verify_dinode_ckhash(&sblock, (struct ufs2_dinode *)ip->i_dp)) {
+ &ip->i_bp->b_un.b_dinode2[inumber - ip->i_bp->b_index];
+ dpp.dp2 = dp = (struct ufs2_dinode *)ip->i_dp;
+ /* Do not check hash of inodes being created */
+ if (dp->di_mode != 0 && ffs_verify_dinode_ckhash(&sblock, dp)) {
pwarn("INODE CHECK-HASH FAILED");
prtinode(ip);
if (preen || reply("FIX") != 0) {
if (preen)
printf(" (FIXED)\n");
- ffs_update_dinode_ckhash(&sblock,
- (struct ufs2_dinode *)ip->i_dp);
+ ffs_update_dinode_ckhash(&sblock, dp);
inodirty(ip);
}
}
+ if (ffs_oldfscompat_inode_read(&sblock, dpp, now))
+ inodirty(ip);
}
/*
@@ -474,6 +498,14 @@ void
irelse(struct inode *ip)
{
+ /* Check for failed inode read */
+ if (ip->i_bp == NULL)
+ return;
+ if (debug && sblock.fs_magic == FS_UFS2_MAGIC &&
+ ffs_verify_dinode_ckhash(&sblock, (struct ufs2_dinode *)ip->i_dp)) {
+ pwarn("irelse: releasing inode with bad check-hash");
+ prtinode(ip);
+ }
if (ip->i_bp->b_refcnt <= 0)
pfatal("irelse: releasing unreferenced ino %ju\n",
(uintmax_t) ip->i_number);
@@ -484,26 +516,27 @@ irelse(struct inode *ip)
* Special purpose version of ginode used to optimize first pass
* over all the inodes in numerical order.
*/
-static ino_t nextino, lastinum, lastvalidinum;
+static ino_t nextinum, lastvalidinum;
static long readcount, readpercg, fullcnt, inobufsize, partialcnt, partialsize;
-static struct bufarea inobuf;
union dinode *
-getnextinode(ino_t inumber, int rebuildcg)
+getnextinode(ino_t inumber, int rebuiltcg)
{
int j;
long size;
mode_t mode;
ufs2_daddr_t ndb, blk;
union dinode *dp;
+ union dinodep dpp;
struct inode ip;
static caddr_t nextinop;
- if (inumber != nextino++ || inumber > lastvalidinum)
+ if (inumber != nextinum++ || inumber > lastvalidinum)
errx(EEXIT, "bad inode number %ju to nextinode",
(uintmax_t)inumber);
if (inumber >= lastinum) {
readcount++;
+ firstinum = lastinum;
blk = ino_to_fsba(&sblock, lastinum);
if (readcount % readpercg == 0) {
size = partialsize;
@@ -517,15 +550,21 @@ getnextinode(ino_t inumber, int rebuildcg)
* If getblk encounters an error, it will already have zeroed
* out the buffer, so we do not need to do so here.
*/
+ if (inobuf.b_refcnt != 0)
+ pfatal("Non-zero getnextinode() ref count %d\n",
+ inobuf.b_refcnt);
flush(fswritefd, &inobuf);
getblk(&inobuf, blk, size);
nextinop = inobuf.b_un.b_buf;
}
dp = (union dinode *)nextinop;
- if (sblock.fs_magic == FS_UFS1_MAGIC)
+ if (sblock.fs_magic == FS_UFS1_MAGIC) {
nextinop += sizeof(struct ufs1_dinode);
- else
+ dpp.dp1 = (struct ufs1_dinode *)dp;
+ } else {
nextinop += sizeof(struct ufs2_dinode);
+ dpp.dp2 = (struct ufs2_dinode *)dp;
+ }
if ((ckhashadd & CK_INODE) != 0) {
ffs_update_dinode_ckhash(&sblock, (struct ufs2_dinode *)dp);
dirty(&inobuf);
@@ -544,7 +583,9 @@ getnextinode(ino_t inumber, int rebuildcg)
dirty(&inobuf);
}
}
- if (rebuildcg && (char *)dp == inobuf.b_un.b_buf) {
+ if (ffs_oldfscompat_inode_read(&sblock, dpp, now))
+ dirty(&inobuf);
+ if (rebuiltcg && (char *)dp == inobuf.b_un.b_buf) {
/*
* Try to determine if we have reached the end of the
* allocated inodes.
@@ -597,11 +638,22 @@ getnextinode(ino_t inumber, int rebuildcg)
void
setinodebuf(int cg, ino_t inosused)
{
+ struct timespec time;
ino_t inum;
+ /*
+ * Get the current value of the present time.
+ * This will happen before each cylinder group is scanned.
+ * If for some reason getting the time fails, we will use
+ * the last time that the superblock was updated.
+ */
+ if (clock_gettime(CLOCK_REALTIME_FAST, &time) == 0)
+ now = time.tv_sec;
+ else
+ now = sblock.fs_time;
inum = cg * sblock.fs_ipg;
lastvalidinum = inum + inosused - 1;
- nextino = inum;
+ nextinum = inum;
lastinum = inum;
readcount = 0;
/* Flush old contents in case they have been updated */
@@ -611,7 +663,7 @@ setinodebuf(int cg, ino_t inosused)
inobufsize = blkroundup(&sblock,
MAX(INOBUFSIZE, sblock.fs_bsize));
initbarea(&inobuf, BT_INODES);
- if ((inobuf.b_un.b_buf = Malloc((unsigned)inobufsize)) == NULL)
+ if ((inobuf.b_un.b_buf = Balloc((unsigned)inobufsize)) == NULL)
errx(EEXIT, "cannot allocate space for inode buffer");
}
fullcnt = inobufsize / ((sblock.fs_magic == FS_UFS1_MAGIC) ?
@@ -633,14 +685,23 @@ int
freeblock(struct inodesc *idesc)
{
struct dups *dlp;
+ struct bufarea *cgbp;
+ struct cg *cgp;
ufs2_daddr_t blkno;
- long nfrags, res;
+ long size, nfrags;
- res = KEEPON;
blkno = idesc->id_blkno;
+ if (idesc->id_type == SNAP) {
+ pfatal("clearing a snapshot dinode\n");
+ return (STOP);
+ }
+ size = lfragtosize(&sblock, idesc->id_numfrags);
+ if (snapblkfree(&sblock, blkno, size, idesc->id_number,
+ std_checkblkavail))
+ return (KEEPON);
for (nfrags = idesc->id_numfrags; nfrags > 0; blkno++, nfrags--) {
if (chkrange(blkno, 1)) {
- res = SKIP;
+ return (SKIP);
} else if (testbmap(blkno)) {
for (dlp = duplist; dlp; dlp = dlp->next) {
if (dlp->dup != blkno)
@@ -657,12 +718,401 @@ freeblock(struct inodesc *idesc)
}
}
}
- return (res);
+ /*
+ * If all successfully returned, account for them.
+ */
+ if (nfrags == 0) {
+ cgbp = cglookup(dtog(&sblock, idesc->id_blkno));
+ cgp = cgbp->b_un.b_cg;
+ if (idesc->id_numfrags == sblock.fs_frag)
+ cgp->cg_cs.cs_nbfree++;
+ else
+ cgp->cg_cs.cs_nffree += idesc->id_numfrags;
+ cgdirty(cgbp);
+ }
+ return (KEEPON);
+}
+
+/*
+ * Prepare a snapshot file for being removed.
+ */
+void
+snapremove(ino_t inum)
+{
+ struct inodesc idesc;
+ struct inode ip;
+ int i;
+
+ for (i = 0; i < snapcnt; i++)
+ if (snaplist[i].i_number == inum)
+ break;
+ if (i == snapcnt)
+ ginode(inum, &ip);
+ else
+ ip = snaplist[i];
+ if ((DIP(ip.i_dp, di_flags) & SF_SNAPSHOT) == 0) {
+ printf("snapremove: inode %jd is not a snapshot\n",
+ (intmax_t)inum);
+ if (i == snapcnt)
+ irelse(&ip);
+ return;
+ }
+ if (debug)
+ printf("snapremove: remove %sactive snapshot %jd\n",
+ i == snapcnt ? "in" : "", (intmax_t)inum);
+ /*
+ * If on active snapshot list, remove it.
+ */
+ if (i < snapcnt) {
+ for (i++; i < FSMAXSNAP; i++) {
+ if (sblock.fs_snapinum[i] == 0)
+ break;
+ snaplist[i - 1] = snaplist[i];
+ sblock.fs_snapinum[i - 1] = sblock.fs_snapinum[i];
+ }
+ sblock.fs_snapinum[i - 1] = 0;
+ bzero(&snaplist[i - 1], sizeof(struct inode));
+ snapcnt--;
+ }
+ memset(&idesc, 0, sizeof(struct inodesc));
+ idesc.id_type = SNAP;
+ idesc.id_func = snapclean;
+ idesc.id_number = inum;
+ (void)ckinode(ip.i_dp, &idesc);
+ DIP_SET(ip.i_dp, di_flags, DIP(ip.i_dp, di_flags) & ~SF_SNAPSHOT);
+ inodirty(&ip);
+ irelse(&ip);
+}
+
+static int
+snapclean(struct inodesc *idesc)
+{
+ ufs2_daddr_t blkno;
+ struct bufarea *bp;
+ union dinode *dp;
+
+ blkno = idesc->id_blkno;
+ if (blkno == 0)
+ return (KEEPON);
+
+ dp = idesc->id_dp;
+ if (blkno == BLK_NOCOPY || blkno == BLK_SNAP) {
+ if (idesc->id_lbn < UFS_NDADDR) {
+ DIP_SET(dp, di_db[idesc->id_lbn], 0);
+ } else {
+ bp = idesc->id_bp;
+ IBLK_SET(bp, bp->b_index, 0);
+ dirty(bp);
+ }
+ }
+ return (KEEPON);
+}
+
+/*
+ * Notification that a block is being freed. Return zero if the free
+ * should be allowed to proceed. Return non-zero if the snapshot file
+ * wants to claim the block. The block will be claimed if it is an
+ * uncopied part of one of the snapshots. It will be freed if it is
+ * either a BLK_NOCOPY or has already been copied in all of the snapshots.
+ * If a fragment is being freed, then all snapshots that care about
+ * it must make a copy since a snapshot file can only claim full sized
+ * blocks. Note that if more than one snapshot file maps the block,
+ * we can pick one at random to claim it. Since none of the snapshots
+ * can change, we are assurred that they will all see the same unmodified
+ * image. When deleting a snapshot file (see ino_trunc above), we
+ * must push any of these claimed blocks to one of the other snapshots
+ * that maps it. These claimed blocks are easily identified as they will
+ * have a block number equal to their logical block number within the
+ * snapshot. A copied block can never have this property because they
+ * must always have been allocated from a BLK_NOCOPY location.
+ */
+int
+snapblkfree(struct fs *fs, ufs2_daddr_t bno, long size, ino_t inum,
+ ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t blkno, long frags))
+{
+ union dinode *dp;
+ struct inode ip;
+ struct bufarea *snapbp;
+ ufs_lbn_t lbn;
+ ufs2_daddr_t blkno, relblkno;
+ int i, frags, claimedblk, copydone;
+
+ /* If no snapshots, nothing to do */
+ if (snapcnt == 0)
+ return (0);
+ if (debug)
+ printf("snapblkfree: in ino %jd free blkno %jd, size %jd\n",
+ (intmax_t)inum, (intmax_t)bno, (intmax_t)size);
+ relblkno = blknum(fs, bno);
+ lbn = fragstoblks(fs, relblkno);
+ /* Direct blocks are always pre-copied */
+ if (lbn < UFS_NDADDR)
+ return (0);
+ copydone = 0;
+ claimedblk = 0;
+ for (i = 0; i < snapcnt; i++) {
+ /*
+ * Lookup block being freed.
+ */
+ ip = snaplist[i];
+ dp = ip.i_dp;
+ blkno = ino_blkatoff(dp, inum != 0 ? inum : ip.i_number,
+ lbn, &frags, &snapbp);
+ /*
+ * Check to see if block needs to be copied.
+ */
+ if (blkno == 0) {
+ /*
+ * A block that we map is being freed. If it has not
+ * been claimed yet, we will claim or copy it (below).
+ */
+ claimedblk = 1;
+ } else if (blkno == BLK_SNAP) {
+ /*
+ * No previous snapshot claimed the block,
+ * so it will be freed and become a BLK_NOCOPY
+ * (don't care) for us.
+ */
+ if (claimedblk)
+ pfatal("snapblkfree: inconsistent block type");
+ IBLK_SET(snapbp, snapbp->b_index, BLK_NOCOPY);
+ dirty(snapbp);
+ brelse(snapbp);
+ continue;
+ } else /* BLK_NOCOPY or default */ {
+ /*
+ * If the snapshot has already copied the block
+ * (default), or does not care about the block,
+ * it is not needed.
+ */
+ brelse(snapbp);
+ continue;
+ }
+ /*
+ * If this is a full size block, we will just grab it
+ * and assign it to the snapshot inode. Otherwise we
+ * will proceed to copy it. See explanation for this
+ * routine as to why only a single snapshot needs to
+ * claim this block.
+ */
+ if (size == fs->fs_bsize) {
+ if (debug)
+ printf("Grabonremove snapshot %ju lbn %jd "
+ "from inum %ju\n", (intmax_t)ip.i_number,
+ (intmax_t)lbn, (uintmax_t)inum);
+ IBLK_SET(snapbp, snapbp->b_index, relblkno);
+ dirty(snapbp);
+ brelse(snapbp);
+ DIP_SET(dp, di_blocks,
+ DIP(dp, di_blocks) + btodb(size));
+ inodirty(&ip);
+ return (1);
+ }
+
+ /* First time through, read the contents of the old block. */
+ if (copydone == 0) {
+ copydone = 1;
+ if (blread(fsreadfd, copybuf, fsbtodb(fs, relblkno),
+ fs->fs_bsize) != 0) {
+ pfatal("Could not read snapshot %ju block "
+ "%jd\n", (intmax_t)ip.i_number,
+ (intmax_t)relblkno);
+ continue;
+ }
+ }
+ /*
+ * This allocation will never require any additional
+ * allocations for the snapshot inode.
+ */
+ blkno = allocblk(dtog(fs, relblkno), fs->fs_frag,
+ checkblkavail);
+ if (blkno == 0) {
+ pfatal("Could not allocate block for snapshot %ju\n",
+ (intmax_t)ip.i_number);
+ continue;
+ }
+ if (debug)
+ printf("Copyonremove: snapino %jd lbn %jd for inum %ju "
+ "size %ld new blkno %jd\n", (intmax_t)ip.i_number,
+ (intmax_t)lbn, (uintmax_t)inum, size,
+ (intmax_t)blkno);
+ blwrite(fswritefd, copybuf, fsbtodb(fs, blkno), fs->fs_bsize);
+ IBLK_SET(snapbp, snapbp->b_index, blkno);
+ dirty(snapbp);
+ brelse(snapbp);
+ DIP_SET(dp, di_blocks,
+ DIP(dp, di_blocks) + btodb(fs->fs_bsize));
+ inodirty(&ip);
+ }
+ return (0);
+}
+
+/*
+ * Notification that a block is being written. Return if the block
+ * is part of a snapshot as snapshots never track other snapshots.
+ * The block will be copied in all of the snapshots that are tracking
+ * it and have not yet copied it. Some buffers may hold more than one
+ * block. Here we need to check each block in the buffer.
+ */
+void
+copyonwrite(struct fs *fs, struct bufarea *bp,
+ ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t blkno, long frags))
+{
+ ufs2_daddr_t copyblkno;
+ long i, numblks;
+
+ /* If no snapshots, nothing to do. */
+ if (snapcnt == 0)
+ return;
+ numblks = blkroundup(fs, bp->b_size) / fs->fs_bsize;
+ if (debug)
+ prtbuf(bp, "copyonwrite: checking %jd block%s in buffer",
+ (intmax_t)numblks, numblks > 1 ? "s" : "");
+ copyblkno = blknum(fs, dbtofsb(fs, bp->b_bno));
+ for (i = 0; i < numblks; i++) {
+ chkcopyonwrite(fs, copyblkno, checkblkavail);
+ copyblkno += fs->fs_frag;
+ }
+}
+
+static void
+chkcopyonwrite(struct fs *fs, ufs2_daddr_t copyblkno,
+ ufs2_daddr_t (*checkblkavail)(ufs2_daddr_t blkno, long frags))
+{
+ struct inode ip;
+ union dinode *dp;
+ struct bufarea *snapbp;
+ ufs2_daddr_t blkno;
+ int i, frags, copydone;
+ ufs_lbn_t lbn;
+
+ lbn = fragstoblks(fs, copyblkno);
+ /* Direct blocks are always pre-copied */
+ if (lbn < UFS_NDADDR)
+ return;
+ copydone = 0;
+ for (i = 0; i < snapcnt; i++) {
+ /*
+ * Lookup block being freed.
+ */
+ ip = snaplist[i];
+ dp = ip.i_dp;
+ blkno = ino_blkatoff(dp, ip.i_number, lbn, &frags, &snapbp);
+ /*
+ * Check to see if block needs to be copied.
+ */
+ if (blkno != 0) {
+ /*
+ * A block that we have already copied or don't track.
+ */
+ brelse(snapbp);
+ continue;
+ }
+ /* First time through, read the contents of the old block. */
+ if (copydone == 0) {
+ copydone = 1;
+ if (blread(fsreadfd, copybuf, fsbtodb(fs, copyblkno),
+ fs->fs_bsize) != 0) {
+ pfatal("Could not read snapshot %ju block "
+ "%jd\n", (intmax_t)ip.i_number,
+ (intmax_t)copyblkno);
+ continue;
+ }
+ }
+ /*
+ * This allocation will never require any additional
+ * allocations for the snapshot inode.
+ */
+ if ((blkno = allocblk(dtog(fs, copyblkno), fs->fs_frag,
+ checkblkavail)) == 0) {
+ pfatal("Could not allocate block for snapshot %ju\n",
+ (intmax_t)ip.i_number);
+ continue;
+ }
+ if (debug)
+ prtbuf(snapbp, "Copyonwrite: snapino %jd lbn %jd using "
+ "blkno %ju setting in buffer",
+ (intmax_t)ip.i_number, (intmax_t)lbn,
+ (intmax_t)blkno);
+ blwrite(fswritefd, copybuf, fsbtodb(fs, blkno), fs->fs_bsize);
+ IBLK_SET(snapbp, snapbp->b_index, blkno);
+ dirty(snapbp);
+ brelse(snapbp);
+ DIP_SET(dp, di_blocks,
+ DIP(dp, di_blocks) + btodb(fs->fs_bsize));
+ inodirty(&ip);
+ }
+ return;
+}
+
+/*
+ * Traverse an inode and check that its block count is correct
+ * fixing it if necessary.
+ */
+void
+check_blkcnt(struct inode *ip)
+{
+ struct inodesc idesc;
+ union dinode *dp;
+ ufs2_daddr_t ndb;
+ int j, ret, offset;
+
+ dp = ip->i_dp;
+ memset(&idesc, 0, sizeof(struct inodesc));
+ idesc.id_func = pass1check;
+ idesc.id_number = ip->i_number;
+ idesc.id_type = (DIP(dp, di_flags) & SF_SNAPSHOT) == 0 ? ADDR : SNAP;
+ (void)ckinode(dp, &idesc);
+ if (sblock.fs_magic == FS_UFS2_MAGIC && dp->dp2.di_extsize > 0) {
+ ndb = howmany(dp->dp2.di_extsize, sblock.fs_bsize);
+ for (j = 0; j < UFS_NXADDR; j++) {
+ if (--ndb == 0 &&
+ (offset = blkoff(&sblock, dp->dp2.di_extsize)) != 0)
+ idesc.id_numfrags = numfrags(&sblock,
+ fragroundup(&sblock, offset));
+ else
+ idesc.id_numfrags = sblock.fs_frag;
+ if (dp->dp2.di_extb[j] == 0)
+ continue;
+ idesc.id_blkno = dp->dp2.di_extb[j];
+ ret = (*idesc.id_func)(&idesc);
+ if (ret & STOP)
+ break;
+ }
+ }
+ idesc.id_entryno *= btodb(sblock.fs_fsize);
+ if (DIP(dp, di_blocks) != idesc.id_entryno) {
+ if (!(sujrecovery && preen)) {
+ pwarn("INCORRECT BLOCK COUNT I=%lu (%ju should be %ju)",
+ (u_long)idesc.id_number,
+ (uintmax_t)DIP(dp, di_blocks),
+ (uintmax_t)idesc.id_entryno);
+ if (preen)
+ printf(" (CORRECTED)\n");
+ else if (reply("CORRECT") == 0)
+ return;
+ }
+ if (bkgrdflag == 0) {
+ DIP_SET(dp, di_blocks, idesc.id_entryno);
+ inodirty(ip);
+ } else {
+ cmd.value = idesc.id_number;
+ cmd.size = idesc.id_entryno - DIP(dp, di_blocks);
+ if (debug)
+ printf("adjblkcnt ino %ju amount %lld\n",
+ (uintmax_t)cmd.value, (long long)cmd.size);
+ if (sysctl(adjblkcnt, MIBSIZE, 0, 0,
+ &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST INODE BLOCK COUNT", cmd.value);
+ }
+ }
}
void
freeinodebuf(void)
{
+ struct bufarea *bp;
+ int i;
/*
* Flush old contents in case they have been updated.
@@ -671,6 +1121,15 @@ freeinodebuf(void)
if (inobuf.b_un.b_buf != NULL)
free((char *)inobuf.b_un.b_buf);
inobuf.b_un.b_buf = NULL;
+ firstinum = lastinum = 0;
+ /*
+ * Reload the snapshot inodes in case any of them changed.
+ */
+ for (i = 0; i < snapcnt; i++) {
+ bp = snaplist[i].i_bp;
+ bp->b_errs = blread(fsreadfd, bp->b_un.b_buf, bp->b_bno,
+ bp->b_size);
+ }
}
/*
@@ -680,12 +1139,15 @@ freeinodebuf(void)
*
* Enter inodes into the cache.
*/
-void
+struct inoinfo *
cacheino(union dinode *dp, ino_t inumber)
{
- struct inoinfo *inp, **inpp;
+ struct inoinfo *inp;
int i, blks;
+ if (getinoinfo(inumber) != NULL)
+ pfatal("cacheino: duplicate entry for ino %jd\n",
+ (intmax_t)inumber);
if (howmany(DIP(dp, di_size), sblock.fs_bsize) > UFS_NDADDR)
blks = UFS_NDADDR + UFS_NIADDR;
else if (DIP(dp, di_size) > 0)
@@ -696,13 +1158,13 @@ cacheino(union dinode *dp, ino_t inumber)
Malloc(sizeof(*inp) + (blks - 1) * sizeof(ufs2_daddr_t));
if (inp == NULL)
errx(EEXIT, "cannot increase directory list");
- inpp = &inphead[inumber % dirhash];
- inp->i_nexthash = *inpp;
- *inpp = inp;
+ SLIST_INSERT_HEAD(&inphash[inumber % dirhash], inp, i_hash);
+ inp->i_flags = 0;
inp->i_parent = inumber == UFS_ROOTINO ? UFS_ROOTINO : (ino_t)0;
inp->i_dotdot = (ino_t)0;
inp->i_number = inumber;
inp->i_isize = DIP(dp, di_size);
+ inp->i_depth = DIP(dp, di_dirdepth);
inp->i_numblks = blks;
for (i = 0; i < MIN(blks, UFS_NDADDR); i++)
inp->i_blks[i] = DIP(dp, di_db[i]);
@@ -717,6 +1179,7 @@ cacheino(union dinode *dp, ino_t inumber)
errx(EEXIT, "cannot increase directory list");
}
inpsort[inplast++] = inp;
+ return (inp);
}
/*
@@ -727,13 +1190,43 @@ getinoinfo(ino_t inumber)
{
struct inoinfo *inp;
- for (inp = inphead[inumber % dirhash]; inp; inp = inp->i_nexthash) {
+ SLIST_FOREACH(inp, &inphash[inumber % dirhash], i_hash) {
if (inp->i_number != inumber)
continue;
return (inp);
}
- errx(EEXIT, "cannot find inode %ju", (uintmax_t)inumber);
- return ((struct inoinfo *)0);
+ return (NULL);
+}
+
+/*
+ * Remove an entry from the inode cache and disk-order sorted list.
+ * Return 0 on success and 1 on failure.
+ */
+int
+removecachedino(ino_t inumber)
+{
+ struct inoinfo *inp, **inpp;
+ char *listtype;
+
+ listtype = "hash";
+ SLIST_FOREACH(inp, &inphash[inumber % dirhash], i_hash) {
+ if (inp->i_number != inumber)
+ continue;
+ SLIST_REMOVE(&inphash[inumber % dirhash], inp, inoinfo, i_hash);
+ for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--) {
+ if (*inpp != inp)
+ continue;
+ *inpp = inpsort[inplast - 1];
+ inplast--;
+ free(inp);
+ return (0);
+ }
+ listtype = "sort";
+ break;
+ }
+ pfatal("removecachedino: entry for ino %jd not found on %s list\n",
+ (intmax_t)inumber, listtype);
+ return (1);
}
/*
@@ -744,13 +1237,14 @@ inocleanup(void)
{
struct inoinfo **inpp;
- if (inphead == NULL)
+ if (inphash == NULL)
return;
for (inpp = &inpsort[inplast - 1]; inpp >= inpsort; inpp--)
free((char *)(*inpp));
- free((char *)inphead);
+ free((char *)inphash);
+ inphash = NULL;
free((char *)inpsort);
- inphead = inpsort = NULL;
+ inpsort = NULL;
}
void
@@ -782,6 +1276,10 @@ clri(struct inodesc *idesc, const char *type, int flag)
printf(" (CLEARED)\n");
n_files--;
if (bkgrdflag == 0) {
+ if (idesc->id_type == SNAP) {
+ snapremove(idesc->id_number);
+ idesc->id_type = ADDR;
+ }
(void)ckinode(dp, idesc);
inoinfo(idesc->id_number)->ino_state = USTATE;
clearinode(dp);
@@ -821,7 +1319,7 @@ findino(struct inodesc *idesc)
if (dirp->d_ino == 0)
return (KEEPON);
if (strcmp(dirp->d_name, idesc->id_name) == 0 &&
- dirp->d_ino >= UFS_ROOTINO && dirp->d_ino <= maxino) {
+ dirp->d_ino >= UFS_ROOTINO && dirp->d_ino < maxino) {
idesc->id_parent = dirp->d_ino;
return (STOP|FOUND);
}
@@ -851,7 +1349,7 @@ prtinode(struct inode *ip)
dp = ip->i_dp;
printf(" I=%lu ", (u_long)ip->i_number);
- if (ip->i_number < UFS_ROOTINO || ip->i_number > maxino)
+ if (ip->i_number < UFS_ROOTINO || ip->i_number >= maxino)
return;
printf(" OWNER=");
if ((pw = getpwuid((int)DIP(dp, di_uid))) != NULL)
@@ -863,8 +1361,8 @@ prtinode(struct inode *ip)
printf("%s: ", cdevname);
printf("SIZE=%ju ", (uintmax_t)DIP(dp, di_size));
t = DIP(dp, di_mtime);
- p = ctime(&t);
- printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
+ if ((p = ctime(&t)) != NULL)
+ printf("MTIME=%12.12s %4.4s ", &p[4], &p[20]);
}
void
@@ -923,7 +1421,7 @@ retry:
cg = ino_to_cg(&sblock, ino);
cgbp = cglookup(cg);
cgp = cgbp->b_un.b_cg;
- if (!check_cgmagic(cg, cgbp, 0)) {
+ if (!check_cgmagic(cg, cgbp)) {
if (anyino == 0)
return (0);
request = (cg + 1) * sblock.fs_ipg;
@@ -946,20 +1444,20 @@ retry:
cgdirty(cgbp);
ginode(ino, &ip);
dp = ip.i_dp;
- DIP_SET(dp, di_db[0], allocblk((long)1));
+ memset(dp, 0, ((sblock.fs_magic == FS_UFS1_MAGIC) ?
+ sizeof(struct ufs1_dinode) : sizeof(struct ufs2_dinode)));
+ DIP_SET(dp, di_db[0], allocblk(ino_to_cg(&sblock, ino), (long)1,
+ std_checkblkavail));
if (DIP(dp, di_db[0]) == 0) {
inoinfo(ino)->ino_state = USTATE;
+ inodirty(&ip);
irelse(&ip);
return (0);
}
DIP_SET(dp, di_mode, type);
- DIP_SET(dp, di_flags, 0);
DIP_SET(dp, di_atime, time(NULL));
DIP_SET(dp, di_ctime, DIP(dp, di_atime));
DIP_SET(dp, di_mtime, DIP(dp, di_ctime));
- DIP_SET(dp, di_mtimensec, 0);
- DIP_SET(dp, di_ctimensec, 0);
- DIP_SET(dp, di_atimensec, 0);
DIP_SET(dp, di_size, sblock.fs_fsize);
DIP_SET(dp, di_blocks, btodb(sblock.fs_fsize));
n_files++;
@@ -980,7 +1478,7 @@ freeino(ino_t ino)
struct inode ip;
memset(&idesc, 0, sizeof(struct inodesc));
- idesc.id_type = inoinfo(ino)->ino_idtype;
+ idesc.id_type = ADDR;
idesc.id_func = freeblock;
idesc.id_number = ino;
ginode(ino, &ip);
diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c
index 18634a93c05c..aabab489573e 100644
--- a/sbin/fsck_ffs/main.c
+++ b/sbin/fsck_ffs/main.c
@@ -29,21 +29,7 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1986, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#define IN_RTLD /* So we pickup the P_OSREL defines */
+#define _WANT_P_OSREL
#include <sys/param.h>
#include <sys/file.h>
#include <sys/mount.h>
@@ -61,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <fstab.h>
#include <grp.h>
#include <inttypes.h>
-#include <libufs.h>
#include <mntopts.h>
#include <paths.h>
#include <stdint.h>
@@ -70,14 +55,13 @@ __FBSDID("$FreeBSD$");
#include "fsck.h"
-static int restarts;
+static int restarts;
+static char snapname[BUFSIZ]; /* when doing snapshots, the name of the file */
static void usage(void) __dead2;
static intmax_t argtoimax(int flag, const char *req, const char *str, int base);
static int checkfilesys(char *filesys);
static int setup_bkgrdchk(struct statfs *mntp, int sbrdfailed, char **filesys);
-static int chkdoreload(struct statfs *mntp);
-static struct statfs *getmntpt(const char *);
int
main(int argc, char *argv[])
@@ -258,7 +242,7 @@ checkfilesys(char *filesys)
* if it is listed among the mounted file systems. Failing that
* check to see if it is listed in /etc/fstab.
*/
- mntp = getmntpt(filesys);
+ mntp = getmntpoint(filesys);
if (mntp != NULL)
filesys = mntp->f_mntfromname;
else
@@ -271,14 +255,21 @@ checkfilesys(char *filesys)
*/
sblock_init();
sbreadfailed = 0;
- if (openfilesys(filesys) == 0 || readsb(0) == 0)
+ if (openfilesys(filesys) == 0 || readsb() == 0)
sbreadfailed = 1;
if (bkgrdcheck) {
if (sbreadfailed)
exit(3); /* Cannot read superblock */
- /* Earlier background failed or journaled */
- if (sblock.fs_flags & (FS_NEEDSFSCK | FS_SUJ))
- exit(4);
+ if ((sblock.fs_flags & FS_NEEDSFSCK) == FS_NEEDSFSCK)
+ exit(4); /* Earlier background failed */
+ if ((sblock.fs_flags & FS_SUJ) == FS_SUJ) {
+ maxino = sblock.fs_ncg * sblock.fs_ipg;
+ maxfsblock = sblock.fs_size;
+ bufinit();
+ preen = 1;
+ if (suj_check(filesys) == 0)
+ exit(4); /* Journal good, run it now */
+ }
if ((sblock.fs_flags & FS_DOSOFTDEP) == 0)
exit(5); /* Not running soft updates */
size = MIBSIZE;
@@ -311,7 +302,7 @@ checkfilesys(char *filesys)
(FS_UNCLEAN | FS_NEEDSFSCK)) == 0) {
bufinit();
gjournal_check(filesys);
- if (chkdoreload(mntp) == 0)
+ if (chkdoreload(mntp, pwarn) == 0)
exit(0);
exit(4);
} else {
@@ -352,17 +343,19 @@ checkfilesys(char *filesys)
/*
* Determine if we can and should do journal recovery.
*/
- if ((sblock.fs_flags & FS_SUJ) == FS_SUJ) {
- if ((sblock.fs_flags & FS_NEEDSFSCK) != FS_NEEDSFSCK && skipclean) {
+ if (bkgrdflag == 0 && (sblock.fs_flags & FS_SUJ) == FS_SUJ) {
+ if ((sblock.fs_flags & FS_NEEDSFSCK) != FS_NEEDSFSCK &&
+ skipclean) {
sujrecovery = 1;
if (suj_check(filesys) == 0) {
- printf("\n***** FILE SYSTEM MARKED CLEAN *****\n");
- if (chkdoreload(mntp) == 0)
+ pwarn("\n**** FILE SYSTEM MARKED CLEAN ****\n");
+ if (chkdoreload(mntp, pwarn) == 0)
exit(0);
exit(4);
}
sujrecovery = 0;
- printf("** Skipping journal, falling through to full fsck\n\n");
+ pwarn("Skipping journal, "
+ "falling through to full fsck\n");
}
if (fswritefd != -1) {
/*
@@ -438,7 +431,7 @@ checkfilesys(char *filesys)
/*
* 1: scan inodes tallying blocks used
*/
- if (preen == 0) {
+ if (preen == 0 || debug) {
printf("** Last Mounted on %s\n", sblock.fs_fsmnt);
if (mntp != NULL && mntp->f_flags & MNT_ROOTFS)
printf("** Root file system\n");
@@ -457,7 +450,8 @@ checkfilesys(char *filesys)
preen ? "-p" : "",
(preen && usedsoftdep) ? " AND " : "",
usedsoftdep ? "SOFTUPDATES" : "");
- printf("** Phase 1b - Rescan For More DUPS\n");
+ if (preen == 0 || debug)
+ printf("** Phase 1b - Rescan For More DUPS\n");
pass1b();
IOstats("Pass1b");
}
@@ -465,7 +459,7 @@ checkfilesys(char *filesys)
/*
* 2: traverse directories from root to mark all connected directories
*/
- if (preen == 0)
+ if (preen == 0 || debug)
printf("** Phase 2 - Check Pathnames\n");
pass2();
IOstats("Pass2");
@@ -473,7 +467,7 @@ checkfilesys(char *filesys)
/*
* 3: scan inodes looking for disconnected directories
*/
- if (preen == 0)
+ if (preen == 0 || debug)
printf("** Phase 3 - Check Connectivity\n");
pass3();
IOstats("Pass3");
@@ -481,7 +475,7 @@ checkfilesys(char *filesys)
/*
* 4: scan inodes looking for disconnected files; check reference counts
*/
- if (preen == 0)
+ if (preen == 0 || debug)
printf("** Phase 4 - Check Reference Counts\n");
pass4();
IOstats("Pass4");
@@ -489,10 +483,16 @@ checkfilesys(char *filesys)
/*
* 5: check and repair resource counts in cylinder groups
*/
- if (preen == 0)
+ if (preen == 0 || debug)
printf("** Phase 5 - Check Cyl groups\n");
- pass5();
- IOstats("Pass5");
+ snapflush(std_checkblkavail);
+ if (cgheader_corrupt) {
+ printf("PHASE 5 SKIPPED DUE TO CORRUPT CYLINDER GROUP "
+ "HEADER(S)\n\n");
+ } else {
+ pass5();
+ IOstats("Pass5");
+ }
/*
* print out summary statistics
@@ -560,7 +560,7 @@ checkfilesys(char *filesys)
return (ERESTART);
printf("\n***** PLEASE RERUN FSCK *****\n");
}
- if (chkdoreload(mntp) != 0) {
+ if (chkdoreload(mntp, pwarn) != 0) {
if (!fsmodified)
return (0);
if (!preen)
@@ -612,10 +612,6 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
pwarn("FULL FSCK NEEDED, CANNOT RUN IN BACKGROUND\n");
return (0);
}
- if ((sblock.fs_flags & FS_SUJ) != 0) {
- pwarn("JOURNALED FILESYSTEM, CANNOT RUN IN BACKGROUND\n");
- return (0);
- }
if (skipclean && ckclean &&
(sblock.fs_flags & (FS_UNCLEAN|FS_NEEDSFSCK)) == 0) {
/*
@@ -656,8 +652,7 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
"SUPPORT\n");
}
/* Find or create the snapshot directory */
- snprintf(snapname, sizeof snapname, "%s/.snap",
- mntp->f_mntonname);
+ snprintf(snapname, sizeof snapname, "%s/.snap", mntp->f_mntonname);
if (stat(snapname, &snapdir) < 0) {
if (errno != ENOENT) {
pwarn("CANNOT FIND SNAPSHOT DIRECTORY %s: %s, CANNOT "
@@ -705,101 +700,20 @@ setup_bkgrdchk(struct statfs *mntp, int sbreadfailed, char **filesys)
"BACKGROUND\n", snapname, strerror(errno));
return (0);
}
+ /* Immediately unlink snapshot so that it will be deleted when closed */
+ unlink(snapname);
free(sblock.fs_csp);
free(sblock.fs_si);
- havesb = 0;
+ if (readsb() == 0) {
+ pwarn("CANNOT READ SNAPSHOT SUPERBLOCK\n");
+ return (0);
+ }
*filesys = snapname;
cmd.version = FFS_CMD_VERSION;
cmd.handle = fsreadfd;
return (1);
}
-static int
-chkdoreload(struct statfs *mntp)
-{
- struct iovec *iov;
- int iovlen;
- char errmsg[255];
-
- if (mntp == NULL)
- return (0);
-
- iov = NULL;
- iovlen = 0;
- errmsg[0] = '\0';
- /*
- * We modified a mounted file system. Do a mount update on
- * it unless it is read-write, so we can continue using it
- * as safely as possible.
- */
- if (mntp->f_flags & MNT_RDONLY) {
- build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
- build_iovec(&iov, &iovlen, "from", mntp->f_mntfromname,
- (size_t)-1);
- build_iovec(&iov, &iovlen, "fspath", mntp->f_mntonname,
- (size_t)-1);
- build_iovec(&iov, &iovlen, "errmsg", errmsg,
- sizeof(errmsg));
- build_iovec(&iov, &iovlen, "update", NULL, 0);
- build_iovec(&iov, &iovlen, "reload", NULL, 0);
- /*
- * XX: We need the following line until we clean up
- * nmount parsing of root mounts and NFS root mounts.
- */
- build_iovec(&iov, &iovlen, "ro", NULL, 0);
- if (nmount(iov, iovlen, mntp->f_flags) == 0) {
- return (0);
- }
- pwarn("mount reload of '%s' failed: %s %s\n\n",
- mntp->f_mntonname, strerror(errno), errmsg);
- return (1);
- }
- return (0);
-}
-
-/*
- * Get the mount point information for name.
- */
-static struct statfs *
-getmntpt(const char *name)
-{
- struct stat devstat, mntdevstat;
- char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
- char *ddevname;
- struct statfs *mntbuf, *statfsp;
- int i, mntsize, isdev;
-
- if (stat(name, &devstat) != 0)
- return (NULL);
- if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
- isdev = 1;
- else
- isdev = 0;
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
- ddevname = statfsp->f_mntfromname;
- if (*ddevname != '/') {
- if (strlen(_PATH_DEV) + strlen(ddevname) + 1 >
- sizeof(statfsp->f_mntfromname))
- continue;
- strcpy(device, _PATH_DEV);
- strcat(device, ddevname);
- strcpy(statfsp->f_mntfromname, device);
- }
- if (isdev == 0) {
- if (strcmp(name, statfsp->f_mntonname))
- continue;
- return (statfsp);
- }
- if (stat(ddevname, &mntdevstat) == 0 &&
- mntdevstat.st_rdev == devstat.st_rdev)
- return (statfsp);
- }
- statfsp = NULL;
- return (statfsp);
-}
-
static void
usage(void)
{
diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c
index 319a324cc070..f4f97a38097b 100644
--- a/sbin/fsck_ffs/pass1.c
+++ b/sbin/fsck_ffs/pass1.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
@@ -56,7 +48,7 @@ static ufs2_daddr_t badblk;
static ufs2_daddr_t dupblk;
static ino_t lastino; /* last inode in use */
-static int checkinode(ino_t inumber, struct inodesc *, int rebuildcg);
+static int checkinode(ino_t inumber, struct inodesc *, int rebuiltcg);
void
pass1(void)
@@ -68,7 +60,7 @@ pass1(void)
ino_t inumber, inosused, mininos;
ufs2_daddr_t i, cgd;
u_int8_t *cp;
- int c, rebuildcg;
+ int c, rebuiltcg;
badblk = dupblk = lastino = 0;
@@ -99,10 +91,20 @@ pass1(void)
inumber = c * sblock.fs_ipg;
cgbp = cglookup(c);
cgp = cgbp->b_un.b_cg;
- rebuildcg = 0;
- if (!check_cgmagic(c, cgbp, 1))
- rebuildcg = 1;
- if (!rebuildcg && sblock.fs_magic == FS_UFS2_MAGIC) {
+ rebuiltcg = 0;
+ if (!check_cgmagic(c, cgbp)) {
+ if (!reply("REBUILD CYLINDER GROUP")) {
+ cgheader_corrupt = 1;
+ if (!nflag) {
+ pwarn("YOU WILL NEED TO RERUN FSCK.\n");
+ rerun = 1;
+ }
+ } else {
+ rebuild_cg(c, cgbp);
+ rebuiltcg = 1;
+ }
+ }
+ if (!rebuiltcg && sblock.fs_magic == FS_UFS2_MAGIC) {
inosused = cgp->cg_initediblk;
if (inosused > sblock.fs_ipg) {
pfatal("Too many initialized inodes (%ju > %d) "
@@ -132,7 +134,7 @@ pass1(void)
* to find the inodes that are really in use, and then
* read only those inodes in from disk.
*/
- if ((preen || inoopt) && usedsoftdep && !rebuildcg) {
+ if ((preen || inoopt) && usedsoftdep && !rebuiltcg) {
cp = &cg_inosused(cgp)[(inosused - 1) / CHAR_BIT];
for ( ; inosused != 0; cp--) {
if (*cp == 0) {
@@ -169,7 +171,7 @@ pass1(void)
setinodebuf(c, inosused);
for (i = 0; i < inosused; i++, inumber++) {
if (inumber < UFS_ROOTINO) {
- (void)getnextinode(inumber, rebuildcg);
+ (void)getnextinode(inumber, rebuiltcg);
continue;
}
/*
@@ -178,7 +180,7 @@ pass1(void)
* We always keep trying until we get to the minimum
* valid number for this cylinder group.
*/
- if (checkinode(inumber, &idesc, rebuildcg) == 0 &&
+ if (checkinode(inumber, &idesc, rebuiltcg) == 0 &&
i > cgp->cg_initediblk)
break;
}
@@ -189,7 +191,7 @@ pass1(void)
* fewer in use.
*/
mininos = roundup(inosused + INOPB(&sblock), INOPB(&sblock));
- if (inoopt && !preen && !rebuildcg &&
+ if (inoopt && !preen && !rebuiltcg &&
sblock.fs_magic == FS_UFS2_MAGIC &&
cgp->cg_initediblk > 2 * INOPB(&sblock) &&
mininos < cgp->cg_initediblk) {
@@ -209,7 +211,7 @@ pass1(void)
inosused = 0;
else
inosused = lastino - (c * sblock.fs_ipg);
- if (rebuildcg && inosused > cgp->cg_initediblk &&
+ if (rebuiltcg && inosused > cgp->cg_initediblk &&
sblock.fs_magic == FS_UFS2_MAGIC) {
cgp->cg_initediblk = roundup(inosused, INOPB(&sblock));
pwarn("CYLINDER GROUP %d: FOUND %d VALID INODES\n", c,
@@ -219,9 +221,10 @@ pass1(void)
* If we were not able to determine in advance which inodes
* were in use, then reduce the size of the inoinfo structure
* to the size necessary to describe the inodes that we
- * really found.
+ * really found. Always leave map space in the first cylinder
+ * group in case we need to a root or lost+found directory.
*/
- if (inumber == lastino)
+ if (inumber == lastino || c == 0)
continue;
inostathead[c].il_numalloced = inosused;
if (inosused == 0) {
@@ -241,18 +244,19 @@ pass1(void)
}
static int
-checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
+checkinode(ino_t inumber, struct inodesc *idesc, int rebuiltcg)
{
struct inode ip;
union dinode *dp;
- off_t kernmaxfilesize;
ufs2_daddr_t ndb;
mode_t mode;
intmax_t size, fixsize;
int j, ret, offset;
- if ((dp = getnextinode(inumber, rebuildcg)) == NULL)
+ if ((dp = getnextinode(inumber, rebuiltcg)) == NULL) {
+ pfatal("INVALID INODE");
goto unknown;
+ }
mode = DIP(dp, di_mode) & IFMT;
if (mode == 0) {
if ((sblock.fs_magic == FS_UFS1_MAGIC &&
@@ -280,16 +284,8 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
return (1);
}
lastino = inumber;
- /* This should match the file size limit in ffs_mountfs(). */
- if (sblock.fs_magic == FS_UFS1_MAGIC)
- kernmaxfilesize = (off_t)0x40000000 * sblock.fs_bsize - 1;
- else
- kernmaxfilesize = sblock.fs_maxfilesize;
- if (DIP(dp, di_size) > kernmaxfilesize ||
- DIP(dp, di_size) > sblock.fs_maxfilesize ||
- (mode == IFDIR && DIP(dp, di_size) > MAXDIRSIZE)) {
- if (debug)
- printf("bad size %ju:", (uintmax_t)DIP(dp, di_size));
+ if (chkfilesize(mode, DIP(dp, di_size)) == 0) {
+ pfatal("BAD FILE SIZE");
goto unknown;
}
if (!preen && mode == IFMT && reply("HOLD BAD BLOCK") == 1) {
@@ -305,19 +301,22 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
if (debug)
printf("bad special-file size %ju:",
(uintmax_t)DIP(dp, di_size));
+ pfatal("BAD SPECIAL-FILE SIZE");
goto unknown;
}
if ((mode == IFBLK || mode == IFCHR) &&
(dev_t)DIP(dp, di_rdev) == NODEV) {
if (debug)
printf("bad special-file rdev NODEV:");
+ pfatal("BAD SPECIAL-FILE RDEV");
goto unknown;
}
ndb = howmany(DIP(dp, di_size), sblock.fs_bsize);
if (ndb < 0) {
if (debug)
- printf("bad size %ju ndb %ju:",
+ printf("negative size %ju ndb %ju:",
(uintmax_t)DIP(dp, di_size), (uintmax_t)ndb);
+ pfatal("NEGATIVE FILE SIZE");
goto unknown;
}
if (mode == IFBLK || mode == IFCHR)
@@ -342,33 +341,52 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
}
}
}
- for (j = ndb; ndb < UFS_NDADDR && j < UFS_NDADDR; j++)
- if (DIP(dp, di_db[j]) != 0) {
- if (debug)
- printf("bad direct addr[%d]: %ju\n", j,
- (uintmax_t)DIP(dp, di_db[j]));
- goto unknown;
+ for (j = ndb; ndb < UFS_NDADDR && j < UFS_NDADDR; j++) {
+ if (DIP(dp, di_db[j]) == 0)
+ continue;
+ if (debug)
+ printf("invalid direct addr[%d]: %ju\n", j,
+ (uintmax_t)DIP(dp, di_db[j]));
+ pfatal("INVALID DIRECT BLOCK");
+ ginode(inumber, &ip);
+ prtinode(&ip);
+ if (reply("CLEAR") == 1) {
+ DIP_SET(ip.i_dp, di_db[j], 0);
+ inodirty(&ip);
}
+ irelse(&ip);
+ }
for (j = 0, ndb -= UFS_NDADDR; ndb > 0; j++)
ndb /= NINDIR(&sblock);
- for (; j < UFS_NIADDR; j++)
- if (DIP(dp, di_ib[j]) != 0) {
- if (debug)
- printf("bad indirect addr: %ju\n",
- (uintmax_t)DIP(dp, di_ib[j]));
- goto unknown;
+ for (; j < UFS_NIADDR; j++) {
+ if (DIP(dp, di_ib[j]) == 0)
+ continue;
+ if (debug)
+ printf("invalid indirect addr: %ju\n",
+ (uintmax_t)DIP(dp, di_ib[j]));
+ pfatal("INVALID INDIRECT BLOCK");
+ ginode(inumber, &ip);
+ prtinode(&ip);
+ if (reply("CLEAR") == 1) {
+ DIP_SET(ip.i_dp, di_ib[j], 0);
+ inodirty(&ip);
}
- if (ftypeok(dp) == 0)
+ irelse(&ip);
+ }
+ if (ftypeok(dp) == 0) {
+ pfatal("UNKNOWN FILE TYPE");
goto unknown;
+ }
n_files++;
inoinfo(inumber)->ino_linkcnt = DIP(dp, di_nlink);
if (mode == IFDIR) {
- if (DIP(dp, di_size) == 0)
+ if (DIP(dp, di_size) == 0) {
inoinfo(inumber)->ino_state = DCLEAR;
- else if (DIP(dp, di_nlink) <= 0)
+ } else if (DIP(dp, di_nlink) == 0) {
inoinfo(inumber)->ino_state = DZLINK;
- else
+ } else {
inoinfo(inumber)->ino_state = DSTATE;
+ }
cacheino(dp, inumber);
countdirs++;
} else if (DIP(dp, di_nlink) <= 0)
@@ -483,15 +501,14 @@ checkinode(ino_t inumber, struct inodesc *idesc, int rebuildcg)
}
return (1);
unknown:
- pfatal("UNKNOWN FILE TYPE I=%lu", (u_long)inumber);
- inoinfo(inumber)->ino_state = FCLEAR;
+ ginode(inumber, &ip);
+ prtinode(&ip);
+ inoinfo(inumber)->ino_state = USTATE;
if (reply("CLEAR") == 1) {
- inoinfo(inumber)->ino_state = USTATE;
- ginode(inumber, &ip);
clearinode(ip.i_dp);
inodirty(&ip);
- irelse(&ip);
}
+ irelse(&ip);
return (1);
}
diff --git a/sbin/fsck_ffs/pass1b.c b/sbin/fsck_ffs/pass1b.c
index 17a3b6495dc4..3fb9cab89078 100644
--- a/sbin/fsck_ffs/pass1b.c
+++ b/sbin/fsck_ffs/pass1b.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)pass1b.c 8.4 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <ufs/ufs/dinode.h>
@@ -88,10 +80,12 @@ pass1b(void)
if (inoinfo(inumber)->ino_state != USTATE &&
(ckinode(dp, &idesc) & STOP)) {
rerun = 1;
+ freeinodebuf();
return;
}
}
}
+ freeinodebuf();
}
static int
diff --git a/sbin/fsck_ffs/pass2.c b/sbin/fsck_ffs/pass2.c
index 8632cf4878b1..1755a1295a9e 100644
--- a/sbin/fsck_ffs/pass2.c
+++ b/sbin/fsck_ffs/pass2.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)pass2.c 8.9 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/sysctl.h>
@@ -85,7 +77,7 @@ pass2(void)
case DCLEAR:
pfatal("DUPS/BAD IN ROOT INODE");
if (reply("REALLOCATE")) {
- freeino(UFS_ROOTINO);
+ freedirino(UFS_ROOTINO, UFS_ROOTINO);
if (allocdir(UFS_ROOTINO, UFS_ROOTINO, 0755) !=
UFS_ROOTINO)
errx(EEXIT, "CANNOT ALLOCATE ROOT INODE");
@@ -210,16 +202,18 @@ pass2(void)
if (inp->i_parent == 0 || inp->i_isize == 0)
continue;
if (inoinfo(inp->i_parent)->ino_state == DFOUND &&
- INO_IS_DUNFOUND(inp->i_number))
+ INO_IS_DUNFOUND(inp->i_number)) {
inoinfo(inp->i_number)->ino_state = DFOUND;
+ check_dirdepth(inp);
+ }
if (inp->i_dotdot == inp->i_parent ||
inp->i_dotdot == (ino_t)-1)
continue;
if (inp->i_dotdot == 0) {
inp->i_dotdot = inp->i_parent;
- fileerror(inp->i_parent, inp->i_number, "MISSING '..'");
- if (reply("FIX") == 0)
- continue;
+ if (debug)
+ fileerror(inp->i_parent, inp->i_number,
+ "DEFERRED MISSING '..' FIX");
(void)makeentry(inp->i_number, inp->i_parent, "..");
inoinfo(inp->i_parent)->ino_linkcnt--;
continue;
@@ -271,7 +265,8 @@ pass2(void)
inoinfo(inp->i_dotdot)->ino_linkcnt++;
inoinfo(inp->i_parent)->ino_linkcnt--;
inp->i_dotdot = inp->i_parent;
- (void)changeino(inp->i_number, "..", inp->i_parent);
+ (void)changeino(inp->i_number, "..", inp->i_parent,
+ getinoinfo(inp->i_parent)->i_depth + 1);
}
/*
* Mark all the directories that can be found from the root.
@@ -289,57 +284,62 @@ pass2check(struct inodesc *idesc)
struct inode ip;
union dinode *dp;
const char *errmsg;
- struct direct proto;
+ struct direct proto, *newdirp;
/*
* check for "."
*/
- if (dirp->d_ino > maxino)
- goto chk2;
if (idesc->id_entryno != 0)
goto chk1;
if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) {
if (dirp->d_ino != idesc->id_number) {
direrror(idesc->id_number, "BAD INODE NUMBER FOR '.'");
- dirp->d_ino = idesc->id_number;
- if (reply("FIX") == 1)
+ if (reply("FIX") == 1) {
+ dirp->d_ino = idesc->id_number;
ret |= ALTERED;
+ }
}
if (dirp->d_type != DT_DIR) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '.'");
- dirp->d_type = DT_DIR;
- if (reply("FIX") == 1)
+ if (reply("FIX") == 1) {
+ dirp->d_type = DT_DIR;
ret |= ALTERED;
+ }
}
goto chk1;
}
- direrror(idesc->id_number, "MISSING '.'");
proto.d_ino = idesc->id_number;
proto.d_type = DT_DIR;
proto.d_namlen = 1;
(void)strcpy(proto.d_name, ".");
entrysize = DIRSIZ(0, &proto);
- if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) {
- pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n",
- dirp->d_name);
- } else if (dirp->d_reclen < entrysize) {
- pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n");
- } else if (dirp->d_reclen < 2 * entrysize) {
+ direrror(idesc->id_number, "MISSING '.'");
+ errmsg = "ADD '.' ENTRY";
+ if (dirp->d_reclen < entrysize + DIRSIZ(0, dirp)) {
+ /* Not enough space to add '.', replace first entry with '.' */
+ if (dirp->d_ino != 0) {
+ pwarn("\nFIRST ENTRY IN DIRECTORY CONTAINS %s\n",
+ dirp->d_name);
+ errmsg = "REPLACE WITH '.'";
+ }
+ if (reply(errmsg) == 0)
+ goto chk1;
proto.d_reclen = dirp->d_reclen;
memmove(dirp, &proto, (size_t)entrysize);
- if (reply("FIX") == 1)
- ret |= ALTERED;
+ ret |= ALTERED;
} else {
- n = dirp->d_reclen - entrysize;
+ /* Move over first entry and add '.' entry */
+ if (reply(errmsg) == 0)
+ goto chk1;
+ newdirp = (struct direct *)((char *)(dirp) + entrysize);
+ dirp->d_reclen -= entrysize;
+ memmove(newdirp, dirp, dirp->d_reclen);
proto.d_reclen = entrysize;
memmove(dirp, &proto, (size_t)entrysize);
idesc->id_entryno++;
- inoinfo(dirp->d_ino)->ino_linkcnt--;
- dirp = (struct direct *)((char *)(dirp) + entrysize);
- memset(dirp, 0, (size_t)n);
- dirp->d_reclen = n;
- if (reply("FIX") == 1)
- ret |= ALTERED;
+ inoinfo(idesc->id_number)->ino_linkcnt--;
+ dirp = newdirp;
+ ret |= ALTERED;
}
chk1:
if (idesc->id_entryno > 1)
@@ -363,6 +363,20 @@ chk1:
dirp->d_reclen = proto.d_reclen;
}
if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) {
+ if (dirp->d_ino >= maxino) {
+ direrror(idesc->id_number, "BAD INODE NUMBER FOR '..'");
+ /*
+ * If we know parent set it now, otherwise let it
+ * point to the root inode and it will get cleaned
+ * up later if that is not correct.
+ */
+ if (inp->i_parent != 0)
+ dirp->d_ino = inp->i_parent;
+ else
+ dirp->d_ino = UFS_ROOTINO;
+ if (reply("FIX") == 1)
+ ret |= ALTERED;
+ }
inp->i_dotdot = dirp->d_ino;
if (dirp->d_type != DT_DIR) {
direrror(idesc->id_number, "BAD TYPE VALUE FOR '..'");
@@ -372,30 +386,60 @@ chk1:
}
goto chk2;
}
- if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) {
- fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
- pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
- dirp->d_name);
- inp->i_dotdot = (ino_t)-1;
- } else if (dirp->d_reclen < entrysize) {
- fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
- pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n");
- inp->i_dotdot = (ino_t)-1;
- } else if (inp->i_parent != 0) {
- /*
- * We know the parent, so fix now.
- */
- inp->i_dotdot = inp->i_parent;
- fileerror(inp->i_parent, idesc->id_number, "MISSING '..'");
+ fileerror(inp->i_parent != 0 ? inp->i_parent : idesc->id_number,
+ idesc->id_number, "MISSING '..'");
+ errmsg = "ADD '..' ENTRY";
+ if (dirp->d_reclen < entrysize + DIRSIZ(0, dirp)) {
+ /* No space to add '..', replace second entry with '..' */
+ if (dirp->d_ino != 0) {
+ pfatal("SECOND ENTRY IN DIRECTORY CONTAINS %s\n",
+ dirp->d_name);
+ errmsg = "REPLACE WITH '..'";
+ }
+ if (reply(errmsg) == 0) {
+ inp->i_dotdot = (ino_t)-1;
+ goto chk2;
+ }
+ if (proto.d_ino == 0) {
+ /* Defer processing until parent known */
+ idesc->id_entryno++;
+ if (debug)
+ printf("(FIX DEFERRED)\n");
+ }
+ inp->i_dotdot = proto.d_ino;
proto.d_reclen = dirp->d_reclen;
memmove(dirp, &proto, (size_t)entrysize);
- if (reply("FIX") == 1)
- ret |= ALTERED;
+ ret |= ALTERED;
+ } else {
+ /* Move over second entry and add '..' entry */
+ if (reply(errmsg) == 0) {
+ inp->i_dotdot = (ino_t)-1;
+ goto chk2;
+ }
+ if (proto.d_ino == 0) {
+ /* Defer processing until parent known */
+ idesc->id_entryno++;
+ if (debug)
+ printf("(FIX DEFERRED)\n");
+ }
+ inp->i_dotdot = proto.d_ino;
+ if (dirp->d_ino == 0) {
+ proto.d_reclen = dirp->d_reclen;
+ memmove(dirp, &proto, (size_t)entrysize);
+ } else {
+ newdirp = (struct direct *)((char *)(dirp) + entrysize);
+ dirp->d_reclen -= entrysize;
+ memmove(newdirp, dirp, dirp->d_reclen);
+ proto.d_reclen = entrysize;
+ memmove(dirp, &proto, (size_t)entrysize);
+ if (dirp->d_ino != 0) {
+ idesc->id_entryno++;
+ inoinfo(dirp->d_ino)->ino_linkcnt--;
+ }
+ dirp = newdirp;
+ }
+ ret |= ALTERED;
}
- idesc->id_entryno++;
- if (dirp->d_ino != 0)
- inoinfo(dirp->d_ino)->ino_linkcnt--;
- return (ret|KEEPON);
chk2:
if (dirp->d_ino == 0)
return (ret|KEEPON);
@@ -419,7 +463,7 @@ chk2:
}
idesc->id_entryno++;
n = 0;
- if (dirp->d_ino > maxino) {
+ if (dirp->d_ino >= maxino) {
fileerror(idesc->id_number, dirp->d_ino, "I OUT OF RANGE");
n = reply("REMOVE");
} else if (((dirp->d_ino == UFS_WINO && dirp->d_type != DT_WHT) ||
@@ -499,10 +543,12 @@ again:
case DFOUND:
inp = getinoinfo(dirp->d_ino);
if (idesc->id_entryno > 2) {
- if (inp->i_parent == 0)
+ if (inp->i_parent == 0) {
inp->i_parent = idesc->id_number;
- else if ((n = fix_extraneous(inp, idesc)) == 1)
+ check_dirdepth(inp);
+ } else if ((n = fix_extraneous(inp, idesc))) {
break;
+ }
}
/* FALLTHROUGH */
@@ -553,6 +599,7 @@ fix_extraneous(struct inoinfo *inp, struct inodesc *idesc)
if ((ckinode(ip.i_dp, &dotdesc) & FOUND))
inp->i_dotdot = dotdesc.id_parent;
irelse(&ip);
+ free(dotdesc.id_name);
}
/*
* We have the previously found old name (inp->i_parent) and the
diff --git a/sbin/fsck_ffs/pass3.c b/sbin/fsck_ffs/pass3.c
index 22cb0393905b..853f5d62382f 100644
--- a/sbin/fsck_ffs/pass3.c
+++ b/sbin/fsck_ffs/pass3.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)pass3.c 8.2 (Berkeley) 4/27/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <ufs/ufs/dinode.h>
@@ -74,7 +66,7 @@ pass3(void)
if (inp->i_number == UFS_ROOTINO ||
(inp->i_parent != 0 && !S_IS_DUNFOUND(state)))
continue;
- if (state == DCLEAR)
+ if (state == DCLEAR || state == DZLINK)
continue;
/*
* If we are running with soft updates and we come
@@ -100,9 +92,10 @@ pass3(void)
if (linkup(orphan, inp->i_dotdot, NULL)) {
inp->i_parent = inp->i_dotdot = lfdir;
inoinfo(lfdir)->ino_linkcnt--;
+ inoinfo(orphan)->ino_state = DFOUND;
+ check_dirdepth(inp);
+ propagate();
}
- inoinfo(orphan)->ino_state = DFOUND;
- propagate();
continue;
}
pfatal("ORPHANED DIRECTORY LOOP DETECTED I=%lu",
@@ -127,6 +120,7 @@ pass3(void)
}
irelse(&ip);
inoinfo(orphan)->ino_state = DFOUND;
+ check_dirdepth(inp);
propagate();
}
}
diff --git a/sbin/fsck_ffs/pass4.c b/sbin/fsck_ffs/pass4.c
index cfcd36296887..a261051c432a 100644
--- a/sbin/fsck_ffs/pass4.c
+++ b/sbin/fsck_ffs/pass4.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)pass4.c 8.4 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/stat.h>
diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c
index 324e725929f6..528a6956c4a1 100644
--- a/sbin/fsck_ffs/pass5.c
+++ b/sbin/fsck_ffs/pass5.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/sysctl.h>
@@ -47,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <inttypes.h>
#include <limits.h>
#include <string.h>
-#include <libufs.h>
#include "fsck.h"
@@ -116,7 +107,7 @@ pass5(void)
}
}
}
- basesize = &newcg->cg_space[0] - (u_char *)(&newcg->cg_firstfield);
+ basesize = sizeof(*newcg);
if (sblock.fs_magic == FS_UFS2_MAGIC) {
newcg->cg_iusedoff = basesize;
} else {
@@ -131,7 +122,7 @@ pass5(void)
fs->fs_old_cpg * sizeof(int32_t);
newcg->cg_iusedoff = newcg->cg_old_boff +
fs->fs_old_cpg * fs->fs_old_nrpos * sizeof(u_int16_t);
- memset(&newcg->cg_space[0], 0, newcg->cg_iusedoff - basesize);
+ memset(&newcg[1], 0, newcg->cg_iusedoff - basesize);
}
inomapsize = howmany(fs->fs_ipg, CHAR_BIT);
newcg->cg_freeoff = newcg->cg_iusedoff + inomapsize;
@@ -375,6 +366,22 @@ pass5(void)
if (cursnapshot == 0 &&
memcmp(&cstotal, &fs->fs_cstotal, sizeof cstotal) != 0
&& dofix(&idesc[0], "SUMMARY BLK COUNT(S) WRONG IN SUPERBLK")) {
+ if (debug) {
+ printf("cstotal is currently: %jd dirs, %jd blks free, "
+ "%jd frags free, %jd inos free, %jd clusters\n",
+ (intmax_t)fs->fs_cstotal.cs_ndir,
+ (intmax_t)fs->fs_cstotal.cs_nbfree,
+ (intmax_t)fs->fs_cstotal.cs_nffree,
+ (intmax_t)fs->fs_cstotal.cs_nifree,
+ (intmax_t)fs->fs_cstotal.cs_numclusters);
+ printf("cstotal ought to be: %jd dirs, %jd blks free, "
+ "%jd frags free, %jd inos free, %jd clusters\n",
+ (intmax_t)cstotal.cs_ndir,
+ (intmax_t)cstotal.cs_nbfree,
+ (intmax_t)cstotal.cs_nffree,
+ (intmax_t)cstotal.cs_nifree,
+ (intmax_t)cstotal.cs_numclusters);
+ }
memmove(&fs->fs_cstotal, &cstotal, sizeof cstotal);
fs->fs_ronly = 0;
fs->fs_fmod = 0;
@@ -395,43 +402,53 @@ pass5(void)
printf("adjndir by %+" PRIi64 "\n", cmd.value);
if (bkgrdsumadj == 0 || sysctl(adjndir, MIBSIZE, 0, 0,
&cmd, sizeof cmd) == -1)
- rwerror("ADJUST NUMBER OF DIRECTORIES", cmd.value);
+ rwerror("ADJUST NUMBER OF DIRECTORIES",
+ cmd.value);
}
cmd.value = cstotal.cs_nbfree - fs->fs_cstotal.cs_nbfree;
if (cmd.value != 0) {
if (debug)
- printf("adjnbfree by %+" PRIi64 "\n", cmd.value);
+ printf("adjnbfree by %+" PRIi64 "\n",
+ cmd.value);
if (bkgrdsumadj == 0 || sysctl(adjnbfree, MIBSIZE, 0, 0,
&cmd, sizeof cmd) == -1)
- rwerror("ADJUST NUMBER OF FREE BLOCKS", cmd.value);
+ rwerror("ADJUST NUMBER OF FREE BLOCKS",
+ cmd.value);
}
cmd.value = cstotal.cs_nifree - fs->fs_cstotal.cs_nifree;
if (cmd.value != 0) {
if (debug)
- printf("adjnifree by %+" PRIi64 "\n", cmd.value);
+ printf("adjnifree by %+" PRIi64 "\n",
+ cmd.value);
if (bkgrdsumadj == 0 || sysctl(adjnifree, MIBSIZE, 0, 0,
&cmd, sizeof cmd) == -1)
- rwerror("ADJUST NUMBER OF FREE INODES", cmd.value);
+ rwerror("ADJUST NUMBER OF FREE INODES",
+ cmd.value);
}
cmd.value = cstotal.cs_nffree - fs->fs_cstotal.cs_nffree;
if (cmd.value != 0) {
if (debug)
- printf("adjnffree by %+" PRIi64 "\n", cmd.value);
+ printf("adjnffree by %+" PRIi64 "\n",
+ cmd.value);
if (bkgrdsumadj == 0 || sysctl(adjnffree, MIBSIZE, 0, 0,
&cmd, sizeof cmd) == -1)
- rwerror("ADJUST NUMBER OF FREE FRAGS", cmd.value);
+ rwerror("ADJUST NUMBER OF FREE FRAGS",
+ cmd.value);
}
- cmd.value = cstotal.cs_numclusters - fs->fs_cstotal.cs_numclusters;
+ cmd.value = cstotal.cs_numclusters -
+ fs->fs_cstotal.cs_numclusters;
if (cmd.value != 0) {
if (debug)
- printf("adjnumclusters by %+" PRIi64 "\n", cmd.value);
- if (bkgrdsumadj == 0 || sysctl(adjnumclusters, MIBSIZE, 0, 0,
- &cmd, sizeof cmd) == -1)
- rwerror("ADJUST NUMBER OF FREE CLUSTERS", cmd.value);
+ printf("adjnumclusters by %+" PRIi64 "\n",
+ cmd.value);
+ if (bkgrdsumadj == 0 || sysctl(adjnumclusters, MIBSIZE,
+ 0, 0, &cmd, sizeof cmd) == -1)
+ rwerror("ADJUST NUMBER OF FREE CLUSTERS",
+ cmd.value);
}
}
}
diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c
index 0f0d9b61a076..41b4a5336350 100644
--- a/sbin/fsck_ffs/setup.c
+++ b/sbin/fsck_ffs/setup.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/stat.h>
@@ -54,19 +46,22 @@ __FBSDID("$FreeBSD$");
#include <limits.h>
#include <stdint.h>
#include <string.h>
-#include <libufs.h>
#include "fsck.h"
-struct inoinfo **inphead, **inpsort; /* info about all inodes */
+struct inohash *inphash; /* hash list of directory inode info */
+struct inoinfo **inpsort; /* disk order list of directory inodes */
+struct inode snaplist[FSMAXSNAP + 1]; /* list of active snapshots */
+int snapcnt; /* number of active snapshots */
+char *copybuf; /* buffer to copy snapshot blocks */
-struct bufarea asblk;
-#define altsblock (*asblk.b_un.b_fs)
+static int sbhashfailed;
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
-static int calcsb(char *dev, int devfd, struct fs *fs);
static void saverecovery(int readfd, int writefd);
static int chkrecovery(int devfd);
+static int getlbnblkno(struct inodesc *);
+static int checksnapinfo(struct inode *);
/*
* Read in a superblock finding an alternate if necessary.
@@ -76,39 +71,20 @@ static int chkrecovery(int devfd);
int
setup(char *dev)
{
- long cg, bmapsize;
- struct fs proto;
+ long i, bmapsize;
+ struct inode ip;
/*
- * We are expected to have an open file descriptor
- */
- if (fsreadfd < 0)
- return (0);
- /*
- * If we do not yet have a superblock, read it in looking
- * for alternates if necessary.
+ * We are expected to have an open file descriptor and a superblock.
*/
- if (havesb == 0 && readsb(1) == 0) {
- skipclean = 0;
- if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0)
- return(0);
- if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
- return (0);
- for (cg = 0; cg < proto.fs_ncg; cg++) {
- bflag = fsbtodb(&proto, cgsblock(&proto, cg));
- if (readsb(0) != 0)
- break;
- }
- if (cg >= proto.fs_ncg) {
- printf("SEARCH FOR ALTERNATE SUPER-BLOCK FAILED. "
- "YOU MUST USE THE\n-b OPTION TO FSCK TO SPECIFY "
- "THE LOCATION OF AN ALTERNATE\nSUPER-BLOCK TO "
- "SUPPLY NEEDED INFORMATION; SEE fsck_ffs(8).\n");
- bflag = 0;
- return(0);
+ if (fsreadfd < 0 || havesb == 0) {
+ if (debug) {
+ if (fsreadfd < 0)
+ printf("setup: missing fsreadfd\n");
+ else
+ printf("setup: missing superblock\n");
}
- pwarn("USING ALTERNATE SUPERBLOCK AT %jd\n", bflag);
- bflag = 0;
+ return (0);
}
if (preen == 0)
printf("** %s", dev);
@@ -163,10 +139,6 @@ setup(char *dev)
pfatal("from before 2002 with the command ``fsck -c 2''\n");
exit(EEXIT);
}
- if ((asblk.b_flags & B_DIRTY) != 0 && !bflag) {
- memmove(&altsblock, &sblock, (size_t)sblock.fs_sbsize);
- flush(fswritefd, &asblk);
- }
if (preen == 0 && yflag == 0 && sblock.fs_magic == FS_UFS2_MAGIC &&
fswritefd != -1 && chkrecovery(fsreadfd) == 0 &&
reply("SAVE DATA TO FIND ALTERNATE SUPERBLOCKS") != 0)
@@ -174,6 +146,7 @@ setup(char *dev)
/*
* allocate and initialize the necessary maps
*/
+ bufinit();
bmapsize = roundup(howmany(maxfsblock, CHAR_BIT), sizeof(short));
blockmap = Calloc((unsigned)bmapsize, sizeof (char));
if (blockmap == NULL) {
@@ -187,22 +160,57 @@ setup(char *dev)
(unsigned)(sizeof(struct inostatlist) * (sblock.fs_ncg)));
goto badsb;
}
- numdirs = MAX(sblock.fs_cstotal.cs_ndir, 128);
- dirhash = numdirs;
+ numdirs = sblock.fs_cstotal.cs_ndir;
+ dirhash = MAX(numdirs / 2, 1);
inplast = 0;
listmax = numdirs + 10;
inpsort = (struct inoinfo **)Calloc(listmax, sizeof(struct inoinfo *));
- inphead = (struct inoinfo **)Calloc(numdirs, sizeof(struct inoinfo *));
- if (inpsort == NULL || inphead == NULL) {
- printf("cannot alloc %ju bytes for inphead\n",
+ inphash = (struct inohash *)Calloc(dirhash, sizeof(struct inohash));
+ if (inpsort == NULL || inphash == NULL) {
+ printf("cannot alloc %ju bytes for inphash\n",
(uintmax_t)numdirs * sizeof(struct inoinfo *));
goto badsb;
}
- bufinit();
if (sblock.fs_flags & FS_DOSOFTDEP)
usedsoftdep = 1;
else
usedsoftdep = 0;
+ /*
+ * Collect any snapshot inodes so that we can allow them to
+ * claim any blocks that we free. The code for doing this is
+ * imported here and into inode.c from sys/ufs/ffs/ffs_snapshot.c.
+ */
+ for (snapcnt = 0; snapcnt < FSMAXSNAP; snapcnt++) {
+ if (sblock.fs_snapinum[snapcnt] == 0)
+ break;
+ ginode(sblock.fs_snapinum[snapcnt], &ip);
+ if ((DIP(ip.i_dp, di_mode) & IFMT) == IFREG &&
+ (DIP(ip.i_dp, di_flags) & SF_SNAPSHOT) != 0 &&
+ checksnapinfo(&ip)) {
+ if (debug)
+ printf("Load snapshot %jd\n",
+ (intmax_t)sblock.fs_snapinum[snapcnt]);
+ snaplist[snapcnt] = ip;
+ continue;
+ }
+ printf("Removing non-snapshot inode %ju from snapshot list\n",
+ (uintmax_t)sblock.fs_snapinum[snapcnt]);
+ irelse(&ip);
+ for (i = snapcnt + 1; i < FSMAXSNAP; i++) {
+ if (sblock.fs_snapinum[i] == 0)
+ break;
+ sblock.fs_snapinum[i - 1] = sblock.fs_snapinum[i];
+ }
+ sblock.fs_snapinum[i - 1] = 0;
+ snapcnt--;
+ sbdirty();
+ }
+ if (snapcnt > 0 && copybuf == NULL) {
+ copybuf = Balloc(sblock.fs_bsize);
+ if (copybuf == NULL)
+ errx(EEXIT, "cannot allocate space for snapshot "
+ "copy buffer");
+ }
return (1);
badsb:
@@ -211,6 +219,146 @@ badsb:
}
/*
+ * Check for valid snapshot information.
+ *
+ * Each snapshot has a list of blocks that have been copied. This list
+ * is consulted before checking the snapshot inode. Its purpose is to
+ * speed checking of commonly checked blocks and to avoid recursive
+ * checks of the snapshot inode. In particular, the list must contain
+ * the superblock, the superblock summary information, and all the
+ * cylinder group blocks. The list may contain other commonly checked
+ * pointers such as those of the blocks that contain the snapshot inodes.
+ * The list is sorted into block order to allow binary search lookup.
+ *
+ * The twelve direct direct block pointers of the snapshot are always
+ * copied, so we test for them first before checking the list itself
+ * (i.e., they are not in the list).
+ *
+ * The checksnapinfo() routine needs to ensure that the list contains at
+ * least the super block, its summary information, and the cylinder groups.
+ * Here we check the list first for the superblock, zero or more cylinder
+ * groups up to the location of the superblock summary information, the
+ * summary group information, and any remaining cylinder group maps that
+ * follow it. We skip over any other entries in the list.
+ */
+#define CHKBLKINLIST(chkblk) \
+ /* All UFS_NDADDR blocks are copied */ \
+ if ((chkblk) >= UFS_NDADDR) { \
+ /* Skip over blocks that are not of interest */ \
+ while (*blkp < (chkblk) && blkp < lastblkp) \
+ blkp++; \
+ /* Fail if end of list and not all blocks found */ \
+ if (blkp >= lastblkp) { \
+ pwarn("UFS%d snapshot inode %jd failed: " \
+ "improper block list length (%jd)\n", \
+ sblock.fs_magic == FS_UFS1_MAGIC ? 1 : 2, \
+ (intmax_t)snapip->i_number, \
+ (intmax_t)(lastblkp - &snapblklist[0])); \
+ status = 0; \
+ } \
+ /* Fail if block we seek is missing */ \
+ else if (*blkp++ != (chkblk)) { \
+ pwarn("UFS%d snapshot inode %jd failed: " \
+ "block list (%jd) != %s (%jd)\n", \
+ sblock.fs_magic == FS_UFS1_MAGIC ? 1 : 2, \
+ (intmax_t)snapip->i_number, \
+ (intmax_t)blkp[-1], #chkblk, \
+ (intmax_t)chkblk); \
+ status = 0; \
+ } \
+ }
+
+static int
+checksnapinfo(struct inode *snapip)
+{
+ struct fs *fs;
+ struct bufarea *bp;
+ struct inodesc idesc;
+ daddr_t *snapblklist, *blkp, *lastblkp, csblkno;
+ int cg, loc, len, status;
+ ufs_lbn_t lbn;
+ size_t size;
+
+ fs = &sblock;
+ memset(&idesc, 0, sizeof(struct inodesc));
+ idesc.id_type = ADDR;
+ idesc.id_func = getlbnblkno;
+ idesc.id_number = snapip->i_number;
+ lbn = howmany(fs->fs_size, fs->fs_frag);
+ idesc.id_parent = lbn; /* sought after blkno */
+ if ((ckinode(snapip->i_dp, &idesc) & FOUND) == 0)
+ return (0);
+ size = fragroundup(fs,
+ DIP(snapip->i_dp, di_size) - lblktosize(fs, lbn));
+ bp = getdatablk(idesc.id_parent, size, BT_DATA);
+ if (bp->b_errs != 0)
+ return (0);
+ snapblklist = (daddr_t *)bp->b_un.b_buf;
+ /*
+ * snapblklist[0] is the size of the list
+ * snapblklist[1] is the first element of the list
+ *
+ * We need to be careful to bound the size of the list and verify
+ * that we have not run off the end of it if it or its size has
+ * been corrupted.
+ */
+ blkp = &snapblklist[1];
+ lastblkp = &snapblklist[MAX(0,
+ MIN(snapblklist[0] + 1, size / sizeof(daddr_t)))];
+ status = 1;
+ /* Check that the superblock is listed. */
+ CHKBLKINLIST(lblkno(fs, fs->fs_sblockloc));
+ if (status == 0)
+ goto out;
+ /*
+ * Calculate where the summary information is located.
+ * Usually it is in the first cylinder group, but growfs
+ * may move it to the first cylinder group that it adds.
+ *
+ * Check all cylinder groups up to the summary information.
+ */
+ csblkno = fragstoblks(fs, fs->fs_csaddr);
+ for (cg = 0; cg < fs->fs_ncg; cg++) {
+ if (fragstoblks(fs, cgtod(fs, cg)) > csblkno)
+ break;
+ CHKBLKINLIST(fragstoblks(fs, cgtod(fs, cg)));
+ if (status == 0)
+ goto out;
+ }
+ /* Check the summary information block(s). */
+ len = howmany(fs->fs_cssize, fs->fs_bsize);
+ for (loc = 0; loc < len; loc++) {
+ CHKBLKINLIST(csblkno + loc);
+ if (status == 0)
+ goto out;
+ }
+ /* Check the remaining cylinder groups. */
+ for (; cg < fs->fs_ncg; cg++) {
+ CHKBLKINLIST(fragstoblks(fs, cgtod(fs, cg)));
+ if (status == 0)
+ goto out;
+ }
+out:
+ brelse(bp);
+ return (status);
+}
+
+/*
+ * Return the block number associated with a specified inode lbn.
+ * Requested lbn is in id_parent. If found, block is returned in
+ * id_parent.
+ */
+static int
+getlbnblkno(struct inodesc *idesc)
+{
+
+ if (idesc->id_lbn < idesc->id_parent)
+ return (KEEPON);
+ idesc->id_parent = idesc->id_blkno;
+ return (STOP | FOUND);
+}
+
+/*
* Open a device or file to be checked by fsck.
*/
int
@@ -224,14 +372,14 @@ openfilesys(char *dev)
if ((statb.st_mode & S_IFMT) != S_IFCHR &&
(statb.st_mode & S_IFMT) != S_IFBLK) {
if (bkgrdflag != 0 && (statb.st_flags & SF_SNAPSHOT) == 0) {
- pfatal("BACKGROUND FSCK LACKS A SNAPSHOT\n");
- exit(EEXIT);
+ pwarn("BACKGROUND FSCK LACKS A SNAPSHOT\n");
+ return (0);
}
if (bkgrdflag != 0) {
cursnapshot = statb.st_ino;
} else {
- pfatal("%s IS NOT A DISK DEVICE\n", dev);
- if (reply("CONTINUE") == 0)
+ pwarn("%s IS NOT A DISK DEVICE\n", dev);
+ if (preen || reply("CONTINUE") == 0)
return (0);
}
}
@@ -249,38 +397,64 @@ openfilesys(char *dev)
* Read in the super block and its summary info.
*/
int
-readsb(int listerr)
+readsb(void)
{
- off_t super;
- int bad, ret;
struct fs *fs;
- super = bflag ? bflag * dev_bsize :
- sbhashfailed ? STDSB_NOHASHFAIL_NOMSG : STDSB_NOMSG;
+ sbhashfailed = 0;
readcnt[sblk.b_type]++;
- while ((ret = sbget(fsreadfd, &fs, super)) != 0) {
- switch (ret) {
+ /*
+ * If bflag is given, then check just that superblock.
+ */
+ if (bflag) {
+ switch (sbget(fsreadfd, &fs, bflag * dev_bsize, 0)) {
+ case 0:
+ goto goodsb;
case EINTEGRITY:
- if (bflag || super == STDSB_NOHASHFAIL_NOMSG)
- return (0);
- super = STDSB_NOHASHFAIL_NOMSG;
- sbhashfailed = 1;
- continue;
+ printf("Check hash failed for superblock at %jd\n",
+ bflag);
+ return (0);
case ENOENT:
- if (bflag)
- printf("%jd is not a file system "
- "superblock\n", super / dev_bsize);
- else
- printf("Cannot find file system "
- "superblock\n");
+ printf("%jd is not a file system superblock\n", bflag);
return (0);
case EIO:
default:
- printf("I/O error reading %jd\n",
- super / dev_bsize);
+ printf("I/O error reading %jd\n", bflag);
return (0);
}
}
+ /*
+ * Check for the standard superblock and use it if good.
+ */
+ if (sbget(fsreadfd, &fs, UFS_STDSB, UFS_NOMSG) == 0)
+ goto goodsb;
+ /*
+ * Check if the only problem is a check-hash failure.
+ */
+ skipclean = 0;
+ if (sbget(fsreadfd, &fs, UFS_STDSB, UFS_NOMSG | UFS_NOHASHFAIL) == 0) {
+ sbhashfailed = 1;
+ goto goodsb;
+ }
+ /*
+ * Do an exhaustive search for a usable superblock.
+ */
+ switch (sbsearch(fsreadfd, &fs, 0)) {
+ case 0:
+ goto goodsb;
+ case ENOENT:
+ printf("SEARCH FOR ALTERNATE SUPER-BLOCK FAILED. "
+ "YOU MUST USE THE\n-b OPTION TO FSCK TO SPECIFY "
+ "THE LOCATION OF AN ALTERNATE\nSUPER-BLOCK TO "
+ "SUPPLY NEEDED INFORMATION; SEE fsck_ffs(8).\n");
+ return (0);
+ case EIO:
+ default:
+ printf("I/O error reading a usable superblock\n");
+ return (0);
+ }
+
+goodsb:
memcpy(&sblock, fs, fs->fs_sbsize);
free(fs);
/*
@@ -292,58 +466,6 @@ readsb(int listerr)
sblk.b_bno = sblock.fs_sblockactualloc / dev_bsize;
sblk.b_size = SBLOCKSIZE;
/*
- * Compare all fields that should not differ in alternate super block.
- * When an alternate super-block is specified this check is skipped.
- */
- if (bflag)
- goto out;
- getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize);
- if (asblk.b_errs)
- return (0);
- bad = 0;
-#define CHK(x, y) \
- if (altsblock.x != sblock.x) { \
- bad++; \
- if (listerr && debug) \
- printf("SUPER BLOCK VS ALTERNATE MISMATCH %s: " y " vs " y "\n", \
- #x, (intmax_t)sblock.x, (intmax_t)altsblock.x); \
- }
- CHK(fs_sblkno, "%jd");
- CHK(fs_cblkno, "%jd");
- CHK(fs_iblkno, "%jd");
- CHK(fs_dblkno, "%jd");
- CHK(fs_ncg, "%jd");
- CHK(fs_bsize, "%jd");
- CHK(fs_fsize, "%jd");
- CHK(fs_frag, "%jd");
- CHK(fs_bmask, "%#jx");
- CHK(fs_fmask, "%#jx");
- CHK(fs_bshift, "%jd");
- CHK(fs_fshift, "%jd");
- CHK(fs_fragshift, "%jd");
- CHK(fs_fsbtodb, "%jd");
- CHK(fs_sbsize, "%jd");
- CHK(fs_nindir, "%jd");
- CHK(fs_inopb, "%jd");
- CHK(fs_cssize, "%jd");
- CHK(fs_ipg, "%jd");
- CHK(fs_fpg, "%jd");
- CHK(fs_magic, "%#jx");
-#undef CHK
- if (bad) {
- if (listerr == 0)
- return (0);
- if (preen)
- printf("%s: ", cdevname);
- printf(
- "VALUES IN SUPER BLOCK LSB=%jd DISAGREE WITH THOSE IN\n"
- "LAST ALTERNATE LSB=%jd\n",
- sblk.b_bno, asblk.b_bno);
- if (reply("IGNORE ALTERNATE SUPER BLOCK") == 0)
- return (0);
- }
-out:
- /*
* If not yet done, update UFS1 superblock with new wider fields.
*/
if (sblock.fs_magic == FS_UFS1_MAGIC &&
@@ -371,61 +493,13 @@ sblock_init(void)
fsmodified = 0;
lfdir = 0;
initbarea(&sblk, BT_SUPERBLK);
- initbarea(&asblk, BT_SUPERBLK);
- sblk.b_un.b_buf = Malloc(SBLOCKSIZE);
- asblk.b_un.b_buf = Malloc(SBLOCKSIZE);
- if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
+ sblk.b_un.b_buf = Balloc(SBLOCKSIZE);
+ if (sblk.b_un.b_buf == NULL)
errx(EEXIT, "cannot allocate space for superblock");
dev_bsize = secsize = DEV_BSIZE;
}
/*
- * Calculate a prototype superblock based on information in the boot area.
- * When done the cgsblock macro can be calculated and the fs_ncg field
- * can be used. Do NOT attempt to use other macros without verifying that
- * their needed information is available!
- */
-static int
-calcsb(char *dev, int devfd, struct fs *fs)
-{
- struct fsrecovery *fsr;
- char *fsrbuf;
- u_int secsize;
-
- /*
- * We need fragments-per-group and the partition-size.
- *
- * Newfs stores these details at the end of the boot block area
- * at the start of the filesystem partition. If they have been
- * overwritten by a boot block, we fail. But usually they are
- * there and we can use them.
- */
- if (ioctl(devfd, DIOCGSECTORSIZE, &secsize) == -1)
- return (0);
- fsrbuf = Malloc(secsize);
- if (fsrbuf == NULL)
- errx(EEXIT, "calcsb: cannot allocate recovery buffer");
- if (blread(devfd, fsrbuf,
- (SBLOCK_UFS2 - secsize) / dev_bsize, secsize) != 0) {
- free(fsrbuf);
- return (0);
- }
- fsr = (struct fsrecovery *)&fsrbuf[secsize - sizeof *fsr];
- if (fsr->fsr_magic != FS_UFS2_MAGIC) {
- free(fsrbuf);
- return (0);
- }
- memset(fs, 0, sizeof(struct fs));
- fs->fs_fpg = fsr->fsr_fpg;
- fs->fs_fsbtodb = fsr->fsr_fsbtodb;
- fs->fs_sblkno = fsr->fsr_sblkno;
- fs->fs_magic = fsr->fsr_magic;
- fs->fs_ncg = fsr->fsr_ncg;
- free(fsrbuf);
- return (1);
-}
-
-/*
* Check to see if recovery information exists.
* Return 1 if it exists or cannot be created.
* Return 0 if it does not exist and can be created.
@@ -445,7 +519,7 @@ chkrecovery(int devfd)
rdsize = sblock.fs_fsize;
if (ioctl(devfd, DIOCGSECTORSIZE, &secsize) == -1 ||
rdsize % secsize != 0 ||
- (fsrbuf = Malloc(rdsize)) == NULL ||
+ (fsrbuf = Balloc(rdsize)) == NULL ||
blread(devfd, fsrbuf, (SBLOCK_UFS2 - rdsize) / dev_bsize,
rdsize) != 0) {
free(fsrbuf);
@@ -484,7 +558,7 @@ saverecovery(int readfd, int writefd)
if (sblock.fs_magic != FS_UFS2_MAGIC ||
ioctl(readfd, DIOCGSECTORSIZE, &secsize) == -1 ||
rdsize % secsize != 0 ||
- (fsrbuf = Malloc(rdsize)) == NULL ||
+ (fsrbuf = Balloc(rdsize)) == NULL ||
blread(readfd, fsrbuf, (SBLOCK_UFS2 - rdsize) / dev_bsize,
rdsize) != 0) {
printf("RECOVERY DATA COULD NOT BE CREATED\n");
diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c
index 4ad86b0dc14d..73be60c5e5b4 100644
--- a/sbin/fsck_ffs/suj.c
+++ b/sbin/fsck_ffs/suj.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright 2009, 2010 Jeffrey W. Roberson <jeff@FreeBSD.org>
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
@@ -49,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
-#include <libufs.h>
#include <string.h>
#include <strings.h>
#include <sysexits.h>
@@ -115,6 +111,7 @@ static TAILQ_HEAD(seghd, suj_seg) allsegs;
static uint64_t oldseq;
static struct fs *fs = NULL;
static ino_t sujino;
+static char *joptype[JOP_NUMJOPTYPES] = JOP_NAMES;
/*
* Summary statistics.
@@ -183,7 +180,7 @@ cg_lookup(int cgx)
if (lastcg && lastcg->sc_cgx == cgx)
return (lastcg);
cgbp = cglookup(cgx);
- if (!check_cgmagic(cgx, cgbp, 0))
+ if (!check_cgmagic(cgx, cgbp))
err_suj("UNABLE TO REBUILD CYLINDER GROUP %d", cgx);
hd = &cghash[HASH(cgx)];
LIST_FOREACH(sc, hd, sc_next)
@@ -321,7 +318,7 @@ blk_freemask(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn, int frags)
* To be certain we're not freeing a reallocated block we lookup
* this block in the blk hash and see if there is an allocation
* journal record that overlaps with any fragments in the block
- * we're concerned with. If any fragments have ben reallocated
+ * we're concerned with. If any fragments have been reallocated
* the block has already been freed and re-used for another purpose.
*/
mask = 0;
@@ -379,6 +376,50 @@ blk_isindir(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn)
}
/*
+ * Check to see if the requested block is available.
+ * We can just check in the cylinder-group maps as
+ * they will only have usable blocks in them.
+ */
+ufs2_daddr_t
+suj_checkblkavail(ufs2_daddr_t blkno, long frags)
+{
+ struct bufarea *cgbp;
+ struct cg *cgp;
+ ufs2_daddr_t j, k, baseblk;
+ long cg;
+
+ if ((u_int64_t)blkno > sblock.fs_size)
+ return (0);
+ cg = dtog(&sblock, blkno);
+ cgbp = cglookup(cg);
+ cgp = cgbp->b_un.b_cg;
+ if (!check_cgmagic(cg, cgbp))
+ return (-((cg + 1) * sblock.fs_fpg - sblock.fs_frag));
+ baseblk = dtogd(&sblock, blkno);
+ for (j = 0; j <= sblock.fs_frag - frags; j++) {
+ if (!isset(cg_blksfree(cgp), baseblk + j))
+ continue;
+ for (k = 1; k < frags; k++)
+ if (!isset(cg_blksfree(cgp), baseblk + j + k))
+ break;
+ if (k < frags) {
+ j += k;
+ continue;
+ }
+ for (k = 0; k < frags; k++)
+ clrbit(cg_blksfree(cgp), baseblk + j + k);
+ n_blks += frags;
+ if (frags == sblock.fs_frag)
+ cgp->cg_cs.cs_nbfree--;
+ else
+ cgp->cg_cs.cs_nffree -= frags;
+ cgdirty(cgbp);
+ return ((cg * sblock.fs_fpg) + baseblk + j);
+ }
+ return (0);
+}
+
+/*
* Clear an inode from the cg bitmap. If the inode was already clear return
* 0 so the caller knows it does not have to check the inode contents.
*/
@@ -420,7 +461,7 @@ ino_free(ino_t ino, int mode)
* set in the mask.
*/
static void
-blk_free(ufs2_daddr_t bno, int mask, int frags)
+blk_free(ino_t ino, ufs2_daddr_t bno, int mask, int frags)
{
ufs1_daddr_t fragno, cgbno;
struct suj_cg *sc;
@@ -431,6 +472,13 @@ blk_free(ufs2_daddr_t bno, int mask, int frags)
if (debug)
printf("Freeing %d frags at blk %jd mask 0x%x\n",
frags, bno, mask);
+ /*
+ * Check to see if the block needs to be claimed by a snapshot.
+ * If wanted, the snapshot references it. Otherwise we free it.
+ */
+ if (snapblkfree(fs, bno, lfragtosize(fs, frags), ino,
+ suj_checkblkavail))
+ return;
cg = dtog(fs, bno);
sc = cg_lookup(cg);
cgp = sc->sc_cgp;
@@ -451,7 +499,8 @@ blk_free(ufs2_daddr_t bno, int mask, int frags)
* deallocate the fragment
*/
for (i = 0; i < frags; i++)
- if ((mask & (1 << i)) == 0 && isclr(blksfree, cgbno +i)) {
+ if ((mask & (1 << i)) == 0 &&
+ isclr(blksfree, cgbno +i)) {
freefrags++;
setbit(blksfree, cgbno + i);
}
@@ -685,7 +734,7 @@ indir_visit(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, uint64_t *frags,
lbnadd *= NINDIR(fs);
bp = getdatablk(blk, fs->fs_bsize, BT_LEVEL1 + level);
if (bp->b_errs != 0)
- err_suj("indir_visit: UNRECOVERABLE I/O ERROR");
+ err_suj("indir_visit: UNRECOVERABLE I/O ERROR\n");
for (i = 0; i < NINDIR(fs); i++) {
if ((nblk = IBLK(bp, i)) == 0)
continue;
@@ -846,7 +895,7 @@ static void
blk_free_visit(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, int frags)
{
- blk_free(blk, blk_freemask(blk, ino, lbn, frags), frags);
+ blk_free(ino, blk, blk_freemask(blk, ino, lbn, frags), frags);
}
/*
@@ -865,7 +914,7 @@ blk_free_lbn(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn, int frags, int follow)
if (lbn <= -UFS_NDADDR && follow && mask == 0)
indir_visit(ino, lbn, blk, &resid, blk_free_visit, VISIT_INDIR);
else
- blk_free(blk, mask, frags);
+ blk_free(ino, blk, mask, frags);
}
static void
@@ -997,6 +1046,8 @@ ino_reclaim(struct inode *ip, ino_t ino, int mode)
if ((DIP(dp, di_mode) & IFMT) == IFDIR)
ino_visit(dp, ino, ino_free_children, 0);
DIP_SET(dp, di_nlink, 0);
+ if ((DIP(dp, di_flags) & SF_SNAPSHOT) != 0)
+ snapremove(ino);
ino_visit(dp, ino, blk_free_visit, VISIT_EXT | VISIT_INDIR);
/* Here we have to clear the inode and release any blocks it holds. */
gen = DIP(dp, di_gen);
@@ -1209,7 +1260,7 @@ indir_trunc(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, ufs_lbn_t lastlbn,
continue;
}
isdirty = 1;
- blk_free(nblk, 0, fs->fs_frag);
+ blk_free(ino, nblk, 0, fs->fs_frag);
IBLK_SET(bp, i, 0);
}
if (isdirty)
@@ -1245,9 +1296,14 @@ ino_trunc(ino_t ino, off_t size)
dp = ip.i_dp;
mode = DIP(dp, di_mode) & IFMT;
cursize = DIP(dp, di_size);
+ /* If no size change, nothing to do */
+ if (size == cursize) {
+ irelse(&ip);
+ return;
+ }
if (debug)
- printf("Truncating ino %ju, mode %o to size %jd from size %jd\n",
- (uintmax_t)ino, mode, size, cursize);
+ printf("Truncating ino %ju, mode %o to size %jd from "
+ "size %jd\n", (uintmax_t)ino, mode, size, cursize);
/* Skip datablocks for short links and devices. */
if (mode == 0 || mode == IFBLK || mode == IFCHR ||
@@ -1264,13 +1320,14 @@ ino_trunc(ino_t ino, off_t size)
if (size > 0)
err_suj("Partial truncation of ino %ju snapshot file\n",
(uintmax_t)ino);
+ snapremove(ino);
}
lastlbn = lblkno(fs, blkroundup(fs, size));
for (i = lastlbn; i < UFS_NDADDR; i++) {
if ((bn = DIP(dp, di_db[i])) == 0)
continue;
blksize = sblksize(fs, cursize, i);
- blk_free(bn, 0, numfrags(fs, blksize));
+ blk_free(ino, bn, 0, numfrags(fs, blksize));
DIP_SET(dp, di_db[i], 0);
}
/*
@@ -1283,13 +1340,13 @@ ino_trunc(ino_t ino, off_t size)
/* If we're not freeing any in this indirect range skip it. */
if (lastlbn >= nextlbn)
continue;
- if (DIP(dp, di_ib[i]) == 0)
- continue;
- indir_trunc(ino, -lbn - i, DIP(dp, di_ib[i]), lastlbn, dp);
- /* If we freed everything in this indirect free the indir. */
- if (lastlbn > lbn)
- continue;
- blk_free(DIP(dp, di_ib[i]), 0, fs->fs_frag);
+ if ((bn = DIP(dp, di_ib[i])) == 0)
+ continue;
+ indir_trunc(ino, -lbn - i, bn, lastlbn, dp);
+ /* If we freed everything in this indirect free the indir. */
+ if (lastlbn > lbn)
+ continue;
+ blk_free(ino, bn, 0, fs->fs_frag);
DIP_SET(dp, di_ib[i], 0);
}
/*
@@ -1319,7 +1376,7 @@ ino_trunc(ino_t ino, off_t size)
if (oldspace != newspace) {
bn += numfrags(fs, newspace);
frags = numfrags(fs, oldspace - newspace);
- blk_free(bn, 0, frags);
+ blk_free(ino, bn, 0, frags);
totalfrags -= frags;
}
}
@@ -1386,9 +1443,9 @@ ino_check(struct suj_ino *sino)
err_suj("Inode mode/directory type mismatch %o != %o\n",
mode, rrec->jr_mode);
if (debug)
- printf("jrefrec: op %d ino %ju, nlink %ju, parent %ju, "
+ printf("jrefrec: op %s ino %ju, nlink %ju, parent %ju, "
"diroff %jd, mode %o, isat %d, isdot %d\n",
- rrec->jr_op, (uintmax_t)rrec->jr_ino,
+ JOP_OPTYPE(rrec->jr_op), (uintmax_t)rrec->jr_ino,
(uintmax_t)rrec->jr_nlink,
(uintmax_t)rrec->jr_parent,
(uintmax_t)rrec->jr_diroff,
@@ -1452,9 +1509,10 @@ blk_check(struct suj_blk *sblk)
sino->si_blkadj = 1;
}
if (debug)
- printf("op %d blk %jd ino %ju lbn %jd frags %d isat %d (%d)\n",
- brec->jb_op, blk, (uintmax_t)brec->jb_ino,
- brec->jb_lbn, brec->jb_frags, isat, frags);
+ printf("op %s blk %jd ino %ju lbn %jd frags %d isat %d "
+ "(%d)\n", JOP_OPTYPE(brec->jb_op), blk,
+ (uintmax_t)brec->jb_ino, brec->jb_lbn,
+ brec->jb_frags, isat, frags);
/*
* If we found the block at this address we still have to
* determine if we need to free the tail end that was
@@ -1468,7 +1526,7 @@ blk_check(struct suj_blk *sblk)
mask >>= frags;
blk += frags;
frags = brec->jb_frags - frags;
- blk_free(blk, mask, frags);
+ blk_free(brec->jb_ino, blk, mask, frags);
continue;
}
/*
@@ -1636,9 +1694,9 @@ ino_append(union jrec *rec)
(uintmax_t)mvrec->jm_newoff, (uintmax_t)mvrec->jm_oldoff);
else if (debug &&
(refrec->jr_op == JOP_ADDREF || refrec->jr_op == JOP_REMREF))
- printf("ino ref: op %d, ino %ju, nlink %ju, "
+ printf("ino ref: op %s, ino %ju, nlink %ju, "
"parent %ju, diroff %jd\n",
- refrec->jr_op, (uintmax_t)refrec->jr_ino,
+ JOP_OPTYPE(refrec->jr_op), (uintmax_t)refrec->jr_ino,
(uintmax_t)refrec->jr_nlink,
(uintmax_t)refrec->jr_parent, (uintmax_t)refrec->jr_diroff);
sino = ino_lookup(((struct jrefrec *)rec)->jr_ino, 1);
@@ -1798,8 +1856,8 @@ ino_build_ref(struct suj_ino *sino, struct suj_rec *srec)
TAILQ_REMOVE(&sino->si_newrecs, srn, sr_next);
break;
default:
- err_suj("ino_build_ref: Unknown op %d\n",
- srn->sr_rec->rec_jrefrec.jr_op);
+ err_suj("ino_build_ref: Unknown op %s\n",
+ JOP_OPTYPE(srn->sr_rec->rec_jrefrec.jr_op));
}
}
ino_add_ref(sino, srec);
@@ -1828,8 +1886,8 @@ ino_build(struct suj_ino *sino)
TAILQ_INSERT_TAIL(&sino->si_movs, srec, sr_next);
break;
default:
- err_suj("ino_build: Unknown op %d\n",
- srec->sr_rec->rec_jrefrec.jr_op);
+ err_suj("ino_build: Unknown op %s\n",
+ JOP_OPTYPE(srec->sr_rec->rec_jrefrec.jr_op));
}
}
if (TAILQ_EMPTY(&sino->si_recs))
@@ -1851,14 +1909,17 @@ blk_build(struct jblkrec *blkrec)
int frag;
if (debug)
- printf("blk_build: op %d blkno %jd frags %d oldfrags %d "
+ printf("blk_build: op %s blkno %jd frags %d oldfrags %d "
"ino %ju lbn %jd\n",
- blkrec->jb_op, (uintmax_t)blkrec->jb_blkno,
+ JOP_OPTYPE(blkrec->jb_op), (uintmax_t)blkrec->jb_blkno,
blkrec->jb_frags, blkrec->jb_oldfrags,
(uintmax_t)blkrec->jb_ino, (uintmax_t)blkrec->jb_lbn);
blk = blknum(fs, blkrec->jb_blkno);
frag = fragnum(fs, blkrec->jb_blkno);
+ if (blkrec->jb_blkno < 0 || blk + fs->fs_frag - frag > fs->fs_size)
+ err_suj("Out-of-bounds journal block number %jd\n",
+ blkrec->jb_blkno);
sblk = blk_lookup(blk, 1);
/*
* Rewrite the record using oldfrags to indicate the offset into
@@ -1906,6 +1967,9 @@ ino_build_trunc(struct jtrncrec *rec)
printf("ino_build_trunc: op %d ino %ju, size %jd\n",
rec->jt_op, (uintmax_t)rec->jt_ino,
(uintmax_t)rec->jt_size);
+ if (chkfilesize(IFREG, rec->jt_size) == 0)
+ err_suj("ino_build: truncation size too large %ju\n",
+ (intmax_t)rec->jt_size);
sino = ino_lookup(rec->jt_ino, 1);
if (rec->jt_op == JOP_SYNC) {
sino->si_trunc = NULL;
@@ -1952,8 +2016,8 @@ suj_build(void)
ino_build_trunc((struct jtrncrec *)rec);
break;
default:
- err_suj("Unknown journal operation %d (%d)\n",
- rec->rec_jrefrec.jr_op, off);
+ err_suj("Unknown journal operation %s at %d\n",
+ JOP_OPTYPE(rec->rec_jrefrec.jr_op), off);
}
i++;
}
@@ -2067,7 +2131,9 @@ suj_verifyino(union dinode *dp)
}
if (DIP(dp, di_modrev) != fs->fs_mtime) {
- printf("Journal timestamp does not match fs mount time\n");
+ if (!bkgrdcheck || debug)
+ printf("Journal timestamp does not match "
+ "fs mount time\n");
return (-1);
}
@@ -2194,7 +2260,7 @@ jblocks_add(struct jblocks *jblocks, ufs2_daddr_t daddr, int blocks)
/*
* Add a file block from the journal to the extent map. We can't read
* each file block individually because the kernel treats it as a circular
- * buffer and segments may span mutliple contiguous blocks.
+ * buffer and segments may span multiple contiguous blocks.
*/
static void
suj_add_block(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, int frags)
@@ -2206,7 +2272,7 @@ suj_add_block(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, int frags)
static void
suj_read(void)
{
- uint8_t block[1 * 1024 * 1024];
+ uint8_t block[1 * 1024 * 1024] __aligned(LIBUFS_BUFALIGN);
struct suj_seg *seg;
struct jsegrec *recn;
struct jsegrec *rec;
@@ -2270,8 +2336,8 @@ restart:
recsize <= fs->fs_bsize)
goto restart;
if (debug)
- printf("Found invalid segsize %d > %d\n",
- recsize, size);
+ printf("Found invalid segsize "
+ "%d > %d\n", recsize, size);
recsize = real_dev_bsize;
jblocks_advance(suj_jblocks, recsize);
continue;
@@ -2312,7 +2378,7 @@ suj_check(const char *filesys)
{
struct inodesc idesc;
struct csum *cgsum;
- union dinode *jip;
+ union dinode *dp, *jip;
struct inode ip;
uint64_t blocks;
int i, retval;
@@ -2354,11 +2420,23 @@ suj_check(const char *filesys)
idesc.id_func = findino;
idesc.id_name = SUJ_FILE;
ginode(UFS_ROOTINO, &ip);
- if ((ckinode(ip.i_dp, &idesc) & FOUND) == FOUND) {
+ dp = ip.i_dp;
+ if ((DIP(dp, di_mode) & IFMT) != IFDIR) {
+ irelse(&ip);
+ err_suj("root inode is not a directory\n");
+ }
+ if (DIP(dp, di_size) < 0 || DIP(dp, di_size) > MAXDIRSIZE) {
+ irelse(&ip);
+ err_suj("negative or oversized root directory %jd\n",
+ (uintmax_t)DIP(dp, di_size));
+ }
+ if ((ckinode(dp, &idesc) & FOUND) == FOUND) {
sujino = idesc.id_parent;
irelse(&ip);
} else {
- printf("Journal inode removed. Use tunefs to re-create.\n");
+ if (!bkgrdcheck || debug)
+ printf("Journal inode removed. "
+ "Use tunefs to re-create.\n");
sblock.fs_flags &= ~FS_SUJ;
sblock.fs_sujfree = 0;
irelse(&ip);
@@ -2369,7 +2447,8 @@ suj_check(const char *filesys)
*/
ginode(sujino, &ip);
jip = ip.i_dp;
- printf("** SU+J Recovering %s\n", filesys);
+ if (!bkgrdcheck || debug)
+ printf("** SU+J Recovering %s\n", filesys);
if (suj_verifyino(jip) != 0 || (!preen && !reply("USE JOURNAL"))) {
irelse(&ip);
return (-1);
@@ -2378,15 +2457,23 @@ suj_check(const char *filesys)
* Build a list of journal blocks in jblocks before parsing the
* available journal blocks in with suj_read().
*/
- printf("** Reading %jd byte journal from inode %ju.\n",
- DIP(jip, di_size), (uintmax_t)sujino);
+ if (!bkgrdcheck || debug)
+ printf("** Reading %jd byte journal from inode %ju.\n",
+ DIP(jip, di_size), (uintmax_t)sujino);
suj_jblocks = jblocks_create();
blocks = ino_visit(jip, sujino, suj_add_block, 0);
if (blocks != numfrags(fs, DIP(jip, di_size))) {
- printf("Sparse journal inode %ju.\n", (uintmax_t)sujino);
+ if (!bkgrdcheck || debug)
+ printf("Sparse journal inode %ju.\n",
+ (uintmax_t)sujino);
irelse(&ip);
return (-1);
}
+ /* If journal is valid then do journal check rather than background */
+ if (bkgrdcheck) {
+ irelse(&ip);
+ return (0);
+ }
irelse(&ip);
suj_read();
jblocks_destroy(suj_jblocks);
@@ -2404,9 +2491,17 @@ suj_check(const char *filesys)
cg_apply(cg_adj_blk);
cg_apply(cg_check_ino);
}
- if (preen == 0 && (jrecs > 0 || jbytes > 0) && reply("WRITE CHANGES") == 0)
+ if (preen == 0 && (jrecs > 0 || jbytes > 0) &&
+ reply("WRITE CHANGES") == 0)
return (0);
/*
+ * Check block counts of snapshot inodes and
+ * make copies of any needed snapshot blocks.
+ */
+ for (i = 0; i < snapcnt; i++)
+ check_blkcnt(&snaplist[i]);
+ snapflush(suj_checkblkavail);
+ /*
* Recompute the fs summary info from correct cs summaries.
*/
bzero(&fs->fs_cstotal, sizeof(struct csum_total));
@@ -2425,10 +2520,11 @@ suj_check(const char *filesys)
sbdirty();
ckfini(1);
if (jrecs > 0 || jbytes > 0) {
- printf("** %jd journal records in %jd bytes for %.2f%% utilization\n",
- jrecs, jbytes, ((float)jrecs / (float)(jbytes / JREC_SIZE)) * 100);
- printf("** Freed %jd inodes (%jd dirs) %jd blocks, and %jd frags.\n",
- freeinos, freedir, freeblocks, freefrags);
+ printf("** %jd journal records in %jd bytes for %.2f%% "
+ "utilization\n", jrecs, jbytes,
+ ((float)jrecs / (float)(jbytes / JREC_SIZE)) * 100);
+ printf("** Freed %jd inodes (%jd dirs) %jd blocks, and %jd "
+ "frags.\n", freeinos, freedir, freeblocks, freefrags);
}
return (0);
diff --git a/sbin/fsck_ffs/utilities.c b/sbin/fsck_ffs/utilities.c
index 4f56f1ed8c26..56655089b9d6 100644
--- a/sbin/fsck_ffs/utilities.c
+++ b/sbin/fsck_ffs/utilities.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/sbin/fsck_msdosfs/Makefile b/sbin/fsck_msdosfs/Makefile
index bce48211b586..d5fe24b220b7 100644
--- a/sbin/fsck_msdosfs/Makefile
+++ b/sbin/fsck_msdosfs/Makefile
@@ -1,5 +1,4 @@
# $NetBSD: Makefile,v 1.6 1997/05/08 21:11:11 gwr Exp $
-# $FreeBSD$
FSCK= ${.CURDIR:H}/fsck
.PATH: ${FSCK}
diff --git a/sbin/fsck_msdosfs/Makefile.depend b/sbin/fsck_msdosfs/Makefile.depend
index 6cfaab1c3644..678747db6f2c 100644
--- a/sbin/fsck_msdosfs/Makefile.depend
+++ b/sbin/fsck_msdosfs/Makefile.depend
@@ -1,13 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libutil \
.include <dirdeps.mk>
diff --git a/sbin/fsck_msdosfs/boot.c b/sbin/fsck_msdosfs/boot.c
index 887312ed7c41..f91609470ad7 100644
--- a/sbin/fsck_msdosfs/boot.c
+++ b/sbin/fsck_msdosfs/boot.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 1995, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
@@ -29,8 +29,6 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: boot.c,v 1.22 2020/01/11 16:29:07 christos Exp $");
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
#include <sys/param.h>
diff --git a/sbin/fsck_msdosfs/check.c b/sbin/fsck_msdosfs/check.c
index 9519315672ab..f672a2ac515c 100644
--- a/sbin/fsck_msdosfs/check.c
+++ b/sbin/fsck_msdosfs/check.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
@@ -29,8 +29,6 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: check.c,v 1.14 2006/06/05 16:51:18 christos Exp $");
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
#ifdef HAVE_LIBUTIL_H
diff --git a/sbin/fsck_msdosfs/dir.c b/sbin/fsck_msdosfs/dir.c
index dbe4e0c7db2f..19516d882e2a 100644
--- a/sbin/fsck_msdosfs/dir.c
+++ b/sbin/fsck_msdosfs/dir.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Google LLC
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
@@ -32,8 +32,6 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: dir.c,v 1.20 2006/06/05 16:51:18 christos Exp $");
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
#include <assert.h>
@@ -997,7 +995,7 @@ readDosDirSection(struct fat_descriptor *fat, struct dosDirEntry *dir)
n->next = pendingDirectories;
n->dir = d;
pendingDirectories = n;
- } else {
+ } else if (!(mod & FSERROR)) {
mod |= k = checksize(fat, p, &dirent);
if (k & FSDIRMOD)
mod |= THISMOD;
diff --git a/sbin/fsck_msdosfs/dosfs.h b/sbin/fsck_msdosfs/dosfs.h
index d89a08689825..a8da745b1ce3 100644
--- a/sbin/fsck_msdosfs/dosfs.h
+++ b/sbin/fsck_msdosfs/dosfs.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
@@ -26,7 +26,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* $NetBSD: dosfs.h,v 1.4 1997/01/03 14:32:48 ws Exp $
- * $FreeBSD$
*/
#ifndef DOSFS_H
diff --git a/sbin/fsck_msdosfs/ext.h b/sbin/fsck_msdosfs/ext.h
index 532e840acfc8..d0f4dd6279f7 100644
--- a/sbin/fsck_msdosfs/ext.h
+++ b/sbin/fsck_msdosfs/ext.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank
* Copyright (c) 1995 Martin Husemann
@@ -24,7 +24,6 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* $NetBSD: ext.h,v 1.6 2000/04/25 23:02:51 jdolecek Exp $
- * $FreeBSD$
*/
#ifndef EXT_H
diff --git a/sbin/fsck_msdosfs/fat.c b/sbin/fsck_msdosfs/fat.c
index e35e2f27d305..567bfcd428cb 100644
--- a/sbin/fsck_msdosfs/fat.c
+++ b/sbin/fsck_msdosfs/fat.c
@@ -30,8 +30,6 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: fat.c,v 1.18 2006/06/05 16:51:18 christos Exp $");
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
#include <sys/endian.h>
diff --git a/sbin/fsck_msdosfs/fsck_msdosfs.8 b/sbin/fsck_msdosfs/fsck_msdosfs.8
index 602451b61374..7c90c8b11b5d 100644
--- a/sbin/fsck_msdosfs/fsck_msdosfs.8
+++ b/sbin/fsck_msdosfs/fsck_msdosfs.8
@@ -23,9 +23,7 @@
.\" (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 January 6, 2020
+.Dd December 18, 2024
.Dt FSCK_MSDOSFS 8
.Os
.Sh NAME
@@ -34,10 +32,10 @@
.Sh SYNOPSIS
.Nm
.Fl p
-.Op Fl Cf
+.Op Fl BCf
.Ar filesystem ...
.Nm
-.Op Fl CMny
+.Op Fl BCMny
.Ar filesystem ...
.Sh DESCRIPTION
The
@@ -73,10 +71,14 @@ making any changes.
.Pp
The options are as follows:
.Bl -tag -width indent
+.It Fl B
+Ignored for
+.Xr fsck 8
+compatibility.
.It Fl C
-Compatibility with the corresponding
+Ignored for
.Xr fsck 8
-option (skip check if clean), defined to no-op.
+compatibility.
.It Fl F
Compatibility with the wrapper
.Xr fsck 8
@@ -123,9 +125,8 @@ to assume
as the answer to all operator questions.
.El
.Sh SEE ALSO
-.Xr fsck 8 ,
-.Xr fsck_ffs 8 ,
-.Xr mount_msdosfs 8
+.Xr msdosfs 4 ,
+.Xr fsck 8
.Sh HISTORY
The
.Nm
diff --git a/sbin/fsck_msdosfs/main.c b/sbin/fsck_msdosfs/main.c
index de54cd18eae7..49a811964ab9 100644
--- a/sbin/fsck_msdosfs/main.c
+++ b/sbin/fsck_msdosfs/main.c
@@ -29,8 +29,6 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: main.c,v 1.10 1997/10/01 02:18:14 enami Exp $");
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
#include <stdlib.h>
@@ -70,9 +68,10 @@ main(int argc, char **argv)
skipclean = 1;
allow_mmap = 1;
- while ((ch = getopt(argc, argv, "CfFnpyM")) != -1) {
+ while ((ch = getopt(argc, argv, "BCfFnpyM")) != -1) {
switch (ch) {
- case 'C': /* for fsck_ffs compatibility */
+ case 'B': /* for fsck_ffs compatibility */
+ case 'C':
break;
case 'f':
skipclean = 0;
diff --git a/sbin/fsdb/Makefile b/sbin/fsdb/Makefile
index a2e280420479..28016b4ccdfc 100644
--- a/sbin/fsdb/Makefile
+++ b/sbin/fsdb/Makefile
@@ -1,8 +1,6 @@
# $NetBSD: Makefile,v 1.1.1.1 1995/10/08 23:08:36 thorpej Exp $
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-PACKAGE=runtime
+PACKAGE=ufs
PROG= fsdb
MAN= fsdb.8
SRCS= fsdb.c fsdbutil.c \
diff --git a/sbin/fsdb/Makefile.depend b/sbin/fsdb/Makefile.depend
index 7fdfb8aa8455..8501b85f8689 100644
--- a/sbin/fsdb/Makefile.depend
+++ b/sbin/fsdb/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
@@ -10,7 +8,6 @@ DIRDEPS = \
lib/libcompiler_rt \
lib/libedit \
lib/libufs \
- lib/ncurses/ncursesw \
.include <dirdeps.mk>
diff --git a/sbin/fsdb/fsdb.8 b/sbin/fsdb/fsdb.8
index fdf98bf91aa5..6e6b87ae8ab2 100644
--- a/sbin/fsdb/fsdb.8
+++ b/sbin/fsdb/fsdb.8
@@ -26,8 +26,6 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd October 3, 2016
.Dt FSDB 8
.Os
diff --git a/sbin/fsdb/fsdb.c b/sbin/fsdb/fsdb.c
index c935f88952b4..48526ad4044b 100644
--- a/sbin/fsdb/fsdb.c
+++ b/sbin/fsdb/fsdb.c
@@ -30,11 +30,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <ctype.h>
#include <err.h>
@@ -63,6 +58,23 @@ static int find_blks64(uint64_t *buf, int size, uint64_t *blknum);
static int find_indirblks32(uint32_t blk, int ind_level, uint32_t *blknum);
static int find_indirblks64(uint64_t blk, int ind_level, uint64_t *blknum);
+/*
+ * Track modifications to the filesystem. Two types of changes are tracked.
+ * The first type of changes are those that are not critical to the integrity
+ * of the filesystem such as owner, group, time stamps, access mode, and
+ * generation number. The second type of changes are those that do affect
+ * the integrity of the filesystem including zeroing inodes, changing block
+ * pointers, directory entries, link counts, file lengths, file types and
+ * file flags.
+ *
+ * When quitting having made no changes or only changes to data that is not
+ * critical to filesystem integrity, the clean state of the filesystem is
+ * left unchanged. But if filesystem critical data are changed then fsdb
+ * will set the unclean flag which will require a full fsck to be run
+ * before the filesystem can be mounted.
+ */
+static int fsnoncritmodified; /* filesystem non-critical modifications */
+static int fscritmodified; /* filesystem integrity critical mods */
struct inode curip;
union dinode *curinode;
ino_t curinum, ocurrent;
@@ -111,7 +123,7 @@ main(int argc, char *argv[])
fsys = argv[0];
sblock_init();
- if (openfilesys(fsys) == 0 || readsb(0) == 0 || setup(fsys) == 0)
+ if (openfilesys(fsys) == 0 || readsb() == 0 || setup(fsys) == 0)
errx(1, "cannot set up file system `%s'", fsys);
if (fswritefd < 0)
nflag++;
@@ -119,9 +131,13 @@ main(int argc, char *argv[])
nflag? "Examining": "Editing", fsys, sblock.fs_fsmnt);
rval = cmdloop();
if (!nflag) {
- sblock.fs_clean = 0; /* mark it dirty */
- sbdirty();
- ckfini(0);
+ if (fscritmodified != 0) {
+ sblock.fs_clean = 0; /* mark it dirty */
+ sbdirty();
+ }
+ ckfini(fscritmodified ? 0 : sblock.fs_clean);
+ if (fscritmodified == 0)
+ exit(0);
printf("*** FILE SYSTEM MARKED DIRTY\n");
printf("*** BE SURE TO RUN FSCK TO CLEAN UP ANY DAMAGE\n");
printf("*** IF IT IS MOUNTED, RE-MOUNT WITH -u -o reload\n");
@@ -142,6 +158,7 @@ CMDFUNC(uplink); /* incr link */
CMDFUNC(downlink); /* decr link */
CMDFUNC(linkcount); /* set link count */
CMDFUNC(quit); /* quit */
+CMDFUNC(quitclean); /* quit with filesystem marked clean */
CMDFUNC(findblk); /* find block */
CMDFUNC(ls); /* list directory */
CMDFUNC(rm); /* remove name */
@@ -161,40 +178,42 @@ CMDFUNC(chatime); /* Change atime */
CMDFUNC(chinum); /* Change inode # of dirent */
CMDFUNC(chname); /* Change dirname of dirent */
CMDFUNC(chsize); /* Change size */
+CMDFUNC(chdb); /* Change direct block pointer */
struct cmdtable cmds[] = {
{ "help", "Print out help", 1, 1, FL_RO, helpfn },
{ "?", "Print out help", 1, 1, FL_RO, helpfn },
{ "inode", "Set active inode to INUM", 2, 2, FL_RO, focus },
- { "clri", "Clear inode INUM", 2, 2, FL_WR, zapi },
+ { "clri", "Clear inode INUM", 2, 2, FL_CWR, zapi },
{ "lookup", "Set active inode by looking up NAME", 2, 2, FL_RO | FL_ST, focusname },
{ "cd", "Set active inode by looking up NAME", 2, 2, FL_RO | FL_ST, focusname },
{ "back", "Go to previous active inode", 1, 1, FL_RO, back },
{ "active", "Print active inode", 1, 1, FL_RO, active },
{ "print", "Print active inode", 1, 1, FL_RO, active },
{ "blocks", "Print block numbers of active inode", 1, 1, FL_RO, blocks },
- { "uplink", "Increment link count", 1, 1, FL_WR, uplink },
- { "downlink", "Decrement link count", 1, 1, FL_WR, downlink },
- { "linkcount", "Set link count to COUNT", 2, 2, FL_WR, linkcount },
+ { "uplink", "Increment link count", 1, 1, FL_CWR, uplink },
+ { "downlink", "Decrement link count", 1, 1, FL_CWR, downlink },
+ { "linkcount", "Set link count to COUNT", 2, 2, FL_CWR, linkcount },
{ "findblk", "Find inode owning disk block(s)", 2, 33, FL_RO, findblk},
{ "ls", "List current inode as directory", 1, 1, FL_RO, ls },
- { "rm", "Remove NAME from current inode directory", 2, 2, FL_WR | FL_ST, rm },
- { "del", "Remove NAME from current inode directory", 2, 2, FL_WR | FL_ST, rm },
- { "ln", "Hardlink INO into current inode directory as NAME", 3, 3, FL_WR | FL_ST, ln },
- { "chinum", "Change dir entry number INDEX to INUM", 3, 3, FL_WR, chinum },
+ { "rm", "Remove NAME from current inode directory", 2, 2, FL_CWR | FL_ST, rm },
+ { "del", "Remove NAME from current inode directory", 2, 2, FL_CWR | FL_ST, rm },
+ { "ln", "Hardlink INO into current inode directory as NAME", 3, 3, FL_CWR | FL_ST, ln },
+ { "chinum", "Change dir entry number INDEX to INUM", 3, 3, FL_CWR, chinum },
{ "chname", "Change dir entry number INDEX to NAME", 3, 3, FL_WR | FL_ST, chname },
- { "chtype", "Change type of current inode to TYPE", 2, 2, FL_WR, newtype },
+ { "chtype", "Change type of current inode to TYPE", 2, 2, FL_CWR, newtype },
{ "chmod", "Change mode of current inode to MODE", 2, 2, FL_WR, chmode },
- { "chlen", "Change length of current inode to LENGTH", 2, 2, FL_WR, chlen },
{ "chown", "Change owner of current inode to OWNER", 2, 2, FL_WR, chowner },
{ "chgrp", "Change group of current inode to GROUP", 2, 2, FL_WR, chgroup },
- { "chflags", "Change flags of current inode to FLAGS", 2, 2, FL_WR, chaflags },
+ { "chflags", "Change flags of current inode to FLAGS", 2, 2, FL_CWR, chaflags },
{ "chgen", "Change generation number of current inode to GEN", 2, 2, FL_WR, chgen },
- { "chsize", "Change size of current inode to SIZE", 2, 2, FL_WR, chsize },
+ { "chsize", "Change size of current inode to SIZE", 2, 2, FL_CWR, chsize },
{ "btime", "Change btime of current inode to BTIME", 2, 2, FL_WR, chbtime },
{ "mtime", "Change mtime of current inode to MTIME", 2, 2, FL_WR, chmtime },
{ "ctime", "Change ctime of current inode to CTIME", 2, 2, FL_WR, chctime },
{ "atime", "Change atime of current inode to ATIME", 2, 2, FL_WR, chatime },
+ { "chdb", "Change db pointer N of current inode to BLKNO", 3, 3, FL_CWR, chdb },
+ { "quitclean", "Exit with filesystem marked clean", 1, 1, FL_RO, quitclean },
{ "quit", "Exit", 1, 1, FL_RO, quit },
{ "q", "Exit", 1, 1, FL_RO, quit },
{ "exit", "Exit", 1, 1, FL_RO, quit },
@@ -278,7 +297,7 @@ cmdloop(void)
known = 0;
for (cmdp = cmds; cmdp->cmd; cmdp++) {
if (!strcmp(cmdp->cmd, cmd_argv[0])) {
- if ((cmdp->flags & FL_WR) == FL_WR && nflag)
+ if ((cmdp->flags & (FL_CWR | FL_WR)) != 0 && nflag)
warnx("`%s' requires write access", cmd_argv[0]),
rval = 1;
else if (cmd_argc >= cmdp->minargc &&
@@ -292,6 +311,12 @@ cmdloop(void)
} else
rval = argcount(cmdp, cmd_argc, cmd_argv);
known = 1;
+ if (rval == 0) {
+ if ((cmdp->flags & FL_WR) != 0)
+ fsnoncritmodified = 1;
+ if ((cmdp->flags & FL_CWR) != 0)
+ fscritmodified = 1;
+ }
break;
}
}
@@ -306,7 +331,7 @@ cmdloop(void)
return 0;
}
if (rval)
- warnx("rval was %d", rval);
+ warnx("command failed, return value was %d", rval);
}
el_end(elptr);
history_end(hist);
@@ -374,6 +399,16 @@ CMDFUNCSTART(quit)
return -1;
}
+CMDFUNCSTART(quitclean)
+{
+ if (fscritmodified) {
+ printf("Warning: modified filesystem marked clean\n");
+ fscritmodified = 0;
+ sblock.fs_clean = 1;
+ }
+ return -1;
+}
+
CMDFUNCSTART(uplink)
{
if (!checkactive())
@@ -781,7 +816,7 @@ CMDFUNCSTART(rm)
if (!checkactivedir())
return 1;
- rval = changeino(curinum, argv[1], 0);
+ rval = changeino(curinum, argv[1], 0, 0);
if (rval & ALTERED) {
printf("Name `%s' removed\n", argv[1]);
return 0;
@@ -928,30 +963,8 @@ CMDFUNCSTART(newtype)
return 0;
}
-CMDFUNCSTART(chlen)
-{
- int rval = 1;
- long len;
- char *cp;
-
- if (!checkactive())
- return 1;
-
- len = strtol(argv[1], &cp, 0);
- if (cp == argv[1] || *cp != '\0' || len < 0) {
- warnx("bad length `%s'", argv[1]);
- return 1;
- }
-
- DIP_SET(curinode, di_size, len);
- inodirty(&curip);
- printactive(0);
- return rval;
-}
-
CMDFUNCSTART(chmode)
{
- int rval = 1;
long modebits;
char *cp;
@@ -968,12 +981,11 @@ CMDFUNCSTART(chmode)
DIP_SET(curinode, di_mode, DIP(curinode, di_mode) | modebits);
inodirty(&curip);
printactive(0);
- return rval;
+ return 0;
}
CMDFUNCSTART(chaflags)
{
- int rval = 1;
u_long flags;
char *cp;
@@ -993,12 +1005,11 @@ CMDFUNCSTART(chaflags)
DIP_SET(curinode, di_flags, flags);
inodirty(&curip);
printactive(0);
- return rval;
+ return 0;
}
CMDFUNCSTART(chgen)
{
- int rval = 1;
long gen;
char *cp;
@@ -1011,19 +1022,19 @@ CMDFUNCSTART(chgen)
return 1;
}
- if (gen > INT_MAX || gen < INT_MIN) {
- warnx("gen set beyond 32-bit range of field (%lx)\n", gen);
+ if (gen > UINT_MAX) {
+ warnx("gen set beyond 32-bit range of field (0x%lx), max is 0x%x\n",
+ gen, UINT_MAX);
return(1);
}
DIP_SET(curinode, di_gen, gen);
inodirty(&curip);
printactive(0);
- return rval;
+ return 0;
}
CMDFUNCSTART(chsize)
{
- int rval = 1;
off_t size;
char *cp;
@@ -1043,12 +1054,41 @@ CMDFUNCSTART(chsize)
DIP_SET(curinode, di_size, size);
inodirty(&curip);
printactive(0);
- return rval;
+ return 0;
+}
+
+CMDFUNC(chdb)
+{
+ unsigned int idx;
+ daddr_t bno;
+ char *cp;
+
+ if (!checkactive())
+ return 1;
+
+ idx = strtoull(argv[1], &cp, 0);
+ if (cp == argv[1] || *cp != '\0') {
+ warnx("bad pointer idx `%s'", argv[1]);
+ return 1;
+ }
+ bno = strtoll(argv[2], &cp, 0);
+ if (cp == argv[2] || *cp != '\0') {
+ warnx("bad block number `%s'", argv[2]);
+ return 1;
+ }
+ if (idx >= UFS_NDADDR) {
+ warnx("pointer index %d is out of range", idx);
+ return 1;
+ }
+
+ DIP_SET(curinode, di_db[idx], bno);
+ inodirty(&curip);
+ printactive(0);
+ return 0;
}
CMDFUNCSTART(linkcount)
{
- int rval = 1;
int lcnt;
char *cp;
@@ -1068,12 +1108,11 @@ CMDFUNCSTART(linkcount)
DIP_SET(curinode, di_nlink, lcnt);
inodirty(&curip);
printactive(0);
- return rval;
+ return 0;
}
CMDFUNCSTART(chowner)
{
- int rval = 1;
unsigned long uid;
char *cp;
struct passwd *pwd;
@@ -1095,12 +1134,11 @@ CMDFUNCSTART(chowner)
DIP_SET(curinode, di_uid, uid);
inodirty(&curip);
printactive(0);
- return rval;
+ return 0;
}
CMDFUNCSTART(chgroup)
{
- int rval = 1;
unsigned long gid;
char *cp;
struct group *grp;
@@ -1121,7 +1159,7 @@ CMDFUNCSTART(chgroup)
DIP_SET(curinode, di_gid, gid);
inodirty(&curip);
printactive(0);
- return rval;
+ return 0;
}
int
diff --git a/sbin/fsdb/fsdb.h b/sbin/fsdb/fsdb.h
index fee35886f675..1a8bc770005e 100644
--- a/sbin/fsdb/fsdb.h
+++ b/sbin/fsdb/fsdb.h
@@ -28,8 +28,6 @@
* 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$
*/
extern int blread(int fd, char *buf, ufs2_daddr_t blk, long size);
@@ -49,7 +47,8 @@ struct cmdtable {
unsigned int flags;
#define FL_RO 0x0000 /* for symmetry */
#define FL_WR 0x0001 /* wants to write */
-#define FL_ST 0x0002 /* resplit final string if argc > maxargc */
+#define FL_CWR 0x0002 /* wants to write critical data */
+#define FL_ST 0x0003 /* resplit final string if argc > maxargc */
int (*handler)(int argc, char *argv[]);
};
extern struct inode curip;
diff --git a/sbin/fsdb/fsdbutil.c b/sbin/fsdb/fsdbutil.c
index c8a3a8a525e3..737dabba643f 100644
--- a/sbin/fsdb/fsdbutil.c
+++ b/sbin/fsdb/fsdbutil.c
@@ -30,11 +30,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <ctype.h>
#include <err.h>
diff --git a/sbin/fsirand/Makefile b/sbin/fsirand/Makefile
index 1fc54ff44687..04bff10f2314 100644
--- a/sbin/fsirand/Makefile
+++ b/sbin/fsirand/Makefile
@@ -1,7 +1,6 @@
# $OpenBSD: Makefile,v 1.1 1997/01/26 02:23:20 millert Exp $
-# $FreeBSD$
-PACKAGE=runtime
+PACKAGE=ufs
PROG= fsirand
MAN= fsirand.8
LIBADD= ufs
diff --git a/sbin/fsirand/Makefile.depend b/sbin/fsirand/Makefile.depend
index 6cfaab1c3644..910688a678fa 100644
--- a/sbin/fsirand/Makefile.depend
+++ b/sbin/fsirand/Makefile.depend
@@ -1,13 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libufs \
.include <dirdeps.mk>
diff --git a/sbin/fsirand/fsirand.8 b/sbin/fsirand/fsirand.8
index f3fbd8d6c153..5e826c6588a8 100644
--- a/sbin/fsirand/fsirand.8
+++ b/sbin/fsirand/fsirand.8
@@ -27,7 +27,6 @@
.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: fsirand.8,v 1.6 1997/02/23 03:58:26 millert Exp $
-.\" $FreeBSD$
.\"
.Dd January 25, 1997
.Dt FSIRAND 8
diff --git a/sbin/fsirand/fsirand.c b/sbin/fsirand/fsirand.c
index c4db8848f18b..2a5eb0c5136d 100644
--- a/sbin/fsirand/fsirand.c
+++ b/sbin/fsirand/fsirand.c
@@ -1,7 +1,7 @@
/* $OpenBSD: fsirand.c,v 1.9 1997/02/28 00:46:33 millert Exp $ */
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
@@ -32,11 +32,6 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/resource.h>
@@ -112,7 +107,7 @@ fsirand(char *device)
struct fs *sblock;
ino_t inumber;
ufs2_daddr_t dblk;
- int devfd, n, cg, ret;
+ int devfd, n, cg;
u_int32_t bsize = DEV_BSIZE;
if ((devfd = open(device, printonly ? O_RDONLY : O_RDWR)) < 0) {
@@ -124,10 +119,10 @@ fsirand(char *device)
dp2 = NULL;
/* Read in master superblock */
- if ((ret = sbget(devfd, &sblock, STDSB)) != 0) {
- switch (ret) {
+ if ((errno = sbget(devfd, &sblock, UFS_STDSB, UFS_NOCSUM)) != 0) {
+ switch (errno) {
case ENOENT:
- warn("Cannot find file system superblock");
+ warnx("Cannot find file system superblock");
return (1);
default:
warn("Unable to read file system superblock");
diff --git a/sbin/gbde/Makefile b/sbin/gbde/Makefile
deleted file mode 100644
index dcc034fd7564..000000000000
--- a/sbin/gbde/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-# $FreeBSD$
-
-PACKAGE=runtime
-PROG= gbde
-SRCS= gbde.c template.c
-SRCS+= rijndael-alg-fst.c
-SRCS+= rijndael-api-fst.c
-SRCS+= sha512c.c
-SRCS+= g_bde_lock.c
-
-# rijndael-fst.c does evil casting things which can results in warnings,
-# the test-vectors check out however, so it works right.
-NO_WCAST_ALIGN=
-NO_WMISSING_VARIABLE_DECLARATIONS=
-
-CFLAGS+= -I${SRCTOP}/sys
-.PATH: ${SRCTOP}/sys/geom/bde \
- ${SRCTOP}/sys/crypto/rijndael \
- ${SRCTOP}/sys/crypto/sha2
-
-CLEANFILES+= template.c
-
-MAN= gbde.8
-LIBADD= md util geom
-
-template.c: template.txt
- file2c 'const char template[] = {' ',0};' \
- < ${.CURDIR}/template.txt > template.c
-
-test: ${PROG}
- sh ${.CURDIR}/test.sh ${.CURDIR}
-
-.include <bsd.prog.mk>
diff --git a/sbin/gbde/gbde.8 b/sbin/gbde/gbde.8
deleted file mode 100644
index cd34b6e02b54..000000000000
--- a/sbin/gbde/gbde.8
+++ /dev/null
@@ -1,273 +0,0 @@
-.\"
-.\" Copyright (c) 2002 Poul-Henning Kamp
-.\" Copyright (c) 2002 Networks Associates Technology, Inc.
-.\" All rights reserved.
-.\"
-.\" This software was developed for the FreeBSD Project by Poul-Henning Kamp
-.\" and NAI Labs, 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.
-.\"
-.\" 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$
-.\"
-.Dd October 3, 2016
-.Dt GBDE 8
-.Os
-.Sh NAME
-.Nm gbde
-.Nd operation and management utility for Geom Based Disk Encryption
-.Sh SYNOPSIS
-.Nm
-.Cm attach
-.Ar destination
-.Op Fl k Ar keyfile
-.Op Fl l Ar lockfile
-.Op Fl p Ar pass-phrase
-.Nm
-.Cm detach
-.Ar destination
-.Nm
-.Cm init
-.Ar destination
-.Op Fl i
-.Op Fl f Ar filename
-.Op Fl K Ar new-keyfile
-.Op Fl L Ar new-lockfile
-.Op Fl P Ar new-pass-phrase
-.Nm
-.Cm setkey
-.Ar destination
-.Op Fl n Ar key
-.Op Fl k Ar keyfile
-.Op Fl l Ar lockfile
-.Op Fl p Ar pass-phrase
-.Op Fl K Ar new-keyfile
-.Op Fl L Ar new-lockfile
-.Op Fl P Ar new-pass-phrase
-.Nm
-.Cm nuke
-.Ar destination
-.Op Fl n Ar key
-.Op Fl k Ar keyfile
-.Op Fl l Ar lockfile
-.Op Fl p Ar pass-phrase
-.Nm
-.Cm destroy
-.Ar destination
-.Op Fl k Ar keyfile
-.Op Fl l Ar lockfile
-.Op Fl p Ar pass-phrase
-.Sh DESCRIPTION
-.Bf -symbolic
-NOTICE:
-Please be aware that this code has not yet received much review
-and analysis by qualified cryptographers and therefore should be considered
-a slightly suspect experimental facility.
-.Pp
-We cannot at this point guarantee that the on-disk format will not change
-in response to reviews or bug-fixes, so potential users are advised to
-be prepared that
-.Xr dump 8 Ns / Ns
-.Xr restore 8
-based migrations may be called for in the future.
-.Ef
-.Pp
-The
-.Nm
-utility is the only official operation and management interface for the
-.Xr gbde 4
-.Tn GEOM
-based disk encryption kernel facility.
-The interaction between the
-.Nm
-utility and the kernel part is not a published interface.
-.Pp
-The operational aspect consists of two subcommands:
-one to open and attach
-a device to the in-kernel cryptographic
-.Nm
-module
-.Pq Cm attach ,
-and one to close and detach a device
-.Pq Cm detach .
-.Pp
-The management part allows initialization of the master key and lock sectors
-on a device
-.Pq Cm init ,
-initialization and replacement of pass-phrases
-.Pq Cm setkey ,
-and key invalidation
-.Pq Cm nuke
-and blackening
-.Pq Cm destroy
-functions.
-.Pp
-The
-.Fl l Ar lockfile
-argument is used to supply the lock selector data.
-If no
-.Fl l
-option is specified, the first sector is used for this purpose.
-.Pp
-The
-.Fl L Ar new-lockfile
-argument
-specifies the lock selector file for the key
-initialized with the
-.Cm init
-subcommand
-or modified with the
-.Cm setkey
-subcommand.
-.Pp
-The
-.Fl n Ar key
-argument can be used to specify to which of the four keys
-the operation applies.
-A value of 1 to 4 selects the specified key, a value of 0 (the default)
-means
-.Dq "this key"
-(i.e., the key used to gain access to the device)
-and a value of \-1 means
-.Dq "all keys" .
-.Pp
-The
-.Fl f Ar filename
-specifies an optional parameter file for use under initialization.
-.Pp
-Alternatively, the
-.Fl i
-option toggles an interactive mode where a template file with descriptions
-of the parameters can be interactively edited.
-.Pp
-The
-.Fl p Ar pass-phrase
-argument
-specifies the pass-phrase used for opening the device.
-If not specified, the controlling terminal will be used to prompt the user
-for the pass-phrase.
-Be aware that using this option may expose the pass-phrase to other
-users who happen to run
-.Xr ps 1
-or similar while the command is running.
-.Pp
-The
-.Fl P Ar new-pass-phrase
-argument
-can be used to specify the new pass-phrase to the
-.Cm init
-and
-.Cm setkey
-subcommands.
-If not specified, the user is prompted for the new pass-phrase on the
-controlling terminal.
-Be aware that using this option may expose the pass-phrase to other
-users who happen to run
-.Xr ps 1
-or similar while the command is running.
-.Pp
-The
-.Fl k Ar keyfile
-argument specifies a key file to be used in combination with the
-pass-phrase (whether the pass-phrase is specified on the command line
-or entered from the terminal) for opening the device.
-The device will only be opened if the contents of the key file and the
-pass-phrase are both correct.
-.Pp
-The
-.Fl K Ar new-keyfile
-argument can be used to specify a new key file to the
-.Cm init
-and
-.Cm setkey
-subcommands.
-If not specified, no key file will be used (even if one was previously
-used).
-.Sh EXAMPLES
-To initialize a device, using default parameters:
-.Pp
-.Dl "gbde init /dev/ada0s1f -L /etc/ada0s1f.lock"
-.Pp
-To attach an encrypted device:
-.Pp
-.Dl "gbde attach ada0s1f -l /etc/ada0s1f.lock"
-.Pp
-The encrypted device has the suffix
-.Pa .bde
-so a typical
-command to create and mount a file system would be:
-.Pp
-.Dl "newfs /dev/ada0s1f.bde"
-.Dl "mount /dev/ada0s1f.bde /secret"
-.Pp
-To detach an encrypted device:
-.Pp
-.Dl "gbde detach ada0s1f"
-.Pp
-Please notice that detaching an encrypted device corresponds to
-physically removing it, do not forget to unmount the file system first.
-.Pp
-To initialize the second key using a detached lockfile and a trivial
-pass-phrase:
-.Pp
-.Dl "gbde setkey ada0s1f -n 2 -P foo -L key2.lockfile"
-.Pp
-To invalidate your own masterkey:
-.Pp
-.Dl "gbde nuke ada0s1f"
-.Pp
-This will overwrite your masterkey sector with zeros, and results in
-a diagnostic if you try to use the key again.
-You can also destroy the other three copies of the masterkey with the
--n argument.
-.Pp
-You can also invalidate your masterkey without leaving a tell-tale sector
-full of zeros:
-.Pp
-.Dl "gbde destroy ada0s1f"
-.Pp
-This will overwrite the information fields in your masterkey sector,
-encrypt it and write it back.
-You get a (different) diagnostic if you try to use it.
-.Sh SEE ALSO
-.Xr gbde 4 ,
-.Xr geom 4
-.Sh HISTORY
-This software was developed for the
-.Fx
-Project by
-.An Poul-Henning Kamp
-and NAI Labs, the Security Research Division of Network Associates, Inc.\&
-under DARPA/SPAWAR contract N66001-01-C-8035
-.Pq Dq CBOSS ,
-as part of the
-DARPA CHATS research program.
-.Nm
-first appeared in
-.Fx 5.0 .
-.Sh AUTHORS
-.An Poul-Henning Kamp Aq Mt phk@FreeBSD.org
-.Sh BUGS
-The cryptographic algorithms and the overall design have not been
-attacked mercilessly for over 10 years by a gang of cryptoanalysts.
diff --git a/sbin/gbde/gbde.c b/sbin/gbde/gbde.c
deleted file mode 100644
index 421242c38c80..000000000000
--- a/sbin/gbde/gbde.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2002 Poul-Henning Kamp
- * Copyright (c) 2002 Networks Associates Technology, Inc.
- * All rights reserved.
- *
- * This software was developed for the FreeBSD Project by Poul-Henning Kamp
- * and NAI Labs, 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.
- *
- * 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$
- *
- * XXX: Future stuff
- *
- * Replace the template file options (-i & -f) with command-line variables
- * "-v property=foo"
- *
- * Introduce -e, extra entropy source (XOR with /dev/random)
- *
- * Introduce -E, alternate entropy source (instead of /dev/random)
- *
- * Introduce -i take IV from keyboard or
- *
- * Introduce -I take IV from file/cmd
- *
- * Introduce -m/-M store encrypted+encoded masterkey in file
- *
- * Introduce -k/-K get pass-phrase part from file/cmd
- *
- * Introduce -d add more dest-devices to worklist.
- *
- * Add key-option: selfdestruct bit.
- *
- * New/changed verbs:
- * "onetime" attach with onetime nonstored locksector
- * "key"/"unkey" to blast memory copy of key without orphaning
- * "nuke" blow away everything attached, crash/halt/power-off if possible.
- * "blast" destroy all copies of the masterkey
- * "destroy" destroy one copy of the masterkey
- * "backup"/"restore" of masterkey sectors.
- *
- * Make all verbs work on both attached/detached devices.
- *
- */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/mutex.h>
-#include <md5.h>
-#include <readpassphrase.h>
-#include <string.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <paths.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <err.h>
-#include <stdio.h>
-#include <libutil.h>
-#include <libgeom.h>
-#include <sys/errno.h>
-#include <sys/disk.h>
-#include <sys/stat.h>
-#include <crypto/rijndael/rijndael-api-fst.h>
-#include <crypto/sha2/sha512.h>
-#include <sys/param.h>
-#include <sys/linker.h>
-
-#define GBDEMOD "geom_bde"
-#define KASSERT(foo, bar) do { if(!(foo)) { warn bar ; exit (1); } } while (0)
-
-#include <geom/geom.h>
-#include <geom/bde/g_bde.h>
-
-extern const char template[];
-
-
-#if 0
-static void
-g_hexdump(void *ptr, int length)
-{
- int i, j, k;
- unsigned char *cp;
-
- cp = ptr;
- for (i = 0; i < length; i+= 16) {
- printf("%04x ", i);
- for (j = 0; j < 16; j++) {
- k = i + j;
- if (k < length)
- printf(" %02x", cp[k]);
- else
- printf(" ");
- }
- printf(" |");
- for (j = 0; j < 16; j++) {
- k = i + j;
- if (k >= length)
- printf(" ");
- else if (cp[k] >= ' ' && cp[k] <= '~')
- printf("%c", cp[k]);
- else
- printf(".");
- }
- printf("|\n");
- }
-}
-#endif
-
-static void __dead2
-usage(void)
-{
-
- (void)fprintf(stderr,
-"usage: gbde attach destination [-k keyfile] [-l lockfile] [-p pass-phrase]\n"
-" gbde detach destination\n"
-" gbde init destination [-i] [-f filename] [-K new-keyfile]\n"
-" [-L new-lockfile] [-P new-pass-phrase]\n"
-" gbde setkey destination [-n key]\n"
-" [-k keyfile] [-l lockfile] [-p pass-phrase]\n"
-" [-K new-keyfile] [-L new-lockfile] [-P new-pass-phrase]\n"
-" gbde nuke destination [-n key]\n"
-" [-k keyfile] [-l lockfile] [-p pass-phrase]\n"
-" gbde destroy destination [-k keyfile] [-l lockfile] [-p pass-phrase]\n");
- exit(1);
-}
-
-void *
-g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error)
-{
- void *p;
- int fd, i;
- off_t o2;
-
- p = malloc(length);
- if (p == NULL)
- err(1, "malloc");
- fd = *(int *)cp;
- o2 = lseek(fd, offset, SEEK_SET);
- if (o2 != offset)
- err(1, "lseek");
- i = read(fd, p, length);
- if (i != length)
- err(1, "read");
- if (error != NULL)
- error = 0;
- return (p);
-}
-
-static void
-random_bits(void *p, u_int len)
-{
- arc4random_buf(p, len);
-}
-
-/* XXX: not nice */
-static u_char sha2[SHA512_DIGEST_LENGTH];
-
-static void
-reset_passphrase(struct g_bde_softc *sc)
-{
-
- memcpy(sc->sha2, sha2, SHA512_DIGEST_LENGTH);
-}
-
-static void
-setup_passphrase(struct g_bde_softc *sc, int sure, const char *input,
- const char *keyfile)
-{
- char buf1[BUFSIZ + SHA512_DIGEST_LENGTH];
- char buf2[BUFSIZ + SHA512_DIGEST_LENGTH];
- char *p;
- int kfd, klen, bpos = 0;
-
- if (keyfile != NULL) {
- /* Read up to BUFSIZ bytes from keyfile */
- kfd = open(keyfile, O_RDONLY, 0);
- if (kfd < 0)
- err(1, "%s", keyfile);
- klen = read(kfd, buf1, BUFSIZ);
- if (klen == -1)
- err(1, "%s", keyfile);
- close(kfd);
-
- /* Prepend the passphrase with the hash of the key read */
- g_bde_hash_pass(sc, buf1, klen);
- memcpy(buf1, sc->sha2, SHA512_DIGEST_LENGTH);
- memcpy(buf2, sc->sha2, SHA512_DIGEST_LENGTH);
- bpos = SHA512_DIGEST_LENGTH;
- }
-
- if (input != NULL) {
- if (strlen(input) >= BUFSIZ)
- errx(1, "Passphrase too long");
- strcpy(buf1 + bpos, input);
-
- g_bde_hash_pass(sc, buf1, strlen(buf1 + bpos) + bpos);
- memcpy(sha2, sc->sha2, SHA512_DIGEST_LENGTH);
- return;
- }
- for (;;) {
- p = readpassphrase(
- sure ? "Enter new passphrase:" : "Enter passphrase: ",
- buf1 + bpos, sizeof buf1 - bpos,
- RPP_ECHO_OFF | RPP_REQUIRE_TTY);
- if (p == NULL)
- err(1, "readpassphrase");
-
- if (sure) {
- p = readpassphrase("Reenter new passphrase: ",
- buf2 + bpos, sizeof buf2 - bpos,
- RPP_ECHO_OFF | RPP_REQUIRE_TTY);
- if (p == NULL)
- err(1, "readpassphrase");
-
- if (strcmp(buf1 + bpos, buf2 + bpos)) {
- printf("They didn't match.\n");
- continue;
- }
- }
- if (strlen(buf1 + bpos) < 3) {
- printf("Too short passphrase.\n");
- continue;
- }
- break;
- }
- g_bde_hash_pass(sc, buf1, strlen(buf1 + bpos) + bpos);
- memcpy(sha2, sc->sha2, SHA512_DIGEST_LENGTH);
-}
-
-static void
-encrypt_sector(void *d, int len, int klen, void *key)
-{
- keyInstance ki;
- cipherInstance ci;
- int error;
-
- error = rijndael_cipherInit(&ci, MODE_CBC, NULL);
- if (error <= 0)
- errx(1, "rijndael_cipherInit=%d", error);
- error = rijndael_makeKey(&ki, DIR_ENCRYPT, klen, key);
- if (error <= 0)
- errx(1, "rijndael_makeKeY=%d", error);
- error = rijndael_blockEncrypt(&ci, &ki, d, len * 8, d);
- if (error <= 0)
- errx(1, "rijndael_blockEncrypt=%d", error);
-}
-
-static void
-cmd_attach(const struct g_bde_softc *sc, const char *dest, const char *lfile)
-{
- int ffd;
- u_char buf[16];
- struct gctl_req *r;
- const char *errstr;
-
- r = gctl_get_handle();
- gctl_ro_param(r, "verb", -1, "create geom");
- gctl_ro_param(r, "class", -1, "BDE");
- gctl_ro_param(r, "provider", -1, dest);
- gctl_ro_param(r, "pass", SHA512_DIGEST_LENGTH, sc->sha2);
- if (lfile != NULL) {
- ffd = open(lfile, O_RDONLY, 0);
- if (ffd < 0)
- err(1, "%s", lfile);
- read(ffd, buf, 16);
- gctl_ro_param(r, "key", 16, buf);
- close(ffd);
- }
- errstr = gctl_issue(r);
- if (errstr != NULL)
- errx(1, "Attach to %s failed: %s", dest, errstr);
-
- exit (0);
-}
-
-static void
-cmd_detach(const char *dest)
-{
- struct gctl_req *r;
- const char *errstr;
- char buf[BUFSIZ];
-
- r = gctl_get_handle();
- gctl_ro_param(r, "verb", -1, "destroy geom");
- gctl_ro_param(r, "class", -1, "BDE");
- sprintf(buf, "%s.bde", dest);
- gctl_ro_param(r, "geom", -1, buf);
- /* gctl_dump(r, stdout); */
- errstr = gctl_issue(r);
- if (errstr != NULL)
- errx(1, "Detach of %s failed: %s", dest, errstr);
- exit (0);
-}
-
-static void
-cmd_open(struct g_bde_softc *sc, int dfd , const char *l_opt, u_int *nkey)
-{
- int error;
- int ffd;
- u_char keyloc[16];
- u_int sectorsize;
- off_t mediasize;
- struct stat st;
-
- error = ioctl(dfd, DIOCGSECTORSIZE, &sectorsize);
- if (error)
- sectorsize = 512;
- error = ioctl(dfd, DIOCGMEDIASIZE, &mediasize);
- if (error) {
- error = fstat(dfd, &st);
- if (error == 0 && S_ISREG(st.st_mode))
- mediasize = st.st_size;
- else
- error = ENOENT;
- }
- if (error)
- mediasize = (off_t)-1;
- if (l_opt != NULL) {
- ffd = open(l_opt, O_RDONLY, 0);
- if (ffd < 0)
- err(1, "%s", l_opt);
- read(ffd, keyloc, sizeof keyloc);
- close(ffd);
- } else {
- memset(keyloc, 0, sizeof keyloc);
- }
-
- error = g_bde_decrypt_lock(sc, sc->sha2, keyloc, mediasize,
- sectorsize, nkey);
- if (error == ENOENT)
- errx(1, "Lock was destroyed.");
- if (error == ESRCH)
- errx(1, "Lock was nuked.");
- if (error == ENOTDIR)
- errx(1, "Lock not found");
- if (error != 0)
- errx(1, "Error %d decrypting lock", error);
- if (nkey)
- printf("Opened with key %u\n", 1 + *nkey);
- return;
-}
-
-static void
-cmd_nuke(struct g_bde_key *gl, int dfd , int key)
-{
- int i;
- u_char *sbuf;
- off_t offset, offset2;
-
- sbuf = malloc(gl->sectorsize);
- memset(sbuf, 0, gl->sectorsize);
- offset = (gl->lsector[key] & ~(gl->sectorsize - 1));
- offset2 = lseek(dfd, offset, SEEK_SET);
- if (offset2 != offset)
- err(1, "lseek");
- i = write(dfd, sbuf, gl->sectorsize);
- free(sbuf);
- if (i != (int)gl->sectorsize)
- err(1, "write");
- printf("Nuked key %d\n", 1 + key);
-}
-
-static void
-cmd_write(struct g_bde_key *gl, struct g_bde_softc *sc, int dfd , int key, const char *l_opt)
-{
- int i, ffd;
- uint64_t off[2];
- u_char keyloc[16];
- u_char *sbuf, *q;
- off_t offset, offset2;
-
- sbuf = malloc(gl->sectorsize);
- /*
- * Find the byte-offset in the lock sector where we will put the lock
- * data structure. We can put it any random place as long as the
- * structure fits.
- */
- for(;;) {
- random_bits(off, sizeof off);
- off[0] &= (gl->sectorsize - 1);
- if (off[0] + G_BDE_LOCKSIZE > gl->sectorsize)
- continue;
- break;
- }
-
- /* Add the sector offset in bytes */
- off[0] += (gl->lsector[key] & ~(gl->sectorsize - 1));
- gl->lsector[key] = off[0];
-
- i = g_bde_keyloc_encrypt(sc->sha2, off[0], off[1], keyloc);
- if (i)
- errx(1, "g_bde_keyloc_encrypt()");
- if (l_opt != NULL) {
- ffd = open(l_opt, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (ffd < 0)
- err(1, "%s", l_opt);
- write(ffd, keyloc, sizeof keyloc);
- close(ffd);
- } else if (gl->flags & GBDE_F_SECT0) {
- offset2 = lseek(dfd, 0, SEEK_SET);
- if (offset2 != 0)
- err(1, "lseek");
- i = read(dfd, sbuf, gl->sectorsize);
- if (i != (int)gl->sectorsize)
- err(1, "read");
- memcpy(sbuf + key * 16, keyloc, sizeof keyloc);
- offset2 = lseek(dfd, 0, SEEK_SET);
- if (offset2 != 0)
- err(1, "lseek");
- i = write(dfd, sbuf, gl->sectorsize);
- if (i != (int)gl->sectorsize)
- err(1, "write");
- } else {
- errx(1, "No -L option and no space in sector 0 for lockfile");
- }
-
- /* Allocate a sectorbuffer and fill it with random junk */
- if (sbuf == NULL)
- err(1, "malloc");
- random_bits(sbuf, gl->sectorsize);
-
- /* Fill random bits in the spare field */
- random_bits(gl->spare, sizeof(gl->spare));
-
- /* Encode the structure where we want it */
- q = sbuf + (off[0] % gl->sectorsize);
- i = g_bde_encode_lock(sc->sha2, gl, q);
- if (i < 0)
- errx(1, "programming error encoding lock");
-
- encrypt_sector(q, G_BDE_LOCKSIZE, 256, sc->sha2 + 16);
- offset = gl->lsector[key] & ~(gl->sectorsize - 1);
- offset2 = lseek(dfd, offset, SEEK_SET);
- if (offset2 != offset)
- err(1, "lseek");
- i = write(dfd, sbuf, gl->sectorsize);
- if (i != (int)gl->sectorsize)
- err(1, "write");
- free(sbuf);
-#if 0
- printf("Wrote key %d at %jd\n", key, (intmax_t)offset);
- printf("s0 = %jd\n", (intmax_t)gl->sector0);
- printf("sN = %jd\n", (intmax_t)gl->sectorN);
- printf("l[0] = %jd\n", (intmax_t)gl->lsector[0]);
- printf("l[1] = %jd\n", (intmax_t)gl->lsector[1]);
- printf("l[2] = %jd\n", (intmax_t)gl->lsector[2]);
- printf("l[3] = %jd\n", (intmax_t)gl->lsector[3]);
- printf("k = %jd\n", (intmax_t)gl->keyoffset);
- printf("ss = %jd\n", (intmax_t)gl->sectorsize);
-#endif
-}
-
-static void
-cmd_destroy(struct g_bde_key *gl, int nkey)
-{
- int i;
-
- bzero(&gl->sector0, sizeof gl->sector0);
- bzero(&gl->sectorN, sizeof gl->sectorN);
- bzero(&gl->keyoffset, sizeof gl->keyoffset);
- gl->flags &= GBDE_F_SECT0;
- bzero(gl->mkey, sizeof gl->mkey);
- for (i = 0; i < G_BDE_MAXKEYS; i++)
- if (i != nkey)
- gl->lsector[i] = ~0;
-}
-
-static int
-sorthelp(const void *a, const void *b)
-{
- const uint64_t *oa, *ob;
-
- oa = a;
- ob = b;
- if (*oa > *ob)
- return 1;
- if (*oa < *ob)
- return -1;
- return 0;
-}
-
-static void
-cmd_init(struct g_bde_key *gl, int dfd, const char *f_opt, int i_opt, const char *l_opt)
-{
- int i;
- u_char *buf;
- unsigned sector_size;
- uint64_t first_sector;
- uint64_t last_sector;
- uint64_t total_sectors;
- off_t off, off2;
- unsigned nkeys;
- const char *p;
- char *q, cbuf[BUFSIZ];
- unsigned u, u2;
- uint64_t o;
- properties params;
-
- bzero(gl, sizeof *gl);
- if (f_opt != NULL) {
- i = open(f_opt, O_RDONLY);
- if (i < 0)
- err(1, "%s", f_opt);
- params = properties_read(i);
- close (i);
- } else if (i_opt) {
- /* XXX: Polish */
- asprintf(&q, "%stemp.XXXXXXXXXX", _PATH_TMP);
- if (q == NULL)
- err(1, "asprintf");
- i = mkstemp(q);
- if (i < 0)
- err(1, "%s", q);
- write(i, template, strlen(template));
- close (i);
- p = getenv("EDITOR");
- if (p == NULL)
- p = "vi";
- if (snprintf(cbuf, sizeof(cbuf), "%s %s\n", p, q) >=
- (ssize_t)sizeof(cbuf)) {
- unlink(q);
- errx(1, "EDITOR is too long");
- }
- system(cbuf);
- i = open(q, O_RDONLY);
- if (i < 0)
- err(1, "%s", f_opt);
- params = properties_read(i);
- close (i);
- unlink(q);
- free(q);
- } else {
- /* XXX: Hack */
- i = open(_PATH_DEVNULL, O_RDONLY);
- if (i < 0)
- err(1, "%s", _PATH_DEVNULL);
- params = properties_read(i);
- close (i);
- }
-
- /* <sector_size> */
- p = property_find(params, "sector_size");
- i = ioctl(dfd, DIOCGSECTORSIZE, &u);
- if (p != NULL) {
- sector_size = strtoul(p, &q, 0);
- if (!*p || *q)
- errx(1, "sector_size not a proper number");
- } else if (i == 0) {
- sector_size = u;
- } else {
- errx(1, "Missing sector_size property");
- }
- if (sector_size & (sector_size - 1))
- errx(1, "sector_size not a power of 2");
- if (sector_size < 512)
- errx(1, "sector_size is smaller than 512");
- buf = malloc(sector_size);
- if (buf == NULL)
- err(1, "Failed to malloc sector buffer");
- gl->sectorsize = sector_size;
-
- i = ioctl(dfd, DIOCGMEDIASIZE, &off);
- if (i == 0) {
- first_sector = 0;
- total_sectors = off / sector_size;
- last_sector = total_sectors - 1;
- } else {
- first_sector = 0;
- last_sector = 0;
- total_sectors = 0;
- }
-
- /* <first_sector> */
- p = property_find(params, "first_sector");
- if (p != NULL) {
- first_sector = strtoul(p, &q, 0);
- if (!*p || *q)
- errx(1, "first_sector not a proper number");
- }
-
- /* <last_sector> */
- p = property_find(params, "last_sector");
- if (p != NULL) {
- last_sector = strtoul(p, &q, 0);
- if (!*p || *q)
- errx(1, "last_sector not a proper number");
- if (last_sector <= first_sector)
- errx(1, "last_sector not larger than first_sector");
- total_sectors = last_sector + 1;
- }
-
- /* <total_sectors> */
- p = property_find(params, "total_sectors");
- if (p != NULL) {
- total_sectors = strtoul(p, &q, 0);
- if (!*p || *q)
- errx(1, "total_sectors not a proper number");
- if (last_sector == 0)
- last_sector = first_sector + total_sectors - 1;
- }
-
- if (l_opt == NULL && first_sector != 0)
- errx(1, "No -L new-lockfile argument and first_sector != 0");
- else if (l_opt == NULL) {
- first_sector++;
- total_sectors--;
- gl->flags |= GBDE_F_SECT0;
- }
- gl->sector0 = first_sector * gl->sectorsize;
-
- if (total_sectors != (last_sector - first_sector) + 1)
- errx(1, "total_sectors disagree with first_sector and last_sector");
- if (total_sectors == 0)
- errx(1, "missing last_sector or total_sectors");
-
- gl->sectorN = (last_sector + 1) * gl->sectorsize;
-
- /* Find a random keyoffset */
- random_bits(&o, sizeof o);
- o %= (gl->sectorN - gl->sector0);
- o &= ~(gl->sectorsize - 1);
- gl->keyoffset = o;
-
- /* <number_of_keys> */
- p = property_find(params, "number_of_keys");
- if (p != NULL) {
- nkeys = strtoul(p, &q, 0);
- if (!*p || *q)
- errx(1, "number_of_keys not a proper number");
- if (nkeys < 1 || nkeys > G_BDE_MAXKEYS)
- errx(1, "number_of_keys out of range");
- } else {
- nkeys = 4;
- }
- for (u = 0; u < nkeys; u++) {
- for(;;) {
- do {
- random_bits(&o, sizeof o);
- o %= gl->sectorN;
- o &= ~(gl->sectorsize - 1);
- } while(o < gl->sector0);
- for (u2 = 0; u2 < u; u2++)
- if (o == gl->lsector[u2])
- break;
- if (u2 < u)
- continue;
- break;
- }
- gl->lsector[u] = o;
- }
- for (; u < G_BDE_MAXKEYS; u++) {
- do
- random_bits(&o, sizeof o);
- while (o < gl->sectorN);
- gl->lsector[u] = o;
- }
- qsort(gl->lsector, G_BDE_MAXKEYS, sizeof gl->lsector[0], sorthelp);
-
- /* Flush sector zero if we use it for lockfile data */
- if (gl->flags & GBDE_F_SECT0) {
- off2 = lseek(dfd, 0, SEEK_SET);
- if (off2 != 0)
- err(1, "lseek(2) to sector 0");
- random_bits(buf, sector_size);
- i = write(dfd, buf, sector_size);
- if (i != (int)sector_size)
- err(1, "write sector 0");
- }
-
- /* <random_flush> */
- p = property_find(params, "random_flush");
- if (p != NULL) {
- off = first_sector * sector_size;
- off2 = lseek(dfd, off, SEEK_SET);
- if (off2 != off)
- err(1, "lseek(2) to first_sector");
- off2 = last_sector * sector_size;
- while (off <= off2) {
- random_bits(buf, sector_size);
- i = write(dfd, buf, sector_size);
- if (i != (int)sector_size)
- err(1, "write to $device_name");
- off += sector_size;
- }
- }
-
- random_bits(gl->mkey, sizeof gl->mkey);
- random_bits(gl->salt, sizeof gl->salt);
-
- return;
-}
-
-static enum action {
- ACT_HUH,
- ACT_ATTACH, ACT_DETACH,
- ACT_INIT, ACT_SETKEY, ACT_DESTROY, ACT_NUKE
-} action;
-
-int
-main(int argc, char **argv)
-{
- const char *opts;
- const char *k_opt, *K_opt;
- const char *l_opt, *L_opt;
- const char *p_opt, *P_opt;
- const char *f_opt;
- char *dest;
- int i_opt, n_opt, ch, dfd, doopen;
- u_int nkey;
- int i;
- char *q, buf[BUFSIZ];
- struct g_bde_key *gl;
- struct g_bde_softc sc;
-
- if (argc < 3)
- usage();
-
- if (modfind("g_bde") < 0) {
- /* need to load the gbde module */
- if (kldload(GBDEMOD) < 0 || modfind("g_bde") < 0)
- err(1, GBDEMOD ": Kernel module not available");
- }
- doopen = 0;
- if (!strcmp(argv[1], "attach")) {
- action = ACT_ATTACH;
- opts = "k:l:p:";
- } else if (!strcmp(argv[1], "detach")) {
- action = ACT_DETACH;
- opts = "";
- } else if (!strcmp(argv[1], "init")) {
- action = ACT_INIT;
- doopen = 1;
- opts = "f:iK:L:P:";
- } else if (!strcmp(argv[1], "setkey")) {
- action = ACT_SETKEY;
- doopen = 1;
- opts = "k:K:l:L:n:p:P:";
- } else if (!strcmp(argv[1], "destroy")) {
- action = ACT_DESTROY;
- doopen = 1;
- opts = "k:l:p:";
- } else if (!strcmp(argv[1], "nuke")) {
- action = ACT_NUKE;
- doopen = 1;
- opts = "k:l:n:p:";
- } else {
- usage();
- }
- argc--;
- argv++;
-
- dest = strdup(argv[1]);
- argc--;
- argv++;
-
- p_opt = NULL;
- P_opt = NULL;
- k_opt = NULL;
- K_opt = NULL;
- l_opt = NULL;
- L_opt = NULL;
- f_opt = NULL;
- n_opt = 0;
- i_opt = 0;
-
- while((ch = getopt(argc, argv, opts)) != -1)
- switch (ch) {
- case 'f':
- f_opt = optarg;
- break;
- case 'i':
- i_opt = !i_opt;
- break;
- case 'k':
- k_opt = optarg;
- break;
- case 'K':
- K_opt = optarg;
- break;
- case 'l':
- l_opt = optarg;
- break;
- case 'L':
- L_opt = optarg;
- break;
- case 'n':
- n_opt = strtoul(optarg, &q, 0);
- if (!*optarg || *q)
- errx(1, "-n argument not numeric");
- if (n_opt < -1 || n_opt > G_BDE_MAXKEYS)
- errx(1, "-n argument out of range");
- break;
- case 'p':
- p_opt = optarg;
- break;
- case 'P':
- P_opt = optarg;
- break;
- default:
- usage();
- }
-
- if (doopen) {
- dfd = open(dest, O_RDWR);
- if (dfd < 0 && dest[0] != '/') {
- if (snprintf(buf, sizeof(buf), "%s%s",
- _PATH_DEV, dest) >= (ssize_t)sizeof(buf))
- errno = ENAMETOOLONG;
- else
- dfd = open(buf, O_RDWR);
- }
- if (dfd < 0)
- err(1, "%s", dest);
- } else {
- if (!memcmp(dest, _PATH_DEV, strlen(_PATH_DEV)))
- strcpy(dest, dest + strlen(_PATH_DEV));
- }
-
- memset(&sc, 0, sizeof sc);
- sc.consumer = (void *)&dfd;
- gl = &sc.key;
- switch(action) {
- case ACT_ATTACH:
- setup_passphrase(&sc, 0, p_opt, k_opt);
- cmd_attach(&sc, dest, l_opt);
- break;
- case ACT_DETACH:
- cmd_detach(dest);
- break;
- case ACT_INIT:
- cmd_init(gl, dfd, f_opt, i_opt, L_opt);
- setup_passphrase(&sc, 1, P_opt, K_opt);
- cmd_write(gl, &sc, dfd, 0, L_opt);
- break;
- case ACT_SETKEY:
- setup_passphrase(&sc, 0, p_opt, k_opt);
- cmd_open(&sc, dfd, l_opt, &nkey);
- if (n_opt == 0)
- n_opt = nkey + 1;
- setup_passphrase(&sc, 1, P_opt, K_opt);
- cmd_write(gl, &sc, dfd, n_opt - 1, L_opt);
- break;
- case ACT_DESTROY:
- setup_passphrase(&sc, 0, p_opt, k_opt);
- cmd_open(&sc, dfd, l_opt, &nkey);
- cmd_destroy(gl, nkey);
- reset_passphrase(&sc);
- cmd_write(gl, &sc, dfd, nkey, l_opt);
- break;
- case ACT_NUKE:
- setup_passphrase(&sc, 0, p_opt, k_opt);
- cmd_open(&sc, dfd, l_opt, &nkey);
- if (n_opt == 0)
- n_opt = nkey + 1;
- if (n_opt == -1) {
- for(i = 0; i < G_BDE_MAXKEYS; i++)
- cmd_nuke(gl, dfd, i);
- } else {
- cmd_nuke(gl, dfd, n_opt - 1);
- }
- break;
- default:
- errx(1, "internal error");
- }
-
- return(0);
-}
diff --git a/sbin/gbde/image.uu b/sbin/gbde/image.uu
deleted file mode 100644
index 82e6f2e47489..000000000000
--- a/sbin/gbde/image.uu
+++ /dev/null
@@ -1,3305 +0,0 @@
-$FreeBSD$
-
-begin 644 gbde.image.bz2
-M0EIH.3%!629364"&9H\`Y1=_____________________________________
-M________X7"_"W7I7N^[5>OM;NXTY!ZK'VZ]]MS?=??>>OM=[?/I-WMSSFM;
-MO>[&RU[OMNKV=>\:^>K>]N;5WN];V*7F[O6[[[>G;WWRKZ]ZK7?7UZ7=[WN=
-M[?<5WWR[97V[M=U[>UAYYW'WNW<^^WUM??7U]UZ=>MZ?7KOOK[;WM[O>]'O;
-MKWU?;[Z^=*YZYNLNKYQ7KWO=Z]W.>OOO/HR>KV^N>L]>>Z\O;ZWWN[O=IOK*
-MT]>WUUS=V]:Y+[/OON]>[?9[GWS>][OK27KI]UK.N]]]WOJW=URR]L[[LU>\
-M77VSN]YM\]Z*]NW>S[GWONYONZ^[SI>^^YWN[6Z^YUF:Y]Z^[[=]=\NNY]Y;
-MO>^NEW>S=GGKW>^^[;?.[[7?;[?'7N.^YZ^UW/K[VY./:N\M]S:]WWV>^I>W
-M./3MVW>]GKR^]5K-=GG>^\MW'NWO>^^]?/7O7WO/?;O7UU[O?=]OO=<9@7V]
-M<\V=W5OOMS7>;[[Z^O/OO=ES[>7VON]Z^WE>]OI\^]ZE??+,[WG5FW33V;4/
-M:]O-[M:SUWWOENY[S*]>[/0]]O!=];G>MWEGOO:MW>K?7NW6NVHO6NMWOJ\^
-MOO?;K;UUM;>VV:Z>YV]T]ON9MCWGMN[WGNCWWW=[Z[5/O?5=??;WINOMG>TO
-MO+??;U?;XS=]VK;<W>UYYYSNOGWO/I[WTT=KV[JI[:]]WU[?:NFNO=W>GNZ]
-MFV]W>WGJ+S;OO>T=+Q[7UP[WKNOHR;C>M5?=SMNU==O>Y3[[?55WW;U\\U>=
-M[>^;NUU?5VNWGON^^>W3ZUKNNN[-WW>NVC4\QUO;N&77;>W>>=\Y].^^[[=]
-MZWW?;YTJ]BFW??=O3M[V[[Z^=Y?>^\L];;O?/OM\]MON[N.]Y[KSV[PWN]W=
-M+ZK=]/M]SO>]GN^[>]O??=U-Z=[OGWMQ][ZP3[[;OK[V=]W?:ZZ^]>]SO`.)
-M[?7>[=U7O>OOOEM]]W=?>VUE:-;,ON]Y][O5V^^][OK[[[V]Y]WVV]M>@Z.V
-M?7OFU\???=[[E=WM-/MRV/.9MJ)6>[[UMNWSOGQ]?/ON>]]OGE/'K;?=J[ZU
-M]?9=U\[O<T]H9OM]WJVN?7>ENZ[A[M[O.2]U[O<S-[7V^[YT^OI]W??/HO?<
-MZSXWWJ7N?>YW(^?;[?;S[)OO=][SV8O?<GS.]7OO?>WW9:WUWWWOGN>^^]/?
-M7GK>7N5[VRSYNVIWVU>YNU;KSP9=9][+;[VOMMZ^^C[WO?.GIWJ^NN^ON]WN
-M[V]OO;Z^J[UMNOGFN[WM4]>OO=UVOM]X8]MNO>\9&^N^WU]WG;CJ[NMW=O8.
-MZ5?9U?==R^;?6N]O>M:VUF]N]N[,VY'K*WSW=XZN[O>K[M\Z:?7>][IUK%[=
-MV.]N[O6O?77=OIWMFGOG>:?.^YWWS[SX5>ON^VY]3WW=[K[7O6^^]?7>M]\V
-M/<UUQ]:^WOMC>1TDZVWF[U>[IO;"[[NVR]:]GKWON^\S'>]]=O/?>W>K[[O>
-M6O7K[V^CO/NUY?=U[O/7GSVKG;[OJX^[S?=;W5TSO>[Z^USMN[O?=WWVUZWN
-MWNS[[O>];KQE>MWS:US8^[=[ZWM>G??/=>^9W=?;OO'CW;[[X'S/<YW???==
-MSNY"J?X`3``!&```IL````5/P`3$P``)@`````````3```"8``-&F@``:&@:
-M`JB%5/_`````!4_%4_P```````````F``````3```--`#$``````"8`!,3*>
-M!51*I_@`)@```-)@`$P`F`3`3``5/P`F``3`T-!IH:#30R!IH%-@!,$TP``$
-MP3`)B8)@C$P*HA53_P`$P``````````!4_#0,0#0#0T-`T``)@`!#``E3_3!
-M38`"&```F``3```542J?X`!,"8`3`F`&1HT9!IH,AB-"8`3$R,`)@$P``3)A
-M-,3)@$R8"9J4_31@3"8%/``3`3``&@*H90TR&@T#0#$:9-&A,!,3`)@`$PF`
-M$:81FB:8``F``)B8`3*>!&3`1B81IDP3``!,IX!,J?J>`":4["(B(J<C``(@
-M"(`B]!&1```$0`'41D1$`1``$0!$!L$8```!$1$0`&(1D0``!$``TD9$`1``
-M$1$1>@C``(@`"(``!)"$G*%(@"(`B`(B(B`(C\C`(@1&1`$1$``1$1$`1/OL
-MKOMIH+QS3GG]CAF%<+B]I?#`V7-_"-Y#LDSH9(@]7VLR`[HWF)TW`6KW'/:[
-M(XX%BKB][$SP'KU?K:_(1N9_H^2@JA3P.J%L@];AP_!DU0#Q+M]J`25MW8VF
-M*XL679-BSK:$@%7+58\#PQMY/2W?@M+-W)\E?]B$TIE`=%,17/[11-(;\I/#
-M3K0@:YL-M_DJH(H!9LQB\>C6A#Z#2)'V&%ST*32:^<7Z,WD!2Y^/JR(;=ORJ
-M>,<*PVQ,R&#QC8-[$9MU[)EC?'-!R@=(2:X0\CG?++DK!YO[LOU*6-G(56S[
-MML*@CU_P?SNY*I`D2CK+X+*<D33>[&5,NIT^H*%`ZF8Q<'K7)XIWZ8=1A[<'
-M;TS"6Q^U[E3BL90'SR0^'D=A@&E@R::PDR3?^0@H869KI`T;Z3$XA/LY\]1E
-M/C0"&C\V"&S3KB$?U0>XUFH\Q[N+OQNKX'*LW]</]KK<$L][=G,6P<.>*#OQ
-MPCD->$>?-13U@<R>8#8*D.'R)W#N8IFE^^*R@S%:&O"R%#-'W?!YNM3N5PZ`
-M/#!F3E9,(+E-0&:61NBQ11&;HL-7T,4#Z:MA]`E:==_$3](_^+,-FT4#KAN+
-MBE/&6*K[.Y6IUY,+C%C*7"\Z&7P!BW("$L:%`G#&<?&$\=LA)""T$O078Q1Q
-MMTR<,YL&6.H!.P$NQ4C\5:*(-AQ?@B2`II;>'-[R2,L8NQD^'8NKDO6%V-S]
-M.XJ9#YRP6=JD;F2*J'B=3QEU]OH\;!N7\Q_OE"0`"(B``(B(B`(D-T3;PKMS
-ME!5Z$Y68,"-/Q<GA,D'YFYSB^;*9@X#0S:+&?]I6A(/?N%TE=YWX'"3:")XR
-M@>>PAYR72R[0T3+!<W`!BSS#NJP"^QE)#]U8NJO;%H#8@ZFPD5^(XZ5R+S?9
-M,;7[T@)0"OI+_%3*6R$4M)._@@GW,9&OV[[;-#T`VF``;R(4:!QU[=*3AX:Y
-M]QUY1>9,F9+<[0LJ,'K!]IX"V'V63B#J53F7=OS`#2?&W!1[9G`*'&?SYV2N
-MW5W]E$!P+VH9'#BZ;8[/'<$>1S4//EG80Q8;"06GUQ=I<,<MC0,MGN:3J,A'
-M(Z")BMPGM_S&X/51E6LW*\%2%.ZY_$-(C++?8^[IC?>]Y7D(7FTGIUAK$E9@
-MG$JE)3V?>1[&:XGBU&L)E>&W&XYK%=/0]20P38X^,$3A/B+Y`![Z4:ZJ_RZ3
-M5O9QO4@7/4:,]*_@!XU8;!W>8B]V%ZATFI*&3JQU@A;8*IW`S;E&3A9=#W.J
-M`H@<XS:A&850DGDFMDVN.17D2I+*HT6*RA4%6L.8R2EE9WHTLWF.JTJ`"I18
-M<2LSCK4:D\M3#S"^@YI(Z?L(9(?EN43_C'54GG!XRLK6*(4D))8LW^RF[G,#
-MT?*CW1;UJ+,6E'GXP4F8`K^F]0@\(77%3F)+%RGE>5MZ#+DN\BXYH.2C>"<%
-MJF?>2G6_7\\@-/$FU7[5XKM.7&U+XO\E7\+V$,8:`K'Q&"(^ZA[8'4*!.B=9
-M_TQ@Z596F1WTPA:,40MQ5CS*H;5H21VQS6@9P$^U;$\D=LR-1HU^42O(>K+J
-M:L@X=VR&SWEZ=!Z.]1PX^+V[E>F>=!PSK.#KV'"G^,MUMU;(HF:<A\21.#;Q
-M>QL+H*ZR(TM"9V,/*)3X+*%=HLY<)W^`#[H(PPH(<N./[$:SQ!O7,$8?+:GE
-M$X-TB5BUFQ<W'N?X150PB5$'_%R]N?>$?;XL0)TC##3VW2WP(S!3X5H#\($,
-M%2D%>[/>W\9=))4F[$:]V]J?9X@\OUKEG;3272J_<IN69W>R(T:R##2:"L;O
-M2"SKT7P)Z9$@T"?1B4<_JD--\(C4:'3+J>($7XU]F1[G8;U!R)]'8+M/WAYV
-M=TSANI97]6K?,&AG`GA(6*M,JV:*BL<25%3%@Q?0K8E>0Y:U,MY$"J0WSD6M
-MB;C;W<?7(\=W=3J9`NQ76BR['PN-'R<W^1[DA.AE["+&3)4%U;,RMP[Z;H.]
-M*)=:2B9!)V'%47_&7_F94`TK<#7B7+,&",N*X?5/?KKN,9=PG)>[A*5#-WKZ
-M^4*GD`WKYL[5FCI)Q-KE<DFT7L<I0UHML:XC+O#5]<UP_#\+B6N26F([)0Z>
-MV\Q\2*G9'!?`BX'Q2.:J*%%LRJ6?D#\-)>B>NA7!,I0#4C-)7J6Z#7YF@L*C
-M]KEA9^]?J]LJ'.H-P>\ZY,8RA\7=_1<DN$0:^SGV<EB?.YKH=2$DL=]["KB7
-M.B<UMV0,$B)9\KS6]^:^W*A,B?[VTUP8K3K>97H'F'?-*@<??7:@&1P?V9-S
-ME68E_5XV*#)M^*Q:.L6!GK.W0I+A,;^S>VIJ4&-\)4U#613H+]^6-I6%=O:V
-MCO7^I];_E<=Q,7U\WB_KZJ>+K2SR`FAD/D$RN'675:N`\RWP\()^OKK():JT
-MB-E5L,!,=,GS;)@YE?/^^C[V1V_@"Z.P033VJ*^A!AE5Q_QVMTI'=[0Y^K5E
-MA^`0E>6=>&9X=>"XH>%8M6TT2.A_S::_D'=^LWN6.9\UAA,\J7;C//PJ]C)^
-M:\;1(O$K-4W@@=DVC2^'C'U-545^#=I*P.58$<K]L[5VSY#G-NKT_T>+T"G9
-M?LE2U\W^6`M;<IL['I;Z+FP`<W[=6R,4=U?-W\IS_E;`?JEHV#=)PAHWIJ1C
-MZ-VX4EWQ$B<OH!0]Z#C,7ND!!^1PSPQT>5C&^]2S'&$)=V502NFDJF^HF'35
-M.\%4(M+Y.VMX)OW?Q1\?-M@8V^L!?6D2M6!SI5*!^A$6L"^"^]L5Z"9E#XI1
-MA=-5"CIK7Q=2/A/V83`RIEWD-TV2!DX^H_U"@MYZC(:O=;W;L>9O=%W=>#U4
-MZ]L=2H3_W"<?"8=Z@A?T&T-$,%]NH]0_NG>N..'ZVK.^%FCDG?!F8S%$\2HO
-M?IY+618!N;^FV85%.C0.Q3A+1=ZS+U<(O&G2:!=;$'SW;Y9B$$7<<^.$P-_2
-M92+RQZM'_`>12>R<//V4^^FBAIN/K]$YH+.YZ7P&I<1&$$O3_WU,D^L@RO(:
-MT%Y4&,.+51)V5J60-&D_%2\ZER0VB;19<_Y]J[L#D'P9'9:3',PE8*BW%4KI
-MJ[&D6%X;X?O=IKY`Z$$SF>'1@N72M<?WBG?Z58T77-PEK2=6.,8&YN]J>-XF
-M`8J+I5'F*J(75:2GKH]V&^!LX--5ZXQ20I:+ZK)9>/=SC,IRG7JU#6N/C)Y<
-MS=Q(T2=4+T>T_O`JEA6JWN"8!+^))2+?432]+))3O"3T&):8C2>Q&>V&J98.
-MY9\\QVE%LKZC=O95UY)^AQW@X?!=]WC'""_B%8<[^TB\8X3#WQ!WI2\;+@L$
-M0HHMOQ)Z4X[[MP7=(>MNO`?E'K--#20D@$A&,;!(?.LDU'[7I91VV#_.BV[H
-MP5,5RU@>O)>$[<#H$8V"V0&`T1&XA*F-$Q<Q2"9``GXQL(Z].FXO"[G-46%-
-MLBX_=&$T89_0JA>:5A\`.:-[2;/P6NMJLZ:3GP`/.Q.NE(*#:LAXJ4-99LT)
-M-ID,,T/2_VS/4.TD%7-$RUDT;UFQFUKRFV7Z]C:<YLNW]L)Z:X5[KS@O9-5/
-M)%H95QON)(".;G*JE3_NO95RQ('G,#T'-:\292P&>E"-MM]6_QCH[T`7!S74
-M3YOR.*:#X;9I+O)J"G1=U].?[.YM3;VAGY&-70TI2(!G2K=RJ!>?AB'8:7_I
-M/L+4I=?6%ULTFV**N3]#K$X5:9"ZEH-,/S;H-#S,1CQ.T-PJPDB3@#Z(VD]I
-M]L("A/`:@7Q!?U>UG_@Z:/+Z#SN$E21[R')ZR,X<>",[`S'0FR["<G."Z<!R
-M@X>Y\^$\#S<!%U`OX1`LRH%-KG6)=,"V!%=WV+Q>Y""@M=04)(OCRT+42_7^
-MS&V]B&#`NB-KE\MW&),/\/DZCN(&PJ<>PL"M)$A1[GS"N<DOIUP[*WUH./@\
-M&]HP?<BT(^TTUW)GMJUK[R?`GIL=4SATC8(\Q^QL>9^)'BI&VQ-)9W?<B7.G
-M8'<D6-&'"O-/MO4\<:E1IN8O=*8EJC#.`3)R@##0-FW02,U=MH7?C86Z?KQB
-M=!:T[H\I]/?K+/K0@8S#G7I<A%51[T+`C-*>IK,$>N,[K[$)--3"Q<^7"S2V
-M5P5=BK%%/<AA=+_BH:G-8BQ0OQ9=!$B;D04@3A'9$JVVR3]$8#0![_Q^U75@
-M796@9?*^M$EY$GS!!UBK_OM"N)M<&5OG5GA?:U;ELC:XX>JC62*6F[)8%2*;
-MXTE-2&)%]LA<B$SWEZ2H6/X(`DKW3Y%C/M,.--?.$'!53K$G[[8@P52)8E/N
-M"&K*;G"'3!6;G\O/S[W,Z:J,#RPG!*QU7OQ?UR:<K0=!8'44JV<U,UX-&W8@
-MR<HJ>DS\D\_KUW/UQ+4Y3C'YJ@V0>&D?'%&B/["^4C0FWE;+:I:;MPNK:;1/
-MV6=(0V`+H%>:KN%*F>R!F3IRS8%6)8[O17E<>]-/@.$[!-4]>,)Z:>GFGU#2
-M5O_)=\5B*[(0?ZV1$EYRT^J%P'Q;-WLC^TMI[=)=$!$XY^`K0GV6@A+QGM]Z
-MQ1;,"[0'!97SB_'S/B[Y>;<50/2&/J*6_AW;0A8&RP?SG[/R`]A?7K`$P5D\
-MKC,M.O(*M3/6MB_FL\<"?II+/35,(Q+X^TJV\NJ*QZ?]^IF3JGH='PB!?H8_
-MM!3FR=HN>P1C;8%NY]W2@%&AQ"9L:9_]0E'\8KOI\7RG8/5\/FHH8N,%#4O\
-MWES>AS5&N!J@/#L:M`)C;6A'!=FC_,W#.<&^R&Z+"`GQT2?K(#KS(L+`Y?)K
-MCP#?<J4G5Z9B8EI%]IVG"XF"X<;PC0`(#E?(D.L-!4(A\H^6#$HEHY"J-[G^
-M\SND>C;'2>1&L'G=!`EMUUAH'[&J9K#BVC>6#G[E0T)#7PRV9=7O\*"Z3A;'
-M/K^8T"YBF15.'XV)EZ)%!TTY@$42I8=RY5RV.6]L<AF4UN,O"QH(HC?5%93@
-M*_B(]N93V0YW'-:3%E-#@'J#.?J5=.0,-@C@=R<;`&?><_`]T8'"9LQ1+AIV
-M_ET<\KE<XY-:468&HV-0K?I7.*1H]3NN079QL3]QR&3$-CBGFEJFO_J0:@5C
-MUG=/4JQ-BBNNC22>*G31(1NQS?#<TSR[#_$2-XAO'P+!Y0`N.#O1/ORKZ$,-
-M!"V;'=:3=Y<V.O\\H`BH]`TA16X['']L"S:_]K[QQE'_AL:S>W+0R%\EW$P+
-M(;40NK"#=5#>_2J(RP,/;`>8L.=YPK,`LJS.M7TL=`[)HJ4->?>A(,V)$1P;
-MC?&;M^C;OS"EIG3EUZRI*'ZE1[6^3G2")'U(1B9%@%O^^@%.&T`@.A,67:O$
-M?U`PSK,E%-M+JN?K/[U=_$HI.8,%8SO0=;HJW?+L^+%5PS8!S"\D<%&/@,"%
-M_3:!O6-*4)GKFTTEFN87$H1)/QB>.;=\9D(.JC#8'V55AZ'X2J\<5E#<I;X^
-MV\WKH+G,1P<17)-]OX^,:/CSSB;6PZ0'[NTX?U!_:8^P.%J>EH+-B9B/YUU[
-M_V/&"'D;YX%P6W699`7$F]`B9`'=+RR(,7E-T;S>%0C_:I;::@ZU>N!HV0C`
-M$/N33[_WS19QN$(S`U&3H'L;U>_39M[HW4=SWESHD\NZ88-9BO6]U`#0"G!-
-M_*I!W.PR<LVA7TNI&O5L>&I"*#F;;1Y`"J4:XV:S`6$>8%M9='ONF`9-L6BA
-MFD_(\4P\#V^J6\V;S'IJFU)7CIQJ?3UCD59)4THHV;4[),QJ(Y6#W8$)P-V7
-MO9^^38)Q9;U/Y`6A*?\E)05BC=M-(STFE@+^?)3(#DWZ']9CSJCL\^FYL5?,
-MN)D<=^%(!YN60H%B1I+>?T.ZL#.9(CFRMO0V?6-P*!'?VL^V/'U=2NQL36X-
-MJ0\E-_-IMVYNJ<]Y;D,F1"DX*3T=;+[/9L#=`<J0L>ER34&`^:F%-F3O#D+Q
-M$8:*^I38G_WTW]RN)H:"OPNC+.T7O32F\%G%)?+75LPM:$F4&)=![(&3&GO@
-M&FC(7;_IL@EH'Y@'K15QK<+IGBWKY=O7J\/08C6[B75=ZJXXIU233\^HS$5&
-MSWI5H9.%.!^8018ZZ5T1>Q;3X"-<_\V;C!4V8=UI%_D<'-PBE@]9Y?-K6*9)
-M?)9P(N&++8LPNNVC-:-\2&FNL>"4P#DU/TP&X')*>IL;T7$SA%R&0[PYR7P"
-MT4WG)6?6BXNDA#R)2191XTUDG;<6QM.?Z>-O9+U6V*!L-8$(`&ISZ62I]PC3
-M.LNLY4=D4IKZ9LU5DCW17KK=B+F%#D(Y<QY>%YJF$T*)&`FN=POR'"+UNF=G
-ME`B-F^ZU,6E^A1XZAA3-U?6QQ>)B1`'C%Q*<=@IM+LR>"4%)26\YRROK"S8=
-M]E08V/V<59::9ZWMS`@_PE1>7-B+_RQV(F(\'(.R;$5:503.3Z2]@$[A_MM4
-MXO#;=A7H+RE\)((TJ[T4"9,(W-GY4&Y227=&CEE_XXAJ$O>%X):'^0?]V"%-
-M"S_*HIT)3?"9QN%\LX>+5,C*!!"AKF0KGOB@H72HV<=K(+83-47Y$A9K\SC1
-M+9RD7,/]9!ADS"$&_-Y$07SVM#/Y6>]W$H@,Q_"`4`WPPHU!Y?MFGDUS@9I\
-M9SA/1=*;<RF$Z5#/E>UR<V<>-IFYBFM33W%(?]L^U>-,9H]TP+Z-JP:5ZDA+
-MNC*8)=7)SQYJ5M;*NW^)>3862XJI[''?<WX4LY.B+5@TF$<W)Q,HXH_UD!J'
-M@I'+IXVV8%6N,:@J,*0>,)'ZGS%7R@KX/RI*;\3FJ<F>3:`5-DDN?M\GQ:?`
-MM&!="%>ULO1U;(\?_8I)+S"%8B_,Z,3:F&X*.V5-55?[$ZD`7PVN80)P=U3Y
-M&@EHD0725=0VK:.,$'K!3592LBPUU#;80U7GW!\THD2-=%Y`?<UFU6>!7PQ?
-M"UV1SI]&Q:`7IL8H3W&JZ$PIYD?W>*#I:3FJ^+O:,5WQ;)RY6M0$WMB86T]-
-M)A3(#!>0BN,A?R+NW#=1P;[>!/(^F6'.=(:B]X_10T:U@X.ULJ;B1N*_->X/
-MG*#;,PE#\DUE?)=57*HC&N`M1#1;Z7@X8L949)[*!V$J_4.N*'A8L(V2KY&@
-M*?Q2'<+W^H'`L6),P90)?ZNGI<F'NNH=E90U"@?HNI`S<+U$*UGHS06.Y-S<
-MI44+GH\'\/AYEXV<KL22OQ,8TZ:+A91E\T64`B.NG?C3DF*2R!C^#TUH!YJ:
-M)GO<)"QUZ&$NLX`:N^!(KE5Y+$@%KNN+M14:[L0>7%G]!A!E7:\"ZNJDB*\J
-M!^_4^"2K3LM<ZGQA8M"5&MD=CM4N:0%#($]Z#=MM:?%;]?3R'+XB2/BTJC.^
-MK<N1CQ"G[XUDNX*FLWVT/)U:!(V9(^-48.]K)2ZMJ@R7))I8D0OOR#.$%TR`
-MA`:2&W=ZP,EVMT-DIV$&?C.R#8L"09S.^46X/=?XT_9!$`<!PN5_>'C4YNVL
-M3KK4M',5@[SKX7;,=6I8V]URL>G3+J]<3?8U1T41GAFWG=>O$6-A%%1N>Y5'
-MAA5C`OGFC&`.QO'K(!N/5TU0MTOS4!.@X6V=R<7+GPK$>/VUZ(]-<B=%N<ED
-ML`:,<EKJ*5'(G9"ZLFI1-3]78R%]B%"O'\#=[SKI/?)W<D`\2U0URSC"!>N0
-M,!NU?9'H9B34VC116\#V/%?N3Y`AH8HQ=-.,1I_RY]?L29VQEC*!N0Q)@W"V
-M<J((@0?/B+]<ZC.5(BWH,^I'$_"'2=WJZ;\?(XLI\^/BO(G9=H"=>7+ESQEL
-MX'416G$O>>UK7J9&\,5/6M.7'1;=IQ,^;$'95%XPFEBHT35LGI6<5.B;1#O[
-MM^WBEM$5*.\1<M>N5\32DU:I5LKE27E*7:9DIPU.XJ74&X3;N_U"FH[9G?:>
-MA9EXYF[3NS,32%#UL?NNQ8"Q`MY?UJF\%B??OZN_6[8*<4OG&79=;@0_I2A;
-M2A#4BWS5+!^O77#&<,BK":<5]B@VN!59?T_XU!4CR+8>N$"R/?-DT6E;>8;5
-M];61"409>??#$0J/*[R&+*>KU#1CHW%%P#/+,U;O/^[G!/C;H2)&-DWKB%?_
-MRP-7HAN8VZ=)(Y-?2MD9/WDO9BW_BI%BHE[^H6%52<6`WM[&_W^1(U/X9]`Z
-MKC!MX(^Y)9(0:SJ?ZL<(D/#0'F$P<8SIC=`@!T%E+-.;E:&.>N]K'W73"A"I
-MR/.5P"<_5,.H:%.EQ388AI2UPFI!PY1IHR^=2!A%[SJ[J<;A69C1<6RM-)_H
-M$:ZC7*@"&/N<[R:DP8,X]=H7]7,A2F5$#O&?IP#A4OM$VYQ5<\G7SL7<O=57
-M5YKQ^#/S)SZOB?QO$L'Z9<)83=HA,RS8^U11R=$S\\2S^=.RE<I'&8FX\3`;
-MJV@R(6[>6?!9):BS4GF[W>\\4`\@=5Y:\.AP?<+:_CSU-4]5CWV\I!I2Q;N>
-M,"ACP/KL,G1GT;(I^A7F%'":\X+[+A/@:++ER/\WC$G6SHSS**)ND9-B:O[<
-MW4O;4C)P1GAU6MV(JIII=C:MB?`2<2N<6P$0K<HQ6%;.U<WU.<`3$":GVL-8
-M7U'DW##L`*IVB0K!SOW#B?7;'D[N9.?,<S=GF616Y5^"3=RG1"F7P-J"1>T=
-MC`FYE>3RU3582+[^_7_3!;QDZ(6-&:]L?EU7%_9&E&UUTXG@+;CU&6H5W%2X
-M=,GAZ`VGO]>X2#BB44LM1J<^U=AJF65K\]FO1SAO'K4$4EH[:.7B*"<`<AB&
-M0OCB[CPDXW$G1?W&W9],KX*X#"I;->V70/_=UFLQ]C#B0QU<KTF@]TXF`?$"
-M&^T%Y<YN'4L%63FNY")LYQ$G,M/Z0-63"7WHQK$5WN%:CIU;6SN4:7?L\,.;
-M;!U7MOGX\=*YFK,^@![24V?*M,XB$?+5<X%4CJ'S^`C>3["TN?P2R"2-=M[(
-M%*YBR9;'=-^%_)KII?-BX(N^10+=9%]&1G<<(HY'LV4$;HGG!/NC2"K$EC%N
-M<!\S!EID>]C/=\A?'F0YA-M)O8LN6?J2P+KC6!G\L/7,Y5J4_C!?F?6?(TNA
-M1R-5<CVH](2QA;DUZ^(I0BM2L5ZA)Y@Z(P/FM,0.HW6!0A[R-;O`SU5P/SUQ
-MT"N;)Z?1?ENJA3(5E3#2YOD.];X^4[,YG)3YM4^V5]J\6$>"O8MN91<$R8HZ
-MOJ/@?&,$DOIYK5T;GF;PDI=-'>HC`F"UKP*(@/K@.M,E\,D6EC<#B:"JT_%!
-M,A-L>TQY"%[,J_YHRH<N'M*^4VI;QS62&5>O+3B=!ST^XY0.]CWT_4=4-GKF
-M=GTS/Q%3405:P0^"WJ'BFDH#%0!*Q;+^0.NIX&SD7\=G#-8GJ@XI6K]\=J`?
-ML4,6G>L$!MV_:DFC@91RW]9:B_.]LXAB+DVZ?:596RPY%D[6UQM6K?#'54GB
-M=^*F6L/&LI=V#>RYKLYTB0G5K1>7MEQSQ$3$"OI1VBK?L^LQXKQ=MMLX)E`^
-MSXQYGCY4#`-B;<6?YGX5N;=J>X&U.R1_0Z:_X>Z8G&9KQN@V\Z`.5M7CHUZ&
-M6X9-\%O1EH-#8XWHDJURS!*UL,6DQGV)I^E!S-/&GNG'[V#>=]%+`O;.\E_(
-M\5A^%VS"=O:-]EJE(:GG-Q5LA)+=%;G4.,R%GBLP]"DW<MMUY$WS%V7>"><L
-M\4%ZZFF=6O.W^\EC8O1B9J92<A1X.8)Q7GZK+VER![^H\W8!"SHL'N'TUQ/W
-M[QWHA!PA/F*:&PPW?WC]^WC6K;L?_J,9J0>Q*9#8NA>(.#L$[NN#4$[=%V6+
-MJA!"\+SH[+ZDS64G2Z:]\<4(`Z\WQV7_?5KC$,:U,*I.A93MU"5C*/3OWF^N
-MY5U\4*=B69='G@U.Z<JX<@=P+LM1[A@362.P/`RV7N40%'I(]/@3FAC8ZCKW
-M%BLO3V*[:[DHN_04+%=9)D307=.PRAV'X=@7TC^PA$++WM?-U&S?)2F@N<GE
-M>U3-F=Y(9MH;D=;DKI.T7H.LHYK(;SFH#W2TGC&^</"Z?L>^B`3?*)-]<U6Y
-M$9?+]KK<?/;4Q;EV\R:'X7.@[_IN$F=`K/EU5FJY:*=/:8+)\HRCXF8R&OON
-M9A>&XF0=FN];0\J]&`4,97O_^Y[FX\MA%0HO7ED*@!T-5KZ/='U<!#.]'H/^
-M9J0/U>\"BHX&"+Z-NO2J93U)*;0U21E=4)G(=6_*7)8/8$@;7^'@>6P5U<PB
-M-:I4>E?77EBI[7G)Z#RWQ(:GOT.2=6PM53(JK/(Q5M+M5!+N2Z>[QLE^I"3"
-M_GM*/%Q_[S?Y5NON&HH-OV<XVQ^SL"<.YK`J>)'R>YINM\W=PS'X?:Z\E![/
-MOYL=YW%4P6'[!B3&-[";FY5:/14I)DJJ^A`$W3?5M/>YVK89%I*,J9++%8[7
-M7,&!*/M<ACOTOLPQNS<.,>?Z=EH"`GH7$[Q[02J8GJ1]+L)G2B):1C:T#BK0
-M34TOI/E<)@BM-$@W1XA;*UBN+SA%AS(6^Q>,,?W4)U+Z+L2S$`W$?]F-4"QK
-MRVY!,@?+Z^7A;&:U?-025].,*NQ5ZU@HI&?1C05DM>#,%ZC<>>9C]3=K#4!!
-M'Y0=%&]K)[S24Q9%KK)D6F%4LYZ#X2KVE^N''=$O>S=(91#VXEM9ECQUU7X4
-MK^?&$M^W,:%;&V$E[96O^`5^@UG12/.'/Y>SO(NE@RZUI!&D)3^;4A5J![=9
-MX'1^$AMTNB-?;(5*(4,PD1L(!K&KF3,MA.2\@_[@#GQL\ENC>@_1R138&`Z'
-M'==(@&?K&Q`A!7J0#IE^A:\,)BONS0CT('>Y@BJL!1O6T%7;'U_V<+;$]R[V
-M&_6I6T'[4EG-YR?-@R[4)/P.L99EXE-M6CRNB54_A?L\)4]Z'..=;^_YXH5W
-MV=C0P`:34M3LSR.6,S&[F-6PB46=)PD2R_*Y+'5<T9WXMR*C_VY0*SGF.`R.
-MJ(+)UY`H(YU:U]4=SQ;&[W![`)O_AF5823/B!#-:+;/?5'3[O',I1=DBI]Q/
-M;FS'%=F]W&(#>@H?$5IZ*QVI%[S*R1];4Z@DBAN_TBK41T.KK@4J=)H\UY#V
-M,$2)3%_6+?)EJ@5M,-RTJ(O[U]!"$!5((LKP_7C;O_9"U0?T0G>\;*=F=W#2
-MFG".-87"3VM)<%>2%9F\;9L2W4L;/AN>TU#30W2?9V52QW+YV6*<E$82NR/^
-MKPK%8*P@J6F1A9?<1LUT!48SC[U6=)4.FL#D)ID:C(O0>6Q"4TRU.W/9]%YP
-M=UW030;';"VAH"P_D'Y0`FIF47UR1A9FN;IT1E#CU-,O0O9[2X"=VEF"=@TR
-MO/RO)UQS"#RW3E]LD&RM8%_Z<$"&6+MX,8J(9KI;;YSZO&+1E[!K%/I?;07G
-M6)^-X<2[+6\MS13DJUVQS*@6/!)/=?6<>XTDIBO;OG_P'43I/ICY^Q7G"K!A
-MOT9WY#C`^*EO/,[19/DR+6'`',9DN5ZWC!;$;AHK8U;0=TYXM"E(VUR>:^#2
-MI;3.(Z#KJUBXJY?;C;2+C:(`Y<G.O7&*VAC&3B>]/X0_?;/YQX$7($DML/49
-MFK[-.9VW?6=!%D]U)'+RZ@_RB&]TSY_GZE5PKEWZUJ8M7FJ0Q[C`@+OONQ1;
-M(S9Y`0&:[7#0%JP1H7C[/]QY=K;'Q58W/;Q/"=%>B/3H,2D\@0"Z9@5A;<4E
-MK&@5()-DC(_^++-%Y#E&%]*WI!Z5;F`K)/T;=I7?W`D#P"VR.V="XAQ!WM,'
-M4:N+:349^1U@8OYJ0`IU9-.PX=JYZ4S15FJ02L1XCDP%Z']O-'GIX1!1!?7^
-M]^.(G7/=FVS@GOPAD9U>O%U(#2HI<K6:C<^\IXG2:_,[(S:.=?:R)B<FQ84Z
-MKO01TY0<MTCJ$S[N\($[T*$,(W8/NJ1J^P.,=>$9FEOE\HA\D?/5ZTSO!]5(
-MPA;N]FV3*FAY0Z1\OI\+_P3RT(5T&6&*)VF<!@Q^+&H4^.*VYF)CF][UP1\:
-M@BB!#_"D?`E_#FT;M[X^1O8>5V'/%"0QPPJJ"U\-=8LEWO53^=N4!NF3NUKJ
-M[0#;QE-=]0X//Q+RD#??<^G]X1C)I)T]>_N_A$Q=U5J+I\"F&<9W-*L]_`Q)
-M'(B3*:?B5U.JPV2)[%?)<,;R2^-0+;`\.J+7!Y-YX\9!*NV8'Q9J*7'9_R6U
-M&2:T@O>J8#;L(8VFX3`WVU#`7`^>U1Z\PVGL*N1AGSK6KAGQF=$/SRV%[JF3
-M4[%NFI)56E26&-6JG1?VUV_1`AV`L'MCZ@]NG.V\7?P<<J-[.$^=PJ.BB#-H
-M&&_\&29ZT7S;F,+ZH"6<(]WL(^>I[I5)>87#&`^?`_!!5\QY9T>.XD3M>&SR
-MPX#[.^L`<)(*CF;%G-Z9)-^X;H/_N7`\5GR0Y7E6!S-L-N+M_E)Y,]GVC/OJ
-MUT/B<<D+GM%8"ST]Z"'LX(N4,(0K]?:_,R+RTYU[0F&`XT%_8S06<GR.IK`2
-M]=W,%GZ&-X!NV=?*G"&"*WJ"L1\>]A])X"H)?I+GF6`U]?1/6Q^Z-<#C[W<T
-M5W!EVU`*M-(SN[FMF;UF1SM/OR>#YN;],NK\^=^[ZY%&+Y)+%+5>W>FN4NR9
-M9<V1J!P#$=[C;<\(,B/?VPR:6)Y[P*C`)_U25(E2JR?)Y8]@Q$6"X$0AJ;U2
-M!EFL[X;4\TY^B1F2SW%<2L3F@5*F\?&-((9*0(];9$09?>=MG,5OAW0"YK?E
-M/W^3T%LN36+<YUC/SLB,YNKVI)>..5I:3Z*!Y0&T5?U&%<RY/X'Q'*<T`\#]
-M:-M"];!R^](?+F.ZK(V>*:$Q=@X>X7\,BL:9FMAZW$`*<0NH'ZJV?JU-T$6[
-MQ)>$N%)=:V6;9TDFRV:X&BZHHC2.?C&BZS@::&-<_^AXX_1)=Z!B.+N#R4/P
-MUEBK7%7YO2D)K(G+$U2J<!XSKI=8>/*V8<@+7CN2N="C*$H^<$VU_$WN^CN`
-M,%02KL,@#E2IBC&S,K.JX[;O.4]U>1Y(:++2F+73F&)1H)B]6]\BW(5-Y]`*
-M5:XOXM4&G^^&&,:4/3OMQ&(=/-RF]BJ\<T5W_\BP%;)WN:G+<:'I:RO24,EW
-MT$]PYSI\/"6+55[NDE@^"V\WB4=$@,IU*,W9PHBYT=#MI;*9WM8U6%\"%EK&
-MTNPYS)?MD+%BN$:$#)3%\`KG3KXS8'2MY_I7M.O?'XNX7V.><4L!(W&O"%<)
-M,-=H/I>5PA50PH)C(#4$&'0:8XQRH8G]9\WV]A#NO=EVA41V(3V[`G)U?Y/9
-MLE8"ES5Y+^/;$,K"YK#HPA2PDHA%)+7^%*,610#-QT/W`4_JA"/F."Z?>1OA
-M^NTC(H+H3PAY^;"O?,!\#Q6QBZVYI9MS3F3'FWQG5+QI+5RABJ':2NO&'C%@
-M^V8Y&"3H3IZPS(W%-""N-C8UNTJ2E7`XR?*>ZPC$G![S_Z<H=%0QY/P&.8TA
-MM6R#!C_D&<]\TLC8M9^*X`J%GCK)Z]&,LEKU24CW%:BY@AWSJX)E3LHT*2&O
-M,:3+%>%C[,%>[&<Z2O%2K$G.BGM[$L0_A@QF51RP%.^1&9#Y+2S<3;-I/)\G
-M/%_QXAF4@Q3$1YFT3[O;L<M0Y7WG9YP%$2V2_$3I?VINTG)4-2\<'7HZ9&G<
-M,'ULRD[&C_%PX7"34GIG[W^V%Y9RV-'=$/@*M0<+*>K),L*"IY*N58.:[_U2
-MJP8NG2LCEA=X3_9/K"^:^_`3,?1<KP-^GP*HB@1OLQ@])6WHLSM1$8:EG3O4
-M^JHSRK`8>4">[8#.QW\@NH1`F!D/(*.(JRQ\PV;VM1:6L;=?X2C[\2PA3C7=
-ML"?H+HK\2"P,;'3E?S6;W.'[H#YNE)<;,V1M<]2BD+UQ"<M*Q%Q#!J`[9-[!
-M/W?A?SN%UQ'8YA4@J`R;[<ZV\)!%LST;4,5.Z8*7>\/+5N(#SS$@C=U"_L=B
-M8F.&XEBQ[YJZ?&F%8\=?XIB57+FUIR:V.:]%;D%)5::]'*J?)84"O`BB_TH1
-MM9AW!OJK!%G\ME9';NT1J<YA"=[GK,6/S]EEL"W8"[6VNX]]:8[+;Z25$JAM
-M;LMUD)P"4MN&"X%#^!D?41*H#B:'<?WV*V-/)C<R1#A9S:7N"6.@CI*S4@&5
-M-571'-=R!.J-`K+NI"L'P2"X]5TX(2-@I7:V7=BTXE,N0N3Z4)_NQ5GQU&K_
-M%+_IIE"[.^#*AAV#[/[&#PO)M5NQ"P9YB7X_XQWAZJ=XW1U`9A`$\B=M.0[)
-MFY)Y>!(#&GIMNX1=]1\YJUQ333'M>"N)9=>%3CPBKJ_B0NFM6XD,GU@=\22)
-MOHU$`^,=6"$A';1A'#\D[.?9\7RD'LA`VJ%'H.'^2-<"22J``']V=2/-]#6X
-M)LR1*O^<P(3YHP*#IOTXU+:1+J3%]C-)WX]6I3+OM@6R6Z]_Y7_%G\`L;=)&
-MF0=3.,1=`0Z?SL5L&T]#<F]`C]FH3T;)1EPQ'6]=:]P$2P$IOU)[+1SL)X=L
-M?"M(F/=TLM,.6ZU?K_N\>267#SR1J(B5R^9Y8=SASFEE;^<F'KMH.Z([2\H!
-M"WX!P`K&!79[L]2IT71CF,ZT*AW<:$Q78=]AJ^\NK8FBW>\KP^45[RN03!!M
-M3Y)/8RBOK#='/<3I<'!/:;3/OD;^Z@UJS:!K<L(G>Y(`<+B7;3^3T\-:^!]8
-M5U'LQ+.]/UGW"S8=(9,F@)?\P+.B+E%>\7G:H'UWGZ'(JHP7,M$EZLH5L#D"
-MCDA/M56\4PREU:)VG;<>'J6`CNSHP>`,(EGN1_4:FX@,4(XE+N\R^/$=")6M
-MJY<"&/DF,(5Q3BZO4(.3G_K?R,-I9^5'R\JJ*7SC]+>?-0&B/K!(7^@S[S:D
-M'\MQ+*@6,>00<I:5M_R5!$X>,(Y5P;Z""F5`3P#.)O/JTS.J-^H9/EF&Z'YP
-M$SPIC*Y='$1DD7C;\K50P!L7)#O7DWH[/K]#6<*<(M!2=GLHP!(\56W[[4RL
-M07O2RQUS'*^U8*7,\T+F.3GFV1]6.VU?)-N%VBK.]C9([93)-ZT`WMXV;WX=
-M[))]+S#['ZY164%7/QMYI4=*!RZTUOR'PVT;Q9..FX7&?'71Z%L>H"M157&F
-M++N)3R%8.E8)K`XM(L(:?MQK1H@!`$OK\>O#/Y&!^"6/0IN2O5^8;_GCDD6U
-MOA,H"A5-.I0=2[2"?,<0?4_F[@7[LQ8J6A3U@DYXR>;.OETGH50Z@4Y=()(B
-MB:?[;!8X2LC4O.ZF[VO5V<B41%&(K[9!`U>B[.!5\V8?*9K=B5_0@*$&RN,*
-MW=F4T7=0)/;4+L=[L$SCHQKK^DE0J&<IOF5VM"<$<'QJFUA<5?V6A)T$Y,A_
-MA/T`ZRT<1']K>`63MN<*1'L8Q*2B3#""!DF:9R7:(,K2FK3:+\TPXXP\(?WH
-M=B5O554O`UD)26'W+`A<Y%9LSTDVN!NL>K(7BMG>6^.]WKX;!?-8*&1YT@Q5
-MW[<U[9KZF[22'A;UVF^=6DR)G>#LT=;%$GN0NH`:AG]L=*JQ-3D]IRHZ]U.;
-MQ@F0'+M4(UIRO!3JMU:SY,P/OH.0SWP*>>;;]M2U[9;4+A""[0;"'H9;P66J
-M<X2?LG3`8T>:'?"1J6T`%K_2?XV,LWS^LTS6212(U6LGZ`9`<4I:8QW(4@]H
-M2(?R/2/H7B46?I.L04V\=0=GU&T.F4C2+^M_+P6&?-+Y?X=(P8!J;ISZR\]_
-M8]2?"BB;MBWMN?^-O+8J!TZ]R@=1JC_0-L-E18IA3?,[VT69<%VWX.N0<O@G
-M/=CDWGWK-98^*2.`K!HKK1#>RC5#\N.:`0NZ1E$SRGT^4S&#W90:R$WWB\#6
-M`$XCSVN8NOC;\T=A4_Z]Y(HP#@/&*%2(.S2*[+PN(`(MTG<A-^`2QHV18O.8
-MN//4DQ/C@=0?'Z&($VD$[3;_<__><"9,4E>"XKF3]$E6X@T(\,%->]GG$1>#
-MC==G"7N-46<#I,XU6K<^2.\30A-5*U0)OZ2UCS3UHK1:*BH5&U_O&O4<3<F8
-M"+9V2;\:2X?.D:;QX,$`6U5'W?RYR6P2G'5FT-Q-LIJ&;Q=YUG<@"'<\VK\N
-M;F%Q(ZJ7-%EF:(YYDA&JW*;/:UN.:G;80KB>,X;A>.57+.,BP<B/_CO_<D`!
-M5K]9"A6I%2KXW391:;36H@;;WU?S=8#]/MG0VF!0E&O+?KI3KTZ(18,.?VW=
-M+,3241;,<Y7:I<(-R!UV@(OAESTI8'YSAF8DB2VR?V)Q*,<N#^AY4/G`CKJB
-M@B%.A\M35%-_8EL:")U^H.CXGQ3UH2**UY'U8X@TU/.BY/0P)''CU$D=T=/Q
-M^R:1Q9?+$W53OL)..9Z%H"6R#&I]*F\]ECJ"NE8^VS?,GW0>^//=*1T-M-K:
-M&)FU2ZC\*=%JSVY8EPB^*"49%!EG_+H$%!`UL`]@WT;-4TR]3;3O'CK0'A+X
-M$Z)X<*RZ[EQ+6$R"2.GXR0R8DUI5<QVF,V3+2+?9=.QA`_\VI!#2W&X_\]GC
-MQ09.AD&N>O"\CS^_G&P6^NR+YII6Z_!QYR_CIF8[Q8>`$6*6R8!,AR9B$&&*
-MQLR:H_?SI39Y]A@VLN6H(I$H1F[WH;4MUT\9S.[\9"_LEV7(SA7#8T84:F#]
-M1+FR3Q\&B9XGY>[/P7*S^,.,C!&V`02(H5VUEAOE6-3I1_CMI<[$&'5Q\%XH
-M/"6()*4L?.@(VQ`/9=GSVT]]P%1YD+?=84"-Z$9<INKP:.[HM#;<'4?J;`;-
-M3!E%-,0555)5]*H1U`*?K2W`185Y<4CMXAW-^#,M].K"H?%?$T>5"#=\)"[7
-M[L>9OSM#K.J/&Q-'[8WV_?E<^HX&^X-[RVHVE,:F=$V_'@(JRYLS[S##%DO9
-M0>M,%GMC/@"ZO]SZ`FV#'MI64ITLD73(;EXX'D4ZU@LN;**FXLF0L`832#8H
-MF[MQ;AN?$7K/7.,=MS1F<<G39`X3F$!`MJ_B'N1C57_;U9?G3F_,/@`#1E/"
-MR[\D>1PT:`R\'XQ(/ZOLKC'#%,8L$>.V1Q[AXOC3IS:72)'$_=2'\@,T$P7Z
-MJ+&#,>2=71]WC$+SQ[1QM:`EQQ"OBXJU)T<%J\V[6YX6YQU@WN67+?Z:UMF:
-M.,+]"GRAI_)R*-9SIPOF?-3E;8O)BMM:]ENG-0=_BFJYI.T&D$?$ST_^C%L"
-M@..TVDQ'RFV#24M0LJU:,/)D<6P7+)06[8H]&KJO#7@?`SIA4\Z!+N>*_?P`
-M</7+8^;@/5O=^P,.^\V,O"CDG:`HL_%@?(Z7&1%L>Y/!=&HJKJIAW!&(Q*]>
-MLH3S2>*IF$G^4,W_I5\<;XV1L3>'3/-6JS$_9Q_*'M!\,*A1!'>HZ&`*IR2@
-M0@H!:I(%"SS3KO`N1D9\)Q8SLJ*;(H(86B)M+!U>8M%%0F:*H+ZCDQ=RQM(9
-MK<,;A$S7_<H_?\\$)[6=5SN=8HW$9SG?JC#X2`_>0)RG+*Q3,T>!=H?M'_C`
-MW$>N1.CPT[[A[TH/N8L/`+18TO/2N^^4+Y.PKI"SK.#-D_W198URJ_+'Z8\&
-MPSP*:;7]EJ)K%9*\``.Q;Y0Z@EE]\E":^>!@CV2X-OS(<51T'*[#6,M1#F=Y
-M5A;+GA8P=0PV[?^O+N-83?P3WRNO?O(`:\C_F_OX-%:6'*F=0B:,NT8+`3?R
-M:B.)VX<X;"NW>5@R>[3K,FC'8Y]A@6@E]P1?)KC-%Z;3PJ*^@"DYZH3?5%QA
-M:["TZ1\3RM08*=IQ#D_^7'"P_$V=L!IE!;+\`!V__LEE>E>J3"9M$D):Q%6R
-M:-.,(S.,YD:+N]48XPH",7#0L)>ZBU=F4R)K^-WWH,<$&:D_,D!<K0"<;1RR
-M/[PB\J0;[6LLI=L28OM1T\9>:1?H_.8LOC>STI9^&$01AT-X4M8`W$Q6:KWE
-M`A`[$[4-R)2'6S<C1O0^%FVD\(2C=]/!KX]"N++(>?H`_`DUEO@2`$,W/OCE
-MYU/IZOR&\/PU82@):QBUD11A_G4$U&*2]4/M8_#*+?-0FY">]NAQA.3ZX6ID
-M_61H!>-FF/T@>?LL>B46G.C\%9K3DCL@XLVG4BP:M1_9_/CSL=`A1)R15(09
-M"-8302RRN/VB\.<S<X_KMZDO3#K"=DMA/6[<=S[):K@O%C/-X-(TG\;WN%O\
-MPA*:!IMO[J`I[/T$@PUN7'''H%IG]=J*N>\<^1N*IT8R-4@:BOJ*==`+*)F=
-M.)Z@+3_R5)1_DA>/A[6:47[U8*\K=O>!JM4SH.^"X-JYY2H1"6FBBV2""M,U
-M0XPKQ;UJ;Z[HTTIRRYG"US/=E*RI'ECK.Y7*)'-*R1C_10;WAID8@+3R.5B`
-M8+L#8AQ[8F.!>-\O$7J^V!T(+F6?_0=FAB?%]1^=DP[[Z^,H)10E8)3&:@5I
-MH*1\F\V^X$[S4'X033_.._PD!ZN'F`+^44/4$6VN1D2G!!\X0TGG1@]*GF:M
-M&T*F1[K\N=-9$[030!L/MO(T<(X1DPN\1T07AY>%R()KV'[,#FT6&$I1R7D<
-MJ9ST]W<CU&6_?'S%X*%NP2YIY?MC`-C#4.0/C\3LH[]3.G4S;(Z13*,%J;]4
-MX_U!A444CQ1Y;)NI0$=W`(/\7Z2P,+%-ILU.O,UV?(^C['L=4;@E'465`S:M
-M]TX[7'^TW8/\BP4PX*P"E;J!F@0&>D]H!!%F+'I&*O@U8,F*6U?+>AT67=Z]
-M'VT50EX._#LXE'7UFO1J-*B%.?&X;4=B\WB_&B?^`GR=C:<#*0<0I%(,]G=&
-MM4YR;FJ6@?.?:Y(?)6JC6R*\5UO-L_I6=I!]6%S;R:X-"^5.=:P6<03ND1V>
-MND$O'^IC(-_`!5@6_8U;[K5!8;<),K"38U3ZV3CLOI=S8H\_=?'-20QY_`%Q
-M:B68X^I&WUC5=&B8,#&VQ-LUZ>I61UUI:J_G*_\F_VR3U4%3LW$C(@9T"Q1%
-MT:O[)=J]N_'ZJ7%TWY?MJ!BP_U#89A#*#`(:$^I\C8]V%:[Y!_YG;/5R?`EW
-M[?]'".`KIVNL>WZE^R3P]C$^-MZ''^0%=VY_%SS]PH.8/M(%>4+]&?_?6+S:
-M[?B!6Z$,VQK<L+=IO<,=(U5.:87N)'WF)<$UN\=62TN!"04+)*+SOOVK3N$\
-M/E+(T;8#X1=K5OHB]@D322NZ0A%%GCR-PKF1Q/3C1Q-3=@[8BIY"Y3)&L.K$
-M0RL"OO>;_J2/H3.'LGL>I53ZG`155Q+'I"HT,FS)K*&M5K$R=R4M!V#OB/A;
-M90P1A6LG4'\+D719!H)"DP"='IQGP0F*UYH8R5#`.M7_1P/%BVS5V]>U,:]&
-MAW485;G<6-T9U1W7BV8+C^D7L#5U\3"3=1EWM6IB`'7KH&;X;;M`SJ:YW1V8
-M$,$][US]E`U[*405?'<)GQ\."LG3H-;:Z0(>[;4*%;6_>!4_!O_*)_(3$L`;
-MO0[P.]3PU=_3_]]3#]E4(M8816X-YTLXMXL0%*^]N+,/.:#$L>:DXU>JHZ6)
-MFS[T''%^L9%CL3?P"[SEY,62D'QOG"0+-:".>"6<YG>'#XWGY"8)D9_A$#DR
-M2T<'`O5I9+,LN^=#/?`-SF74RLF\LI[2./11BGVH%=$M$(KY2NI#H++9\K'=
-MF'GPQHP7NXTR+Z8TO!GD#Z'ECU[B+Q]"F;(Z0KBNM"35W(*!Y[_32J.A.:'>
-M6$5SN$8C>L\`?THWA;?'YXP%@I50:_<L"A"@DP7R&U'<N-TZ78*$%C@`[?7!
-M$>_J>I^B*IFA@GNY@V==8?K!11-`Z!&QO'Y".X;IR"Q'H1LN%1V)K&6)GID-
-MI*]W'94S<'@FHO!U61J-(IMU(/$P/+B>]^K"RJESN^GAMC@;<:W^Z';(B?2Z
-M-)XI+$!,[((MJ?&X:YFFPV;JG#=8$Y5KQH)HX/W8J1+;"E#KF9R>?:_^FD0?
-M9MYLXS8;3BQ8!)[H'._:E#;VF#YJ0&;U_HD=N)E6`>6?A:L>!;;B]>&>'%J!
-M`J^*;V>><0CQ+U9%(H!1=*W;L7+E_'=/*H1!$-I'7<T[.]:UQMB!;NP/'Z0;
-M6D#;?9>9Q!(8CT/;SM:QN(P?0DX#&0):MD.V_`7>G%$:K,^`@I(*G>70]+;T
-MS#G(N%[?&28QA8*DQ]Q>M`ZV=T)W$Y2@FZF!M5]']F,X"4.Y/>"::XS\8#WT
-M*`-=+R$J(&R7"NF:+AF>3=?ID41-+(2A3Y8AZZOD]&)+6"^7-V%I/>!CP"R-
-M$9,-1<:G-\]JBIZ&5^MZ&@17!?.>5A4%K>I>"\/N+^RE:M3'#P9?!3#<?D<<
-M`[\\Q=HA1'+IQ+\";P&XLDP)92"&M"'8.K2'4!"1=.,K">G]N8/,,!;J%CDJ
-M#C^N3K],")70:N`-86TK]D,\6C";1+=,9*<65*R-'?$,OHSZ!@?IC_W,9]+.
-MN]XC7]&,+EB"T'*#2(F=E<L^*<J&'--OXJ%+CP/RV('O)_K#`SZBI&R;1"(6
-MHFZ;DD!6-U$*/KU\H0LQ4'O:NJ[B1ESCL$)53^6<7_Z*FFER]"E)I44&:[V3
-M5.7G+IW!!BVF=:T<NA<2=&.Z)\1[99\S/XH+\6.V2`NNR[J#T\*<`[T:#]K3
-MR=E-)*,MG=,&A#F$9P^8T[]G(NA0B6\L\0#WR37T07S)W5&V(YLFDW*E5U4M
-MFU_=\`R9TB:-`Y_/T&H]"4OL$:2\G#G/-LGC]8'(74&<(#PR5TP2AQK87UD,
-M]WV#%,%:TS'5`)H>>-K.ES&LS9_O@Q)T,L3,'N8Q#)#!-#=GRR1/L,A70VMZ
-MI0E`KI;:3`.GVGD$9-L(RZOQ?]@([KT&M`?!U[E![B^)S/@\X=/'Z-&46_%^
-M$E[[-*!LBZI:5.6%8X?%/[.L/!8O<2>/AC%O4U4J5K+';H*`(W+79#LM,8?_
-M9Y4!35H=X?DUR3&/6LT?!"1-HCNV]D(L6*U0GVUKK"D4J//73](J2XQ6;1!I
-M]G\G`$2N.C2@/ZE]<'ML$6D$Z!QNV#31&QUM"O"+H!;<_1*C*M;M),\@J6@>
-M5*`\SZ^B(4Z!!>I&AZB%FAA%W&J`"85[&$C4A4BKT:T\PC&AOV!%]>Q'2^?J
-M;$#"L2OZ^$'C14@4,QQ,D,=@<@E#/*U2@^(5>W;1(&A<^;BGAO+O.3-BR]21
-M3@GDK+96PFG=3)SO.1SM.2[YY-0>`<:XBP9&>_Y\::N'^>!(F%:M%D9!(M3B
-MY@LK!AH0'3E<`=%BG,BZC2,=U/']YT;EY%DB#5@M3N<?N^V)D=''HX1[2ZQA
-MQ(.'^TNL#)4M)^$]9:X]:[N5!+5D"]O[A.MZ.GYD#2VI:C/J^8^9+9'^#O+$
-M`KLYK<D\@34;PV=Y;L2&B(UU->?-*_\`!^.[6T6<.*6&V452@2@F6&N(\]Q@
-MT;[^C@U)!&;-_;'779\QU(,,P'-;E7:2D<D>^3NX@[J$)A/I[XMC'0E"4K?"
-M7A`]D2R\/4B2IQJUSV\K!KB*K=83&)*-AQNI+AMQ_3"24_MDW&ID7[:2:5\<
-ME2M.]^AX/!9+H"XVE*EEC'\<GC0_%42ARXV$72^YUGA?+^HX[FXL+8*#@KJJ
-ME;60&A*R;4JJKR>#.P/?<X1T?7P>$(0X;I<6D9(G__$)NK--6!P3>JLP\!2/
-MC>Z'^E]D]V;]L+04,FWUVLEB*DH,46:B;"-B*Q]<CV'K%;CWT-L_WMNSH;/=
-M"9!B8;)11,.IP'*$/WG`_Z>V1"(7(MS"OP5&:L(K":?*JCOZ`A)"N)!2W3G(
-M,SO:6W;Q?+@<BOG#;%3;4>G=\YU]75;/GSCQ7C@I<BIV^49V@MOI'@);084U
-M!+;%V`-8M_N#+%/WW(YB<LB@SAHJ(_*2IL,SB6`,M9T\M4FXT$_OZ^6F?9&"
-MG<(&9&F`O@W#CB+<6FE@8D2FK@*P<`41(NU>]&^IG'@F*/HI`T#,'&U.XD5:
-MR$\KNHXU;'D?K1ZN@D]QO^J,M]M'ZC2<'?58C/[SZ]G,8?%:I]-_93][N!NE
-M1O<Z$G3N6;"2P)59XU*%[1J%;_>]@>2^C]9,TX(52]6M6+\B=JO+N.(\R<%@
-MO#I49FN/>NY[I8B<HYI,)6"@I%F'\XL>6%%SNB`R[4!NWT1I/D3C0HG=2Y.$
-M#FOPQI76=/,*Z`)*OHE,NXIMS7_<K?:T]OE"X[[+/*?TV+?\^,1XT/NKT;&M
-M7=0#YA;`$?[[!%M`0^5NIGAS;'TS;)+,5TFCYM%7%,P>YL2)SS3HB+FL5/S3
-MVD#+X_I&O7U%^6!GT[C(9&=UO*>DX6(GD9BZ=HAN<9H0^BUKXF"R0^,IO`)M
-M,,T!1%GD<!%_BQM>_+\?9HV7D:]'#_3XSI3Q6^T@*==?<9(A6N`4VC:$_)X"
-M3XO6M4S`MWUM%ZK5.'"(W!BT-6?2ZSGY%C[V,@\6L4UN+O\-ABF;YPP\H8@S
-MKV7`>:RIQIJPYJ^]\+(0_FD/B:BV&@DC68&0-K]*J&C$\JX<&EUK!ZWG@]NN
-MW#]Q+_<4Z0^JLM]$+(U.NN.[@J\BRL0-B80Z5?H(D3HML4>QW^$F)/,$NJ3:
-MFLY2YE4`J:%$D"'>^:BUWP3_HBE$/ZU")$00:=L$33J"A:?\B81*";L@7=6H
-M:\0QB7#^NEGT'%/%NIL#!:^XP3_L@:AKL62T*X9\5Z)=>"]9?IGS"!T?VFIV
-MI'+]^KYA`/2I%`Y![4%.5GW%@:Y=:!(AH4>C/3F+!,W@=,45J^QMP`^3S^T,
-M;(SMODVKP&%R+NH[M-W#XUPB*694U\!SQ1T5H/B?1:_&^,3ED%-^UTZY<=&E
-M%!][/*?&\YH@[S),F/%2NN@CII!_0KS^)7$B<J3_>JT<[N\?EK<0CU^XL$<8
-M&K``$NA033ST(P5M]!78P`=Q>\GS<E8<1N,D0`HND]KPMQTN_H5FWT;2:OW$
-M\^D1Q4Z4"QW+(RQRI?8+8AD.@99H(HKDQ0LBPL).2X+]4WU3Y`?O<SMO4FG4
-M;_S5%`EUU51&$01K>A3"T]9H&]K(0?R)21YS+K0PS/0=/]588@\.]$;:<#AU
-M@.?FPZD]ZR^0<@9#,)N(\ZS^=9:6)\-)3+KK21U]0F03I4)U-H\)'5\;VO[7
-M%#6A9!8^Y8`3F);'1U58H.4TUL3HNW0(5">D_W1N8>I62O.^BM%E^O>,U,'<
-M\$',CS-U,(+B2IC2"CF:GU7=QO)7%,3PTXU0FE?96/JLD69/U%@B!]])!HA=
-MH0,!UW$B,E6<OGC!PZ#.CMEU\Y@EC&(18WL!V'2\<?ZIXN"C/'[]8T'RQG7Q
-M06M3AI5TV[0PP69EHG<!Q'+8!:STD2[!E#?>:'=8CT`_X6]-?5EX]9-9361V
-MM>;A*U"3,4LFH60HKKT^D4Q8S66A*@\O+5&1=>/G'[Z\X53>@LK;PQS<N'>#
-M4QWPBA/WXI\J4'=_+>SXJ65/'RCE/$T,<=5.*%W=0U2>N.J[I7H3'GBSB[W:
-M`>J78=F_G`F<R2?<S"E&YT+3BGMIRM9'TJ2TT)1^WN326#?G\L.VF3Z?@LV$
-MW5C^*ZT+$*SLO`(B9CR::%^F1(8#?:IE2.2-SAT%0YLFNC;G,[01FG9]CD+E
-M9H<6AY&KP_0QX8LT>E0XT@$2U%2;U$,CZ,HISPEJU"CS(C5P/,]/Z.40Q6)-
-M1//@%(JS+P1Q,43$[5^8A]O$:2UR]8IHI]CK$KV?61_9"C^F0>S[G='Z5XAE
-M\*AQ7L$4CM/J=E'CHKT>BHGY\EM%4</"/Y)OB4)'BC_JG%LK+P.\Q*E`-Z`3
-M7=SZ\%`O3YH6=74'"1XLD6SQ#>LH=1@H2O"GSR/BZ)=*WE[S%[N*/A,^/[_0
-M24J)*RP6^B1F.FG=I\%+;$QBC<K:*8NR4(3&[O?G;OWM1L->QU!48$P/)-)+
-M\^,Z><^F]6#%=9]T?,QE"9\.^"/4E%K5U=;]M,/APJ!:F<P*S_C1*@]^_ZR?
-MXY>3@G7Y<S7Q(I\H>^B&$L_#\RFLH]^21"S#<>]WY%/5%M!(;ATDDKQS;ROA
-MR9IB"4WWF)BD\8FJ$6ZG&.W\KE'6[ZR/[HR6%MV&-3]''[0B4GUF%R>5?;A@
-M+OWT"8WKH"OU@QDDBHB^?HN7W<Z.P/>Q=8FZ/NO[Y<'*VTE?,ZC&J6F6Z^&>
-MZ$F$@5#\$/;48*/U1>8$YW<:"35D<8L';4HUMH`[E'+)J;=_FAAR=('B`,F`
-MOXK03CC\65^WV1M&2>J&X)CCZBI/QH_-K#MU=/XS0JGU9T4F`Z&WP]X/=\L6
-MGAQ:C62G"-)<*KUNDEO^]F^)FN&//I<R.3\9WS;;8&6WU(92_L1L,2_D6T^)
-ML/C>8QE5"&B1Z9\&?JPUOR50?G%EWR4%JCFEK?^F+_E`Z$7:7>WF7<X>+2CW
-MC!,6!6["I@!GSL1.]3GSGO%C'%7MCU5&?292;?3G>LOVD$+&3+TWC!.&\,W.
-M4D2XWV=4"K""*J)Z!/$<DZ8(2RV5!L.Q!0,@`W,;%&G9GI9W96?T#SK6Z5!%
-MYR&$3WX:$YEX5)J#W*+\JI;*X#O2LL#N/*W4,/2!`$R]W[GC2T$?I(].17^0
-MFZYP7OK](T+A9TE%)M<K>M)KI]@:.4TZ.&*53=.:[NB/^I69F.*3*O$UP8>>
-MI;<6(U#M1=_/Y=\\3:B5U49@F<<G%6654E_TM<,EUVIHQ_/-8UX`Z(R_*PJN
-MM1-@OSXXMAT[.ZG%:7??N/+67YOW0HK<*0CQS^RV3N%Y"5P"DFP!^A^A($Q4
-M=+:,[X9C.4ZD1%JK?K]#<<133@?87ASJ)8/737^9;J4(F-+^CT<*5Q-$L@)&
-M&&N'7R3GC4KA3>Y&E+FRX=1![GVS*H7;KI6N`[WW,4X.ZT^FSR?TH8XLOWSV
-M"K$3WV)4)1YM+2U"*?CQ#WS'&K*2F33D``_)#`$FP.XYV\F14<E?#T#RU:XX
-M/[APYS6!34N%"+?_.<%=7LS?P=Q6O_?Q.^/5T`:&,$FZ+_J((D.W9*4F3N)Q
-MK<L'M#9FQXM@M8[5#3J)9"_H7-A%\W4/K/+LI:B[8CKW96=&3A.X;D;4\:W;
-M9=R7%1NE<EKK6/O*(?Z/OMD#)9Q(XJC4N,)OD;^P342A<>;*<M\&UU>$KK\)
-MKK51[A5V/F>)P;/G+P?,(3+(M#SWXK7Z";9H5**@Z2)7><I'F1E?Y>Q8B1!R
-MA^@2A)*/Y"CWI3Z3KSE^!NN2=V-Y_B[:/N/I*$T^YWKJNVB,+'-/`1:59"<I
-M^!CFUKB&OL]UE5"XR+=8W'A898=$&9CW-OH?3.RSSJHF=WN+<BU/YV[04`(2
-M`ST!%M(@L'0:KQ].CN^>9Z$=I7`IMUT2[I?M#\>2A8%EE2K1VKD/`E^.[:AZ
-M!R/[HJ+`ISZE1A"`HM@U+Q&V8'P4L9!!RF+%M_+9@?+K(NU9\K=:9F4"T<D<
-MKS;?+@>(J>M\LT-IWH7_`7M$JO+RRB:^RHD*V42O8ZGRBGJ+C3T"2W&_?`T7
-M/HDMHJ8)9.]LB=$!G<K(JW0B:<%^.QX_T8/6I\&PN%N:N\XZO>EH#4()[AQO
-M+C#CKP;FL;VD''(NU$KX4'.0'"G_RQB``[E@CGA,<PAC;M#<SDB(GGDW4'35
-M[D0=OU%KD'<7D6&;'OS@2GH,8K392(1LQ%V!K,ZZ!;O4-]RR:"]%E="^6I3V
-M$ILF4HJ5/$O'5BS:45@7-:*%%A"LC020\Y6&<>++<*-S;V;#:4R=I+,!-YD%
-M8%@.U%+VG?YG!M8BV1H>Q@E@R'!JT<67U[S1<TH%SH4*8+`0+CV_!6<$0I"H
-M)-JU]5%\&[NS77<AT##M#/)'%9*1NN.]&_8S87!J7KH)V)['YC>J^)Y40T-3
-MUG^9,7G^-?USVF53)`/QWIJ*(%HKG?9K]8*]9DAHJ#.,GN6R/[5Z'\VP`KYP
-MO`2@1F6S'WI+.IP[CF%2>8`@O#X<`6](CGE&-WBD$&!O&?3/2>HR27Q[(%<4
-MM=$Q\L>=&`&L)Y?DU`/)*&[`PBG_?Y3@YG8KF<G!#$0J"KV>],2U2(<RO>="
-M7G"&?7JT;TFMN)%H,!?+ET.OY%D%2"BUAJHN[/D*V"USN!PQN1JH;/>\%(Q3
-M.CB&7H_L5#ZD_(/@FKP<@Q43XZEZPS4=H`U%@9/9HB"8&LA0:8KE]?`$4E2<
-MO&KS]OJ$^V1.5U5^:1SDI`_-OSTZY?>ZJQA!#'52*\-.^SI?OUZ,Z:O1MT]:
-M@T2*VL(7&:CD?R6V28)_^B%(&I^?!5WWOHZ^Z&0D4OK6:/ZT.#<0BA6V=%B$
-M`QB&R4T_T_?E8XWD^7]5RO&RP>98EXCNL&.<^N]YH3XUUZ'KA4M:[4F'O!GM
-MTBZ1O/0@AXDPF\;SZ\K`G[(JF;8D&1S4V3R2?\O)4".R/JFXV-0SP;]JCI6+
-MM'8X\6O]:1V0KW;<B!<3+8K)4[5-4(N&(9)2)?VZ@FX\$&?B#/Q$LNB2MQ<7
-M2ZS-(T4K">;_BQPRMQ3IV2RP`B7MFS76'=2]#VKN`.S=+X>.E9][EP?RG@TB
-M*<.DYIXA@.=^IR?RH^_D#'UZRF+(;G(HPYGJ=1N+-\J9VE3UD?A2((";4VON
-M;??QR(3P<4;WITO^DA\3'Q>1"]8)MD(V4],ANDOW_,VK`$<G$?MZ<?*%8,*X
-M[UKR,00R]5<]2X?XMPD196-G%\<AE\+F9EQ^H0)V28K]ZLX"!"5E(=08YD1^
-M,?<.,,23!F:.?+H9#4E3^:UFK^D8O'A<"CW\Y"]9$O7$$;*U][W2"`>$MCY@
-M,JKU85+PAX/Y^E:XE&0$"*4"D_A28GXJW8HB(5VEHUS7*2\_K?J@X5N)=/]N
-MH8AXN!+EW!(&6?$)ZWKW>[>HD*H^CEJI[_?>AS>^1<6/>P%BHWHHWF'LQX9#
-MJH?P<3L4*@QWMIB.]<25^M6LKKAJSMEC[#WMX_9PA9.L3ALT>D;ST(9;0[YS
-M"O9DFEFU73OB+=^,Q%CC7(8X<"4W_?5Y;,S0@0IH6)W\?UQG*+[EL;^-8I\<
-M0Y<NV.50#(,TIH8,7L4\W`5#.Y\QL$Z*YP?'1Y1(3*@F,*_RC0[-E82F&G-2
-MG,R!2*.VMKXY.D2KO%:Y=*&%ZOL/1NM<B0$JC5'=MF`]O9>(\V-`75V4TA$$
-MXP\";2;D99CI'@XO2?=3`3T`61'2<3*`</?;K`P'CH9>A6&L.OE?6T3[*N!,
-M?GQ'7Y+GCY86WG:2C24(&-%D]]8NG%IV.+!]#(2/E>UJ?X75QU0>'V.R'2/K
-MF@XP5DNP5E!3@BTLSA&<B62#XD*D7.A^W%LY)-<Q@_5S,ZEVWJCKVWS#T.S"
-M0G*OVS.WM""_943:9AV+P_$+A&IT>0H*OU*DXXT/ZZVK7[7=F7O8Q6-/%IRY
-MW*0Z]'"WG@``S0F^329`![>X/U.\)&1GIJBP^U)IRV;S.O<,?,/,I9IMTR?I
-M)5,_:WC.%4$[QMM&-N*^:W1^7*U<BFV8\1R-HGW!3NQJ.[_O?ZQF)%U].3ZC
-MEY8O<YL!:K<SM0(DJD](BP&#V?CD$]GM]N^W-Q>W&'A=<>6S4ZM'K^[SP9<K
-MJ:^BY)?`E(.N??[KF=5J\^YZ2-4=@>7'DZ24>\/!2&S-"BNZ*K?M5D]GA[M3
-MW[M^M'ZT,VW4UCSC?#F>Q\F2OS[#B5+]?8;0>EYTD+5%#->ZN\DIZ]:A@H59
-M01I5;")$NPAA)X>@5Y]2%-A9H,?+OS/AI9QA=3[73]L&/IJU8?5D((BHLD[X
-M4>0$$E@K14YAAH:GM;AR>_LB7&**'Y?E"4W(M#E1O;%A)_'NY^@4/#RH+?[_
-M.ATT8WG+=O`Y^7O),BYTOMD,0#''L=%9O2[CNUG)>$!O.?^%O%:BM93IJL[,
-M)P@)#A82J<+=#&3TY313J&2L.7$\82AI]$^K/VU-%G4KX]AQSS,69=3]&NO>
-MR9FWA!M\<E-P*._RVS8.I"NPD)/@0]>M&G?-_:>PVO@(V=-%;EQ*)Y<@9$P"
-MM\<0G_@,D5+;;!`=HQEQ67K+(6*$NC!$:4&.#<`9=>_:(^ES[#BMS*A7Q^*?
-M`3H*8$J>IP\KOUQ!>M[U`"#$0@M/4E`-WO]\A$667TJ"C-VQ9_H0@5+/";9]
-M!@,+!J8C@*](L4`TZ63[EQH\DG<IG18U&Z/T'[(>RDCPG4OSW%,1)%\1>ZW`
-MJ?*?=H[]42+R9=E4!9Q\0QHK;#F[![^3Q9^D#?@+-N7R-AYB,/,+Q#]I2+@A
-M,__/IC)HO_G!?I1NPOE\QEGJK=H4]6JTJ"X9^IPT`]755TNU%\_`,8$[B+N:
-MU6>;UM*QZC$/RHM&*QU'8_!U?/A;J_I4OHA,!C(9,\IC<'<T`<6H9<OO7TWO
-M;/+H-"V-QIG\@=4=2J=0;Y<JEH:;+2!.<MN5M^4NN]`'.5OJ&'!-[97(]!D:
-M+YX'M%J@;X]+41)/<3M`^Z8BZ["&S-<.CP0L]*GQ;FKH4@\EM<:$$^5]WLA$
-M8_"ZJN0/&PZW1S2";H0332J!OYDLQ,O=&**&.G'C(;\3O(YW:*IK;+O4(R5N
-MB]&;<'?S;BSA%6)G*G\?1^"X`*5G(HIWX!<S\VG&(ZO5L0#7JC\BG$3*@@AP
-M%%NU(#U_<W>XL&;,<(T1A;MGT?_%+X8<J^BJ!:[FR7&>V#(O;I8AI)MO[X/J
-MJ$LQ`QF/RHH@X!LLV?AXH.MJ]!1X?PR5];!+9M,/AM])\Z.SN`*);A_6J[0`
-M2QK>:CEDB=MLS9A"[12&PZ3.N::;+:Q@J82.1,?5AN8[(4>6=]J'6RK%J"2H
-MY?)^^M"L*.0(=H,41[=XXX/ZPX0X4Q%H)P24\=B$:;V)Z78;?0#\<;`U9B[I
-MV5"':![WFYJ\?J%+*,PAMPIO!DC)DD:VL8/[X;RST)<EN?O638"N)W?%M-RA
-M2XBNWN'6DM?)8H&5&[>_JX`9W"U5A>0Z<\3`DY"<WM_QO)Q1MY%!0Q6(]YA[
-MXDW@],A!8H<D(>6)75US7(-)7G&X4HBSBK&64+(6R#$SPD;M]K[YL#*W5[(*
-M9^<]ASK#;Z/?#>^#1)_!*]E]K3;B'-;46D+`BG0^;<5D@R2NGA[!$D`MD;Q.
-M8.8=5)UQ(LR6!B)F.!7N&W;<P&G,/BQ*803:?+1L]O[WJ"P_`HUT;4KZN7#K
-M!%><Y9Y0#OJV]$>C":+#UP03UGWM4Z\I*-KPV'J=_>-!&RVK6!TJF[R$PHGR
-M,)0C=*[>\5';F$55"U=#YBJ4<\0$,9"A^O7H>3,T=N2/XD)1%]!X3Q)?7I:M
-M]>7KKCJWKBF:.OJ$HDLT#0\L2?&,2?%19G#'QHZ1\ORA<4IN:6L#5[[VBH&V
-MGJ/4+VWB"&NP9F-C@G2P$D2A_NJ"`H+4ZA4F9WG!'7`&97Z]:E/WJL`\Z^,<
-M!$;D=3_NPA>)4_*!=@P?D#1/@B($<FB.#N\DAQ3G"FGMT/X][+5[:<XZ4ZYD
-M&_5@Q.WK2*A6GRL>9R%![7WD(O^4B/`F=L^`YT@LJ\Q4_6%4[8MP6:0Z53X&
-MFQ5C9#IK$E.OVWW;L,YNS^9)`_\7(#59++:*_AW>2)D@/HC5K37@"4P$0FMG
-MD^M^O4_+7Y30O8XQ*D,LDS>F5X"D@)[Z:'-''?V(QH%A_QL@X*O\NY*4C9BW
-M#08MUN/K`S"D?</VIY'\:MDY3T$.72^A1]96Z=,FL-+64H&)2D@$^7;PQ`G2
-MVOX.^NA'NPGD^4:^0X/[0F!X*)7>"QC"S@[)8B&Y:N$<E<2VSW&;3X&J$YFA
-MMDXJ9\D<:I(77'7,7VUIK%GY;^Z6SS%!&D0;Q8&A??&)QO8R5EX^$*,-+Q!=
-MT@Z59C9\HY9H*!>-%]STH6O_UB=,FGZP)<F9?)%U:YOIY-([\6":TN>2WWZP
-M,7UFN:@K65I&RJ5SH+LG?,*TL/?8+OABF@/G'X+?PUV;[L^!B"MP8?1RJDL;
-M&,\BUED-QP'30J(!0!Z-'5CJ#\003QOW34521J.TY@8JUKP;9\'FH\.0\?#`
-M7WP/=9AP9G9GM?CWD?A5I?#@_K*#L+#EK'%KX"7M5(F@R;?RV6T!Z,J"!2,O
-M>M$X3$)U`]4I7,6]M'*_M*G(Y>9G1F+M+M'W:='6@])G]D`#`=I:_F('4%B>
-MP,#A7F.%]#57"8O;A9;KK[&(S#<?4^7$'$0%J<C?QA-$5:&`+5^D/'#!X\\X
-MK%.F$632$]-;9#M9H1F\^U"+[^%?)+RI7>M^Q)O1V%3\:O*%1>^JHV_7?UK"
-M/06($V"0V83$IBF)2V[LF1HDX],/=1]8>\G*N_A'J[L.V$!N)#O9?C-44^^W
-MH-RZ]MP8L0.PU#"6=+YI2"JZ6MP&2E^)'6>O'8![6)TD,]BQ\L7JEN.:Z&%#
-MNO.X)9,*$5Z$@455>J7B&P7KG+A9HWEVB7'.F#;"MQF6@H%Q'O\XI[!%#%I"
-M1/.W5)(XS!1C[O/6)3RF.G5=80@#3IUI7"K>BLI;5<R&YIQ8?O'GW3]Y^<N=
-MDGZ-(O#W?-SZ;<:8X7#.'"""R8_H30.DNW`NGD2`)F)JU+F!PV'=5/[R`<K_
-M<3O\+$>*B`MC2Z9W&)13ZRIO4%QI`B7V;I%=$PJM3SL#LW90(4@_)UQ-3SCG
-M``Q_I^+[JX4JKXCXS,`L.)48M-7;P&-.?SD:;/8O\[8"1\@/6PCC;>$O5Q'3
-M`AG=.IHGZEWE;!J%1D^)R(DE%D#\(K@2YSZ:#C'$))&AA!%`.P6[YOV^R&C;
-M(K*23U6,5Z\:2_*$G@VI#R0!K@6P<I77C$$EPJ)`MS@PST#N3P&9+`&?FZ8S
-MY]M@>SWKN\2]Z!"S;L^FV3287)[UY9UAV'KX^"<*-FR</7.$Z'I+G;#@F*H7
-MV[=]48,9RY,G9(D<FL@^<B?S-#RV;EWX:3F[/A!,NPJP?7@%X_$AVB"1X>KL
-M^%,>M?RP/R&PJ0>:GOJ:*S]@0[7XT]8!6W123XY`U4<P,]2V9DS79U`TS88>
-MHF;M,$%628**O""TX9;R5>5:Y6^)/\6Q()G8-/@+RW@VO)U--#K.#910,7R^
-M?+<.+]>P:$/GU)$"Q0O<2OA$]>BJ+#>=KO]I)0^J#Q*!%4%!D$0B?;$G&9(*
-MM[X+O,DDP-C--@/!5A@=\3:/PZ>C'TE[444,!-,3J&_L=K25IYE+^1(PK=25
-MF%Z2M'/G/K.Y[>@UX5-CD4\8B<R.>=E2HSP.,"P2(_)<_`LR)-!>=4YT1'QN
-MG0`LPSE/UTO:N0^%"\RR(!G,14^.:.B%S:5R.@TM;@JW*I3>T36`4HX6>5M7
-M10]6X8?(-+FA3)$3!/F5/-&LG*""]`6^Y0YGT<DP=?NN>%<UQP^=<KDS[_Z-
-M+R^%DMC#-9`1,VT*8[F-QMS.4:-AI!B6<Z)9O3UV^:Z2;3IQ9TC7AT?BVD<%
-M3NAG3#L'(HAA"3=(I,G-.K-/MW5UW)6N!M#AG[(O@S]A1]H/'COY0`:]L`QF
-MFD4.(01;@=[2M/GNT*A>KI;P6`^U'H,?C%A87"YGD1>UY)*E@.P_RD]RQ92=
-M\A?>\-*\$'$>X4LS0C0*$@(],ZU[J$H`R?3\;/3+*P;334509?J!T".5)RY>
-MKS(V:8^=597C4[BYT+<_OFTH1A*"@Q<OD)!CX'4@VO;%JO=Q]M(F1P3/7DGQ
-MR2$]D41S^C37@N?TIOX'Y2[;6<VT8)LT:UK,;)U]#(O"&6?.+<[U0R%E("8]
-M;_/])Y+)Z4_4NA3:^GV339F`/G5JQ^&<HHYZ=',F[*4RT?JK!:?WGM$37E\H
-M`BZ)L.#:KD;%,*7F(-%9TU8J5Q"7]P)I,'32SZ4,IDIH$[>X0:+_[1;DS$$"
-MT5D,!I3'G#OO"+KR@*&M)G#R8(C@.VLS)G]0IVT1[IHX:^=9PXO.IA3!>.R>
-MJ'S$)0>90Z?CP'JIY:2WBWAHQ9<E2)ZON-O2AM_RH"NY3NM-.$>L8V0_83*)
-MCK'P$U2NN%3=B5FBH7#D@BH3[P[60?^Q,CH$VP'`?'I:8+AXZ-;!H^%G%X=[
-M<QC4FP:-H='KE('U2F"@\(56]Z46+71]Z1Y0E@8J9Z08OS=K+O:1?L8N1/PN
-MY_`;8F`-AF>`($#,"4NT*G#VYQ>QU%#Z_X2/S68>;;!)9,[FN(S40S$E@_=P
-MEEC$U/YV#]MCM1"[%K"?[9X<Z'E-OAP-@0E%.X\8%[L`SX/Y7@AVHQX<<9NW
-M,8D>!Y#AI?U4B!:*X/)(WR0(LFT$6:/ZTWT//:-^'/C825Z#J^@ZJU8#K9P"
-M96B:W#;N1FA;)&#ZE<XEN6J7X`(V/]QTG!*-*3@[;5SG.HN]H$W^U^B3V"]-
-M?Y#"F@!,RCO05__GK44U8IO1^OX8GHWQA!L'G4:4C\N/2I6;')-"-GGN]X(J
-MN;%F1OEL8=F.V5<.RO\>H*)CI<>;5+B`M@>P;@)FE1,9$(T:L:16KN>R559Q
-MM.B2S;[\R$D)T)EL`Y=X14X:-*^AP';5(8:9T>>K_WI5K=M,N.""+=_P:52$
-MR5H6K4]5SYC([PZ>5>+][#58J5+Q.BCQ4;$R"3H\7RQK;VKG4LWW156@Y3CZ
-MOXD.G]?`11B$2GD##F_T14H,RM>3A.L$9UH;V^J@I_06;N%0;R55=\5J9Z=F
-M,[,Y\,F<A8Q]/(4,E'&/!H5U1S-CC+^K"[=,J7BD0E=2;D:+A(Z(OD:@]"=!
-M9+[KBG?#U>IRGE&_#LV$"Y7D%^LHP;C+HN>!ULT!J%#V/;'>YM_[,<3=[C.F
-M)D;B\`'F)UI.N!P<D;\![O#,3KO`';P]<>!8KKC*[&0NK0)OU!1)\M.:6M9+
-M>5I._2@]F]/<1:QV$V!,5$2J@DZFK2#3%AE/&658W?M!L/E:!G5S:)C@Z!.6
-MT;5[M.K/``;KSS"WU&)LT)JO<SX["Y&JD0VNP\DB;\OW6T"].++VYRB>J%DN
-M5240N!4;3\JFF+51;(2MW:SM$9:'`B!33//F@@1?O.8S/^L-E"X5^\T#[9)$
-M1RJ)SHSE)*X9YJEYH.T][.+FC:8K\QR^VP;J8]W8E&.U7()&H\Z%JX%[4)%H
-MUEOH:XJ!P%'ZD$[</?28H$XJX:(F(D?GE!_^EV>P9)`IYD[@=+CM6FE<5AU3
-M!QQ]*9C9\P=L?O`^UWH94%M_/XW:W/\S',9HJAUSR`Z@V-9B^&LC\:(H[,[=
-M\5!LSQ.T1J45%:IU#6&[WQ=`^9*(:M4O2PWI^>/@"TAM)=F-VK)/;^NXFRQ5
-MH7J_:&VC/ABF%9LEIZ&0#JZH)D$]!%UZ,8U$(SE;^BVX\U6B^0`:KSFD:(`0
-M7[9^<VA^GWD*)(U*A/:,;L].J%X!_E4-XHWE/BR<@Y2=9)?29P&K';<<9C[G
-M@A5W&C;_D>MA28F8]`'5'CQ>*UE/K9_P5APLFK`$V):]EM,>7C6Q-&VY$L9;
-M];85C%<;)AFIXRBIU&`?#0=-(^00@4A7_8/=7/]>C>V++ON2*#K3D6"4R1>D
-MX-F4W5H!.&#IM`ZSJ0#L(>4Y]Q^-S9]OOZ"JC:#DA`T:#HQ)3A+<J**`@&C:
-MH$99RK8F@[`.*L,F+BT<.CKBY+)SRS?_S-748/_;_1Z0/4O\.I&EW#NP,W<)
-M\47C"_O(NK!W6XCP./@VA^G5?V<A65CZSHYGU;@ALL'*A?2V^="H]^]5#V9>
-M4QI8+,9+=@CGS=R)11>Z)P[9+2.,M,XK3U]F9%EC-PM3_)76L7SZ;8=D?\&,
-MK_D$00UH_]R^DS[^0L'@?WQDS]9U`!]U^]\`D#B[NNG99*ZIHX?`A[$5CE9Y
-M=$E(FSXB>Z;""]HA>>C^T&I_AWVA=@3RB`W3NT_Z'*+V#*DFQ.+#UP/@[YM>
-M&S4`AHF7CCF527\V;-0=&!S.<J<8RD'BK^?P.G\,?)MA7F\S,\8,RHAY-[;8
-MU'U030RI]P!?&$>WUG`LB9V-2)8TT)A(&QQGBL^'O>VB6-B,R=8EGR4XT):-
-M9EMRYJ^.=J7J70F5UCWT5)%6Q@6!9#1PG1^V>KEX1_SS_]49)99`^>K^NYJR
-MR?`8*(*A*;0^L_&'`U0H"#!N?%8KT2S0[/:*]F7\):1]7CW0&ISY8C2F;YJU
-MB,GR#L<?^%2$[[)9=OYD&YVD5^Q);5P7YX;EQ']S2#"^Z9I;$=-KP/![R'!B
-M!OM#\JU)II;:V=U5((Q&O6(U,UL4_;Z+(,)(DR#]%43Y47!Q9F`5K!.)-5SN
-M#7F<&#3,>%]L9XM5J-VLUH,WR_%:0"%]-"(EFA\O/-R0J"R0ZLUVZQYS0PE]
-M6!QLBC<HNXK@7C"Q5@T]J=UDFS`3(D2-79MMN;%84UN,%8OJRRYG:7T?]_8D
-MB`W/?A47L/7;PF16W"W3$#H5+A8QPIQUP")%#I@2,(76QX:G'S_EZV.^;5VG
-M.FKA]QD!/>&EYI]!I-^CGN-+$M$YO1P/KS=;UGB+1\>4_P*V_UA;9ZI)A?$A
-M!V:`"0S4YC@<F]?EP2UEKH68Z,4ZOCNHG(E]:GN7!&OW2QD]7<WI^F^W^B,"
-M5X5$[91P`']_G;/!-+K56YW#0^:J.)6Y2I:4P(RJ9<`9:^L>"$7[CGCW"0FN
-M%"D<4!@M-$ORVG46CBPHVT!J1>$++KK"P3$,1,7E-UE#8)WT$?!];&J:IL+)
-M;V9$49/\*T&8E!F\8\)8"U1I3KE=KZ_>%O5O^"6F=T(SV;^D>PT'!F(VGW?\
-M]52V3:M/K+-P2K;)75XBL-(99:\>;YY2CQ=UC3T_QP1=EB.[/Q6H5W,:1\ON
-M9>0D%1C`@-6G$U]WG+7SA@J'YG+>7U):"W499H8?#Y^J<0"_7/K<0T89MYE<
-M+ABPHE[O1C=2.O\9_7Q22JHVP20NNV(M6O'#=CK%,ZL131_D\P$8(L"HM?O9
-M5ZV)!O,4^;+>-]>;&"UW*R^FR=8889)EP;A*P!OQ<,!_4:$.VM7^;%<LA.A;
-M(T+XT"_T,NOSS\F"I<M,L&1)].@=(X.\A2(<%O:P\A-#FNS,:/#=F4TWMLV]
-MW@4ME`73I($\;ZNMHI*0T8*,#(>MK`:?5T`$E?7#++_&/.2CHU"A+RNI/D]<
-M2R4Z8S4F!J\AF`-9(']L6=9T-X.1@NI9CSMG]2&>/VEV4-P.:42>7ET//_/$
-M&$@)T_I`3(W@=H?*3TD`/6@N)V916PZ,Z6B_CZD0L\;"IJ-+.XW2WEU-W05N
-MTC$]"_#*RP`XR($CKX=]])6"<'/S.*W=LY<\J"5:P=<QR.O";M=K5T,VQ0T;
-MVKQ1"8CGJ-"\3>$>F-<1NSOF$:;Z=W?Z:J#6J2UT_8V$AMFA@'5QY\52Y)30
-MAWJ2$6@9D_[`7,0)7/O@?SA-3FA%[!TOLQ4"#$C?.7#R59SGF[$$R]BZSC)3
-M/L11.K1^16X\C\MO14D)8-68NM."H;'=AQ%/L506;NM+2B&C>+(A94OQ\:G7
-MQ]&+&QO0:AG:Z-4IDB<`C&W^@SQ7DJ5$4U>E>[.F8NK(T3!CGI#PPKJ^<H4:
-MT-212<U/XG<95A@4U/'E"0I\;=./WYF@`E]W]@T$TK<Q*YHBQNXZ79`/N-PF
-M$FD$\Y5&\[5TDI4-_3FBD@`K0IQ#'^&AO=*1G+24"MA7]O1)?E*J])N(.L_I
-MO82H`EM/%\$D@/%)3#6?(.X-)8*E'X%/`(4`.#[<@V`26:Y9):(`;U5*QOD'
-M7AO_D7>N#1==<-<%E,NHTA3@%LYBT&$8"=I,L$#Q[:5Y24O?.><]CGM[0[[V
-MUU@&C]'9K$Q1]R'C$TCJAFR^A(I;G?1&:-`Q&_%>1GI5^,,T&>PKHYU<W.MC
-ML3#?I,''?.'E#[M#C]IDG>X"H'"G2R[Z`N[`;6<HB-ZXO21(*TA4;KN40]NT
-M&QOM(J@&_,H9N$J=($6KP#(DG>8VW('44=X2^HSW,S/#E)&;7L37',0Q5YZ?
-M`=_\X7WU<&:$*.._+S!_#(MEZ;48E2]XEC[;9BNU<#`1"2#]\9?"71=G%D;T
-MVE1`-?Z)S$R6UBD&W):N#ZRPRK4YT'H(,JUE6M9X"86,Z\!_Y\1`QR7ZT:J9
-M0]S>6;]X[B?2!,%8%.BJ>(8$9A7DL>\$(JMN4F=J3M#Z7AR1EJP-_&I!#!`"
-MF<2(FHD?G8>E;?;0U8-Z#"P<$SI21+IBTO%=)Q[Q<'-?,W+YI0^L>Y2L4@^9
-MK%E_2%8?>P6TXI4P9-PJ1`VN7*[_5+?Z<=\^3&HJ^>X8`+'BM+=^U)8[$S>)
-M,A!C^"Z7<TK$<K@1_SXH(X=G7'G1\`I347V/@]49;8,JOO#O?*!$C=4C3DGF
-M1$\I>I>;GXZG'XOY%Q`'^.5G:-1R(S2][RG4S^?X'1EXY*T"6,#=]DE<G=Y<
-M75KBC9HH7F=#9:6*<3!6=`P*+0+7A@Z7_=[O$#X)VK9`7;.W;)B*39UXU:8>
-M+D)U"U4BG&GW_EW28CR[\9X/--A<(D*"-OBI0;P^[U-HT$1[&HB>8;EF;PI:
-M`-B23\]2G5)<(K(MHF_0%/ZFC\G[SO+)_.0U#9DG<=@LX*285`G)IQK.-"I<
-M4/P-TN($:7QWQ`MM;5&S3,["?PQI%/O[^,:W)V4GL(,RAFUU14$*K#^*$SZS
-MBB:91AN1*Y.0A`=/$A*`#=9+KC:3I#+S*A:^6P4HF?RV%X_>!<'/>$`G*9/-
-M7*0K/WHU(:VA\AXI4<Q[&!C1=QF\90_,)KG%9K+I*NHJ[0FZ%E`75S>88#^-
-MB80#A&)]0O<[R9'Y)V4!T>N,E+\<DJ)%"92-Q>L#^WP73C]]^6";V_E5`:(J
-M$PQVM7>:-REY;E$7=G0$&&(EI.K>28`<*6P@&#7:H=&A>65\FIJYMXBFKGIU
-MWZ5X31;/`3;1[08G'4#YBQPY>H-SH&*#KD@_^HP)#P^0R_ES\GF_7LL.!^(G
-M9\'OC/$3=@_EGSNU%+/'OT`Q;)4=D7*:03.5>@NPATG!U8L"_?-:7F>F>B.(
-MJ$:+CF+@$XG:'=%W*W]!Z(&/$'&Q&-B$U8OD;[\#&`-&[I17=,*HOT]/HC@3
-MUYF&+&N&1]3?0I"L5^,/X5^K1E:3>AM6,9(FU-7B2$A0?3[%%`N?:[C[-RZ^
-M5T-#NH=O!G^C7;1'LR?<$C<L>0FZ2[]-K&#^G)KI$S2]LD0O[5IIU^D+-7UE
-M5"1N`<^P;9`D=XFVXT?]*>3&,QS"XDH!\[#*L/-S)<PJ;#"H`^19;]Q%#W8N
-M`LSI[G,BO4C-P4EA)+/A7+L6W;T/2X\.B&[-R%:F5F49/;A"TA6D%:<)I+IF
-M$<>D.NF^UD>#"MR!#V^67H2XX5WQ(/K35J$16PMKRZFVDP1:QY]6WA:>2]EV
-MAB@HJR^!<SK^9H^IV7S7NA&KO0\OQG@-Y)356Z\,\XR^D0GJZWO4AR6'F:LW
-M6PW^%(S[AEW-./@VGAR1"/9^.M>$6'W`6B,U5'?=&_RWRA&MY0;E*+L:O^O1
-M-^?>O#%N;NI4VF9D'#M_*72T9CCA;2N7\FC4DT?VV&D;2%EB1P8,?SO!Q9H\
-M.7TX[@J0#TVT2A4+6H'2GIU(NO+T7#B_[>VHO`S!R5XQ'*96F"/'/;B;P#P>
-M[@90&37?((%B7N\\<<B54)/$ROL&,$79RL="O(ASRU+Q<R"@M5]`9:#G"?6)
-M%'9?K97!6>;V/JHD,)03YBF(HL#;BRZ$/GJ+;]_,_`*7N1P4S8[AE%-84UY=
-M:\281;W&'6B]U/LO[1;;8"?(S4J@XZ?0V4;Q^1%M-ZR)"/+QPHV_XE9E<'=E
-M?R2B3T+DK*WMSA0;]J-D!MK"V>Z#_"6V\I64L>FZ[_PFO'3J?/&4N&4]<P.S
-M[[O2QF^4Y[5O-=`4V?\14'&D,3!Q^TF"X]\PCFZ='&+HY]?NJ@%K3%>?R+[\
-M@02Q'=FN`%Q>D2@0\@M6ZD7^!S!R'?68Y$TS:&ZK3-!KO+_BM+T9?*FV\]=V
-M87Q7)O'RF@-<CG=SYLY`XV8$9#B@NO0_K=\S<C*OG]^&E84+"Q)'\_C>)V?]
-M*^1*MH<4^YC6;^T3T7*WQ)$-..F,DUV_O,^PU-B7&+==(D!L38%=ZZFHBAA0
-MV^/2,VL+:/QY^XS;TS@9/1@\0UBLY"'-2=.AH-6K?'81`7\X?&J^N.R3LCRM
-M@88Y.N2O=M.T]I>P\NY%F?<C@[AZI]AFV^&0[.VQP`2[A.?$8MW>1GV./=\H
-M=AS:/%@;N@+6[2Y-=X_)GI#YM@[:72K]^ST\5JYJ3F\F-!NND;4<7U\:U6TU
-M8,E.6<^3H6#@&+SN(/NTP?!;"L]_J@L.<5R<E/#D!^$T8<RH/)%K,]P,!]B-
-M@R+=Q/":C`5A7CN976L#5KW6H!M59@;HC\>`ETD49>:X_5$I3P\4+QQ-14"D
-M!M5O4@7[QDQ2WE_(_S#1^.69Y)=/#(1S2S$B<X]$D\[+'E<":7SS.*D@17PS
-MJ'BV\K"W21T_^ST8II`V=7Y'X=PB<Y]<<YP!0>AZIVTCI]WME)>JYN+=W46B
-M+D)*1/*(ET5C8\YZ_OX2<L$BVS"T*U-;]1+Q`&E1$BXDKSN%[_YNJ=<ZMP<=
-MT(:K)F=R$`^43L#B\77>=S?`<\\:&7&$U+N+KG`)T2R']K#81&-K&AI-Y"IM
-M7<8-J!H)XZG.F&"X`G07$10Q_,K`F$D2TSZ8M]>3CCTCI]DQN@^Y-UQH?Y>&
-M)_FK(J<S5",J-SI&R,6\"D3I=1EVJN6)Y\E$2G(F8H<L!7"#]^\TRM&"DFXX
-M6`\,@I(%@-0X/W&2JK_PE+>IBEE3^3,[@TU5`$0,%Y'FV"2RHW"BC6+K`<RE
-M:N2-V$\FZB78=YEA@K5O]L`.A^QQ6^UFXA;M(XGY"MK`RC:>>C4S,.Z)V$OY
-MT[ZP<4!?!$'&G\[CZ,A[(\KHQ.FCI[-Y=#,[DL!-?($BBLJ42EN)-@MCCET;
-MW>W0NGV3:S5BD6/<->,K/8UH#"&17S71_F2&P]T-:D6-!JO;<WK3ETCQ%GW9
-MV,:&<7-]EJ>=.\X6+WWKW0+.P\`[+:SN[HO)\JL96PJ5/EYQ,Y[K**=TC*GM
-M.E]@T=Z@QL)!M#?/-AA.?14=/+8@#1I!'QU`VYG1GT>DK&I&0!J\G7>NB_\_
-MC'@;"2A%UO=0@`+[N95Y71P/<%NLE.+L_90^UZ#V<.V#RC*+M"HQS5A9L?*S
-MF8R7%QD,2.7B!G0_V:X^_KI5/\>(.;D]_>$_Z-V;$["-U76W7N3SHOCRT!KK
-M@TA8MDX4<E3*1G90HLWO[EOW'#SL]*"_`063V1;`$S[=T;&NL;#.0$!JP6!,
-M:`;[2ZDNC1FN]?DK:FF&RE0DSAG);SU[O1<41/MK1)ZZ1XR?>MM=.]_1N?4K
-MB.K>J'-K(Q#2E\4T;J%Q?>_$>GSD$"1]3D\!R4Q">E&7]._&ZW/.XAJ/!3%G
-MC%!U25A8=D(B(8_'7:K2DE5GQIK.4FW7-5)XPUA;O>II1N9R!M]6UO1<O+%_
-M#*J\<<1]N7.=!IVD`Z?"A=U[`%PN3+5>^V(2__'*>T_"8R(4#>C9,/*!IL02
-MN.0=T-N38M%4<ZJL8VAU-TCI!F)^<ERS`?'4(VYS<DZJ%][J\\\"#7!U`QG?
-M@!TXOATP!&@(WE4]AB;,.!P1"]Z^ZLQ[1%F>9^)4L1!%9O!A\__VB;-?Y?E:
-MYQJ,)"V[S1CCO"=`KI@T)5I#/%`]BP)E3>[B`/P%WGB[JFACJ.OKLEM7!B>Q
-M\#%_LL<,%LN'5D)]7A]L%I*E$#4DI)%`TQ3<RM^.+C]G]Y"1^DF4NWOL$`WK
-MOSVY>(HKL5/9LE/9$^>7B^)AGS3P,*79%7NK@B$I676LY08(KO\MT$!BPY/C
-M,$6K,+A3R!WV:*GXH-4XQ`RZAX]QJHV37(UTMW)MCOI.PZX&P0Q#%Z&+M![8
-M!F3K>F-W:WT]4/?)?VYL3\?<87I$>TB5-I(![3;)*&.HH1.85"^6K-P-PT;D
-M;&G$E%AJ>_2!ZG;@,7@\_R!T)*+-C<Q_,E^@F"[NH<QRA-U="\I\HM@8N;AC
-M3QDIAKM#2-R$RJB_0.B.?!2!$^7F^C*QO#\V73LH;]*6#B2L\`A6@KT&!B0Q
-M'E!WK(307O0DSW<HPRN:54$9,!+NOL<-JV61TLG(HEKK$#8'::YZW$^+.4'$
-MS:[L[YS>\KM?)@OS?=FVLMGIO0<3LQ9^K@$`>;X!WFGG,MI5<.<>X"11+QG.
-M>Z>:56XUC_O$W!U]\`"N@ELIJ<G^J"P]L_M':CJBQ:[4!8+(S$'O%"L?"\Q`
-MO(5%":XJQ:93%"MH".6T[EKC;^W$PII+?/)65.0O@(X??F&I^C@LB70'OPS9
-MF0:<U847T^5?*.<V?@E,+/401A2@JEU3[Z*@PUQ<9V*)OL>M'_.2FEJE%&W;
-M'[45&,.+?@>32;'?;WP!G[^R1'O$GDM6+ZPAC>X`@\1O1D%W!J_#_<'AXH_A
-M*20%W(\Y&RV_,ST4EJ*6ETJ$:MJ'N%K8O>@66"O^:&JYNN'5?V%<NKZ-&F$T
-ML16(V_2C,LA?)FZ%6AG83\3I8W;>!@&>/U(+$.TV&Q/M-D891*@!FI&BWJA4
-MI6\-DMI4[!Q]M_?QI5V276FKU*F<?`("V!F7:E=1XAD>,"O4)CP-@:3;=3?B
-MZ[51**V"+GZX5<[-=C7F*7!^@ULB/.I$^%63Y(T)F)7?C-P3[HNPQC_6X'2Z
-MC$B1:?FINX>SHHK@"L]N":J?'"#O2EJ/N?M(;"H`1!NY+.("J>S%'*ZL:#V/
-M5"YP;'(-N$SN9'CFT;?7KW3H$0?<VMK7#P*8FKSU(PGW78"Y\1_9X>*CVU\V
-MZ-C:(X77K=G#,21W/5:$K,[2<N\L-"U`J>HWO/RYIH4HJ("4^&1M:'J:[ET[
-M*)C#PIBHH`:&4M*6VQY/4?/&)=SKJDI&+COPZA:`"^I\>1Q"$Q,[CW29=+4)
-MB)A8S16L6B2$&HU1<]2HR/!L0WTDG4S+/77;FDO/GW#ULN6F*QK[_'U.X*]C
-M7@TVN\_(A"]LJLKSFZD-_\ER@+8R206#H$-4-CP@$9<##+0'+]]LIMW]*5(6
-M$U/WKJT[04KH0>_7^N@1?M9FV.5X5\P17)`,<<>'I#&\!7UB6YMBS577[O9$
-MG3&I4,R/M$/8T2<ZS5&\K=#6R:#7YM%!GV91QAXQ%^:MZ=HY+6FO-N]&DM*`
-M6J!@QN2[T9E9)4BD+/0$*;?B59,*[=YGOEZY(+'"P]<F:-]JT+KU01E<PK?C
-M&GKW^BS%+9`H+!!-WBRGB[@LYQP0#0.GV>3O.0^+U"G1'^8(_A$&9/]MH+_3
-M2/0'V[[V\_N=8!+OU&DO"QR#\45I,:5\,#>`]L]Z`UH`(*=[^>(\+06=&QR?
-M4?*P*S`XXS+/G$V]?;P,D0XRY)EBVT6>.)/!E12)`'5%#L&H"V.Z9MJ.A.;<
-MF*I6'!MLS&M7U<$A]US^2[F_(6(1GTV//F#:($=XF#6)!P[@Z#LM^8#PB8GG
-M,],G_X_[9;RM_UV76S95+04"H$`<5.TPD<^N.OJ&4B^"5.3!DF8EE`A%W5RD
-M58TW'8+T7"4C_V`NN[\H$B$_V7..$NDRR?ZA^[SR"68?%%\8OLB"F"QAFK(4
-M@/:*J<E/Q<U2IYR`M(P;O0,/Z?;-&"7-UH:4*UYY[PLZI<"@$\OUR62"_-B=
-MNFOW]I;K7":>129H"E+V*88S-<\)7H4+>-JMFJN'0*N71S/R0C3>V\0R=2I$
-MIL"XZ\8_ILS2++N*^/F<?;SW$LB^`_7`:Y?75L1MQNNPW]]K4E"YP]B.MG5B
-M?[SA^*.'3BVA6;^R#XR6,D+V_CB&I9T?4,N$AF<2C71)9]$"W+1H@K`:\8!,
-M"Y_YVC&%Y9\`<UB=U^%[N?&6#2L]T33TB=0?HAJ9C^C(E_1E'$Y$_$P&+_1X
-M>WK+QPF3@8LJTPG=)>_G2A,8[/8^"U(94@NA*;=F6;KK&9O/DB\9'"A%N2D7
-MO\F!UAW@"B^_RX-_@>`1(14NF[>J7F[;Y:O^T_]=?-T&[%;"72NVK/'%BA$I
-M[X009*7`GY:.M0N!*&>+'`\63G(.^\X2X^FL#`8+G8*0Y!*;-?GHZ7#7Z6/.
-M]A0>.53O2P^6K-H3$NH`/W(*`BK'61_@B"9_.+V''D0!>KHXORG@#FCT?Z7F
-MEKBW;@.4RE0F:MS\37:LEQF0*\W<V2HW4I#`F<#S('$P8:^#:=AHBAMR^2O*
-M&O9>Q?#HAROEWJ3F9]+7!Z`%!S/Z3?)ZC5TW.7/(KDO$]>!"/&7?<-;1.6O`
-M/4&=`&\D%#WR1T$GH36>.XX(0?Z?;.6OMB*8[4[+0I.:.OVS3V#"2[%HF*!T
-M%N0NBI#>I[V\I1!5N5R)=/?W7_>BS3?"KR3@0+OI!YS?3H@RG9#K#G7YW*F?
-MF^SR5/W'G/HK$VW*OH_')OR!X%;>52]J@7M8O(WFS!'8Y(%XL0*6>7!\O:"\
-M"CZ4LEJ"1[YQ%^D!R4EO+%\[#>=--],V.KL</+=*[/XXCV^(W2`!B."(^'[O
-MX^(7<@4`6MNPKJV2YYKJ@B<Y^BR"[_H&?R6*YQWZ;M<1RICFHW`T\1GJB03/
-M1';[7=Y%[IOY+*DM<1A:="52D@Y?G/!M,,6ZX<\8^\X+7%?YV@E(N!5:FM%C
-MK&`.G:1$CG>!7<T_`%@/C@R4F7[;WA6"QOUGQL-_0H.DB)C-XRS71DUYL-'T
-M=UI?GGYI!IYA5UIU&1P^;H_.<\D3?GU2;=K0N$=5BE0]9.WQTT>XDPO7!'M-
-MRKWETO^HV*Z2#WV"*XUN?RCQHX:G+D+HZX2725D(6I0<X.X7@,RV,]:S?IQI
-MHUHJ?G?@XV&_LZ<CJG4R2Q^YA"LW8MWASP>C%D#K_CP_W^H5>B>LW(9T)<X0
-MTL9I,J&.0L<P*=SXM0I]'TIW5&>.(+<!>O=-$3MY.0N;Z_;^C32)9#"$YW_9
-MF?R^_8/=$#7A*P(BS"4A[+^8S#5\92D,4*/_RPR!C5^[H-RQ@I2*!VI@P5R8
-MHZ-E)EYV4-VM4)Z?GOUQIX"SM3(R]_!1'@Y/D']]Z2[^6M^1YT3_7M3.U/C/
-MK6,@.6PGO9LO`E*E.01?!RI91543UW1(6,EC>4C94D$5NY/L.M8="U)CWX-%
-MYT.</?W<6F-RO_-_+X<.4#[0%7-ITSXQSCX+%,(.0:3GTEO<$MPJ+HMA19#5
-M^0'4?<<LV>G"+Z6)D&UYAJ3J'<LTB*A6GIR3K/K4G']2=YXGEZU0PX8>)<J/
-M97UH?L;F-YD-3JBYYZUP1DE8Q*[$8"<0MP6QV=,,>\F7%,F:I_K61.1OS2*0
-MT`?VIE,XCM1V7M6SC(I(-(+1(_7N$<U4<E301\QEM/(5\?*\(2FQIVST"J4N
-MV</!W#,?B0JN7MUG;%%7%EU"%8E"`M3!/4?N;82(V6&?F9V0@>_LR9MSW"2"
-M_#LZE9T&/"/[2.^RK%I1+-XO@7W1S*:W!ST$#U>.)<4WM&IG`5_5)(+R=0R^
-MQ?Z\<6;H;J7@VD8<Z;`KBN43;%F&C*0"GF)&[.$,+CM@]?!"E`L@G^$LHSBL
-MO)Y`"NX"$*]WBGI[ZWS4UXYPS:R'RZK-"F2:][L;<BS?52QM"/?-D<!$>2T$
-MI5WB"X<=H[^D8`TCH/L7/!;&`$[0HFZD./1CV(.9AK8X<R+M^IK!]'^JSA\2
-MN/6?^P6C#;-N)KVBH%EK\"X52!F7@8K+$?3"?VG??:8\;5W07_HFRN]+IRX@
-MJI+4:H:B[OGR8:$J&BP7A@JJVSD_VW+L;(SI0'7G,+_KX">YGJ>#Y,LR&SY<
-M"+@BEY^T&Y;A#W='!6T#.:#C+08?),B+-:/%1;Q`\K0K(PQ)"+A<DU:5"<EV
-M`(OUDJ!+`X3T=XQ*T.?)9`?J(#?2._`>7>'/0[]"8<&5AR'408F*_'K>\EFW
-MN;7NVJCI-[G/TJ4?H@:_LY*(+G*H`>L$%KR!8#E\B3J&,`DRP3D6TS?/7(UC
-M4WQW'SW?$^II3\J9HBH=A!]=9PMS/>_L=Y_173#31^['%A^:XV$<&WPT-B::
-MPAB*@,OY#,&>H+9%.<=180U.N=:J?:*EB"(X,@8"U%$8].61$"8F[ZL>`IQR
-MQ_].ET,K7ZF!9-X<3;4HY85NO2T8S7#;AAT9"#3"B2/;J?X)EZBM#+G[0D96
-MZFLX9[IHYF=G0\JB-4:S70=)TH7L0+DK5?I1`.&J[UE?OC,%'R6:JP+1X"+Y
-M6&\:?Q:..WX01//[2CN6,GU[^,!MH!.@E>#4@CI5OB2E,'X76-*JK6$DI+KV
-M45C5F.'?%!G`/T6Z3E%4-'<C`7SVD`ZC]!>GMSF_@5&I5-2;F_"^(LT)!L69
-ME08^2K)2U^R5[G1E\#XORXW@)^Q/NG(&;%EWD<C).AU53Q=]>@%Z3Q)?PX&"
-MZR=W#4XMF.V^0TSRBLI!\8T.A4E^HT]\E._Z,?)T3QH-7Y:A?\]F]9TN.G6)
-MJ3&OAL/&F70ZR.U%D`D-:J_L:/E75E3?H_GF*F8$:)P?^!A$+>'<+G\N.OA$
-M17&?@1@:$=YUO?Y+W'G5`++\-E+`B3"<5)AY1S+1W=7>ET8@-3[1=C8\[_</
-MABDG':Q68CS00"6^=?VS:)4#^.;JT5:+2W(]\O;/&Z&KX0SECM3`JP,?=W64
-M.L:\70`#KCU#AZ+5PHEY4C)3^-^SU[Q4TST/#!H9T]!OJGG!QGTU$96$44GJ
-M]T\9;M!J:I5]$F*0*HO>MDQJR$3+RFX4X+P["LNO]2WYJDUA=6E5)=0DL8$E
-MAD28,%+:S%B_BICW3V*87VBP%'7QC]17_594]0FGS3ME4V7Q(8XB.'*MY<W]
-MV*4#1(:5W__*L9V.\[><UX:_PXG)*V1N$.209=(UX\BR!Q;1I."-GR#$TC_=
-MM[6@ZV54M?$BY&?%IPUQ%OP]*XB/`QHG68F:%B:ZTLGY3LY3%/GC+7!)\G)L
-MN3YZ^\F<O4!+'$1X$"YY6S-4!9\[=PYZ:N`]2;*0G@WR>/VTA"5PG4(M-4WE
-MCX)*FO=2-G27(_.IV:/KB>N_+=RV&AV\T8?R<,@@H"<,4\$4[)A4U4$Y!D4T
-M5>D[OMP(LZ`_"H+9+W.N8XYS^/`?V^@9R2&"O:,D;,`/1V4V6GM.D'U+1J77
-MU.;./3=90[U\N.0-J+_O:,8:L[;VG0I6%AD[((V!LSS6%DB$TKRZI)*4(Z)%
-M@@SB2WDJ*5;=9(_'WDK..:[_W;^'*S!1>9#*N2_R43*L&:VDKM%D""D-"LXF
-MPD*6NO):9O2F']P2&?BI<'CK4^R&3EGMR/C&[:"W@M32P`2O;<#)-(+YOI5[
-M,1RG3=G<6M^[<_7BQD@^THSO5K0YZHB]SO1N-UQ;8ES'3[-7WAT-5C6Y\?6#
-MV4"!^_;Y;;8T^P*.U7.*(*RS9!Z%F13>G='?L>9H5U"F:A/'':.^&Y_+=I"V
-M9]V]ZW15V8[(^W!8:[POE)_\L@G3=\9%9VA'U5:C$JRP"`?VYU@\>-P)I:0#
-M]]#;E&T0\0_7I\36B*_:9`7W[O0JX+X*D0*$Q=H$8[<>L15V2E>H[*V`92_(
-M.+5+Z3@@![!.R/WV&*-Y>33FA?JX_I_UO@=%>-9`L<&:,@?]&T&V2H<%.Z:^
-M=O-:T?1J``[5&=50RWD/\^A^N64\Q:@`!!T!#>=JBH=??O_V69VTO/+`Y?,7
-M(U;":RTV^]HEA`^6TM)/.;XH3=<$@(L!4SHA96>=!(VV6(WU@XV@H$124Y<J
-M0^$,YXZ7)"AO_4+K0;$"%#HG%26T9\\>B>AR9:#M:(,K_`/*,N/0/EO,IJI?
-M>K@YJ.;_7(2^A67_<`)5H/F2\\.2M^1BI1EVZ%8OB$./Q`K$Y6A56LC'/J!+
-MI?8->T7O+IT,75&L\!T?91?Z-)@PMU-P85NV6Y0-[ZDEYM6O7*_6ZE@AH^^?
-M3!LN!:22.)W+-FM($U.W0==O+HWKGYBL,4TQ2AI@JE8(.PZ0LM8QI++E8%GW
-MDO/)DGCN8[BD)(/B$*-$B=V(X\-?9?<1)M+K)1+F.9#[MB8S/'OULMNG*W<M
-MJC_/JZQ/&3C'Z")WJT'+'+U]W/]O!LL[#)UN8HB,?F`A?0O-ZU,PJ7@#[=;1
-M+3&`BBA/=L!76>9#,_^JZ^NN@V<O%FZ-V;#M)Z<XMAW30$.[&I42J&_0R>U%
-M$02Y64%4$O4PATHVX*Q2(JD2.T6#WZ<',N.K<^'C@$L=;7.+^G-38XE/*&*I
-M;).4?,KOJ5>]RO,NU1F]KW\.CNIN<@H.%P_NS&`@[+8]>#G/KGWENP]U$/&-
-M+1YY`7;(VYVZY:8PB]5M;'%=N3:^,,;CF(_L_E@M7I)9NCHEFVBG=)AX:H,6
-M(CZ&8^$K\_8GI8H>CG<ML'%+-@>UXABE%[D,I#<4WCU$#E!@/2E_P@11+*:P
-M89V0V#"!^'IB.PL`6G1>E?UCC/N0=`FR+.<8%CG>)^<'2)=DR5D7;1D<M4L)
-MJ>KH\3LDL\,!(<]$LFQ"?*U3O%I$,=+#*CR,)6PZ!O+D5M^<MT7D??R<H?8_
-MYHQDIW+<6M':-"O)4:8?\PC6&9$[:KOB['<[H@G85E-1WC5J=!LE+F=N>]IH
-M[R*^;P>;:K%T::>&>;JSL=R74/'#1^P`BPR60J.;$(PIE>E7S"D>2^]-NR?S
-M%@294U>H1+VNEDZF)OLLFT+>WWA[.E7_G)D^,ZW,94=/@HHF!DX"+8T$P#VL
-MX8T!G5B<&QV9Z]:PX\JZ:!QCO3;5^3;S:JUK`PK,FHMLV*#<<BYB[(I5^*JT
-M6OSXO5MVQ61Y:/6A;K>C:JRQ0?_I(O`4EXIAJ5U>#(,Z**=#9OOFN=NQ8]=:
-M9+<1#ICA]*_F*\GOA_@QCS4&+4U@5OLY7UG%1W(?OT]@H=L2A;&ADR]1T9,2
-M;_IZT%@`M]B(ZA!]NN69B[/6O,H!TQT7RNE46T^`2.NFJ;%-QLX5J@5A5?H'
-MG71K_<L<KBZX@/8]<0AO^GNU8MOF^.%\5/0A(&'"'0\=FV,_7P3+!SC3)<'^
-M9\,?*%I=K7'H/?OE@TZE>U;7VR$==_1L%8F`/9,\H#YYM$D9(:T[-=Z58Y>Q
-MU78QJB];YGWT1(BJD5]^&0U0-I?([-;HO'7^"?:/7<85[?V>.)-[.J"=^:B2
-MP;H*J$:_3UT>#?.#V!1OTSW>0/39NV7^CQ'(G-!QDPB;)E6H7%FLR2X]2%V*
-MUGQ'1?:GK&3A=AR894`(J)OUU[9:D:V;1&>7RT0[>2M'?AWX2-#Y\5_LTZ1B
-M43!&4/&_8FXQO>.K!WT5XP??PK]BR8')CH2AX*G[LG5^*Q@M:%-N+9+CL1E@
-MIY`J0?;RVI./EL%IAM>2#/[?93H0@]K7O)O"Z"9[?C:=4I]_*TX;H47^;HH,
-M[#1AY@`GUT?1*@T-R2#9[6$W+<L;YK9:O[X_,;<>7?=\I=.</6_=S0'YKP::
-MJKRDP@`P;_R@WQUNM#@]R*\K"<H,EV5>%^2D4Z8TZ;,8KM=BUZYH!L<(.8K1
-M%@`TVY4*J:EI%5`'V\1G;.1F$D:ZC/X'WK)79]ZF(JQ1_QIQ(!'@PN]SGSN\
-M/JY8JR3RFD*'M5;=&O>Z4&#3#D!P>/UC$G#*I"ZY2A-$'3-'_@UK8UPC]7*Q
-MU_=LBJU.GVQC#M>4,TLPJIUZ<I]EWST/"$[R/[CK;/IQK5]2B!8Z[F+3Z#69
-M#'$KW>*'XD3$4_SW+@9V[G:9@Z8)AL$!<UHLKY:HML`;OT/2E?[*@PNGR^?/
-M1/.GA0%U1K;(Z_Z3CXY:BG?FEEP9`Q>C=^1$(3LG%#TI9.XM>KE,G*P?:N?%
-MXB"D<\K+%)@=YL?P1]XW2W@JZ715[."FV[O37S/<7Z'\8T+1RJ0IVI&[?NR)
-M@/R\IR\D.8)W@ZW/Q2V<0FYOY,O5N/!ZC+#(,NE_B>B9F*EFC]R>XU&XX(D]
-M6B999P@GOG>V/V+2:ZV3.;E3\V6O;&`77TI00AYUFY."+@:RZ(:.4MNUI9!L
-MW<T8+)(KASBL\Q2P4CVQ09Q;U<$94?FO\58:_@,_,W=*!A%%"B]T@ADZVB4.
-M*G6TS]FMI\A&)9DJ>3WA]3@L)$-!)%UHD`YYEZ?J3IFNJ`U6L":MTBR"L-Z"
-MJE^_``7NC@U\C!N,F4`W,_N2DP.E*HHARZ6P9\[3"PEJ*ZQ0[K^4_\BJ:>F]
-MYS#@?[\YKGN;GVXF5.YDS,O6\5ZM`MK6%5/?<$`F8#+UE6YF=.A*$`9]7>'#
-MF].GR><Y\LX"I[K?6LJT`;&)4T#L6#0:3$E$^+6%0(\2TDEC0)7\A04P?.IZ
-M*'>H#]L]9\-[9L,,SF%6/8.-?7EWO@).N![=EW.;[%,/M7"Y30INML(OZ``H
-M!`PT5711PO]($A3C-9%M+[XYEJ([WHS6[1W%DJ67%F[OU3$5/@YO::W$:9];
-MX:.KIM"GR`+A_$<G.8L1U6LRXA+'NZZ(6-[YKLA%=+CU`/E7A""8!>,G0FQ3
-M>>G)I'OQR;6F0K)-]>:H^0]<C+V=UL%ZE4;H3ZDUQ:UX?IG'P%#8S97*Z<"L
-M>;R"!.SD+3/A.D*WQ*.'M5Z+>U_*YXP9.,`[Z]:'1GA%+$S<WFROO6EPNN$@
-MCY!Y!1YD($@5O"WPDE>OO<1\?6FNQ/\+XCP-$+4ZN+6_'7_F5%M"V9V&9@_=
-MUV3>G15A'BV=<M"IGTOG')(GT8&R`9'/Y]AD2$:G%4*/H;4`WE,&-"[FO+HA
-M5[[TO@4W/#RTH4+'PZK%RP:8\TJGC#+4H:Y/'3<N&2?4RG84/+Z&=S6^N:@`
-MV9L&*J:J4O]8_\^BB4=HT]?@F/KY=VVN^Y.E2L"_0!3K84#W@;MEK1\W#&1G
-MF/XMD^CU=<GR75[G2WSEEXH/4NI94Y^>V'0ITXYR2!VP,OKM0#$E3>PZX9`>
-M-MW^*OGQ200ZX93D^O&!%\5%[!K`]XWIO9PO,B7CSB\5@3Y5*92:S;GMEL#K
-M2D1/ZD$)BOO25KOW*K32`Z=*]YQP`7H_9Y"`C$>Y$Q<M^8NW(8EJH6M2E5%_
-MK-N)=^%B![^_`=U7P6*-O_KGYCX.`&+"=7"FY044/L8(U<G,(Y'V>>X*4/])
-MVZD/9VOOZS>'$`?%\]AR%4!C.>!V@"PQL<':J9]T$9G6SLGN)5"XUD<G?B2(
-M<Q.@TG+4F7GG?+(V%*JNT?4TWR[.!^1%!4&D_.9.E6\PA$WQ[3Y;\&>,KA#!
-M[$R,:-425')$#HH&R+/62*M%VKSAY1V;-$U51VMDN6K`7%=9DJ'S><%"/#KL
-M9>\R%"S6$"2O]O,!4)$Z?2$C687"@ZEFBT_R@-X0NNN.RS*RSQCFIW]+@(&^
-MVB[;VJJQMS-A9[-N<;</#7O>0[*S2=_?UH@'OX.`K?OP7*)7WC,@I0*',N-U
-M/K`J[[C]0RZA3NF,SF)^I%WDZ!1UVR6L9D4_[G)NAU(WG[6V?PJ"JKP4'[C6
-M]E2QAV9#%A0^[>X[:)'A%D1^9N;EYCHJ@H]'W]9Q76O<70_><C$F0(MR:(@"
-MFI2EHD8J'*?SBYN,N'&_E:M%_+W;F.9'7RHAXL!/L_&JEP$R[CY][0?-J5U(
-M`6'U./GNR44Y;Y_:=(S<,X5M6"(ZH/[P%T#-XP8"3U<H*[L`[E?CRCM=OTN.
-MLQN[PAD/OT[:W?,V#S"SI&/:MGU0/B9;:^OL1ONMO#4*2T=IKW+8B16)(7*9
-MQU)OOIKYZ&]-#%*K8PGOG_7H,V3(UZL9G5]1CR3['LY6E0R8%TG67`A*C]K:
-M`K$^=?VC(S=K/>YEY'I,.O0WV['A::#+/CVJ:HI923I7KW6H5'PO"2U(_.1?
-MM/B(9KA,ENJU$U+$&Y#XQF6(!7<^F(J$IK;J/",K?([GDR/&4`'*F96+J.^T
-MI.!1Z</$(J+5*`6ZS"3^',4::E[N5C@W2]O!)VS4[\`N:Q#]'P^W=$",EJ+(
-M+H^<X\GNC":Z3@`GI/[$L-;:$`9196.ADS%X-)(@>6!10?KD^'^*AIVA%\"R
-M[.\L%4,\5.DLMBUI=!G85V<Z[S/DJ(DQP';WI&=_'2W.=>=IK>2''TKPP5R=
-M.^DP$]NT#.'ELQ6':CMT^>:(*O/9C`-<=Z+B>YO?G+<QY/>ZXF2EB;79Q7K+
-M):3783]I>$7N7=UA)_7-UU8/J^;(=O?REI!<\SG`TT^]*D`E]I^P4W;MR,05
-MU*G@=H4U`IORK),KC@25Y!9>;6O26C)0OR\-,-\\-(EDPGXNL,0CT2M/_(ZK
-MI^/J.SR[DGKOD38=:2.Q\S'%(#6XPK8W0#1J[9:DD.>O0VV>S"$IZD5YS1%$
-MQO6@!7S4?[.@`T)#60_[O*T*L6A]*6ZYX9+B#F8R+9M0Q-,E3F(59G\XFD%3
-M<`VG_LMIU2(3V>R:_@Q&:QLJ@V)5=(X9S:Z`X>EH6_34*,G7_\*YJ04Y*Z9V
-M^.=W[Q\W%NRA">3'^>CLTNPM>;#5L)D@V8XG*T&#9SKHUH@"S?<#8NE`A'3A
-M[-):69.:MC(\4(M_SK0P\:KNT+0KIWVBQ[PR4I=I%0$'K4E$'\SAASPRO3(;
-MS2RJ/HPF9KW?XY=:PL`5ET\K1$<SW-T!'_[H:56;C68X>^/<Y#=VL4&N>GVM
-M,/'WA6C:00;K&#X(?'!X_R_I<H7HCGS*8*6)LAE<?:4VYV+`4L8!'<^546#;
-M/8M]Q&:UGFO"9T0H[SG'D;*+@.;_V$3(CVZ/BLLH'B.*;Z>!F&48:PNP\69C
-M"MU4U4*0)KB_WP65`+07(*UG/HQQS*?6'7:;&5RI#6'ZCK:&9YP%B.ZRV1T6
-MY4Y2=VY`"3$G_ZK!$*E"<TV.B\\]".5IYU-11(RM`H5MZ>_1H6C?I)`3G822
-M<:M$KJ$QD%JGH&+UV0'ZVZ&):GK[KVC3\K;HJD-E*C^P)KG,&+W51Q=<)OOF
-M12]DK\P:1FI^0;C@0R>,<&T/'=`"&_#"R;EA]4-TS:`B]*9L#.GV*^8]EJ.M
-M^(U&>:#]O\O?5,_,`W]C$13`3Y+DAZJ."49^"&4T,3*-?[<?'9^0B\^$KBCH
-MAUA2[%=N8,RG4E!-#P>X4Z:57+T#@3(AC\:Z"8G$>MWJ6%?$;GBNRH6WEWK]
-M#LRP;.05S$9:5F=^3#AVJ/(4-^-5X9>F@X3C+`74XLI41SP2<H>*6UXD(\I5
-MOF2,03C;QYY`MOE&`CY<;UF[D,JGK:("+IM*UR]^T$VO/J)KY_AH5"2)1$S`
-MCJ)G)3#+!HL[DCX=C4F8YMGEB?3T@,LQHY>/I&#G>94YWB+CM8&=IBC._*7T
-MK%7%TZ^D\LJC(25)JA(-7_\W\#'UAXHZ%V\L=(YJJ+Q.S?F37:RZH.UI^^:B
-MHP4U\Z_#.L^=//A$W47)7`<-P!=Z%&WH\2,B/JR3>>ST]YH"<36'T9,R'F=9
-MC794=_H*648U\H>]916[I$$Y"XK(&N\V-C-,\7)*R+ECA,\S0`B("JO9(R-G
-M7(L8/JW2R(&%71OT@G[5_["<U'$!('4TGZ4V37)3S^'8:_(4BXJ[>R;2%,)/
-M37LC/FQGS*EZ@`@/$=M!?A=+K:T.<6Y)?X^@>!IPI-DK,>85J1C1I[XTCD+0
-M1(Y"F>26S5SSN%6:\*7D*A8J;1N'('Y_"F_([N=/;@SXR8,89SX^<*OV10D:
-MM.)?;!(C6HQNU9`0E1OZD84])W0B(H^CW,:UG?X;H%\%]#XJ<+KZBJ!<0QB#
-M@0_+6GWU>.U^%GJ0D]%?A5=&ON#>#XQT,%FDR"=!-G1,E]U;)&I/Y^I6PD6T
-MF^LLV#YWY842K/;D\K5'8^NM\WMAJ.S550IP0)(*\<"&<^)1>WZ+6-JACA.*
-M@1XF\Q#.XUGQ8_>3B74;V)+]M@QNX=)I631^9P*#!5A:M1_^%FF!I^1[U?BQ
-M@.7R95/7)FZ9NHPKUNIWJ6HL)"$_:1<4T?;T:1K7?I>R3OS'OH53X-"SP"L-
-M`?/X/9/),;^G/OS$/&\#*)?2-PF>,;/5`8I(7DF.Q*,@S+C#(ICR<YR;$)8R
-M5/!))C++&P\W.-I,S4P/(6K2E$"_!*6]/&M%_AT2Z,5:UM5V%MJ2O.QP_2Y]
-M9B2:[_'>1ZYU(>8K;4G,&]C?!?!L.#$TJ3$MIRO@V9X*)]MSOAJ!;[3K=O(C
-M7(Z!Y4UK!@*/`Y[8.S-8FE26D4\RCR%SGOS(T9TP&%VCSTN1@/N)%LX[X"[#
-M1?)_N#G!EC)=),,&BB6/9_9!<\-MO+9IJI*Q=\F\=J^(;3TH:,C,YTT'?^]H
-M1/#.</)X"R([<GC@HFN-BU<QMI0&8<+D>4\J%G_T0O*3Z/'^H0/#JP/4.,V5
-M/I2PU^9='9S!1HHMK74X9DCG3Q=8<`2#FZP#B"Z_Y'M9;"(8;`Q!A5<:W`?7
-MRG[GR:\3U&)G:V>ML3?[*J':PP8`?R3TOL(M4+STK;2=[^WIX&"')EW-BX3=
-MKW=/=3`*[?N:44JFW<V'K9[RD9K]]4%&V.?82_:LXM4W9[D\3+8$^%#8HSX@
-MADN08`+H9^N,D."WYVP/Y'Q,**-/E(C@RSU<W<)-M-%?VGHOH2R4#^HZ:$#_
-M?$6.IU[X:$#5D1&2<>QT>-2_`/84*,FU"V'+;)BMEBY5:3+(J,8/T6C%[/_!
-M*L;L.TZCT/3HZ^@/#_TC)_3L"1.[Z+Q(FA,,1VLT:2KUQ*#442*=9Y0X<>S]
-M>RLSP/3!%K-0YW/>_M&8HW^8C=CG:.,LI>V$P#MT*B)]^8B8[3B_[DHS#X+-
-MOQR3>](1H])E)$BTL5*X-_FVM\M*ZTS5;8>+-=^L\<O`8NY!E+ZI[$+^EV<Y
-M[D[HT)XU&SIA`S]SXB?O%'2,E#]3[M?_-SP>;#"N3O\8@-@`$JS[#CC,(ON<
-MI<*3?DRS.&$@*>@PZ]9EX""F@^[?,/2@?\%`3&?>"#:(.L:)$`7_0`/">3W:
-M+_,Q8?Z-1U:CR#2]M&OP->&AM9%2UV2?M895?3NHH34>_#/$HA&VW&>M+ZV@
-M99YH6]["E.38OULK44>G8_-!'_"LZ1[J58F!IWQ;9NS?)9*II2Q4U>$(D>T9
-M&K9X!MFGX@\$$Z[OH<(%G8=UM,LLJ]$ULV%,8&'_1Q_1?&X0/'>V!NN*^*F?
-M84X`=I+@F%$8$04YHA;N,7&/T`[)30/!F86:85?07\BWHVCW6WG<$ZC86BS3
-M5@'O<_0W3LDL5%R4;U[U-S.E?R/\#+$8V/<NQW)3D&FA#+K9VB9_G'M^?<8$
-M+Z.3C&?403O]NHC>SDBF?ZD[AVT-2S4^2UB>['<Y$R+ZOA6=*LWXA,=;H'Y]
-M/#SV=VEVPKYP2-=)R)1C#450IP<ZK6S_V"J%H.2'S`^UO]BB^4`\:="PB2E%
-MLF?2328%6RM=6QP\-&"UN:,"E30@V)T5*C_/V(0TM(J),=31505`'>0CR,@<
-MZT6*&,U/M\[T8X(3JUU^I4-S]E8%L/VVMJI.2@EMW>O:<##A(5?`S7>CO&>8
-MVLJ&C+@A`"G?5P-6K09+L</N,CA40J\)L<HGWQVQ$<J*FSJ+/^&_<LB]'5P4
-M@+U3$SWY/'6D--<]?LAQUZ"\X=E-3R<1#QA<HYUAS:>65I$>=K7..0)HN/4O
-ML+>POI?S#CS\("$2R=>"<IJH-UON7I@RJE3I58'0",6/N=YX2_])W'^_V4M!
-M8*/P8:WMX>3LIFK$#@L<]2'(98F,,5C^[!`2_+S%7&`L+=E.0/$?NO\+K'6T
-M!"#K)DN3R&N4@N*M%!?M'L9>Y1W.?'IJ$?AP->\K"X5Q.'0(&7?P<=JH^-&#
-M5+^I;*K@/S>>KT87)W=^RSOPH)"B4'P9"'JJZHN-FMO^/VL1"?4@4Q(CRY$>
-M!`ZSW.#^@><8;HG?+HD-2'3\O_4-5!N'%(CKRE5=^6AG@N@DM$O*V4.8E*@M
-MUO,HGT_6\87H-6'][[TE0J*N1Y4^9E#WVQOR,^Q;,V/BL(.Z04'VRD,,RF/8
-MFA&+T@[U7@]I;C_ZPT_<(3CLO!)X-ZS_M%H)=P4]4%.`Y4#[<`S2%C[<<#JJ
-M]6HH>B97X9U\D==`L8KBS`;$VODE[+NC_%<WS2].][EDGMB'-V(?#08LY%K)
-M'ZX%OX2@DZ_;)<-G)KSG!&OR7Y8$`=F*D)DQE*#*9@$4%E&\XL8[RH!#/7"?
-M8(CO4W>*]-2YW=_ZPU*^G@O3(4&KV9.Z1,>RD'GM=Z'LGA94:*$U<YT84K),
-M9]T`O9<=/:$F;#7JRA*]6X>PG=A&Y\[1FG/JBLRV8KV49RY'>[T!!3M7)W<U
-ME(UF'+45\HFZ`^R/(BM-)/,N3:XT:V3Y[>$W+5W?"%J73+]#LF#Q2"\('IN?
-M"LB*9/RXKGP>'C36;8.^0KGQ\@6'/R*4^#I]'O'@HM!/9<>V4C3E23CB$Q";
-M>[37(7@IKR#AN(R'+!:(#"F[4<,XJR2E?TL>A7\4[D$NPGW+QENJ\XA@S,6-
-MF*G<3W\KP&[XKIMJI<8.1=SL>5ZUAH5LNCGO)G"<CK8HJEA4LRZWG$"NJJSW
-MK.ZH7OZMBQ[8I+;X?QU26;,FG^VR1KSO8@BUPS<4DP-2-QBXN(A1CA-4PB(Q
-ME8$5T<@EG,`R?\`@S<S'#,#IE4Y$'W!T0#6<6$V"=/8:M8/`WQ6ZE%P?O;LZ
-MM+[A8*4"4H)S[U/^T,,S0FH`BHJQ81V,FL<85',>TUWUPG)KZIOWRO2TQD%/
-M&V(I2H)T;G9YOQT]I<7.G`Q,)JHWQY))^2M7F&V`QL3A0DH][%KA(E77]-`L
-M6A!,BB3LR5E8_J"[>[[XI9FG%T`A+=H8J?;3%"R![DE?%E/VCV]+2:CX;5(J
-MQ/4&(1`&,$?"\CK79=(4&/WA#DG&**S%,+:+\\YJBY+)FTFOBASLJ_\`V+WS
-MJ3!74[Y)3B=<KYHT"CCOZIDL^J*K[Z\+&XR!`G&SXSEV/V"1D2?(P>!4ZJ*/
-MUR5W;Z=>%^/F(?'WV<[I>2.M,7^84`\MD*J?;24J@'\\+*YY">Z7[J;XD,ZA
-M=S,<9S2][?2O[Q//'J+_C$Q76R6DF\/_#)SE'80'YW_=-[F.SY59TLQ:-MHF
-M(U7EAGS]/!CEP^9.Y5Z=0K`F6;_.('2R`\@GG:_WXTJ\.=,S`@7KQ5%HTAG9
-M3HTO,'NKUTPQWA3R(O8$YU>C>BF.X.W%E;MT>QBM,/L#^?B*+R5W:S%8#@P_
-M\XWFZ2%`)(<Q@`41U[;0HHF48/P;N;/!>@8E2T?YWPE#KVHO>V1_:VUF-'`&
-M3P<?A9$13+7<WMHP5H>ZK5B;%"3EA0!W,`]JJ#,.C@"7`$P83#B1=-K_(PXK
-M$J#28M*H2D`0)'&S/Z5\&HIQ[[2\A!("M5G7+JJILMDAYIM.*=M"S/)>=TV7
-MF`<8>1Q@,-_<RZE:=JAETL'H_I[8`^Z6Q7T:]WO\Q2'!F3IT2"M64'S\ZB]!
-M>U?D:&%T+`;#%PJK)AIL^56N2/@]U&O*:*,PV-JA2I$>EB'!"7KS?AFJP02%
-M++(UN>*(8N"XBY8&A/7QX_F6!9<@;7K,6>=T/^?F!\H>Z>W9HD7/<6?BUM\:
-MC*)3@/@8GU;$R@G,*:S7-P+H(E+5,G0',RK=MCP%/R32MSN'PULI(RMV;@Z"
-M;7)2=/&I/&E-3YBM(PE4E)\6GDQ3(R``_E?"^T6!VE`E^3GJ#7$P,HL['^>^
-M%H5YZ1LT_+NQ:0^N%:MA%A:K^!"GJ]I6_=WHT\Y-&9(N9GMIU8X]H^5[M^DK
-M/?<M)1(FQN$6P>'8S$0H<E!4/(?3RBA$7>1X'=MB?NI"5)3OG00DQ,TZ6('R
-M<;(S79.#4)NT0%;O5+031-=:JQ1K$N4X#N>E?D^WY%J1M#(K#7=H:6;OC1+;
-MVE%?Z_%K%YYO;_2;YZ@FJ-9W%:LF0FZ0=W7I+&6O'NX%,_E.@$8>UR@Y\[<Y
-ME<7!AC;&`X,\O2,:3X7H5!F6721MPG;PZO(1D+O*(#J#0^&<\>,[S-;#?&EZ
-MB+4_AH%Q>A='PFZ:4YN(-A)ASN_@EB=Y"(O%]C]B6Q,UUP3[>'K\;!<3;]5Q
-M*_1K^$TFZ<BYH48W-C;6!/\Q+KM))?%7S_U`=#[C^5.K;:6R:O(!N@&V)(_X
-MD2]9K6U8%1=*^.)'U^H6)?1HA<DL^=UK%2BS`AAE#:&`L2D/%GGU7\X8Q/P+
-M5&@7NAO'@"Y\[?*=L!?(:W.1A[X8[.\J+L]-'%<%64B'78JJBT[D[UY.`=F2
-M;IM[OD;(C,EC2-Q'QJ+762A/;$#4KZ7VW1$C<=,H!X?`3SF<WF%!3)^:SK\'
-MBJC.M2^X*90^@`6&S=6,XD1B.(:=317GZI>BXF(?KO`Q='\16))\5I^$2OA7
-MR9;!2!3>E#7R)`ZMR?W;F'-',J!?<DZK6JB`>YHW=H7!H$K+/U/JJKY\NGP9
-M:&=P7[Z7[D+#6&4N8<II,GVO9P?8TT(6-$<XQ)QQ?:'QC.MN2VCV\$=?:H.W
-MD3(6(W=WDS)Q2=YCD;ND1E0NK$OMV&Y,)$)C&TOE%GLJ3$YC_3Q*`[;R<Y>T
-M^@9?J(YB],Z52^2,HW+^ZS7">.5)?&\;!./"5M4[>O+9LX\G0\6&:C^A)2@*
-M2$BXG\6KJ%Q[LIKTVMBXBI#ST!@V7Y``22HW?VWQ*I"9[E<JP2&DAK@7+5\'
-MQ%T8B"!2_0C)[TD:6'8PUU/LZ&V^IY"L$Q'QYE3?2;(9K]DPZ)$Y)H(20W?P
-M3N=J*G3."T52V6-1#E(47)#9N`/0.R&<!-`ZKMH^&GI^.]B-2,FE-AO8PC5N
-MF0&+M*:@^NF1?5IGH'T>RJ$X+)Z\$F:^EF#Y]VX!,H3U"D;;)V&$=^4`%,-A
-M05PKYH1",%%]5`Y;NVZ3J?/IV6/Q_7?KY"<3OHLPQ-JDTND7#4'27^TQUGX"
-M#&AM<HLB3STG]1@Y*!-K+^#>_'ET@&9US((#:!TSM]20*M?GHH2FJ@./-SV5
-M-XKD]+:J[]I0J!#$]^G=(_;FU%Y`_P%BR=P:X"3-XK3OF9#9,)I>)J5*O7BT
-M3`3S$)^959$V^+G4KG_ECRS+#OK_,NH^@<]L\6QY"G3(XRR+"V1AP7X;VM#'
-M_/;H%P/6@F>58-IAN6X0#O\"R5#3<WZ]^3RQ_[E^[T5F-[V"!Z-6Y`'NVR,(
-M0:/<SA>BU6!<6W(DEB\=`KCW7-F;DGE6G9^=R?_M0@24^2!`:%XI-(#F4<T=
-MK.MK[FI*B8FH3(L@&]27B=9K#T:"A/JC@)D42O[XY:@S8+,B??(R@O<?]#K_
-M`850IPNK24SY(W70;)O&O;>T[J%@2&6\J&&K'G-.5*@_"ZY>MP6IHV912].-
-M?9IDL.2/71/2U]A.QY+/)%ASZ$#L_D:&%48F.)(<DFRC>UJ,I5"0"Y,7%4FC
-M$$,8XQI60,YE'R6D##)/:2F+E=5#H-V"/G7DB+;WHA9CMUJJW_M=IOP^Y+WU
-MZPH<2YQ&L_,Z\D]]@(%FH4JM1!3GN1AXB'<[SVJ'@$04<_2+N<MK.?+LKJ$A
-M`'7Y8N-*_G@RF3VZ.[HDI]*8[=?\Y/]?JSH^QQG#:\[_H_-,]:_I:%;@9U)P
-M4W<0J!`^?1-9+QX\C`:M7T82L1EFG5Y27_05*CMD`FWKU)WS0D)/[#&SD7K0
-ML5]SY`LBAC._.H,O7C6:YF$/!*M1SF4"H%5F(T-=OGFX<1'Y*RV;UQ89+Y_X
-MXY`UP"NL^3Y0[(K&K-_D6&00SQM7<"[V%64?;BGCF,0GE(81AFN6MPOJPHMD
-M94L^XK/2,9>;.\)PF#.&1&U792N_\:GBL0U["T]"F:+?9:14W]*F1RZK.]V?
-ME,EQJ!%2I36/E-)?=K9%C.O$6!N=B-1M+%)XP1%Y\=FFTQW[_@+>='5&!O!]
-ML;9'38D[\N9K4F7>.FD7G+MOB.#GI[]CB6V<<M62^N*\;36KG)94N6=(URN/
-M7D$*(4.E/*2.\0#YKDE-L\WQBZI<'#DXHTH3=\[[[NVW>&8N619!&1(_+B]8
-MOXM<79A/B,2WJ;+W;_=5<'##@LX?H?I1!YANJBHX^CP#SF?8.Z_/LM)J-/SM
-M6U7\PK5KT>KYO-!YOY9/("3M4XY_Q'#D;2(03Y-_N!>=N@8A;\(G<)30(%:G
-MM<W9/'V@GQ^7"-_T=,2I7IDRZ4CS0N,E?0S%,ACO"R):VZ'_;D,'-PJBR5_'
-MZ%`HPHV*%1@X%\Y:A8+A0[1:=6W]EWEZ=/#8UY;.)<GOMV1[(5G37OC4R,A*
-MC5Y!=-S788:B@7YDIV24QC!,$';9\:D_JMR]93HU";WGIENWKD)DL92L6]F[
-MP#BA'%1-LGJJ\GVJ/8BKCPZ*S#>(MNCMD'3K<U^5@99$0])=;FMPO?2]F5*8
-M?$(K^Q,/4,87\8"^!#@U>3[KK`G'!%J,#U$V^NX9U@FE7W>>3J]7Y'(X0%PO
-MF;2A='"4%N@ES"1`CSJ0"-`/[2M6"+VN\6W/^J7X[/-4F'\Q`R,ZSQQ5(-6Q
-M8B"JW?(=O[WK/4Z+37$48H6N'K?4S)`ZM2L[RN^W]FVRS$0*_YV[O5A/3GVM
-M=XR-8N6PG"SML[0ZE!T]?9'"`Q`-1R.4%-@OJV$I#7`H[W<E)8+^2.KW3L=G
-M5'YOH?`&/C3<].`$5>%U@DM`1Z_^(C/S&)LN)-_#DD05+"_>)7K[8F2,*=F^
-M!GU_@MM0V&(95MQZ/V;H!8"MM>S4P'F`CK#YO_&_O#5POEQB&?T)8C+P)'BC
-M:VQVJ`O+PAA+R<"88VZ62X_1?-'3OJBG-6/GI,'4'S6I!ZT;Q;JR<2Z8=EO7
-M=Z0HDBE;0R=_<M5G$LK\\.V'WXE0YTE9*Q8TEQW$K-4N;"<#T@=`?%N_P%-R
-MM@NW3<;'T0!O?;^P_#Y8VT#\"U*P[^,_YGJQRDS?<K/^!0(<"2T,YO852CPZ
-M7`[Q\@&&C=[W+*;_X[+4<B0<E!$Z.I`$RL:,;P(!X=1GD"74,L'8:.]+;$M^
-MZC-=8X^*L@?!$R3$.#7'GC#_5X[S2E>B]-A:&72#5>1,^0'7V.QS0^&7\ZL*
-M-Q8.;[N8DRT:E-1_JTS?GA/\@20)T2U?W`]=EW$(,U[PM@B<4!,+(Z1P`PNT
-M=VR?.1RBH/][YP=D[VTVV\VRQ5JB\G%8$4W5.W'M#'T`GXK_H2\MP+A]62;K
-MPME!%4C/WJ4W1<PV7[061T1?S]R&5%:(8W]NQH']&N.`2#H[@3@KK8KM,M3_
-M%,U3U#!F=+V>OF#0JM#N.UUD'W'&2R3AI$H%2XD,7!;>DG.]3$><GG7&+HTU
-MXQE(AN:C(T@_74KCFXHDH,Z-&!O-5IR9LX^RQ4Q17#SKF_WV]F7CJ.$2-CR=
-M1\G]2M'IP+'WR6,_2!<!?#'*XU[I2O3G1Q8NT?:!4'ZF!(?.&@\1A@H1VD+I
-M'@OTVW^YS,PCW!0YE0:%633KPN!-YBU<9_TM!&@"3L$F.YH)P"L8AX65SLA#
-MC=QMW;.=WNEOMSH)H94TWW9(-QS^I,?IIDIW^;0(0A+'?F$K%G>,N6CFY$UY
-M=V!P2DL!6CV6.&8+'P[\_Y>!<\/!9"';;/CO]%MWJ8$'*Y(>*-7;M][IEFY%
-MZRWQ%8!E1_"'>MW#.N@@2Z)(A;/,F!7GCQK"+/Q;B[L)?Q6O'M/31:S+5'OF
-MR2O\J3Q6$@*>B[$V#@R>'*Q9MQ78]\<<E5-C4Y$<P%`@8J@?AR[V>385L34F
-MTFH:R?4'I$`6'5HB/47:;VO4(/!W:C?D47CK"/G?(L82W*/9#7&2<'E[$2^O
-MUX6,:S2)&`3,OO'@[1&V&B=-LG4:A]3E%&R464MXG8/LH"]P"R5N=Z`HYJ>[
-M-KCZ#&.R3ID.-R:)YA#/)LVV'74-`2[EZ7%0T@#SOTD07*R#.)+2K^J_7':Q
-M@9BSF",15B@VW0U@?"0?T#]=Y';,J2:KK7#X\T[8C]O<GM'.+&/,VX.O7BRD
-M#<?9R.Y)1YN8+@QU(F,>(/CA5VW3%NRWC6LT4)W9KE7O1CWFC8#="B%4/H1K
-MYS5BH47=%`QFFW7%*'%74:)8V]4**A,#1V)WR8S*70,N$ZSWWU]H*^.N61X>
-M;]A3]SJ3)/47MI350ZX=1L,W,ZVK_;H+VP4]I4[G>_^/NM$4#%A2IKK26YJ&
-M+`4">/+.':]Q>,\Z:WS#MN7+U;M.,6L\597"7NOI#/I3[GGP6#05F9Z@[1E*
-MD!KQH$D2\DH,-&WUH3X!JMK9X9J4,BIVBZ!5SY>W#,X*3X]G$L7-_M5K\IOH
-M?(HMP1"5G^,,.@KM"!]1=?ZJ&.G(6;*O&^02J$:AQ'IF<)]O!)A5>1DOH'?W
-M:")&[T$>B?`U"7/F12N.YF,G)(BG>+6`@OH[UH/KLY44IM'G,/@%(SO#C4.N
-M\Y"QYG*<_`BYE`V2H6K3F/IM'(H-QB+,7843T.T;PRE+6/L_$7[2D'G-*H3!
-M?Z=KRTDRLU8@79&`/VI+_O8BNZ[C)B&Q!9RU;(5,XC/'".\_%4Y0MG0X;N<;
-MPYF.A10G;KX6OQ&S7$0$VQMLC`0ZK/M4+TT'9/8^!RYOJ$S0S5YT"!><Y_[Y
-M:<+3N]/UCV<2U)XB&PJNZ"]UR0H]$GQTH?^;&^21F&,RN,HD5.).EYNICC+<
-M&NL!AXDG_C^];R91XDF2G$BVS/#JJ$3@U,=B<CNT-`R,N\RVVV8SA,KOIOP=
-M!YU>M))T98:YTFHAU=,\C6?/#,(!]RHH[-Q2M9ED9ZLR?H8):P3SP.6JOCQ*
-M#T*'N$6K!=`]-%\*CV,>E]9?T\1+#@;#5<=.D!T(PU"T?'6Z;%/"IF#Q<D"R
-M#I[XM()75.J`?1F&NV^CM$O-L)!WJZ#+R^4P0>[//R2]!$81YAAC?_7Q6:L:
-M$J_.%S^3W1_,\>4V81*12;%\0>@2/,*OV,9%O9+M26Q=_%.!(A!J3X<#D>RS
-M>.]F*A<%PY.8`PC+B!^%D[F'J-G>,DH1Y098!K^$;!7M\-=PAYJSA86CDO;;
-M-0M0[R(ZD@/D97$\4XD?--S]20*6FJ)@LOX@,#<R1/SB3>CFF+9NK$I&[GV3
-MC\,W01`E/VW+U,+R2AI)/B_1.[T4R+V&S"BA;9NPZ<@,H_QY0%*AYQR9QE@H
-M$*V<?=%$?(](/+B?M4Z_6MZZ]:-F*RA=Q09Y=/$YD)E&?RIG%<P3$,/B2]L_
-ML!0F*7]OV,YC7379>V52"=F)8=_^AD>G9DV-0V7CIX;18!@6`+6XWORG;BVC
-M3<@9B*!:]&>P2UX)6`E7<@9*6\IKD;%*V^45"7+LZ18G"VA*7_PM,FR2HJ'8
-MD,VO0!=?I47D,'D!(L",.J]K3R,$:B@TBO#]M#DGG;_\*/:YSA)`XOOD(Q(#
-M&88F^Q34CYKU:@0.:)1E9'R2_CY5"+;,.530_#LA+[*>-Z=+!WN?!>'9*7`R
-ME;F/F&>E,SLJY*6S0SOF(4*_Z<@S9^\53WQS7)#8LZQ/VWS>?ND*K.;E@SP=
-MN;1)Q"S_:0GW3V':"4R+A(]8:R[=T^4F)%B.%'QJ1D_W6S]-!T(K55+@&19P
-MN'Y4>QY;6"HO4^"%_9;;N8>9&!-5K"B1?^+K)LZ$8@UJPDE94HYL8MV_K@EK
-M>%9(G1D.'9@]-5#(G[*[?-"M/7X_MK/=WD5"`4PAKB58Z3EQ<9T/SV=4V<;<
-MQI-.0V$9`DG@Z8@@%"I'$\M>.\6&*Y=U/=[(CIZV#P:$P*9W[MTBV9%$TOY<
-M,OXP-(%E_S4O/DJR=)N$'!,KB^@=6557^`IEW&!'7\=7WMA!?G@M\^0]#5YA
-MM"1T-)_U<'1&1NWY[4&(K_$.'2?1B+;E%Z4>%`N(IV9Y*K7BVY_Z@8A6TW[*
-M7H5I\%]AZ1^X+>J/W/*`7:+%VMY#O>:.JSX&!\[2)G-T;0UWVB,@OH:E>^7O
-MBFX`:7]:7.=7Y]$8GR"83--'<4T*9'>4L-S2._0#B..[6V%AU2AT`FRD$=:"
-MM7<20UE+\^*:\?&7VY92(^=P+5L>&*'U,>(1M<&(%1N^2/<MN3E8N:J]E]TA
-MEJ1^GK&+#`_R2A*]<V;O]"4C,&:\83DS]:?MTU30+P"Q*2*P;ORX50&:4U[/
-M*40QDJ7Z*"U7@2&`'1_C_&81+"!71Y>,"22-[P95;=WQVA(>RR%B5[S.\9X:
-M6;;%R)N".K(B38[@5'=PT.-"%LGY&IG70OF(WAI%*^-"-$&Y=[-ZW^ZRAY2R
-MDO0-5>"H#/N_'W*ZG"\U;"(A'WZJIBT%K*G5'W8G<8C<F'I%R[*N,DXY@O:+
-M;9>#-GQ89^^CQS_4J#!'FHNB0"_;53Q(GAW]<`"IVB>IJ[/WB"J6LEE:=6+Q
-M*V,'4M%L:/HX.#$N&PDX->-H9<`3:48T_M58I^R#*O7F?($L/D`3)1L]85O4
-M@,WN\DEBT&L6[O&)CW^^2*'?[L1)?F_-I,!ROVMGTV%#,E=.-Z.P@CI3NV%^
-M?0P\:>P$RD8JR50/&7.YN1\P>U-6%$/\A9U6B&F3,MH/EH%FX$D1BCP\[.3&
-M#1ZU>D`NJ">_A\^AK=3/T:80WAE:O_=1<(/+F\K>RW>:5G>.D,P51</V5F_F
-MXB9JVKK#OPP*)P;3IBL]/1C%-X!K5W3%;ACG+FSXMH)OG-O2XTCFO171:SQ7
-M;_U#F=4=-G%?#G.-*5&`\:.3Q!@D:EQYZNQ$.,/OG"8**B?ZSAL0)AJ<-27)
-MT=9_LNNPMSJI3J7/T#]AYNFT48C9-HT0+)C2"N.?D_P(_Q9IZ'$^7HA"T)*]
-M_YH!Y1NA=CWN\U'V;.&I\(X>[K*E#!DE&_'VJP)]9%\501([L-:K!^KO%JDI
-M[I-COIMZ'D70A<IT,?HVGJ/A/2/HF7T-O?N9-[8W#X)03`$?^JURH65?:BO0
-M!_0\A#A'K&-T9+"C]5)?#)"DK6E$2M2=;-/>;VK(-*#^2]-QS"S_SNLBHPDQ
-MRH`$#.!D3?4-KB^5D4=J`'0^Z,TB:I^78ZW*+OW*BGL1CCRZ(5!J..&JD^Q<
-MXS!W17U&J7*]"E5C)`C@,7H($!1ESTG9R8L))>6_/[Z>G;BGMU@2$Q8=RD$_
-M'Y9/<Q:SWT8@$='^S;%@964-*PSYE5.-RO'YXJ2UD:Z=VC33F;MFBKZ*4=ZY
-M/B*4`,5E*<\'Y3X?C<[S-=1=@$#\P+LN=D?J?58C\,]Y`M(?NK5_YN*9/GN.
-M@?^Z=<PIP<(UP+6(+F3<KG<A[X2+F9$L?W81)"'V!9V,ZRI;@6O'_6!KD)!?
-M>K:IUA0$N:--)AR;T=3X0NK%_.25"O[D\J'/OWY&>$-F'87Z:,KU*/KN$]8Y
-MRAS_8BU'LY/:H4>VHQ"SG`U>;6QLVDMDBSFS#XLLO88\>BDDOXW/EC_'UF:6
-MZDD-P56Y5UG(O6[>!E3M_*98R[;ZDB<,+<_)G2ZR')LY`<[+]L4HX5$N`N-\
-MAM\#SM/LS48'&&J6U3=.2FJ:_AP<Q4IZ,-YE.P)@WQ^*FU?=I%:IXU.9;!/L
-M)!*_>:8:&_7G180)1.7-)*:5&9#;7%O^.H;XNSX*V&G+^PO=Y10^+'BUISY9
-MT[X78E%50C=4M?#Z-Y<ZN9&/=P_7L#SI.T2_=:=UP*3\T%`<`R>M>4?RO+7M
-MQM5?J^DOSCK1_B(OXF(9[!^WIX@VQ)`^>Y10ICYGAV:`N[R;]/D^<]:`@UP-
-M<A8^K9AU^E77,:<"L0J%[H.^L^0[%!+TYTE?[6N^3[FG7QJ*90;9JIJ6OQ[V
-MJ9ME`GQ*-BSN0MWYX9JSL<_R$X<"?@<TP6)NK!PGPQ)U[\[`&FG^_03>:DX]
-M!;KG36`94`H=JWD65.;^A[H#4*<ZBVGS&^W#E3)VJ0E!;RB7G_Z:J94J`;Q^
-M6+)1<B!=G'!DCQ$-%FB;0\*ZO37PQ#`C49F<82E6<'PHEKZX$[F^Y6S\(JM%
-M%[O21_T_ZQ)Q1IX_$)AXJ59JSA'SI@:ZE)],(^35-@`Z:?&]0_&D?PG>!R<"
-M&X<0?/H(L@OP@""%1)3:T.=8U?*(7[J1WZE6LT:CYF=!DX>1]<K@&=:I=T8B
-MK`MO*OMH(H8@YI9ROTOC8RY"4F))F6CT1/#V5K^:0T*I)F1<"W<>%J>OW8I"
-MGP)4'8INX*:E54P9S^3_UL0OZE73$ES$6G_FZMN'9QR2F!$;4Z[-Z@N,##S[
-M=J_^5/8F<R"8M-MVD!0B`@B'%+UG<$+"(!9_N]$3IXKWL`^*^!^=Q@M_8/D<
-M_/UL@,KX!4'9%*S/S.N.2XC:!6R1H$L!,"T?#4(U#`IEC5_?Z(#*K?X5NQN_
-M\5WE>C>!LD&`?R][OR*FRL:_H%"5C!&"M8+%/Z)YG-YM\2G]:P#2IUL-JGQ5
-M5>:>YCNP^!V1HZ.PX_(,;R;14(]-J0F:%4FVSPUDH'MVG[]7IK=:_^Q?ZLOY
-M4O\$H2.`<-2J'$PK&I?`*_^.>(`H[<117@S]'GZ`K^(WIM5I44/2BGTE/PI,
-MW31U?1HW6K14EG9W?IT>*419,5#-N\(H+:^13C6LVQ(L@]J&/EZ^85S:%_KW
-M$$_[8''Q\K?B5UV89Q37[MA/Y$A%:>""E^Q9U5325Q"IS4OJ27H)$1Z=G"H2
-MBY<H.M/H@5*U#^A&*ZO>@I[21%Q1.`/?945EB,<W`;?_4V_`,GQ8/G0!X"+[
-M-D@](0'4%6Z<\>/5=;UC2>>&>B`>`D^>RRK`@[FP/9SP?_O!][3EB%[Y$9UK
-M3>@VOH:[5]#M?38L>$Y2CFN/ES/,7["%,9M-&R7R5$@`XYXUE$L(1>2,&@YY
-M2(9?Q+N^76(BOGZ@;G[C=]I7HZ)AD+CLR25G8J;9@FJDRJ(#9VA^37F1.+_@
-M8`(;<$GG#YM34V+?=%N>SL?-;416UOU]XRP^<87/7QS+XX&1I..=D*=<Y&!^
-M_1!A9#=XN<]?_[C)-#).W5VDA1P\]?5/Q!YE"G?,OE:?W9Y<J31=*L4IMM]2
-ME!9V-<MI7!NO6)PL7V1\IN\"YM]_89YAY^";281(V<@V<;L.-?WJTKS)J9"(
-M33,*LD<\X9.UC:Q3;?[%17T_.EI/K%DP1Z\!00P]*Z)_=NAAS1S!D(A4QK*K
-M:W;"4P']NSB]G5L84FW:Y?:Q($^*V'A+&Z=HJNOY/Y&[913`O0*FL;U*C-/$
-M@52+,:H&M7#.N%DWQ;YVU:_YW.0"D*A,`1+XWB/$`RGB(8>@WAVZ/"3C@?;W
-M:/$Q#-.%>Y6`0_J.R;V]-P/>&?^<SI8UH2X:#K!0[CGG"/_<[^BTC?"8E.(`
-M8F<U^#B,#A&FM.[<:+3+GS7)\3Y9"/KVZ(&/_4R8QW7L\RMO>PF:R[&H?&H`
-M*`C[G`)AN2;NIVP[J$5#/3<<!CVY^M;NFTG[RD9=(&Z"(8K;\5)>4+D:KPVF
-M<73KSWAXZ!*TU,CLI^46,C*P-S%ZV'H6JCM1'-?-DU,GEAQM797_I%$J]D#B
-MI"W(.,^L5"H6C-CMLQ*JZB\-6S'>R%E]`%=)/$\OI4M*<%I87?CS=K&4O8N$
-MJA."LPUD+0VG;>\]!*Y_U:6;@P`)Q#B5)=.J^:?HV_);X*5R#1J%O.2.\<)!
-MTD0@4D43IT[,&&&O.TGJG-RCTAG174KP/$JZ;WOOS/48^I,$NMZ(%`@V]V`3
-MPAY4OS(0/L]1B/67786TXR:CO!L'O_M7UST'W:C>U3FOTKQQI[0FWU]$Z+Z#
-MBN(1>D-V6MZFZ_A-:4VD$OK>QU\/\94B`^,A/2-CE2(WZ[DFAYC>9%8%M=[?
-MF&0]5(OA_P:?G)`EIS8@&7OE<[W,1DJSV;LJBGG7.+'(JH4^YP==+D_+&/,?
-MJ*;\*[J)AT9M-5,\1E7AZE'XN0?/=)UR`('0'P+.:/IEYUA\UB&78T#V!XIG
-M''8/J^EQ22E56A>*7JO4KBWEQD8-B8/W7$$#QP,Y:FZW:MK`-Y/G0K`=/"=M
-M<3X!Z!U"UNIA!XK;)5BH24*5IP8T\P2+]XD6*9?R^5""*?I'U.F-XNUE/Y+Y
-M(=<AXK7COA`J3.!?TWRH-<];KEE*]V+GM.+>%XGTSAD,-22NX2'M,;[[O#,Z
-M2ANUP%M#H+\Y4S#26N^09,"BT\<@'+JU"\4@#.2I?&4'I-@-N"TVDE=;GAJ^
-MMQ?''*K^-@10VEHJ^:LJUT^E2MZAE/T5_@/")KVX[KHZ6;>%"85WA+XG&L,4
-M#N$7"2>QN;GM%X]M+<YD.VR)D2+XS1R1WE[II?G6)Z$I=YA\$%03!K*^("!0
-M_?`YGL\%_`P*;'/QD)6B\3CJF(1$)+@3*XQ(YOV]>H`F.,S3(8QF1B"<V!P$
-MB]%;(N-(RM7"NH^E&<3>TR0Q.XPF-*=?O[#!_N97%$/K-"EZE\KU"\ZL,Q1R
-M0;(LW'YN:.&DLTR4&<!YH0W"-X2>^L4/5>E-]Y]@PDM93)L1-3HO%UPD&<2B
-M,&<7I6`%[:]/7%87M74T<<$W+J=T5+%SUP&"/KI_6FPB+[5ST5#]S:5,CX#:
-ME"4P2H4X[-8>[,0;T3AI8WJ%E;;A.%527A608M]Y;MWD;Y>-:7.]@&CX3)!L
-MTH(M]#-\2PSU'T'1(OHL@8?P&6MX](#PFT\YOO&(*`6#R[UUD`P=1.]I<:3C
-MQ#R@'G`&WQ9;O=TO'(]G5C3K;`T[<DA)##NWXB,"=,E#_*!CK$%`\XM#H(7W
-M[H*Z&[GBQYBH:#!WH-03L:1Q9-F^].6;!3";A!H9<U=30]8"KP8<[/=3G9R3
-MX,ZH4WPWL#N:U(L&'7#K^8,AF#4S=JN-CXM"[_XVU:V>B\[I*KND&7V(RKIS
-M3..2Y8)(-0,43)M79C*EQ.]/;\J,XQ5[/'W-=H+*Z&*_OCJ_1^5&`3U2Y&A0
-M4F"%,ZFI%;"6]_YT[ZS76H^1P9[&+7E^E\=ON!GA?0,9<PEX8CL-W8N0:U[/
-M:$E<SB57(<Q=_Z@F)\"%[DV+`P;OO>I@H0%5$%F_[R+NRC_9/86X6V.FQK;C
-MZF:W)QAM@N/#10*69+<=KM&TK#;6GK5JS^G6<C<.$;I`[W;,FJY)1T2C\Q<O
-M%HA\QR9")PKB9O`SC%$WB.X-30V,;T*,N6"N-_);HCI4_II/@/?<UIK3`.0/
-MZ'$D]5<QE5X\MZ$`6=9<,FPR8HH2_LL-)I)&Q/ETA@V]?<R7L[@^&/TS,[&K
-MI$6LX]Q71N\>>`T9'LR\UCWO.N##D4(8P=KRV2Q2]JX]\,"M"U'YFWP0%AV5
-M)`5?>RHO]UU_Y[NYH5ZOYPUHR7J2]K4X"^U6_4R/+^_U'J$[0,:OWY&R8Z3/
-M`!K_X<8#`A`/2ZLK1I*_,7/K`WY9FE7]:;Z+`P)WH^#)^FNLN7I$DR9WGS2W
-MFMA\#TJ0A,(Q1S5.,HH&24/&U1)=505B/K&4]XMMC7@\X0(AY/$'W'+QPQ[B
-M+H9-V:8+'S$GL^_;SL`GW.+GU.A(D]GRO\HE^)/9RP?>\'W2OZW!->_A;/\K
-MU:T<#+>#XSUR.D(L#(-CMF(GO";DEQ98.\R7OLU+Y[KXBX7!>$92U-<HQZ.T
-M/(5=GF9_OP_(E<[G;?2`8P3XC![XU#0?=-99M]+R(XCU08'MRRN$(12(3?D*
-M!X(M_ZN7\($K(*[].IK8_U&)P%%KN;O4M&X+F>>&^5O>,M$GOAEH5]@Y\-U0
-M\]GBOA`&H4,G-J[.GKDZ[ZC4Z=G+"7T)L!J[?A>`:#X)W1U^6N"LOF;.8I=&
-MLH+BLQP:4L`B00W6M+]K)0/;22*EO&64IKDRL[X]=2E@.N3I4T67^/"UO+W8
-M#Q77K(18U]GC0M.MM4$)."(%]R@FZ.^D9Y'':-+MR8=MLOZCK.,/YLU7<7YC
-M/`R>9$NCGL!R!&[WQR.5Y7_,8TS"^-CH6QNL%&*_L=,03,.G&_DK(&1H'L6;
-M?.&>I,#Q.I*O*G61<SD(P.]*<:>7.=O"OJ`JL(];`)3D[3#H=5/M9/$@#:(\
-MY+=3QS4(%J)$/;R.\-8F@Y]DV65^;7MW#Q8IMHN"[;KI:Y+<$[=>!H>1;N`B
-M$'K@X;NU^PNJUM-"(M,XD59P,.=4>&0S90ZBHKPHF-VNUNDTT$#'34*=<3#8
-MH3\YV_Q,SS2[AV)=L;+E693>TZIO^IZG1"4:-ZEO-,M8$8"PH9(27Z$$]_TN
-M*"7)]AO?2H.K*V(R)\C#3A`P";,=5@3_GK,#H,CQ_1#5C@G-G[NKQC2#WX6=
-MNMB&QA@.+>CK?FVU!G*.9SUH".<EF:-Z2\B8]H*_G?0`SK^RK`H^<F"W(&K!
-M*[-M#%1^0H&$H].$ZUN/(KJFZ-[!5QIUE*?7+/)?(JZ;YN]XE,O_+M*<G:VL
-M,X7GH1'0!J)KT;%_Z#9[<[\'"MUG-YIO?;CT^*D$R5-NNT@/C')L;NM*_T]_
-MJGJH(58$KL1EP4D'`!ENQ-&&*1_@ZR:6@EUPB=3[T]NW,4LI^-1FHU><+MJ+
-M!2D:)7,*!C]#O9*:A%O#QJR&=RGC^(5\3GY=C6`YAJQ-X*'*6?'_5=,_WGLL
-M3>M\*%8D%]<-)N?!<^<T=F01L.,`9!8J-W*^].S0]GJDF3$6[-91JQ"A&X;H
-M??GQ/NG"<_LX!D[R7V^M^T9S;OW+BKBRVNG5'51YK61/YG#\T3N3UQZ]TG,%
-M+8$YS.Z\@;3^"MBA*MW3;E`?I/BP+LM9$O2O!EYCQBE*H%&+6/R8^9LF9!;)
-MZ[)GBKM-0VPTUVY9G9".H+N-%$5E.X"XK*)(XTA]",P<6[[OT@!/1%10B(4%
-MW?*#@#\620KAB9R!PB-5=+:*?9_PY1O(5ZI.]ETO.<6&S<UY"/.7#HFR%+W:
-ME^X-\^QE:W>"#GB9U+8'<,H<B69-N<-"\/>Y*GT3U')@4`H]\(GD'3QS!K6X
-M-*H[$-".5'*>]P;1)3T/*DOPPEVS=.Y7&"_JRK_(@4%Q]<W5%VNF<&0Y]:R:
-M'8!PGC$/"L5Q09G)WA:`)2&GG3#QXW.9M$`$(@SOVTT@MY[JE0F`".:%Z8#"
-M^O>D99QF$,8NA,):#D'9!P>6N)PL4%$DK/``"@`,&<LL,[AI)BB.U!!O:A44
-M)VO6D6H.-\;+LMW1[6$.IJY@(T(_9J'[^21`_\#>1!]:P$1Y-J!?K-G?&NYC
-MD?GEPYJ#.A-"VS]VU"3)P2KJ'T4K<[`0*Z_AV*TK+UC[*7KN.U>%*I^OZ1.?
-MY1LK6,3JZ82H[8*G,8W5W/-3'1+8`%91>W3_H:];:G',D&;.+6U$"8Z7G_N%
-M)T*A9PT@S2/B.KOMUTD">+'FKX=<?>BT!$^;P9M3J%;CVG+[C3-YJ74,=R*U
-M3RD2;7SJX$+Y`L8S)W]#*%'^SQZ7;UFU[(ISN2B-2/)"D;V8<<:&<#_I!<PJ
-M+KB%-E_X#MZ<]R'-M_[W98J=V6"2WP3/:[P7\?Y<Y?C-?+U,+)<1.TB%BB3\
-ML4$,WF/:4P!JXBE:(S-]QB7@#QG;#L;/86S[*Z8BIK'__P'U($?=H.`,G3+?
-MZ9!6_B"-!B`JX+#RV,B'KE][`^P0-URH<G!'UJ/5,&W[V,63;/4J!>:>(%*@
-MWZ=T6F6?=1%\QZ16"-,.[=*D\D=%TAER<%'8"]#V>/P[:(X+%TK15,/"@''.
-MLRS,(9>6'2*/R[BEV,ELSZ"S^SJ6C`T+@@8V3N5&>7AJF^ZI'^)M9)I$NX:Q
-MEMUGSUB0&*ZY'J<4'[.(51F:DF$P3)Y<)+DUA@;05M9K"^C9\RU-*#4P+LY%
-MQYSY9M=5<$%3(`-G=*`.:_G^<#AA!Q$2&7TJ]A;MBC&2_M:#$#(S6+?+3GK9
-MP\<1/ZGXE>B!K:+@AETBQVH]@X^=]4]164@EPM,46#L)&1=1LE6Y%X$XQ*U9
-MK(X'<@K!ED'#=93HJA<%CTLVM29`8S=U\RCFRPU'!$`FAX^?@YUQ^-34/E)V
-M?FUT[WMFY$P:XB9JMXWK/1#6<9#F9U9@">@[2*\4Z7#(8N_Q\HL*O8!H[B9]
-MYS97;)QSEJR2Z,R)T\#9N=(?5^1IY*4)G.N8C4;;'%`D8#&@3'C>6&R-;LRN
-M.!6]SDCZWAEO%MR]0<<C?TX1+T+L%70-ZD);_$PH*XK0M]O8I6QM07<[`)!Q
-M[I->4`#$@>7?L3UN<U3S=V^1=\$ONO3JF$.]@8'PL!F#]C'6\E!R:858(?R<
-M'-<K>95&.Z8$K?UMG.V3"(JWZ*`A,V=NG>O9&<KDN&@WV@IN9#KWHVE^WX;&
-M3RX<:!B2*HZSFYR">ANB2/C%%=O?[NU01`>QFEE9)YD:SCC,M%B;%[W/LEWC
-MX4?8\&_ZMQPQH<B]UH1+O<",@;;4@P_FQ02G9,\BNOM$_?YR"7@U2;I<$&$G
-MS5D4KG;5\6^^Y<H/L?^2N[@5KN<+6YV*P2-7OX4`K=U:%1`JE>"N$<Z2228C
-M).;;F:9/1M94D"8T"\_@R?I05B<I#_=TMJ(0Y$R'J5*Y(%/G6`YBK1'M^ZQ"
-MSH!=YL:F35ZBZWAA;$)7+W3>K@0FO[CFS_17G`_GS)+R0$?\O6:6^I%C&$U`
-MX)Q&KF+]&U5U9:^[&E/!C@4.P=R'HR]Q9@-TWYLMP6%MZ]PW0'=NA@P!K,J8
-M_IO^]LEK8]\8K:O1(*$7FCBC>+VT.;7,8.#>>'^RJEJ=X_D@=;JB9?BB>4-F
-MW>8'A=9J4C.0#XJX<'H+$S:_B/M;)E/-,FXG8$A62@_<TVQT^L3%_'G'!P8J
-M!JSV_KA%,S')9R5#5W^4L18FO17;+J,4/.NRM&*9*05"M+'RZVUA;,M&5XT[
-MM_;9D9KG<:L@-ZU_.")UTOS=SA/4,^L[)*]2BDV5EFD;.=WFAK#\1*2-ZO/)
-M:XSD76FH%(4GH,P(0A]"?Q4B^8)HFZ4PQK5L\2&YQ8ZE4RJG_&GQO>;5#1%D
-M)<AOSP"O0V@S48A5D+@:OH<?CBND9G<-:M)NS>20<ASP,:;EU9_0VG*'O5Q@
-M"G#!(SE^6+Z5I)E%WK??#%5N:X<(%//Y[4\4SWXJ%&C.J5AA134_6G8K)2^^
-M@R$DU8;_:'8WF#9#'I%V^HY6L;14`[XRT[!P<V,2)S!7[X>N4E"MA]`[?/OU
-M[-3ZV,FRL,`_&\X&Z3C0X58LUQ7_%PO,(Z-&VZR'5X'[(@R7.'J00"8MAMUM
-M'CO;M7CUSZ.'<RFTZ_,-O<.Y9ET5D!,![=C*.1-,DXB60[%<=<V1[O%U&(L+
-M_P2_.X4/.P2#/SC$BF.&B!DN!0$G`'_TWM\5YBA'PC\AM;OMGM->J>KU+*("
-MT]^D0EN]\YK>=2%$QN5W\@``MW2];(,+,Q_HJ(`Q`P;@'"E$QODV>/2<01)F
-M6T_=7^1^E:TA'#B\W`+7<:=0HL]AI#2O::_[FH$6CUC7X3H/"W_I[T8R7\06
-MB?=N!#"4DK-'?ONGUU^OP*45=G^08KQ;Y]ULV6Y%==X$3:E=@LUK3N8LL18@
-M7E`0][#62YIFA$BH>X0^A9-RMB#$$D8T]/OWM;JDS+`IOQI==05";!XL[_CK
-MVA$0T5V!E4Y1\Y1!6WEAG@?$C`FJ>8)A$^J&Z/:L\^'AI11EU^\2F,Z+&`\7
-M+#DB+.*;]Q>33!]+*9TY?61P;]$8:G-DZ__,]#FI76>HGD,R"#5/#=NEU&FL
-M7OYWRBR$TP-;(Q3EA&V"2UPD*2775Z%(]1X%"2BY4>Y"*='P)[WO#*P&<,#W
-M]X-T77R*DB80/#"`BE(PIY$!4;1U&S]%@2WWV>2MFE5W'@&YU\F,0TU!YM_@
-ME3J[Y@,1[*A=;4B&@8H7ELH5]LT;.+V6)V@6=B7CHA4Y#1"6`>M_P,C<SSA;
-MS9HBIQ?NJ!GO7KD)["%98C/A]SP9S*BVGO%*K!WTJ*6)L2\,\-QW$"],X/Q]
-M",]+%\;/<7++.O2.5^!,8=D];Q=`(C0TCM\A^P%N2E3PL1-=9M1`C#U63Y7C
-ME)7AKDR>$#TQIA-.<17]ZZZM874%&EZX"JA**6Y]1F%-T^TVXQ4@W1I8(*ZW
-MVK#!CICY-ABSGHQ?72M%+/!`0N3J-5<;XGN\@Z1`1$IP1F>S<SF[`9+%RI,'
-M'4`C(FF8\\XQ!\\7:3)K?K?X!I7]R@(@QZNTDX2Q-0[2ICNM05K.L-$*"M40
-M,#)!BBD]N\`K#`7;1G!Z(/01"&KR6Z5)H;<3I6JNC5\GI92)&2@]-BO8*05$
-MT&>_D0W63>NO\#>21>J<8JC+,N_,&[*7I,K[\;\=[B#"4]3O5J<;YY8K1HA/
-ML_8!JEH'@U)+:/Z!TFRGH[J44U&%M!EIH$5ZA$L\L:``@27'?:UK89-EZ>,O
-M0KHG*O(UXIR-ZOZ0'Y38+FTW425PL+%>!R[1VS_F4F$%0K_O'8UGDZ:D[V'[
-M\UTV10?8R\6M?;^P7Q(75RZ=XA?E7$_/.$^:D:,S)7W95(C[=R-R[4EF+!5E
-M,HUVA//CS:&VUW/8\9-"H\04LD7M)^2_>#&!TB$Q@0CE'`1[4N=-EY%VYKCK
-M2Y3*&8E_"'FV#8"8V]WVLKA#C?<"&B<%5PH#*;#CUS*QZS)%!LA"=%OE)C.G
-M^Y`DM)!NN`+6(7U#14RK1#1C96*;MW3BD2X@S,VY?+D+_VK)_RSY\"TG/LLD
-MT*&[,[!6&;?:B$*H'>@`@+Q3DR$)Z/*$2V?_;V[G\:(I6AE#>82U2O=)*TP-
-MSJY>+0_FI(A3G/6(K5CO*R1(G<;(J0(.'\K-[';]/N('6$<+2J=X2U^X!_D`
-MH(??L?VPDD$W$`O?[5(OCH4D%SJ5D+6$([B#/A][4.P^Q!CG8G$82I,T_`_?
-MIH"V7L'(/I2(S#!WTHL_?VIAC#'BH<EJD<Q/O=9:.L"@\U?)X;G(/&$]>%Q7
-M\.O6Q"2Y>#O!5(;;#TH=^9/\D)0%KRNP3?E_U&`Z.K-CG>!]6KK8PY=8A7AF
-M\%XQ+MXIT)7R:8!!/@)DG>#<4EC-46$_=7`J<C_RIAXGF<+>OZCZ20+)Y.*'
-MM%O"=KL`!T-1H0\&*F)`KEVK2_:,([/$>XT+M9]P3OGQ`O2J6AI==8Y8\$_;
-MD40D+'1$IPD$\BRY-O49>S^S&BC0_1&.Z:5KC?F[C3;A"X^J7-V$;=#45O94
-M&/O+/9'?H]*B^.X7)?^BW+XA34\[#B^)S,&MFI:/T?:7^+\'_)<>\,;/+NR%
-MD@0ZV38LVLC>+,-K0[GQ@D$]P?VIJ+R_QRE'QPV7R>R\D4>O3IF(,EHS+O/V
-M3O!I((?&D=1XSS`@R!%7V`[!AQ=<L_D>\LRW0;K')=$`G,T9!V88GJZ/+%-<
-M$*SY%T4'3*-1)/FO$4JUDJ,=I#'Q>_L5<1G8>@REOP`],+G,_%69_@]*N5*X
-M:O4H^.MDXVWOS/U`^ZQHPD37!G)UU`AE:5,5E??'GY@;G[?CK^')\A9Z^-CX
-M"&(E#P',R%"_:^^&8]1+Z$><VC%@UY4/P;I#*B^[GLZ<ER](5)V,;J/1L5K^
-MT0OJV`PEX.D4N*U"IS+F"<",_IW!F8/>4(%I[`8C\\@XVW7BIR&EI,`9%FV6
-M;&ZQ7!@$J0P7%5XZX#Y?\T!%]G]TN==$LIRZQGE*:Y]V%B?^$W21@Q(YP'%\
-M6X)U!R\@!YRTHO_/#6+$ZNNR4(;=4W5V!>@"%T-#F?]LH*RG<8M2(2SE>LJT
-MJN>;AAHK47VWF;XJ.,#T$Q=_9N9?3LJ_FYN,DG-O*P/1ASF@VQG5,Z#<VKP`
-MM47K[+VWR!>P*"*$99*"6PBIFW]95HFR]*T6FZ38DW&@GLBZ,;S3+AA1$P6?
-M0RYF@+:HZ1VD],KKR;8PQPQ)A;LMURJ7Z'U;\*O\ZW%*W!>&DFABOP-?R*]6
-M\Q'%00RMAC;\W6Z+!M)N0HPHB%&6I9)AV>/(<9.KD56UZ6Y/KU_31W1-%0H]
-M\Q2F=*:%Z4%*<(;S:CJF8NPHB'*!:&HG+*N:3Z`\)J6_L/'GW8;;NWX%.5K[
-M)1CIUMK=H!R3P)DSM^%!.%4<Q568OT<!1XNV6I;5G.O):KHR1@C]^P8K@E=^
-M(4BFHCI(WJ0C9'+=XN7V9"QUQ.E?J$?.<'_V\LS/"Q!'V_2%_L&-+L8$W5MZ
-MAQC89F?3J/#)6G.L?6S"[/R`$45M,L`D]80+Q@IBBNH^%6%Q)T!AC)/_[YG*
-MP,.<HA9TO=!5E8(WU-#O/?:;^%_F4C]0[/WI?0Q<X^V9\:W.6HT*7FU-B$5E
-MI61$R`]4EM@$$.4I9Q*8W34$9?H)*>"1>=VS@SST/**G[-R<2F_I<Z"2ZV"7
-M&T9WE!.N`6,8O3@-9TQ-^],'/Z.M#7/F`8NK?%C^0P\CM.[?=PE-;$!A7[)T
-M6Z2Y^?0#_Y<9^<>/E`#$E`5TD!T;&1`^I+,I=WP$Z*0>WD?Z!2G*7L1PSM?\
-M**NC#SIL6B<4UV%_RFZX>7),GS8B%:X$00%#39?#X6G8Y%^/U`J<==8XBG1X
-MNF:&/,)7B*;MQO=\!CMJF4F487=$&)6#^RCQI9<[K<I+$3/%7SI><C=/?A<9
-M>:H=ER7#Z?HTQRL;(*A3O24<KH6M5ODE-)9$GC@%*^YE5V.QR0V^1=F9:>O<
-M<#OH.)`D:#V26C#A^._9BS;H'[?#964+RO043[$EWBR01VOFK>Q4ZJPH..5D
-MDCH\W?I:'V+I9KIPL4Y>LC@HT(R^GE]?MH6T)0Q[.!^Z&441Q10;HI6P!Y@W
-M+/'(L.:.`HS4[L-V`PI1V/`I+TXAU]5D7_&+^R+?RY31:%M^&=4.Y#9"G>PQ
-MS*H?50QJ',(1-'H[.*JN)/;G-4:6@6Z_(6Q#Q)7>A6``=#U!?,8`#L;/1MS-
-M!EO0M4<X!+:/ZCD2H0GQO#PXS+0]?N7N?P*I&FPZU&"]@.!4.(Q[D>SP7%./
-MU`IHW.,=<_4>><^4/Q+K"=G\'[MRD,MRS^V4`#/BS])8SK+#*%/@3$0S\+5'
-M9Z&UF](VO!*\L$S]!PMX3TCSY%L$W3;\1QU\P$MI3/!>XV.`QH2OV;?O255*
-MZ6;YPPMA<S`W%S4<=3F8N3P\@BC#M(P#Y?W-O1MCVA(G0I8*8?#67B4M1$[9
-MGE+3M99:]:1LW4"'F$Q)OVOI:\&:#GJ+/0OP?96=D1X/<G\/;]("9RD9A4DR
-M7]GZ+_9$U==:R=IU/Q(IK)=-(^U)>^D:7I`ESE)BN>6B=K>/KA!?;Z0#.&%.
-M_]F.N/KYJ6P!!DRSK.:T!)8WP%'.TO9&)1LD";IG`KJ(!D^L=XX\6>Y[<W\]
-M#HSO'0E!S,S=#V>EXI][C:1@AN?8W$1Z>5QY`0)0:6-Y5S&P9"F8H?C;:L\B
-MRQ4@PVVCZ[U^!?#R=Q.\IG>0X>+K&OY?G2Y0H=#P9V9^!V=Q-8-\,`289CCO
-M*)EX1'3=.=98&MRS,O&(JCR^^J1[9;`Z%KO\>OSQ^W2YB+/8,;C:#4EI09U9
-MY]#\Z_+/&%_1HZ&!L-%Y<8IPE%[`X9^9A(Q!*S'3N]ZV[&&,*QL7"EKFY6Q[
-M8I@F;C0CJSC_7$*;2\4![)$]JPB9DG;X<&`\\][W_@I5VC+&O)Z/G00U*&?N
-M("[)/C/>R*/+3E$_*9`Y<Y)U]5SI?@P%#_VRM2*EBG&"\K"K,IH-RET5SZ%U
-MH/&(3N(]MB$8W>DZQ>NRHN-HF%HS:8Z<]W(VPTR=BZM(6*^CPRSM(B*4E&*3
-M5Y6UQ3KKW2)Q-PMW+Q2,'XC;Y):T,#1,M<AP<)/-7:WL14/4UN*5?O(5Y.RT
-M;MCM#4E=-/GVW@/,B^"JU.,;<!)"N#M_D@V?!)C#[E:UNIU)2>'^\B.#$I@3
-M_RJKJ0E%"+3*6_.X$:UT&MX5U`J-B<;X6U-[36T'&!.SGKF@$[;P1KW0I/H$
-MPKXRX;L/SS?1$OE3HV!O!$>S+.*CT;NVS`RLXS9_\O>_`RC5IR``<)U$BPG7
-MNJ-C!%%[`^[6W(,8J/*7A\*75G$EEI$E,6-ZZD/SNW<\5!+/K66^*1U7G%S<
-MYB'T61&&ZKZ3%WO:]Q0(SG..[RE3<$2"CE457HR84UEKPSA8&(\MHW29CT75
-M>;SPA!9FLWD2A2B*JT,W((8XS\]1,V3BG5L@YXK!JS<6Y(,$NVL332ZXQ*SE
-M@/&[A^)1>T(J\E^!E_U?S8-QU8K5BF2.`YO$G18R(96;([T;0>SNM4R.UF*2
-M2(LKS#V8Y=B`XNY-:2<G4C)`,%>'J7H`'N4ZWI%),3[IT/*8Q"9+VQS2(Z5Q
-MX0MZ](%N)9#"_O"WI(J_8J23'MS1\.UNJ)0:^*OA6>,:%YC^,&"_!/B&%/Z^
-M6$,+#(2J"IZ@4RBM6$!TP*K$-]6[XSUL5VQ>)S>U++XWN.$1PMEZ0<*L:FB5
-MNX,N`4S'DF>`V*HM*/SK+PO<[<*4)JA$Z#<>D+G#%X(8-0O;].LE/\&@L.NO
-MOSS)*LM/F#UHYEFEP[XT;JZ;H'6OQX]IUXN]Q2'@-^R0N`K'$92!9<W&)G%U
-M++`=]0B@P3O37)L4<9,9DQ,F1(0^2;S'@6B@WIJ$.6C*\@EAJ_JE#2#=(S97
-MDXR`9#+<9\X(363=_OS9Z"=^J_NP8(RRKDI3!W_Q40FW`WLM\=]`/I'QW-*5
-M!R3!%%/X3]R29KT*3_64AFE)G&AM'U+,M])W;!>X$FUYR)KKJ^*$B%"3+YQU
-MB\"^.":MIN*%RO-G6M9YN.DWU8_U(BU+$O#I2MR%4E37.&?$%N^$/#'<NNV#
-M2YQUNN68N.W8;C=8QMN5P]2YT^PE0ZF[*(C":&<'D]G7?(@'M-O1C)U_JAF/
-M:(L17VD!.XO&4*%`V-ZETNS[^-^QTY0S[#\QO6O^&`._3N1&NIUXVW/S'18(
-M)YF/J8U:+.\('B]9AM6R@%`HUDZ-^\"QEQ*N./0T!Y2*I$)2&!1^BSR/U"!R
-M38QE)A0;@(VF#</3+;.)%N<B4QX]5BT9H;U8X+LJK@9V([[4=.S+6SM3KO1W
-M`>5"@3GZKW$*TON"$7KBBO:AW+K%VARVX7P_Z2.DSEJSO[7X=>MKK-:J%[$;
-M1,8$GM;NL+Y^GM&%K_H^'BNVXHS97OSHEZ;UVVAX,"J3F1GY`P*/T5$KK1%@
-M+]U8_/,[X3TO<2N2'8\S*%+^&S,',*@F[K([GQT16^!C?8C-WT`>V[K-$D)/
-M8OCAAJH\=1=5A2K$Q/Q$XS6H43#&EH$`?`M^\O;4CU"WIVV/GNMYNH<M*VMD
-MO$GBGY+YL8*NVO3P.?@6D6-TRYL_W#7K@UR-Q]<U@^-%((M**19,WX6MI(EW
-M?U*@VY=:%OUK*H"JDGQI/YO;]"\^KH$2XFS+4FXPL[$S,*3%H\8,QMZV2*F-
-M76\S520ZJPUAUYP32(B-5N#<LPD8P@-##>PL'6,J>$MEC/_!XC'N^R3)'>A)
-M:+#J!877OWH8%LM67^]X^RG6!@.4M(-?'85R43'V>ONR9O!=A(=C;>T5FUB4
-M?"`?[/H3ZV*[@WN?*E\;V/54,3>W#4=\G&0@4&@N(Z'DYHSK*0MSRJMV-DO5
-M)3I`%T0<&G<2G[,EMXE"HP?GPR!5QPW*R9Z*M[!;#CE4/Z?8;Q!A[#"\2;!S
-M$\QO&1\:NE!_ZB,C-1S$5?<.,K)ENXN2/)]>X[QJ6G`,CUVYZ_FX1`/(&A7_
-MMVK^'&SN`YYZL@)/H`FY]Q2<MPNFJ=+ZR8!$VBT\IN[,2HA$>NQNP!BF'HPK
-M7J<IT#Q91V_H9R4R4:NYVDTP(>1+)AQ#DSLR.2VXR+D=^R5JCW[FW:,*='[4
-M5<_)D@$EEG+=TX'97"N06;!&6XO3_SL4!BJ@;C<5DN85:S@WM!?O,BJY#/)W
-MW"Z$)C#<SIM.NXQU^%_#9L[PIK/G@3DBC"$!L],I^Y_MS\SB-#:/59RF!C0C
-M:[4YXEB(]^J@C__4`H&UQ`?YN.)L!!@PY@E;GYDV^'X_]1P'@!(\$7D3IL[>
-M^<KM9T<AC0F9D\)GL$=.`6,PI0V>E=R06ZI/;GS6?E_6PQ*XCP/]'L8]OJSI
-MB*3A(E7#(&%KV^-"OBV:NN5#<^0*LX8GRF@@R:V^>[<6ANRR)LQJ`4,4]FI]
-M&)+"8:@;+ZQJN+W7!=T\F.MD[GH%A@W]=\"`SC].(S#86@1)'RFI_+[D/#X`
-M#[,`-B=:IV:>X+59^Z3;:GQC-J7=N?_;&P@_3X+$['JLSCP?/T,`5R<4X+^!
-MSX(C@$B%M\=$.OMQQHGDPPJ<MIG$0D\4BL7P1[$(X*?[2WQK/[_;R9+0!V,E
-M=FQ75<I](B&$I-97(N/QW]1L=9D9?A,-ZW^>LH^W[B/@-PB)*)Z!Z;]3O+GB
-MZS;8NM)13N[=_NB/3[V*"MD)QYD:WV`XII'<]`YN6/6T6F"%D]Q%.J54?:Z#
-MVYIM#%6%D7)G-C,LG2H>XZ!W_[^D#MV6W7_3LA8P3T4YB64':;ZT"/+E.^,@
-M<^TW;^UIXJ;(?&ET"4H'+Y/7,0$`/RL!D/"X4DU;3/A3+M-ZLOQJ,7'RGZO2
-MSB5.<MZ]]D+B4:D%R#N(M6O*]>3>9IZ7]BE!`T+ZR<W1U+;HH5^/H[,7TVZ=
-M$GW)QV:E^TO-2Y(P*+9U#%Q:')/W)V[$XMW^V#"OI2-H1J%:4,Y2K9_2;=\3
-M7KI=(^?#O$P>L[74W>,PI`$UW=IT0)EKTD55D9J)AUE7V,NOSHVR+R0(M;UE
-MM8LRCG%!;<U_^"3J:)#3#&AT&;FVPNT%:%)`O%*[Z*Y;OM28ILNW1:5E[N]=
-M3FM5^J6A^)^L#;^'Y#'R(U$JCS<4VGH5NGQ#[`C(7,128F9"VH=LB7?QN;'T
-MWBR[+I\@J>K6U@)!EEIDM![.C6]^>IDVKC700S^P(&JP+`H-*[;QI%,W?J-F
-MG1M'/@H<U9>;"98[<1D:QJPB/,<R_2_-%R^0(`+[(D?_JC8./;*BNK$CRAZP
-M`IKR#(_P24"-HR:UX4MXS6V[!>'[CQ+9%UHW4^K%GP551%Q%JECG2)11JX-N
-M58I*]L94+1>Y@(A$E/.QD&T1/J6>^FNR0\;08+L?C#%M)#T->9M=^;CQ@E88
-M07T=HEF=TI.ZUFK#V*'>%4Q?X:V,HH2ZZJ?\CXLHN^><A0%>G]X1IE--@YSV
-M1G[[M(R^M'F+C$BGY`/<`58(M`A`+0F=@SV]L4Q&`,S51U&_D,/*2A_41>OV
-MW)I`4;E2>^#8^UL[QB5VKQI%,%?L<)Q'&S(WGGP<U%G34(E;;='Z';PMR[69
-M<LR[]*<-;AQH@7&?.(T4--%?RG\OG25^XM'\1JQ!+#Q^L&.V^3&)$]O@HFC-
-M":T5*E5!'#:`86QR+U-17!MQ%./FN8W=/54<W:./G&\C+ZM#N3XO9%'0Y.WV
-MC@,_V0(GQ`KL35!$E5D<N"97(H664;T5>:_%4:ZR;8R2A<%#D;S]4A,'ON7>
-ML\T?P-)6PF;!?3H&C&=IH)N3]G6S)MM*0[2.PWM6UH.-P-:!AH)-9^5*6@S`
-M31IBGSEFKKUNO:PB9;L8%>]H_XQ]%,0N'/.,$*:T^U+=!A;H3\/Y(,T#X)LA
-M,/@[E"4%</*Y/ABHM1%W.I-C$-%;^U6WGXB_Y1>Q(4V#[F=_ZURVC'\&QF%H
-M(=5/+O"XOX?^H^ZG[<^?9C*G:&FRE-E%TSE'AB6OCKD*8H48A!R(776+A(53
-MJ5=\`A%]NVJ-P0@J0?LB[]-*6Z"FEQ*OZ]1LSE\CU!%(D>7QE9=EUZ3F.M13
-MU)J@?DPY^U\>%$>N]83_`A"0LSQ6D26`9<J`%;UZ$*V8[F7Z93>@C"SKT.2"
-M3R)98I\O?3I>_:+O-*[G+?6,-_K]9E[*:S0R>MT@_OI\^P>B9\SM=7$N<=.5
-M2_?I6+5):\M]Y%C0ZF.F0?2=CE]6'`#XO17,'QJ]&4(2K9`EQN\NEL7HJ+0L
-MKE`V:AE\A3?,8THE:K>8Z0?_1/\T04H4>SW,Z0UAG0G?XYPAP9SC%T!N@WQA
-MFG1&HL&(&MU&<!XF`0-Z6]O'KC@3\ZB]"8NV8YC5=_;GXZ@D0.<)T'!3K\9-
-M^N3<+[-;M`#7RTKPUG0)[0QG,ULWKO>@*.C%PY<E6B-IR9[[;/%SGA%K)5YZ
-M&.CL`-H^*MD,X/6-5#KHG)U6,C^1[HRFW.YG;[`&F#EWJMD!M*=*/+#$_E6@
-MLNN*G3&?&G>FR]U5E&:U&"5;9!&LB;K:KE1(;DZ7=IO*9LF#<D[SCQ.G^HR&
-M@\JI"<"JT^?L"K&QG&U'^-/![A;F\Q&E<+--#K1:6D]W+@):(JYI&>:KPM5>
-M8^Q#,\"('4UCN]*)B4"N"KU@^GO",CRFJU)>N_Y7,`2/T'=CR17?5@=0\6L-
-M&,C3/N0_)3VH(6UDS[]=#X>^B!SBEL^/LI).,HW8VJC'X,$.^GFL]`YT]QO5
-MQK1XEU:X\?:2K!WBI[*SCVJ63I>8E'>Y61'LX.(XL1LV7N$9-0*U:EN>U'VS
-M6=Q2.A$501UPZC0"C?+UCZ\+G-W!:8IQ>_UIH++QJ_7^@P(6G((+E["ND>=5
-M%3XL1,YV/@NYU@2?!7%*5.J1G;*&)8U=#$FRZE[PLF(M-*ONHD&KTFSD1(6R
-MB4BA*EF#*1:\;J>X"WU5ONB?$"F^;9L#+YTOOU1X4W?L-*/K1A6<;F\<0.O\
-M_6,JM_]`.7I(B`#D>4?'ZZ_;RCBG=8#6C)K(H35E(LA/>AV)ZRN/UC;2PP],
-MT4J&IMD1(+Z)N!).^M8E*LF\(<P:R[?'AF([O#IU<D\/3H'>.#)"A\27*^!E
-M8H64E)-'C0ML7X3]=LG49YZ7A]5ZG5/M&!R&ZD4&_\P,%'?QF"FV:&0@[<,=
-M/0DNJJ3I\=&5@4=N'DXA-:R:O#-D./1<^U[60PE-B5ZCH,27B@P6TC^(3BEI
-M6_.9)"_(HT.!LO]4#SUY/,]G&_#ST;+6U\>3UU;=):^+8)YKOA6=AQR5$?NE
-ME[[&'2E\V)^Y>?826Q>,'`%N<BK:5L+EVN5,/:M-Y;*>[<V#F+T+")Y402HZ
-MK2Q"+WFX=NS0@3*P>&NFL3TW*YUWFP`X(T0A5G9;9-8SY/6-)/P)/^(24V:2
-M>[:#4>L4KD?Y^D9[5/X`N7Z;+6<>$T(WPTAV?^Y'B&E,OP_;VF?HL9/,2#GG
-M*49!*I\&214-E]M(+/O6,NMJCV=FHG+=7%4IC;6-N8DJ!J<!\WYVW<-@5B-A
-M)Y/@9YLM&RU^AGHCM]8\9+N=@U26<=D5#WW^0GY4R%GW/FZ5H`F_B9*Y$<>H
-MC_ZST/4_5/W=Y5I9/$2>'K&*.T_L=H8`BD^TQY)%7D%X(B658VWEB]G\\L+,
-MOPKRIJ@69H3H\HT-+O]@MRQ<!!1=)@6-\^\)/1$?5]:FK*S&IW=&TLP/:0I4
-M6<\<ZD@6N6.2@.DJ4"$?K:02X?>Q-H)5#]5!??BM)^>6@<A;8`WF@('G.J2_
-M$5&]7=$J'8ABE9%K8@3K<B#^\.II>_!8^V\K$Z,.]*WEX95?H8P'_).M?G%<
-MW`M0&O2,@@"F@<\P%(`5M8+.5@P+5#ANRPV^/[J_RE`2@?<7NT5]H8A9>&>'
-M1DV9]C*!^HJ;5L[]DI:U_4<54Y:S;_K#/K-JU"-5)O;L+OCUH1L+R\3R-UAD
-ML%A7A0-P#_E&,M3HE;%G^`]B(K&YL7SX5PNOZB,7?_20KZS`1']4)HWZ/Y(^
-M<JAXMLM"TPR]ABPF<8._G<3JY$KB=:%D82?#!MA')ZEW&W.I0$%966_WJ#AT
-MS7AY\DH"QW7>MOV>!A_E\OMI&;KN7S[IN2!;1YI\/MO%;LO"LSLAX0\>6]NN
-M]-@VU_7JE:5*C`9HKPF*WQN)U$;V]-MPT(^A>7U$#K=KFEFIF^/3?NM+8.7+
-MUB`K[?!+WN+'Z2#NM#KG0M$JZ.\N`5JE(HH/Y#?EA(=N]T3E]#!6X>SXB-N8
-MA-ZW0`1JX&I@^4,@--7?B?]X'Z_.S<.RD&05G,OT-:$!23UOV).&)TOE$;OB
-ML^*9_06SMQV$74?B885J9B64W]'E,OH%8&CAO]U1BVBD]GML`:5E.GA`'#:M
-MM'LQSQ6E'TBWQ)F'^<<*C3[:MLY>?RY:_&Z_T9!GF[W7\O]66<Z):+DL7NB0
-M1,I4&@4C<`CQ0-!J.O#R,]]FTJ04C'=3[_%0QA=MEN''I3_5XURC;J"YL\=#
-ML0]Y1=2,JTFKX*MW>E0N+&_4(9WJM'+X(/D=&Q;D&_J3*"(G(4P]Y0=;;+E6
-M'VG[$>JF[?Q]#>"8>YY1V=I'EM'E+9B""^S=W6/IC`SN@<,K/'1C2_XS3R:"
-M1!M#)H:N8'<:S?2<QS.5K2`#);X,7[;6FS.NT9B-?]_Z+AC3#`'Q6N?W70B4
-M)$;7ETBDD%&L/V$/\*^2OII3&B<NC:J<QV(W\0-;W@%Z(6_QPC2^0S8%L[,M
-M4?"6ZV&N:.X#/TO!4GI[2&83;=5;&-`R;SN_Z7>)Y^=@U11KE3QXRX3AF^A@
-M3"!XR39%EWZC-%!JVGB&6)616+O\D\MQ%3;MP(M%Z3&)A#^+!#N#Y4)F0"8(
-M@`$E;5E#40_#3R?//9[%;_P#Z%3OQ0Y(#WF19W:G.HHTO^WUDG?EL-/DG*LK
-M<,`.6Z=!G7/M.^".)36YKC-;/@6&Z."&W81><98I%4KI;`+TN##V%`!D_5_&
-M-,+M-2'?5`%%P^LY=VFN)-LOKQJMZ,"HCB$9IGX`BO\GO;DQ[(/W\8HR,58G
-M-WJI."B,32"0FE1-+W@4+=V>LIJ6`SX<(R-JU?K(46#B<XM:6O6[Y&IQ^;?=
-M9&IE>0Y0IH14:Z9;MOH/3"JB6"N_GD%H/%L[,@JYU#];5*MK@*HLJCQN5V*@
-M?NG-JC%($L^?#@;4M"T`3&4`@\B#859J]>O$_:H0<HPS4K<SA5:<?Z7Y-.W*
-MCBFRFJ2N9-4*(:*=J.<H!G?#S6I.,S^F`,9>(C_(DK,YF(Y54$WFURJ%+'UR
-M(#=#F.223EU"V.Y_,5OS[E&V?$WF>^&O><*XE#D0_-JS4<:B*%\!7#;CLDNY
-M=0Y$A0O$2*9;Z]^"QH.>-3.FN=6@F\RYI^VH&DU?'&N(#<Y%NVH[\J0X&WSQ
-MN+SN5Q56<ITS4Z;Y-=P"W1*K7P)-.ZDD<-]ES^8RC/,2NFABQ;/=$#(<6G;:
-M43GE\?@QDWE`:M3=M]7RJ1,.)JV/^+O7FYW&+[80,.:A=',#PO-,YSZ#[)"$
-M`Q)7JZ5NGIPQ?>*&*V"R'):W'9"NU_U)Z7!O'.3".>%%WJN,L74>SQM(4I.@
-M_[%<,)^.S;_K,A8?K*Q$8ZH`F>E!HTZS$9KY-7$VQ!GR/Y.:_:"@606+YWK%
-MIU@/XTT\DPF<_Y"(@OIS@34,G/&O78N]@T\IKT1N&#XT03PEID(1@3J<3U64
-MOY5$983R?>#T]Z!=X$=*Y\R:Z*_G;1Z%!VLVH[5E)DS3;2H31#NGZ;!",,[G
-M:L5.^$K5N%[=B7;`53)T$G/H_&MSJ=(6#\H6;72!RM+MM1_`A%L@446Z6G3#
-M(0D6/+I>K"]B,AH21IX`2-"W6=GY1(M"%U>F_AMJW:H!#TN]F69"LPL#SK-7
-M<^E6@SN3#(GF3TK6G-9.;N@M^91*Y/0<KQ43-KR$U;.LS9S.5H2@46U,ELDL
-M-O[B!,AJBV-!*M3H4+?6?->""N!.Y>S?P@S*"KE0O9RUU?NI>W2ZOVHP0W8B
-MWZJGE6`^,F6N?VHO@*HJV[:]ZW6Z)27Y3H3>CJ0I]4HF)JJAI<;2<#J$0NPQ
-MM7`MP@9OJBS)^)+#NF7!B(`LS?SG)Z<*/T,++KGM_K4YORU/UW^P2&_U8C(N
-MH!)3T'F"`L9RF%WLF3",NOJHEJ:U"GVA(J4N!^^%*PMA)'"<?JDK94._4@,F
-MN.>\5PY76<C3^48<18ONZ#;+1*$-MHJ\8(RDH^S.A7>#,5)*[IQG\>:)L?F/
-MM9>^5M+M<SL'=[8(%.\B\?NH=`GA-$PN31F8Q/BM4]$_B6!$3UA=@TE0>6A`
-M9:-_L9?7!9N(IME!&^V;;(2Y@A#*Q[,=_,7M=6Q]9MM\!^;D$I*<JIOP5G>%
-MJCZ,B,*[?"1`@,_7BS&I#KY2<T=`F,'3T:]K6K+I*/IJO!@SSL14F-XN6LJ%
-M%GD@_5>@%LAH$;O;(R-9'7W^JZ4M#L@)F@>).2(L2S0'9&PU/">+MAOGHHH:
-MZM-B0`5<AW*:^$*>_+?R_OH3R=9*%A<F@F)[6,E&6VH>\JV:?G;_?Z,I;(`=
-M!S5RN.>9_!("#*AY:-]VIE:J=/5P^$I4D1?\OSSQ"MR;.*-O2N%>4.V?'<2B
-MB8[4M[L?]#:.+H'T0%<LB*3M%.-`RMRW#]GM;-ZZ1@\6'QZX4`^FO!8`<0!N
-M=S8\`UOB7":]F2&%!DZ+S_J.<L-F7$(KZX=(6'HIL_QCC+O$0;>!$JO-:E.\
-M,G'4W8V+.<[/:UR<26*Q9C,-^*1U0C[04/:=SD:)K^HYY8P@9&'$-N0O?`"%
-MB\=#3!(IJ]G)UMC!C5U;K`Y3]P<9VH/9!+HT><[O;@'XG,_TV!(.:OY\&>/#
-M,+0F!P`M+V'0Z<VA0_DJ!&?2-DJ+#C*U#W<.>\H_;M*VUZHT39:EL.[63D.:
-M=_=$1N#CBCTA,4]4]9D4*NV4N'*G#BM&V8OD^_Q>::-YV(I9^WW9/@PMQ$K'
-M27L_S,T,O>P`<\9+.-D4#71YQ@E5XZ-80J3>UU5H!-K5K1&-W#]^T&.'>E(D
-MC7K6J\UU&*#'IBR0&-/G/8+VHPHG$R:`972%6^X4B_4N7'B;:F(?JP_!<X%M
-MO=P<U\<+N-V)+$90\WJ;486YF.M8'R;?C2=E)*'FSW>/!\@YI=-JN8%X7UW*
-ML/07="&0N+B7L2[C"W#&#GFF'+(GZG2;T74?3$%V@_`?M/Z+6=^4LA<*/5S?
-M1^62WTG*O3\YZ-C^F3]*6\],QR4D/Q1T1X(>!Y4#-"]!A%?#_*8;?G`18`_(
-ME@RNFJ):@N^-50R^C_5%&+$>5VHZ@9U?-)G$"%065!J::(R7[;JI3R_PD*MX
-MF64>JLJU=4OETX?[]M$-=&;RS)W;O^SB.,*%4@Y$!U3DNOLO[`K%Q/I/!]GK
-M8X5P20=_#QZR;^8B!0Q(Q/$=#>KW/KY"G!7C0<Y>"`:56N-2'CV=6KM&[^D0
-MHBS8^`>IW:N_N.E\!@Z'.R73/P;]SKF*HNRF&<WT_L.=N@P=9%AYHHK;"_R7
-MHE`9MW]B:>%/X8I4$2)9+W'HBWKYW_QGI`8``I\S+AJOBIBSGK/2R^:;?GLF
-M\3B"G-$-@VKGU%34@WQ*<(F`"Y!J@%`V6=%8U'A4^@;^OT/#(D@[6$4@US+6
-MML[%&1A>_`W\_U@E1?D!PB_N2Z3I1H:%3&OB]NRKTZI)%V+LM.[-_E[!L9TS
-M/-DQL6D]]UW3QC=\/'D4A=/6:&%?F7YM'2UKN]9">C/ZT'D1?M`:1O'D_[1W
-MWW=N6:\2SA7HQ*X@=)FNBM^^+X=Q6U1&8-ZN&C]>U66#O7FW@*%)NN4:5.H*
-M8&"5?&-D1\=HY*>G?NP:=6]1X+\`]=+!&`R#FL5*V=78\Z`U)DS=G\=E$Z@-
-M/;Y36O5M+@V@>I53FPK\+J)@;AY_EL\,=;.:)&"$-NXGNP7(3*=RBP>S%5"L
-MOVBT`OP''VW?Y78S($S<AD\VQBK2&V7V1+5K)^Q';6E]N@?>,)_$>;^S`,O`
-MEX67DL`;*L^-BJ]0&I;^5C9M!'/6E26=P*U.S\-!W+8:0V7/>%2'FCOYK/8K
-M[`:E6%=S`"C5[]Y$1>=>_@_7[)%K7XSN<N^2&%:=<FH+*4J1A1*D'"*+SB4/
-M[JM/5-CKTDUG\YRKI$32VP3++\#GC3-&G>_SK02&TXEBX4TBR89!H5Y0/"1_
-MI53.!0O8/DN:A(]:%3B]"*`%Z-6+^H4&\A_'AB?P+4TR\8J=O-1&4?_2`D!+
-MB*+M7(7FYIJ<B&*W4DSR]+>^D)82)3$((W46%>;G_:JXXI;;O<\WS0NQ+7P:
-MMM]8>W%_*14`KW,H8_@Q;\[9<LQ1R%W"8CATS],R&^.B[:"8M=;W>/HEF7J6
-M/][(8K-,70M0(678W==RCYI(""XFN-KYWYTD@.U>K>)B(O)&;J08#">"F#;,
-M9?4R'6"V$M:QQ[1XV]+B*2KD9WGK@3^S]E"'0^7>;X$D7R&^4[Q[AA(QN._,
-MZ.&R^R97WGQD14X!0&=*&\+FQ35W%B9&Q:\X)E3(*\$GH5?!.=,Q.@1E$W7^
-M4>`)=[[&,_\8AAC%CI[T0&ML[@7EI3(Q+";/X]7#[S&MQ/8X/]HAB$Y0?@A(
-M;*#2S4Q+P"])+V%NADDYU[#P!0I"B-,Y^1DM[*6K'^9T+%4H9-1XL4G$0C`)
-M9VA/TR$#C=""N9W17X6V4@L8;6D>1@\6-Y+@M_6M*J6<<MR4`5S9X_Z(1/`6
-MHV^U)_$!8,L!1?!P/L9N30`37M0]:^%-=RDQ!`!M!W%""RG26N>7"F:JZ@KR
-M-<G&K/(=:W>(>UQA#(3V]+[:/4ZS&?P+:"=M#S1D4:.G_!1<ITP3EZ"RT;O4
-M<M,&O!/S1?@5/U-3P`G76&+JUXY)&,G>B@R*7#GW3.'I_+;B>*&5G&XC&IQ1
-M&K3(?^IHPO=W06S&$JR-,'!3'!?1O^%94(8[*5$7[:A?+_]&8R#]@!PH=E!S
-MP&7!JDIJN:^S].5UTUBHTJ_=5"M95[)DX!G-9UR*%WK!BJ:"LMU<<47E)82>
-MTOMJ.L1]-]]PDZ_`MKQ6A,,7V&3E-P/Y^%93=#VD!Z`JXQD#07%L%ZSN0+.X
-MG>J'E-%4^'SVTQ7?[<U3D5A^<C;,E"\^/CH.ZR+T#R$H06:\RY$#FJ]VD)"5
-M`(;6!=]2LQ0U&=TW:=A"ZK[)#+"5F44;LU(O"*2='S%'S]"<[K7G8X4SI9QG
-MK'!'_BB/9D/)Y1JFU$;C'%ZN.GBU4V8+IU;GOL3]U'5$8"0@X3>5'_M+"+LA
-M<`_V@7M'_8$@([&4VF,K+@C_#@4Q.9,(7GK%S:B/2F/:JD?.=PK.<;A;N21=
-M1XRO>.'`DP8;FT^LR_%%("X]7WT-_B*7ZFR==V4BS7A_%W$!*LZ/9>@)5\,F
-M992CVBJW*LW?I@;P@[JJJN6OC17<J,TG3=Y+DVG#N"-J*56%5-L=9WK_1:']
-M;]UJ?1.87:S]V=XHH9ZYK=FL3#<2JW1=X&YQ;%66K`D?AQJ)?<RQLXHHS!@*
-M\)5..NN:`UR,8;H/<\C[\<0D[Y:^X7@0K8Z5W'-MCHI^:(<CH#(BUL7^W_L8
-M,<6HE2QPXN&J.]0SPE_2#Y2IUH\X;I@)Y*((Q?5?=)".OBK9=>:G&;:).R"E
-M8QQ[^&Q.8FHY5!A,0[J96"H+#I:SV3`??L)E"!?B]6F`4@.]?`%LST0@%(5.
-M6"@LC%Q!P]R/V\E&+X:NW")56]R6IS+*W4V,.^D9[*#0*<47*AZ.\_F[@7E$
-MR/QSHDU?9AX6S2AA)H!+P<=4A)=_2:BO!"78"1I/?4U]](F/$T)VR\N]@7^:
-M_0%87E3P^1KWD4US7[7_M7/[Z,EP3'A_E*\DMJ#`F*X5,M6!N@FL6:"2>&,X
-M"<$QG;*UIA89VJ:9Q$5<(T5^5\7WMOT)A76CNMF_:2^RW'%'<S0(`CLEM'WL
-M*/-:J/D1[F4FCS1I560K(78)GMYE`T4M#X68ELS1O\)46T^/=I,92@79G=^(
-M/C2SDK3VSE%E<<J2"3O`"#Y@#W1T3^N"Q\3-=;SUB\R_URNEY01N=DCQ85(]
-MW?EK[XN!"C)%J.,+6LL0LE58>5L-==AX.9>XK-AME:RYY">)+^N;0K(6L?@Y
-M#889RL>W/F08&XX9KU51TRBPONQ+=4<EL/9+VQ;@8V?<>8RS!^[#%T5[`(;T
-M/DG\8_Y$"2F-PM@1,KH.T6?*"?F]?**V!B05:%9$752Z*KH^U^(P7E\H3"F#
-M!;@4:R;8N.Z"`MZP'GMDA7TG!00!VE*_`4P(G,8,@)*$79FDGOMB]4+01^>N
-M;:NR7>:V[4JC8G#2W_>"7BEN#I@&+7<%+#H_AKN<X[?]`_6TGJ5;S0.9N=^U
-M`R8U:JC:<C2VY`"7`\`]],:*/20LK#*<!(P9!^[`@JVJ(8"GS;W=',Z(850]
-M,D$#MFE"O0HE?''>#Q1-$!MMARND-$/Q[3TV>;CGU"+Q(\JF&,/OV\W-M3-U
-MO0.M0J26"HDO^99Z<I.^ZYTWI90M>:$9,:H/ODIP0P!GHU1K,AQ3WZW?R/RV
-MKKK39U6)"%N.O@/I(#Z$(U"KMA4&&,FI(>_(69*5(]%[4O`O-U>_0^BMFP@F
-M'"B)]*!/W"OHY#VV%XM\P-O);!42`(C`1`J3&VJ.76,(R[(WKJN7I5#H2)5&
-M+V%_<OQ:P7MAQ:RAQ7_B7H?D&M#5+4&<3*'E63WR&5-\SZI?EL@U$:JR^%$I
-M1XZD]BA.EYV79KV>5+J<Q$HEQ@@$MYY5P(;BL8(Z03JTBG$2W8VT<)M=B&G#
-M1'#8[KWK+$2>'9\V"98!F&SB(*Q--<BTF#18%"[V5=`%]IZ62]43F/J33>(C
-MF@0=]:CPAK"L*1??)M/FFE<=`ADQB7G/O?9M&]3`WV/N[[_9#HF,V$/5%!"%
-M@YOCOL-T]3P(%,=>$%KQ=U?IJUPO@C7_:H&K$F![7$]7W_?/67F`]=9(YPZ/
-MHQZ#I&%S./9YV+:(0AW5F^UHTM1]A`@&[6K:.0D')85`PYJRW'BLD+/-JGC=
-MP#1'+HVLG*U>17ZA:*:(N(BL@@'K>)OK"'Y=?PORYH(3)]^AB:20B"/I:E?Y
-M-QLQFM$&MO#8D'SK:=BZ6DEL>05H47'LA=FA)\]>>FC_3O7GLVWO%`-F]9KZ
-M"-DC$@K%;NJD41V8G'H/R*"E*MA!TK:?%0"P]I2"Y/&1G:"D8)D35&R+_$C_
-MNEF;F2_'/4^("B@^9"]FSR/7V>N\?7L<+$U!YQ@H>)Z`/**Y017;7W.;GJ^8
-M.R;L"XQ`OR=R(6;K]<:=5O*:::->-?R]\91(^^@R!>//`>"NP1-`^:5MMBJ,
-M81LR54_WE_0Z$2F&OZ$-J9Y"Q-BG6I(G4%YJ8HTPIWD;,WF)/I;LM&8.I9ZD
-M_XEG+U6!F<*LFID\)8QHM9B.N<P,-F)N,LR"JR&EF54Z>".8ZU7*KQAK+V&#
-M78E\FL!,XJ-=U!N:VQ$Q$9!W;O=*6!-I0BB8ZW"T<K"ROD=Z[.<$*/]T9<_L
-M`+#S`$K(JS;(PMF343>("FF5Q^D[WV[QIN/Q:VY!HK%)H?2:%L*M)Z^;%PU-
-M;+VYML'(\H1"?M+;O[>B4J<'+FI"0+:"7XO%[;JO2G(?7WDE%&1UI.N[+[SQ
-M%5=7<_C^_FVL`8VORR(;9)P>ZMX<F12DQ&:"*W-!#<+]B%7O<4M_D*L3R,\*
-M<MB:[*2-G)]7XY06<N5[ITA1<:)@K%7;L2!B1=>"\N.2`F"F/]4)5VA$6`&K
-M#<$B#!R-9'5>!P*W/7IYPX$>=JN>Y:=F2&NXY],EC&@OBB<.S\J$&OG?9.^L
-MA@._I=1]>R>]4)"*$U]XJ9N>&[%/L-&`Z6'/1(3@?T+P*H<;Y.5@=S.MVO==
-M<U*%%ZG:6QR[:!F,C<J6E+E8:7]]CX%G2GVLTB\8^#H%E79'-,I`X.4R[P]Y
-M!)7\OL/IM_,'V'!<YX"6E@W?K#F7G46$U?=<I*7Z0IVA9,P$8W2`HS$:7G7^
-MIBPH$GF'\Z3E8GUT0F'MJJ.7E['^@'TH<U@8*X&C%CV7F:3?'2-&O+T0`/J=
-M]N=9VSG.*Y$B1>%22,P-Q?.[QLP$I;1<K[>Y_#=Z(WD:%U*X2251'W%GT`6S
-M+=JXW?$0QOMKZ&"[>1[X^-J)',K]-^.:5LX:2]H;Y.!7'#?>Z_&\Z-'AP^)G
-MFHX3B$Q^`9:8DY.DZ:_PIQ:-X29\RB2KU*=N&J*%L/;T'>%_K+=BHN?DI-$Q
-MIWNY@FM"_\Q3?X%K\$@)ML'X@&ZD-OTO<^O1,2YAO=)%US=%'J#\M'<N$U_X
-M?81-?^D.['3%!O,L3>'MOQHX<QD$GX9TI^G$U890&(#<]QJ?DD`!U+[>JN=7
-MCJVK3J8I4=^MT:7/E$Z@GJ-F@`:]&;0[4VL]%M>"BN:)8`;B/@1,^*_8A#G=
-MIZPUYIZCN/>`T3R*N:T0S'7##35&HY[7U/\BCA"[1/NIC<$5!5O>&RC/FYPS
-MDTH5]74*KSMQ5,\RIY@SF_"W+^?5"D<C0:*)&3"@+->$G9+VI:@*$$E:#1TG
-MYL1])T29I/?2\O5+I8G0!F==W,658@!`6J1GV\!"J4]HL$BHX-$A[A$/],/!
-MEZ[IIFTB=$^X<A2'-/X^1>][C1_<TSX!#>E``"SX(8QJQ\^`BYK5+Z6W@A_*
-MH&>].-?.F8@C"U3-/>12;2.<-%6N82G<4EEE?AP7YR#:?<KAR<9@SAG!XYY'
-M!^[3ZF.6J2`9KE]R[-'TZUC'CL*+%`BDX_BR<F7?LS)5=#C]R\YPV":N"<*!
-MT7>)Q8Y<2%*:<^6G4R[(/ZFB(:R"]LEGVO@+B$T=.6A8.ZM=IQ&.'K=9M?W"
-M0FH*LDQ;!?U.DJ=(`(/N&?HX+`B[,[A]].&O1`Z!+F6W6P1)\V5A/*P3NR<-
-M//AT_+"5F/+5H_A9QW!$MKW^4=#?F1=9*<ZAC^O^@I]P&7GRF`E]PG"J:U<<
-MXL(=GRRC,H22&$GC^0G:0=VV<A?**HA<3Z#Y3M'@P^L>;[-\&^A,:Z`Z.N'\
-MPZ;1,"3%M!F&1:;'$EC&OK_4FR&^?PRP'>+4N;MM@"FJ-![5.9G,[82OY6GN
-M(NC_I$2"+2:!FO?Y)R^!141&`_`Q"DU%45)^/O;6H'4M7(HR<SKDIOBA<9%,
-M$^WK<GYAGJBO$YJ$B3=!%[4[#BHF9(PURVBA=.W*WR(Y]U&_ED!FLI7F6D4I
-MVK\D:5M+&\@M&R9'\4=*T.OU`"BL[0N^[FTZE)'@EJ>C?7.67%;+Z)1,PI*1
-MLIGF\=T)`"33!_)(@4F-#\;.#0"H>F%J23$/$AG0JLF$1]G>8G#6E=AREW-\
-M)L?>`T`?(&B_<4T6&)?1"K^#FOM+:'/:!E+SV.*E.)X"64T+Z>5A"D;L@+]G
-MDY%J;QH*!<*@>3%G=1)5^"-"QW8Q=FTJN)6/LBJ[>GH[!MO/O[1]0&QU(RIP
-M3+T(XZMS2\7(!M?>]>!R8=K_`.V.9<"#6ZF68?'"7%2(6H>!/V1^.S#MCPA,
-MLXTU8-\/:=;)APY?57'\7K(Y@\"EPB8RN2N&G&CS,_^I$4%$TX1FQV?\&XA>
-M5M0TUA1,S>,UXHY!*'H950578Z;P*V(;-&+$35NI8U'1UF[HIU#.C#25=T(0
-M=$T,P_LVO-:[ZJ]A0Z38E\0.01>@$5B+0)(V,5NYO"F/EN4-F:9\8G#R[8<B
-M&C),R-#WW76;4#1!:-C*3`K:Y+N<%Y#-?_NI^!]!0;2-UDED;S.WUGP>S&T<
-M.(]EB,-L>O=;KB&.F:5EF>HG8A>IUO^+,,"JJ4EPSG9`PT[X;>)IM@7/O5ZU
-MDYT_TB</$!@MX*.`E%T3*=P`A,805XL?,TG8A%,K_&XYH5*LQ;E3Q71XU<_[
-MPK4NE0U64I`X<W;F\EV>KS<JF?J<#L/^K`J%DNON8Y5!9=WOF,,9#>Y=XEJ;
-M&H*7.\]V>*Y*++7"(5&`::.A6R)MC0$*WGW84POHLAFQ%1YP+81H'/^)BE?]
-M19?*=][INL]*\^>%H"K\YT^5@1;IIC-F2&G6>9:#!2X&=D@Q30X(WJN&?RQK
-M_0[":`GBF*N=EVQ\83Z%X>!;Z<#91BF1U!X>:Q1.`=NA-!B(M29QZ]%!1@$T
-M7F0:JAEKD_Q@=PR&LWM/X?UB\CS<?>-WP,$0<.2X:^33S"67\[U[*!WG4Y5L
-MCO/\)ZO4KRE9R'G3E$;O#,VR^>'CQWG/VI<18M-=#@2V`47[4^6'M97CM9-:
-MCKD30!4VK<$I,$%[AQR8K7_,LA340I^&),.9PMTW![@7DQY1E`XN`DRV`)IX
-M,)JO58-;A<^"JR&S@G*7NX43!5"0).1(3F'!?P+T?XFA:F9V03A_32^CJ3Y:
-M30_O82&1@X:R?2U*)4!2ODQZ'NY);VF1OM@<E5W&-VMC?F1VX\K@-D"]\E:E
-M$XEU:;#CQCZE,S0(O7>*9`R1Q]&FC\K?.!KNVY.%:O!U*FT5-$&"^?(E4])#
-M[_7"]U?1?A.9+1BSX`?K*%'USHK?>/UF>C=6Y*9O<>'KR)9'BSJ75EY'\+.(
-M9E<L2SZ2"Q>:D/J(>M#\M5(AQP09H=Z!3V<&NFPIV)VD*[UC?])F8!8;Z\-G
-M2*!O:PRVSG-=1);R+;M`(MLIZY2)9A!>)$7(V7$MMU,0RI>9IO"LZ3PN[+ES
-M[V:=]J=$>M\_+/.^PRYMOH0\^=4S=->`Q'BXQY3C#$"-A@:T7J%`';)*<&>(
-M`=EID0O4&X9ZGV(@S'G`W[&C&-N7TH%6!T<[9ZT8/TY)^3QV&@G<'VGO""Z2
-MU/!=9V:TY!FJH;Y4ZUC@6W5`3O/X>-<S-5T(SR*]LXD`]9_U':<K"AU;YDHQ
-M==1RS77_,J<;ZS'\-C=[/8'Y;),9.=HZ(^6HPJ!P=PK[8`D\J`A9"RHE\W&=
-M,_8V4+FI`E#0T*?^?+-Q5]--UC,S(RJF9+/^@>2(77RC5O_B+,+W[-U))O3H
-M.K.XUW@"MB5(KL5R=$-`8A"D"S#>;I5\)<,??D4]4YPG]],,IA<!%G]L.TPD
-MD$4N1?;8:#MO%\9'_$8R^:;%QWXEP\Q$U\+#-YL0>%#IU*]C*>)CQV=^]\/&
-M[J`EQS9'RIU@QX'HD!F6%;8I<[!Q/ES2&UR=)/L+>E_)NFI&T%JT_9G6\4Q#
-M&_6MN!:7.-F-F_88$H</D*>R"$1:LQ@4?[`X?2TW0(JT]1]+3/)]\V`"@NWI
-MN'PMM^)%`.Y84PX+\J][>U2`Y([$TG8G/WLS+E^O()2B<7:*3JE^5-]PC#4!
-M5,W&T]<*<B=2MDE'Z*A)<FRJ,>L':*3T;-.0A!L4;#?U=&W"C`MCF`7BH!=%
-M<[X/W4>:,^_Q>FB]Z91F)_3&(%71F6!\AI18M_4V<I7O?$PW4.(3-&UZU5R;
-M<IE&A]R]<,W+YHAE2@5>:UX%,R\CTN[!?IUSI?5U:C0&WG_??-TR&K$?;3#F
-MV#8Y0.@DDJ)E)+U!$5`K+3@XM-0\Q?3-&*CS%8K$8&"G`A=#((,'/7^O4W'W
-M:<,DM]<(=5L08_-';B[?P7Q:FM&?W&A/-\=@WZ672`K:9/S?GZ,]'![]XX(O
-M:9RD;H4ACDE'B5+Z1#JG[0_\.&LVO*;IDH^I^/7O&W0+IJN^9@4]JO'N[Y:]
-M+4?)8*DDZ#S_T@2V76$+NZQIC(<AI1K"I^-\+J\"2U5[X=A!1H=<0,$+_&,E
-M!W'8^^%X$B_2F56./K3T^(3&1)*2N6!-^5R+1@5L?S^A;^>#`$MTZ,6RNUL:
-M::F3$2EQ`1\AKD5_"?J#ZTC-TVW?YF2_G*`<<>=15@MQ3B@F.F4`(>CUH5C+
-M?[UK[D_<5GU0]LJ6;RENWT0VQQ$OJ9$"<L;9D$R?E_I]AV'E6`RX%==%PF.F
-M8LX&=HB)FN4P*2Y9"B'OA3V*[O23D\%_::-PW=TA?=T3[L4?&.XJ9N.T'"8^
-M[#F2V'0AN:.,0'Y0JERS/Q"%`0,LN]XBS_Z<J4R=*6TBJA!"$>]U_.5F&<3"
-M2?A"24HRK>,`4OJ2"HH1(;D4:T*JQTEU_8.T8!68``_,;N?]Y0T:Z?:@6F'>
-MZ6".?Z!S35Z`UD1I[>12_O@92ZFD3$D^Q@%@C%TJ"6'_)'Q=U+.PH7L$:8Z8
-MG'W\4959=XT+&>S!`\X.:6#'?3*I_RSMWGB[:0,N_G=[SA/&BBEU-H)0Q0]\
-M(H1P>2Y'8']D)6&`::Z,E,'%\UN5#_T`/#>1QYC_:&38(P);Q3)?H359=M"*
-MQ+OG++/TN:HQJQNDR/Z&-TS1C-:A=:H%&+U?>IVIJ^*IFP<U;>SQ(QS637MJ
-M'2,#"X5(-D`A!,+EZ2Y3K_GQ9$UZ1IR\G$<#G\!7^+8#J()%%J>Q,74Z]%S5
-MIB)KH83_PP?;YBK\UJK[5K]2>AJ2Y,XK"24N8*^2^8J&JG"4"Q#K!UVJALB4
-M:QC_[M'?VLQ@ZT6BQ:5SRZWU;K6PWIWADOVZ;NRI.FJ*G01,P`<(ME88(P-1
-M[9:/SJ\ZX>KT?KJ74I5ED*3%4:RHC93'()B_H+L?(%R"^YEC)K(;**S&AR)=
-ME9=A$E%U^MH!^[]U0CX4R'''VA<9(1U1><;%1%Q.(][!#0EC8[B:J0<S@UW$
-M3\Y%S^_.*Q`)"DR-V,$@!W.?RV'-C\?$)H,GL2``+\:ZMRZ,9P9O.TLU]3NK
-MPL=(]'.V>PY$>U_=S^#5+PVF>;ZY9O5(R([\23_YXT>/@LT?M>#0V6<6D:1\
-M%M:D:(%.+A,:J/>77':B.`708[S;==^M59B[9<PW]2[71^D@FM-LI7#U5/8L
-MI"/K):+S%H&8I3(O?X2YPI84U!0.6-U\)YSXFD*K]M`MN+YB9:*R0&J2ZO;)
-MDGVRG\4\7]''(JJ;5J</:.)2NL7V39A:F3FRX'E5QF$GELJ63P?\5$VKN$<R
-M6/I7S.B87^6DV:'F.5)1P3AS$](^15NRLBYB>0$U+M/TJ'HOWR$L0BV%EI_A
-M'<X8345&;MGC[)2.+D`,YIQTM6JKQ<*TP,>@+_E2.\F:S8=6&A[3(@?,#&V%
-MG$%[5F]M$E)Y#CU\S%'U$^[\8O\W3$YF^/@W80MC#EL<"_Q55DCT9Z06>N4V
-M?U]?Y655KE@TU@R"G04W8Q!/.$$\Y5>K8ZD-IZOSE3K'"M;@\6&W91S/YFF6
-MEOV=,PS?1B:DWS""H$_C(NP1KGUB:MM#2L3L.,(_JI\\<+FRRG2A\E&^TOW6
-MP:YX+KY//H7N*23OBK[/(-J&?4X+<?SEE@_4$O3<*9E':P3_&7X6U!L^Q^3(
-M@ROTH*O[EZ2MJG7R3RO'$.W$^OSDE?,K1JX:ZYF-JPD\/2M*N+R^QXF'.Y@Q
-M:O+'U]ZB6&'Y4MX`Z(>VQ*,*D[)'5).Y*IXP<^[%?"`>BQ+YXQ^/,LR@E(48
-M8)UI#\80`NHV96<[?3<PVX8_B!:_$KUE;"T`W67=Z)MN`ROR%.9%/,OIHC5#
-M-A9YZ(V2M//_)WHOHC+8S*`*"REUBW1*$%(\BR3A@A>S&$^8ZIO$(4X9@)%;
-M353VOW>%3#W[E)U$VLEL.0>M+'L^)UYS\,&;PIK71D@3K_7<L&C)XB6ZJ7;M
-MP?5T5MD5YJ-5PG[><?5P8#F']RY1H_]6'Y@Z40ZUX$IAQR(5J@`3D?3>+\>@
-M^H)%N1AB6AL./F'JXDA+'Q=,\Y%BC"_JXZA<6='OF'TO?1#>DCWI=I/5AYK/
-M%P'!,Y+Z$<N&=!!^UO]G%$/S!S;9[Z5X1NRSC3/&*%[M:%L3J3D/=*$#V$F;
-MBH17^4MP@M8-:]X?EXP0;S303F3#5ZOC@*%U8D3B-2/O*G36QS<8U\+IE*4C
-MUQ'=S?>7CV!VDR\I\7_9>KG6@&XKM+0-<W,X8V;23)_^)T8ZTY_9)F.23Y#0
-M.&@-J,/BX]33CSS@5]+%_4]PUK\3"(UJ7F4#I8!AV20XF*9,1['GGE^U3M<5
-M)J[$R<^M=?OW^DNR-GN?;#C3B#0NP)^13\'-/&N2)9\K#+J]?2NJ;SIF-72M
-MP+DSIR%2$_K#Z7NWIJ5\X5V._3YKE4$)ST=/%HB`AFMC#KE(JZK*;6EM%?``
-M&TC_0-I]GL!]M&L<LLY+H0;'%&&;M5J"C<#F+,2==1=:.5>E2><H>[%X:9K6
-MAX;W>JMLF[.BAT(EI,-_7:,)[Y81OD[1F/&<#BJ#,?O[?\Y%OS9$;4>0V;J(
-MLKW5K6D=)H,J?O$XH@$?-79,A,30*!VJJY[*EH)0RE]M`-\]3:>\BK60.<)7
-MTJB]\8"8.]RC)5%@@^NA^)W`7VO*6_-',(!2&1.&?^N,#+]-W]$C+CZ;4!&*
-M.BLUAT.22/EU*WYAAI_D">2V&%RSCF3*58355CKW<I'3SA>^DJ#HWK\T0NBQ
-MRCY3%)>._^?JCOI<8ZCN,5C&^,E8AXS\8ST5:*=6,OOS?(QD/3,"?9!'.G/1
-MS3I`D([J`G"6AFM<0)T5<10Z(PLFO[4)"6A]\TZ^7,!_EA/'S*TT\.?'(^FA
-M?K>VY#[(83*;!1LUBT>5U,+HJ3X,'C&,.,]RH6AE6/_^0]D\/-%F((SXM-V(
-MJ0_F9[W=1@N/S#(/MDUV!?S^4@3K;W.JH#VD8\@I',889A2^#+:\/6KO$M^D
-M%TAF,PZIO^&/E]9CN<-`FS]8CHRF]ASLZ`R8R*F!70'(`\)=/)B1T'?O[:4D
-M;5>#\&^-0O4J">O@K+6?CMR43C(FLE3:J:2))"?!GZMRSG1EV$TFRHAT_/.Y
-MZH-$@UP,GTZ3IFUIX?HYB_E[."Q(9_FQ<YRT/`SW,&5GD>G!#K@<9"`"1\FW
-M$F0S+%;(?/G\*K;6_NK"(+8T&ZT!.*!V_">#/D54:5FDO:03SNU8X(*F6"#V
-M].!.$!`ONSH:/W;6*?1NJH]P4O#J.E,1B;<G(F<BQ"8E%4:T4ONT!F&9SX3_
-M\81U@]VW2_$'ZEI"H&Q(RFK*AU-HN%8OH#;!AM!)9N":7H96L[D7P$_-F70;
-M]H.85GE.L)KXG:(_/=_#[%H`B]B\V[!'VB;_34!26ML9]?==4_L9P[QQ+V"T
-MW5+ZDB;D/_%K>IP9E.#M)Y7LRT"P&9HXTG7NP]^*+9<7;$!G&?$8I'ZU+N9.
-MS=TAT:(>QLM?Y]CG&I!XG\3@,*OJ5)7*]HB/C_D>6YC&JE`,]<!"A3>.$"!?
-M(3'\^XB![%:7LA,IV2E(ZJS6^0<JL%*LO_.@8;28P6=$T<,_!!]D3)&RDN-'
-M\WH_O#&/3WP"=SMN!K\M@^+1>RQ2E"U/'5L3!O$/#\E,[0"<$Q@S:XVQ86OS
-M%W2EPR):8C_J("&<R+2VU/63B=H!:_U2&2XU26W:)&.A,D@_7JC`=7L:4_3/
-M^)3@5VQB5;H*$Y0XO\H&!C4>O;&.?2E+9%"*N>7G%0LF!"!.T'7YYLN!F2@`
-M*]RW_%Q`!3$"O9,\]4V5S=29/UH(R'LNKL\JK*ALRW8P,,X=[;OYSQP-W3G)
-MLZPZ!3W+8#I/]G"\Q;E\(9"3JWR6@&"D;$,\"P[9$4H!=5'S5TPY[W;O&G;K
-MX\"EA/NDLK$TJQ0A+LF-E8HK17^+PP\KWND[FP_S+T."\2;(._MLM<BVORTU
-M;;JJ1Y;(]7\KSIP&Y)F>VYU@]^3II7.2^E*^;!\)F55N[$R2HD!A'$TA^($@
-MUGZM_,A:R"#(%/SI&:@3G6;B7CT)-XMX1\>VW@`9KN"2U+)JS54P;"WSMN^+
-ME'[H?1U_TUJ"F.<#B5OG5F)\B5,&2W'D"9>=*3CVF`*_SKGN&GG'\]+JR.L@
-M23\,,`DT(X(\*L]%3@H712.,N["*XEP`+#ZJ8(#6M-\)9!V&8<>DP"OFVFC8
-M[^&(XJ@7QS52Z>@IT08<PR73_*'C\EME'6?=OZ.%,NHFCYX"$H":V?5DNL#%
-M#W7B&X7WLZ[:5:SJM[&::"YY*5/'I[3\CRUH*\X0"*]*7KD&F?4OVQVH.]=.
-M234RBB",HN?CIEF$2*'=4#U.%N^(\Y:B,>MN>D+FWBJ]=+SGE^BW?:`=.8(M
-MCAW;M:0XZ'-68O-OX8<.XXDO^5)31&^QX`P0=)<R6\X3!-T_ZTJ1727GL.FV
-M83T!]RQ7LXN_X-$NE00H9?9",FP$?D=SDG(Q5`/R`J%I*#&_G0A$."+_Q"),
-MUKIDZ1!0_)K['W9-_%A%>3.I(L0KMH#]A`.<:NAE2O#/]MGE=%0]K)5(-GVZ
-M2XS3MJA$]7*DKF[,^`FQMR"5FF8*A?R5Z\XY&\LE67N5I5D"$2#!X,_U(41K
-M[[>0!4HT#S!TX$8=$T&\'KCC%&+?B7^MMCIOL1F/E%DA:H!U,U?2L(]ZAO*W
-M!67?:4_SEV#]D-5?`;^YH'K$#F))1@9K4\;&E`[5*OLO!'V'C?4%>0Y#P],R
-MI,?Q3NT=KS2?O1N=`U[-"?!1.]6@LWYN0,&%9^4C/UK[A+`Y[4IYNR#W@%1%
-MTY,?M,JCS%(N4OB_JI5SB"N??K7O3&UZ:*JS.,)E//4&SP:73<ZYT9=GHAA+
-M.\7]F^B*IPM+T\*M>%@L/;:"/'NI<L5ENI3G1M;,?H.Y"/I3&`-AZTE1J.I+
-M%K18$G9\UNCI<+<VO6&M;[U)1KS9%Z52/&!M'BQ_"QXOG+E)<T@J&F2H)7[X
-M)W&9J`<2;%8S?FS1ADQ39'K/M#^Q5B.!Y#*`4X13>/.N!@DD"T*'Q#/$QJP.
-M9V6Y3SB\.)--!>\!MGFZ?K(7``UB>8R>V1X1BWDR_S$^MY6QD!Y/HR12UMTI
-M@U<O,1INS*7YW!7JD_!USQ)A-`RC#PZ?+@E64B5//.6OGE+'<'\7O+'6#D*E
-MDC[:185^:J=QI`Z,0W8@_T<DNYP,!!V!VHG>G9'EWI.8\I].;>44]7C>A2AA
-M3X5I;/V*NIC'DU.ITRQR?,*(TX$';TM,&?TIZTOD*^^,;2N1!'%"RV]*0R\C
-M)+)/3<:]M2("H6*71A*8F2IZO\KX`*VG_AW`30IX:C%S+N!?M59)?GQ^*!</
-MMKGZF]!?C=;A4S(/#L!&XTCWA15SFL&T5>BC^Y(,ZIK+?J6IDQ3__<`2@,,,
-MT1PL@_ENYV@[G(<%&IA1*N'[?`:")J.IKA,"!T<8[W_>H$G\]FPEE!-QS2<K
-M/BR-(.*WNCI+80"#M=`V\M)/]TASVNH%N\/5&ZF:OWRA9,;+.-/S;<R4L7*>
-M]?/U$]2X9<5+"4'O-O!\W46_HX9J%U$3VDX#8@/TJI-?1JG'.O>D#7?RPO\J
-MUQ8*I+-C9LN^#9"8WF'\)>E^6H`]/Y>5?&3ZDQUDCR<5XIWE8\Z'I>W747Z>
-M<)9K/(N/<G-?Q$YR?WU^[Z7/R.F)<YIZ1!E=E[&P[?ULQ+SGOV%[I+*T6Q/;
-M[:&*$M:/L.P%V4B%+?1@"ZZ$`P5'N1?_[SB__0XFO1:Y+3P,[:[$_(DCILG,
-M9*8W133/\@;U5RQR;'$P"<Q.U8K<\V6S!ON%X6W?C?/.KD7*)Z\-E"_0X5\>
-MU,6U$K)%%%&`OCBMTYL+*JM%:88K9R8G`+275Q!!W<`]%-WNE7K@>?HM9)+E
-MO#A/7!8X)P7,41W"+\V6<W6B`;VBQ.V$2,O6(4#;[T+OTN\S_/[J*D_Y["5O
-M\519ZBKALKRC)Q-P'*DE,3(#+VR+L:6[,(E[M^=@;<#677J%%RK!QQ:<@6O(
-M<T^Y&NYJ5%U-$Q%.?5(RB\F0_+$"QM=`^TZ+T30>*"7UHP79FT+`]XZG'6L\
-MW'3<*[8QRQUU_BL#$<3CBL[E(@]M")K3M['@V'_!"[?M(#I"3_,U%[)[(5,X
-MCQ?4X)`0K&W+WU'$MNY\^BETX(,E$T_>>O@\3+N\@XWN,(<$U),8FGFQC`#"
-M6NG&##NJ^WE7A0/#\O6!IL)._$8.82-4A"L"1;]/,"R[+2/#U(QK"G"=]*V3
-M+'P)*%W=K8WU>5J4I(JT<!T[CQ>B:I40XX5-:"'7!TZ5%P<B(I%RUQ((F$@^
-M(YU,GN7N0"6XBU%*\<DS'LV&%EWB<I'%[E`T9Z*&-]%%I^\-M/K+RR&;Q&I%
-MR$Q3"V^EO%=?Z<H<<G@?SX4XF_D&VY=6AH0BD&PN?6NI!3OG^@'JXRUXL[-S
-MZ1SY:([%]%5KRXPZ]9.<D/`N,K<?"+S87];PIG\S@4=J8&>'Y'X8X,@T@T'2
-M"'4/5X^"])."F)G:7BO0Y!RO(T,3D"_BLU6XC-446ED8O_'4JJDY,=@\.=9H
-MS[66=;_YS;>3VS]4RY;)U_HEN/.MA"I.)2&B&ZN*1DCH3$IA40*?Q1\E]JE,
-ME7E]&QLK^35FW)MZV"%2"V<EC<?I5MT2'6B+MHV9"!T75!$#4QZ==;QVUX=H
-M;)<LGS@Y[B-7>"#L9HT$VN31HD##Z'@M*+^4$.]6FFXISR>DPJ60E#%Z7Y#1
-MR!@X9^E*",\B@BK+#8C;L[!/D%"\CC7*4[XF>:C*V^9:!ON`QG^_]Z7KPM^1
-M=3IZ#@CSN$1X%L?VK9`=0EV8<"9U]?D0TVT0BBDR+D(/KU!7J;EO0=LKCX-Y
-M7EP<J:WRLJ]#"-6@%G`G#34@D-)&$`(:XQ4R\;"*+]V`V(Y2F.#LU3_OW,!5
-M,,Q88^VIZ*M^D3H,N05P"@RTF**#IF6NR*.#F,CK&G4``(0-`TY1*HQ`(!Q5
-MCD'8NGH0)7MF=:VKU7=>KY5KZ-G;OK\7+,\;E+,#(N^4PW)=[<@PK*V`9/KS
-MH>O/]IUG[/6EM";_'MWGIIM_-`Z5@\6'<K/&,KG:#%S].05=DQJ<)4GIG)'2
-MW0B:@O<M=N0A94G:LX;J5=\HUN&9L1&=.N2:(JJOV#1%QMPX%:C7$P9\DUNH
-MY;$[IU,.CRW$<UHY_GTUJB+JVW=X`K8U"_":*^,$S`6LYBOA^Z+7?DZ*KC`8
-M4')'#K;;0&#$S5%?Y>1]AS7CB;]9O^?.:&+]YL@0D@P"PI,15J`8F'H=]R:'
-M5N,D%$=RQW630!I(OD7#7'!I7XI'U:*9L&1:JS>Q2OYV%\N@:.9JJ@87&<Z:
-MPT_J>35+32$-HV>Y10AV&6M<:JTT5ZK-T?X_6.W$V1^#6.T'WAFZ<YLH>1=<
-M3BUBW<2!8J:NNPA<.:C!=%M2,C=E34G^+]]T>X'WG/K!0)?:8+ZP.#%`?/>=
-M)4#0DN-67PM2DW"D^,*N)O$KNC6W=.[U6LCGT-](</Q&IN&M'#1H*\#E9MO^
-MDXLF'KYA_6KN9[G&T9_:HKR6+_1-A@R,,?&%GG[9B;.HRQ@!L;5PH!-I4O%B
-M(Z^0SXZ-QBGB!2#7QTMU.CL.'/V@_(WI.`K0M&.L],/:P!\RC@S14O0UVU&0
-MKJN6U7SREZ*!5I13:[4+ZHT,VZD:@!TGS7;[PVQBL!_-)C+<W5?MXV%H:C77
-M6MB5US5O&,`.2$TPWP8BM_(PVSX<^+&SKYU;0&[QAN8;ZZB*K0,_W#0ZJ%BS
-MI%"O0,9I<&'1D_(8_^2_,KI,@S+(HDHAI4R$O>V<I@+)N,P%9W&[:ZRT&V-$
-M1(YJ9#P?L>WL1:D*]9J47F<**0LS3[F'1KXV!P8Z+^^1J09A,M7U4N)D9DCY
-M>IM"V*NW-:VB(L#'?D0$?@J!EZ/MK+)KSK,!RS^<G8Z,$\9^ODA)QX)$PQ\X
-M7O\5FAR=)(_Y/6H($"3K&K$7+B#VSM]N2<WXAC1"U[?YF6UW%T)A*EUB1R>G
-M"IJK'?.[1XXR+*W\"W>EQ$-E=!PF/Y"6Q_SQ*8%BAM2F!P)JL)0"NG-DQ+/N
-M)MZR1=$N3;"N>ISLJ,!Q&+%-#EBWV2EKF5U%SY$7B0OW?FGB)[.H4!=\T/HG
-MGXP<N!>M8I2;:+@C]MFTN4NZ[;S"^NDMY!N@]%*GE7@QX,W0VO`$DGLVZ.'*
-MOV_/*,[Q#$9A,2PXSEMIPW$.NM60I'`G'BS!.85#UPN+W[41[7-G+Z.%HV>,
-M[.=#4XU*8F_0;USPCP?15-W`'#3IPE:$5J^%,EP<2I]^RW:4G!88VP'$D`PW
-M&W;/M87]\`,'US%NWFA6N`%:_Z58J'MU.\HBJY^$6^C/188>S2ONO=BFIU'B
-M1\76?<PZ1&K6JM4<4@"YEA?^#KI'2GEG9_/+"(,45B/XJ-(]J]PDR9U]:L?F
-M/OFDR2J8,A?CX;L9;)D$4FNL\L/>@RF6)\,EF^R8ED982Y.=_XX>`B'&@"+@
-M[;*`/M\7\5`*-,M&1VP]?,F93;L+!?P]2.SV59&3OM&H`+FL14H'F6Q&T\<7
-M@).B)SSBDHYQY.BZ!<:I6+.9^*\+J/OV@UD[\0YU!5Z/B5;&(26([R6F6[N8
-M7P3LY;<%"5-"'*Y;PYTS-8V`SMIK!V2%`(85).TBG:C+&7V7B,TV80[Z@"J[
-M3PMCQNV!\D18A3\`L&3V%\1!_[59RGVY7YK4&8,;53YA_DQIG39*%!_EZK5[
-MZH4A/O'I"I7+;@XKH-3VE'%IPJN4X%I=]#9>_X4P_+WR5<O\(\D,ZC"WUGE#
-M!]=T*B9)!KK#SX3G)XHQ[VE[G@];M"1<X/%\/Z&F&!`:O-^/9>/AT2DJ6.BU
-MAN2TV0Z#A&1F8P$HU+QG]B8+8])+C;I9RB"[*O+<6EQVUMO>E%?W61MKGE"H
-MTHH@[WJ%F3/+7O^_A2U,^*@Q[?4U0DLY:PNKK>K[H$E.%*2HFBC8+S'V#I=;
-M>I%9CQ:9B]FX,FCQV'MPS4B?,7(15R-)&R)]VPWJ@>K]$QDWB2#X9#1])KW]
-M>,4(DFJ(X2V<^>U$\[U5YQC@+GZ34WD&>;2FDL3JT;!PO.%62^T;?K=XT4<D
-MA.].J,LJGN^KM2QV*LFR_GRYYTZ7!^OC)-;-`E&19\@'K)3<(]6K0G_\U=E1
-M(\7GD[XSN0H6P079`.SH1EK,IH]H*UI9'E1PUYCD(NW,!^^AE_JT]*XJQ4->
-M(3A69J?02H31=[["IH'UJ<GE]Z(*C@.Z_`XL`=-D.PO`+J4PXN[(S;>8C7!]
-MXG$\CO?727&8[FEJO6BY5^K;-]3NI60;/6>&KY\HD;TS03MJFY/ZJ,HP'['G
-M@JCY=,!_7&YU#"<C87!N29/J4A.3QM7/(,XP.AS)\LV7;'^?8-!.8+9M_E1H
-MR?7.!9)JXX&X`%4\/]<_I;92Q>!-TGKE_[S*1&=CO0BK/0W`#]GY,H+F-:S;
-M'=G-'`_'^Q>G+7PA@Z;XM:E_8[G<9NKCMY.3J\OE=L[584Q#GCT5O-_<55?8
-M&>IUCBH-$L;C$7RECH;UZY6$\="<QR$DYI=@Q'9TWBIQV"@TMWGC[`W>9O4.
-M;ES%=S>&FL:V[">3Z9U0S%L6_Q4W7W$,*1G$TWX\YR%"=NU88*17MM-`EJ2=
-M!S@C0&@Y]-SG(63"%W&4>A!=4*#B`Q.SG@WJO]IIE*'9BSA,EE*VO!+B?U&$
-MP10(30E5Y7>ZXX*M&5P_:.\#D"0R5#M95]>X\/LR-GHA0UF*+-^`+JF:&@HQ
-M_'L6KUX1#$-F!:8NI]SE"3IZ_&H+<GV\V:9!RCI$"S]8\/OX!7K$ENA2.X41
-M")(NP6E=[Q6*4B(ZQUZ=BVEC#&X!K:Q$*OQI#"&7-`0S4=*X5%_5RX"5S#K`
-MRJTOX!JK6M"CC5EIO=,_A=.HMLO2-6RM@ZBFH),SY=!<=8B4M-'4;T$4TW/>
-M:GXO#-CNH&F@C5<BVE?;ZDN;T1PG[%\#I_,`+$IRSIL9WAWA1C+;`D?6!C`*
-M,)'JZ(RY"=9L?Z%/'BWKLFS&AGFQ-=H'`8!-D_W2>$:?3Z+PO<9-LTJ/M57*
-ME.^Z#?H-B9E9)3KP:.@):/ZRIC5T=L!KN/!X*)<%A*G^%';?FI4MP'3GRGIW
-M+Y6/+S+!??P(6!39!?,Z.)J#II9GY'*J^G'XJ@!/J(O!C$%'?3,A@GX#$KW?
-M,D=/2"W9&[3\%^C,EL'R[`AT(E3(OM@7E"]"5";J9,R>JECFI]8CIU<EW_T"
-M,JZ7RW6YR0,V+BV&HS87-F>`H_`O3'31&W$S4W9-/U,J^!33Z4WU,:_Y3QUK
-MT)%A%"DQ)H[<],??J9O-_I*?8MJUV&*)PY;?5="%AMJUU>.+Z@!>)ZM3N59H
-MNH7-;7X(!D4(+K\:/2^`V).DZ]NV?#[:*5)[/G2Z;40\#?%^^Q%]?(&4U,J%
-M4/KW1):YRSQO2H!HRU1YOW+CDCYPD/8R:]B2@)SSUY__OGGN4;D#GX6*UM.N
-MAC*MXK3AW?@_60D;43.&.AC`*/`F5U`8"0"T=9B@5VL1SH-S5CY[LNRT5]L;
-M'+K;:-#'FHQJOK30^>#<&K'DH!]WM\9;DF!E]C2JW)-8(17@2(7KAFQ8D<V7
-MHFP[@`C?]]9V^^N8!QP;ZL126N"^Y.K5"B6@Y9R=9+FSU6@/P,W]FP`%><%>
-M%52.#9?JQ\9*A`OU(=:SVRI'S.S)40RPS;UDEO\4F6QX[B>T7X!RC[?Y[:%Z
-MU3Q+"XM.9N@3`_$A9^/FPO+$3P,;XW<H"MG3RTLIX8M?`E_PJ4=!TZ:/ZU62
-MUAQ^Y,"R[J7CG'^;NCP!8E)@^I:S-/FZLY[27G<KSO7KWF;_K+4Y)WL/Y2C1
-M,#%4ISJC!3#&;.U+V=]N[JQ-(H,[R^VZ0*S.*L]FNF=`M[T3(BP'O$`D:ID,
-MCPX7Y9RACGGO`PYQE\XNKG?4!IT_&7(14\,#.%FZ!F#>$8?_(-RX08.4;AP>
-M(KXY+I%AQO_0<>A;-)WET]E7&8,:?2Z+J2[$0+SD\IO_F<=5&K%5D./A&-5S
-M#U5*:KNK?G`ZD\>(+=ZJWPT>&QHOZ`X>2A^7)ZE4?XLMF!EW`WZDM.T2OZ8D
-M[B($2EPY<)WP[X@BWYU`^C(JH/,%:A*_,<T(A#L\ACB7\U&OW:S%TUV!^X]O
-MP6J7_Q/CKL>L1*-C(=KDL9'2X]?APTQ7A1:&,'O6*4"#2;WK;YMX+41O,X+#
-M&%TW<T_.F:SC8UV>DN]GL4N%6ZXCNA$H79Q(86LF]QZC4[!\/>TI@VKAGPT4
-MGTNXN!SM%]69(@-$I>**I%&^+O3F<5C9O7=I:QV5<P>>X.V0#CCQ9RJSVZ@%
-M2H>ZJR3?`CHEA"A?=/]#-1[19+C]MT*?^&X*EP#3;LPA.3OIL'=:_JB.MFI@
-M;XKC]W>AC^$=C\(SL!]TG$NKX3K6JU$;@:]L25^=O,HMAPO$DMC@\6V)/X^F
-M=[R?YV`NZV!:/^$:ZYBGEL!]C7S+>.(S+')K35+;?<2V)SJN"96*;I]IZ8A)
-M8M/4U3'HSY#]SH>#Q31<WUQ-O_N<!UX"O/%5HG='!W(G[7]>4-@(LZI.,T/;
-M,].V32O]A5_MO./]Z5'Q`AZ<==K[,P[)N?JD^-R<A]_4@><DPI`$X>)G.D\D
-M'K;CI9"*Y!`S2.Q$?N)95;`\+/?HNXBI2C8H1P@7]N>='&KH)2Y'BH_F>E$:
-M7U5Y4`%6W-\.:<O'AZZ^!7UN!3DOT+KZB_0W-"L"+$4ASO@76FCR`U.!LW<G
-MX+T='K^ZG*+[IK$MQ50:/KCJT+_`\H[>SE$3[]0JM)$GF=',!EHS<+/N!PP^
-MG=[&S3]_DT`B`OO$,=Z3_@'W>0<.;),\<2<IK/T:KT<R]AF'Y?E^WF>D^14%
-MT<@]DZ\0JT;%="#86$S.9%GNRZ&<E`]PVA=M=GN/:)_B7>,#`J8#?,*,:X&I
-MO"[])6*#S-S9T;?)(9V:32Z!!`*UX#B1P&MGIYD!1MX*H92BKUVY&.>OY=O&
-MK:@BA36$H,!Q>RJ$/<2-'_,%*/-L\:<R\WA^\=;;Z%U'T7UZ))_;T$AG[H#F
-M*.:D[CTY4OXP<4;8UO(3L*W&Q">&4]EU,VI;6Y<"U%)_V3YXU[F*QBU.'P1&
-M..HF/*L`QX8L@6(V,S-5D<W'P>KZDN1KW[:D7L,MUE*[1:QOD-=;\-[9^%R5
-M$LOQ?#/8R969?BH)@"*8<QC+".%5R6B1;=#P6'1G=2;[RR_]4!L^N<;FEWH4
-M@<JZRF]W[.<@U+(A+>*^9C-C]].B=BALQR8[XF(9GX,H&I\_0[++0!W*53(#
-M]S6QE[T)HBFE?2)!!QC)#V\I<4.&+CS[<Y4R)4N*-#QV--\?\!2446`%JHH)
-MSE:KG":P:+FK3*TRWW+)?5*PM](QL7Q7QE^_U]<,UTL3DN*Y.*Q/GV![6#*V
-M\8"R5:-B,]8(R#F=OV$TLP`',D+7%W]V]^P'6?^XR1IPOHA\A$KLM&HI>:BQ
-M#7"S/R[1MWESGQE`&*!\6>,K"2AU;)?.M=,;>G_VXT1FE#:#>3/;C[<`!*"]
-MO!\$N'53DY6<L`\)YZ3<4*72H@''J*OA+--*\2C@<.+\9HF0`M03*'YY"E>]
-MX%%`<.<E38#Z/$<JO5PZMM/O@=V!O<;S=(0`S[6"F5-PW4SD'?Q+'UD-/O/=
-M_]E?CI2*APP[@5&(1GHB^8%XI+SY:*D-A@8ZT'DMPJ@ZJ+N\VK1F7<6Y7+,V
-M=DBLW\U=<E6)0G?`GSR<&?:]@W7-]73-328::,YMU`=,<?;XJ]\S<Y2\-M)Q
-MG>J\"A?'M4KVZED\$!&Z:8,C(_*"^]*:39%)Q77E2I2V$E>PR!$7^%A]=&]S
-M*=[Y>O>4@.-B\&P]W45?1*L4?KM$8"=@^.1PT:WM<$!"3,&]K=XE:?F;"5U)
-M)V<+?:LR^'RU7FPD%0OQ:O(;`WM5>?"7;FRM>%9"I=I!H"X?>PVBXV4[TCJO
-M$'^PG+6C-I,)+7NZ6J%.D8]BI&NI@J2GMM2L5='^_I-H"VF/G%2(67^[C9]`
-M$`.#%5",:\X+`H*?#?O$%VZV=\_%B&(J!H6^;E41_K6VFM32]C&7I-Z%FV?:
-M\^!O.\L.]`$9\?.%XZRY);F[Q>D9#;5F1.:^:&D']K4>@\V&WN^L$%S?&#^C
-M[(%#7HJ.5NOTU6@18AW"U-Q*.M$\$<N!,#NK`39)F!OSJHZSK[Y/]BZ@1T$Y
-MVOH`H%^6>))X2-*9S9/.&I`ZC_L![O70LMKV*WX`N^*GJ]G9<S\L0@S5H1F7
-M1?97.?$#E1!Z)6PA5NZZ[*U_=33TM$0]I)L8FQE]68@6'T=[+$KC6:NRI\>E
-MD3B?M:L>T+XAD0B5R3A<\SXMI7HGG6N;+>[O,28F7]&;2@&T"E7DUV^@:*K[
-M&T2/]C>)F"O;RR=HQ>OZ/(4*\]+&.A#.9^4$)56_&C@.-YC7%NJ#U.FW#<,9
-MU49+NB(Q,E%C`"T0D)^[+4/6F3C`&H7X0"8N$=Z!,%?)<81$58!Z@G\I&62F
-MW;2@NDNR7^ZZ\LPE1WR3*,7#E&BD1.^`/+M5<@$B*,&N'S*'R1'-A#,[A=%M
-M5:>F__E60*WP)PR>9M,>W7GH2O`G@K2.U8'3!=DUUFYLH8^0C9QKI0TXZ^F_
-M1U-S^K_70\A04UZVF$4,PF0*DAI=9SJA.'ZS/ZAY&N0W4/ND#@&D<TO(;7.@
-M#::%(@]`,@N_\P,$D76LZP,))D2QT)3,Q17IO]$43<B-A>V??YV0E>ZV%'8W
-M-6[/G(0W9L`&;29!]?]#&,H4GGE\/TC@D1_/2`=/P(Y!7!M#B$X\.!XD$9`=
-MB:3\>?E*;-4)AWH+R):O]%`2(A/4M@M_9XF#%^D;B-%=J3G".GV4R:A8GU76
-MSW2I^AY]<)"9I6'KF0K>M]0^!G;+FZS1[SQSA\>JRWG.8TUG]X\-P/^-[02]
-MBVCC&WE-&?ICHDO%D]T@^U)@,/(H^K$P,M._8A$0=0J*'H9UT3.Z'D+`A6%W
-M,KSZ,V;=,#F#CY*E&#89=]R_Q,EF\S\N4NS6<6'DNBPM^DTZPF+L1S^=X`.'
-MFHYR%Z[A^6].J2;PC,^?S721*XCU60+?WOX-\E#7>WK%Z\MS$ABG5=SFFF7K
-M/?[WYDLAR8*XMH<D8_ND-S:>;LX7SN]'TD68]B)O7>;/-#KR<"=HA)YV/:<O
-M-L'+;D\#YWR;R!U!Y5-;M;&8^3ED?R)X(C)>V\:SJ+8S_A#8:V,?\9^W_G/`
-M5*Y-=52U2"*@4TR5TP`;#%2Z3M"F$B-M`H+V_1!WV%O9#41-C'>A+OQ)3;:N
-M*4:;&"(!B.V1-(X<*0H6F<M..MS6O@]^UGY.K/'0^[$?$QMLL`-)?[MNZ(A1
-M."Y/DR!LF$%+(AW2D$[>_6BI.RF(E&*%ZE:([WC';/$OS.&$HME@9$!F@?@H
-M`1MIA[GE+P.O<;KL,)#:J'JE9V1P^DU!_:MU9]QQPHOV//5\2T!K([5P@P(D
-MJT@9N9HO\/-R-,@JU!K=<2H+<\DK8TI]O),FM\BX6Y3$E[6[<OSDKR4QZB\`
-M%!6SDYVR5E#&U;=&;)'._NC.(J>;!)$A=PG/TH963H=\3O_JX[.B;XQ;QLUG
-M&5,(JE2Q0/O,CP32()\L&IQTBPG.9:6W`*PL1Y@"_Z_E@[D74@#U"S\M]X\L
-M'_PY4J2^=!8(RT;N'#\?RTJ%Q::4-0-*`^>`NR>Z562:+I"D7[+/6CQ>E.?2
-M#IW?:`"''D>%[G5;94G9,#77U=4(BTIG:*.U?Q`DC,=?QG1B/<7E6MQ/2,C;
-M[08G?DJE%1RE$+S%>0R&*C]<\W7K^\IF[=M*X>!(S,3CW&]GXCIU?P,F+.*9
-M(*[F.C_@=\<Z>RZNPY?*2W?\[+X1RW_J$(8'?R_M[:+V=X>@3Q2LYP5(:/&[
-MV1*:E3M6N:.;V%I=#(78.1BCA/[P^.3_W=R:.1J$F"=2LT2]_U#6"YXM=D#L
-M.U8')FGFK8::;)K$^_B8?YJ6+NVZU$NA'G4Z0QS\I:P(C0TR]<NU7-&O5SU!
-M'3D(-RP-H8:@L?D4ENU>WRQ7TY8<;!T_5M\5!\"6NO(KB5LO&ES9VB-N`\,\
-M,(KUM\:0]@O03_&UWYO>>:6*VHI'S>TG,_GUMAB\:<&&!:)1X[):N[@9E)3^
-M%/Z1/T3K^6S0JT4'3PG1N>SE%>D)];*&!Q%S6(OEATA9&2&I_Z-G^`#\]%R?
-M@,)SFL(`/QPH:<8K`R\6=6+/=B]7#NTJ,DP9_,IME!.KFR>U'AQVX-.BJ?P;
-M.8Q([0<`/0@EU8CN(UM6?W[(:FH8,KU:/P2OPTJ&F2RJ!ZBYM@C@0]NIFA,`
-M:6EH6W;1-Q1>@\F774_[O8W8Z$Z.*@1%CQ`/`_K'M^?7,W:!.F]D8"O)CGXS
-MCM2WG!LL!)00MD=TF*/8CD;G?E@=3Y6/SHACY44=KF8+8TDKL3NWLMB$&Y,F
-M>Z;O5`PMDC3V8</)*Y$S4/!16H@TPFP1T1D1K&Y5?5)O002CKQ#+`54NH.FV
-M:=5<#6K2KG/5S['KEZ+(@7RGL7X(O[]^Y%>,X0)7PR`36'H6P7`;;&:,A%#J
-M#+Z@2W27*?_YA<8S8E6JN,ZX1QOE&ZQ@"]2&2%F60919.5'AEA;8#Q&0[Q"T
-M#-%:]35Z6HI01;C5#NS9J+HGK#>H9856L]^I<*(GRXO6.:P+'+93_-=BY'.;
-ME`_VSUTEWF+UH:DTKPP#>^1MSAZ!F.K_B$].DOM<K%DUC*V`Z/Z#&"YHZ\9'
-M#7H8A-=:\.?K(U"\HZM+8"`H+>8;BO0#L^&*9>]VM(@T0O*7H@K;VNG'ZK%?
-MD?W9.76U$F1`F`^M'S>1;#C\N;E\;"B8W;%2<!1#=F`R!XGXBZ#,,,:IG)!]
-MFV(9PC!MTQ7N/0-)^CMP'*FB%]]LZ_K$,P^CCHP)NR[$48]T-4PUT:_RC00>
-MI+I42BZ`*([527G8/!C0FUF%NAIRZ+7.`L@%8&_>!3%0>/@@ICB<3(*[OHF&
-MHO4A://B9J,@Z//U)"G?Q&-8[AM7PXL,JIK-,D;ER$(B89SR4?"LX_>M+1-I
-M_($%_%*F<(FX1@!-H+.Q7"T<,=EE#")H?`2\:]R_9G@K(=5>Y%$JH.\)VJ;;
-M.?<Q=&>Y>H$[=NP3PA!^G59[$8L%4L^G?6N1X8L*F<U;>`8#:Y;M43*TEHZ,
-M4YWU2+K;Y9CC^[_I$]L0H35PR/8TJV#J:WECGQ>OHXIK_>",;A`S>OJT2X"7
-MKN)/32%73;ZVX>YC]XCX0A:7-GVO94V)0G#[61%3DB?`H1X=9CDS<6O:1,:&
-M_X1R:V33`$69*&&GN#D8K5K`O%HA+!0%*)F:*/ZMD-F\$'C0GG?Y3JK;%+`6
-M>X0>)911F4YQ(^;Y32W)"%H01CF@^F)Y5876/QQT(N%U110PFB#\\'-)3E,Z
-M?J(G*2:XS""995"]%W?HYN14\=,E/2@C\A/^9K'23P]"OQE*OO]ZY,_#_*0G
-M"023)FAL=;D#!R0*MV#CNE3^+!A*K*X.>T_4ZW=(MVD22^#'@%Z31=:<3%/W
-M:!,8C6WALTC0>\,`H@*X\'96,79A.0A1&CO;C&1.A@[YA%:QEO?3D^K1O\(<
-MCGOZD.F^>%C\TI[@3F_?SQ[!>BA,"\7,IG/.LJ2_98!H:AQR,1AYH]>/9W^)
-MW,M"S7O(3Z)B/\;W,NH]X!L/-:6/FDQRDRZT"(EI39XK^O0"H:(Z8ZKIA!TX
-MY0BT:L(F*.?J=5(FWM.5+7.6F(>2$N.76+<>,/BZ<1ZD=?T^6N,V*2-_<C2J
-M)H:#BM55F+HLU2&S7MM+9N3/MDGCOH:V#ES0'2I!_UC0R_3A?";NI[\I%R_8
-MS?7?'T6)=/TM.`N/11J<4*E:7>!0+6YH&ZMY_>^O;Q:;36\+5LG.!`>K]]8T
-M8!Q2_(C902?[>G$$M672E5]0WA6[P&X8J1X^=35W?MKZ"2F%AEM."JA1Q,X=
-M1/D0PL#G,<OK@4F5Z3S#_9^UHE6<J3P#EP$%'5`278QE&F**!Z^'(C*U"4HQ
-M4&!!`'BM$:^7F\/A!:3W74:MA:ME-D\+FA7!]F_&Y/)Y="T;@\FZVS$BS.8:
-M2U53L91\Z-S=3-`-F$C-U]5,2RXJ.0;5"Q'DKW%DX;AN35SJF4_Z#V:L.SZ-
-M:#-2*'T9$&P@CF%]*M?C71HM9E[<27L01]8A:,HY$Z8AY[(=V<+P^:'&5*BS
-MDX#2R$^(JBK7T8@029H:DJ6`,W-];%:G)W37*%P0.ZR66Q_KA#]J`5>X7#BG
-M9*I!,"_"<PP[^85:]FZ.H9Q26)(Q]8'_*RV>*8HZ&H$'Y"0:U=[]'+L"<`Y"
-M#+:@XO81E,5.Q12'K(6QA1Q-1Y_PCFLI!]<HWML-Z1Y03`^Q&3>%E3_`>E4[
-MLL\H*7_/=L^R22QK/*:T'$;Q";H./?'6*:W8FK2/VCW(=5N]E`%LD2LPC?XW
-MR?]WOI@N4VU8P&?J?6=AK4V4UARN??A>89(`S#<$"#EI+].$KG0T`N!9)2I3
-MPWR\\/R72!ES7;]4^R7MW]\U-2V'!RX<P%'&F2,K'*KIQA?_5X]"O4^GE\!?
-M[$+EDYE4+5YR@%%"*,3O\9CW.:%8;Y$56@$N,D?3J`2++?VTZ,&I+)2B<9#P
-M+#^6\(:#Y,WR]<XB#,O.V6*@0?`Q&=2BA^^I3V;4P(W>;%D1HN*6"\;'M]C4
-MA,Q0%ZGC'88I0+3/M_KT7NR_+]"TX"&XLR/Q6>B'VMWDNS-L(P;3/X5'ORC8
-M(Y.8M=FJ/37<N6>)QW)3AJV-0=:&?C/]Y:RZ>'BX3L%R]]_%"[TG/4<+V-1/
-MLH^Y)$BXGFE`MPEKUSQO7N+*&>'42YAJ0LNY,$#%TD+?YZTIU/UY@A:_)4Q*
-MM,3#L!2O:L?/+<`,2$0'1VZ]3T3&5:E@Z4-/X#F5>K]%>;Y(S3;G@=LV%)5P
-MX]6F?9=:):W>)%-7>3[<NVV>H9X;T=LR\UH<RQQ'])W9U\6>GL-9K1P\+^C-
-MG)C97J`D>M3WL\I^,6AT&RMZ18PYQM?0,2`GY8U^AP0@9?QJ1)?0</UJI7#=
-M/K<J!/8U<C"30E`7>/XG-?R[^7\/!UBD?]EP.9(E6DN,=?U-A4`AIO\[/\GC
-MB*<A6-(%QK&O:0]KVKZ4AKEW/.6DC(Z,T%"!4YH"GD!*QI]9U.MJ\T2[$.]^
-MN"Y#*E8%3ZK1!6*F,Q%%V;7A'<7,!FZC2VY<WS`$O0\]\5&^;]3XD-4<03G<
-MOA4$Z"A%(2V:6/KRK`@C%&K/)')ZJ'\O;W.53L6KK,*B/)=ZVY/",VC(X:R[
-MPX(F$,W'L<_.*/6<S8X"7$1@&(,S5W"=CLC_.I%Z2.,\PW%RFZ+3N*;T&-A.
-M2<>QR(C<LTSO!`&Z`\'G\D\SPX@;=C2%]CMOOWIV"$4J"OX*N4X!=U22?ZL(
-MF0U`!.TCFG/A@P6!<&(+C\J9K!0;D9LDP;7V%VVP%V"2/7&ZP&8V'%2;/-E&
-MZSSM\GVZ.4LA88GP!*;M+9&]*'87'&&"V=#USRT[&%36@.1NJO.OSG&0%=OQ
-M?+!2-)-`]1EBI+4M]"NS;V1-_`!_6E`+OV5NPAQE%X!L[9`^7`/VXZ?%E;S@
-M;H2Z>EAF[_,OW._I<<^L9&6.GB:059O]CEA#LW490-D_()!YIIEN5IX-GP,D
-M]F/@U416>X*/7DSL2"O<]1#XL9[2VO<!]_=NZXP\F@*13X:6Y(EP[K4PY$-;
-MZUU8TS<!?I0BYRG"MM:+[4'E[-@\S$B1-4<$9/`QQMC=RFK(?;1IBATRRV1N
-MA]Y*9!5E;A]_K+PNE!?F0-P]&#WDQ[&,65%MMMAVH9R!7!I;'(CS^VNZ[T$;
-M9DV##XL:ROD-<1'S[^.O&.I<ZS:9+8W%LX6JR;JS1];3/)*SW)E1R3Y*E.KP
-M(,1.)Z9AA"^YM\<CN,]`*\5:M'"2.=FIA!9*>A2/$?Q]*/\27D#%)Q:/R<:[
-M5^A(7]=/>>6K\R)_3D]XH/BC/AGI!F$G("D^LM]PCOHSXIZ#IO+P'!'1;$,]
-M@P.'KHR\@<H7C@U).&PM(-90FJ>PVY/88)LW,^.Q^O7,FV,9D"6O),!HL-5$
-M5<;NX*G!0SG%Z<"!T(OT,F`E+M9_(`CBEUT+P$*IPS;3&\;H:7VC.T/D9*W"
-M7H<D89M#3F&MUY>,,C896@]'0)^QG`0R5^"`T7W3,L=WHRB$02[2P%_:(F<#
-MSVN;!NZKAK$XOD)D\I90$Y0[T;NM">L1V&^Y<X8E[1KTIQL)8FN]]'H/4V`I
-M1N*ZWI&(8Q%(SQE_B]P;AUKY>A[*\7T75/OBV1+D%9:X'4;"WD1X+7>9.J:=
-M?*J^:K-Q3S"')=XW(1Y<ZK\?"[&7=<@0@&RT[EN_X9*A#)(,S$`*P8>:?^,1
-M5492*U;*_7P?`>/'Y2:/:#)DQ&$R:@<:_Q^+_#2<W^B`K&3.?>59BF(TW(GF
-MO`"]&G'$AQ[-9=AI7U+0&+Y_]ZK6IQWM?09N/8S`-*H[W?;6Y`+KD$8EC?_H
-MJ>ZNDM`*P/XBD^_&!9R&]IHAC,>8E?L*[52\QMIP-X;U(?QBM]6S\4TOSJKV
-M.XM",?]7_.JY3MM,Y.@)OBJ-4OI^E:&0+ZYHB\1I=<`QG/G%B:<^J`;N5-SW
-MO_K'JR@27)-IMM<=:@-9XZK^<XGDT<5'\_M;XJ3RU)KZOTH8'5:$$ZAV:U+%
-MM-'7CX$Z*$IB=Q.M7["OQYB\L;P/^U_G[W6#9'*UV\RUEEC&TWB"FJB23Q[;
-M(NMZWP.(3@]";H:H%;LOE)7>Z^W0@^^I9+V,R;4.IRV=C$':)]:2;!Z-BJJ)
-M?BMUJ`SU@:N7CMBELW,F@P<!6<88\%3D'MB"K.[>]7!$OK27Z(;!V\O&^L[:
-M#%Q]J4#3^39%_SUB8QV^4[>*-S9@]J.?^CV`N"_8#^_P>_3OL6$"-[-*$BV'
-MF\%'#5BC[/\'5>#RQNMG0Y6=28646]QE3MAE5%%9)R.`>>Q7KV>&D"DA$-]8
-MBE$>[PJDGZSA2QC=LV'X_'75]3QP(VYW*3">P$;QSX00(ER2Q=L9HO7:0@S.
-M0/?:_Y(M9B,1'39[V,?/<GM8YL!KK'MCP@.MJDIME-?FJ3I14G=1O5SQ<4;E
-M`/FC&O>+!Y^#,.3/"0$U.4_ZYE/%B<Z/+RJ^,!DR==NR^G.`KB)9`S^N\NXR
-MFNVFA$T_3Y"?JP""PH1US3X9D#8K9TKVMVL??$4:_?2%4ODOTK1;>=76B4U(
-M/+ZL4Q!O_W=9;8/J+,)8H#77SG5RYIM]E]!BO<BB5G3=:GC_H?`%"4IHW\4?
-M'YXG6DZ?9Y'JP,'8Q;':M9&<^RWDQUO6^>\U2<A"R]@HMNA3P!=4-,GF5`,`
-MN]0!D^)#N#Z_T"/O:82K/PN7\$-<=)NC0,XM/IEQ,'Q9L&*>4*]=(+W"?LMH
-MJB&S]4G3Q"OJ7NG91"#^48"80WX#4GP&"LZ-F5H_GA#8YSG&NC*U5(DKQQSS
-MHWU'&?_8=YZ5[M2Q_%T:]V&J6L<72@U)+?6WRY(.@%3&E$;,TC'@AXU&6=GB
-MP_M\R'<)=.G(MC.MFL2\R'W<*T:F@SPTN47L+:\\[GQB5I^S4_,"F-Z.%7]S
-MR;[H;S)\3LQ335<KTMEJ7DT.>4*DYD]@;JJ1U&<NB['@]^G;>!=A@9M(>PSY
-M+[V?#6S259;<O9^AV:7_&ULGF-G/A>X&%"\<D8!"WV"[)T896N^5YH>3$+%9
-MZ_AG[OJI7%&0X3S0-"+CL=`?P.$$Y4@V&-S5/9L!%=1<4RU0H@82P=%\;C?$
-ML&?0X?SZ3H-ZEE*=2BC89\(7E'?,#JNG//S]FF28+_+D',>+^-%C,0W1U%B@
-MJO:YY`HX,CVO?[3$`HBIKLEM$N(0]5WJ[1!5-8>AI4]BEAX.N?7@E2-ZCW9W
-M:Q6"(5V#$_.P1E71HC/%N/W$/FQ&L/TV^I29C#):16>(U*Z-2=S!X5V#S#)M
-M=]AUV.JD/A/1<Y&;61UAUKU/S,'J,X:5+?7XF>NG;IDJ^Y9F8^D\U"0W+3\8
-M=U@[(L-6A=_,T-B3/#ZR^U.Z//=-++B.,%0"*-UZVCIX6H6M+HF7P-'3!AUV
-M>MVVU\]!B08.4`EI0B;KV$J)_?S2!!84FU,\EK]3A3&A-E';93K/+,\?2<HR
-MA,X\)[/0`;[[@!*\Y-S-`+_)EI49K2Q(?KW(#3YU%@.2IPR6*7*[^$ZCMKS8
-M^.V5Q`5Z>E9V/S\Y:YFW=Q+6X#83`MDIQD47L9B6E&,.UPC`5B77/`#!VCU%
-M#Z[%CT>:X!\]0(0--I9N=-1O@SATO&MU<;SOH7<EK3Q2##)J+-<6U@HN&.O<
-MT;?U\:WM2W&7@U(/(QZ*E5RZRG?UARY77S'G=\0H92RV%.>CRTVVK_=^WXP!
-MRP3,W97]]HK;NQ41=WW69MNOZ_-0Q<)IGZ70X<;9`G=MW394R>F<CB9:'@.)
-M!6'K77&:\)0]]-\ED4"_,DI/>SM";NW?>MY]J8H3X!VFXT55S82OX+LV-%HE
-M.Z$?3/`U<,40/H/,)D<_%%_C"$<KQRI1-(%P>.<Y2ZCY(S\>_P\1&*6^YSM#
-ME2J7P#&P32@8JPFIZ2*J?H=>9Z.8*0R5`"P0*J%F/J'[ZYKYF2\;7+RZQ4!Z
-MQQ"M+:G9(C!&/28NBJ[N'^YX0*Y(`D/&E(8A0"9R1>PN?GF_FQKVDVC:YM36
-ML%D7%L>E_4E>IH"UX19-[>],397X[M3:O@;M/\E*93&D"NDO&5<<25;U]H7-
-MZ\.Z&*D\]5I;`$\@;_#58#7&*88$E^KA4Q6GC2BXD]-J_"%3'VX29$<:Y-4]
-M[NO-O)G>CN?\QSMZ*VQ.E3GXI@Q(.ZOR\&]11H1-KWJ6*I;5(@YMCA(=+Q'_
-MF$)`>DV=DCT]K$A2T=[F>B[G`_+KOJ,/Z#[P&>E#F4"5X>[:_XBWF'V]/4O*
-M2@^)_,D:PUD.&4_+NOQM;N!_PINQM.^2+H`$=.[R#._#5O4C!C&;(Z^:>TAR
-M[X"(*\([;$)0TX(G^O$HHZ@,D)5[&#4VOI)`&_2L.&^")B=IQEL&,VD.&)_7
-M1'^OPJX-KU#ZGS):`[-.-76*M()-E/+QGEE4T[M54*N_[KH;F4:#P6O1B>:?
-M[XPH>QQQ*G:BJ7W=IN2^.GC]LB*%UR(M$6M#/6]*H?[0G+F6#:ZQ6HYSKTP`
-M_+/INF4H2=@K3U3:D3=U)U*=CEZ!C&K_Z*OFEJHB0T:`Z=413)X]C^G%H$RV
-MF1]8/EE1A%:&C#K(W:N\("UOUW<E45EF=.)#65$VP@?CB"?GE-JH\#E:[?YS
-MF+KD+R@??-Z.?I_.TQUX!7>C+E(6->9P=*!EV!\$EX[U1B:)A'ETN-QCXT8Z
-M<::?N!1:B$E>IA,(NZOO7!E1<,P6W$Q5V_I-_-W2V^!Q3*EW2GM/)G5"3TGE
-M'B.=,<=TCX[:O"ZLVJ%[H*P1%=\L0\_\/%8V)PW.\'B6S#=YX/=SB:/^&PWC
-M3SALM\!0>T#'AE);\@L%+FC0X]7/O.+T>8ZO(U&\CP+51B]7\^\"^!*\5CYV
-MU[=>G[Q5\F`&DM;U$ZHU4I")J,+\"M@+?IR:C0Q1H%3+P9`<=147H!>RH4-V
-M,9Z9>R'BA$2>4755]WH:!0CTPJYUKB.^^6B%FI8'M>V.W*R$9_A/)?:1P^#D
-MJZP*H'7NP(,NR6!)L?#1X&F5%I9<*)8M@#SD*`/-RT5CFT9(]#G")L7\:"?'
-M,Z-+:B*3]>(;8_25[?*?X-/XC,`MSLTCC_^^I]P=U$A#2:P$*T'?SVR*984E
-MX+AJ3%'P.J&`VA/,0UG2O@D%A:3YTBV&6R89.H[.R=<#T;HX%;X]X05X2Z>2
-M-Z2PX0!G40ZW&,V,/'YI+$XDVYF^[2LDZ"IT*SR&:]TF91#`0T3/=E3Q.;KU
-MX`4(+3+=$=4SCJ-=MZ[Q<LL=D8U^3+NM7\6Z[TR4I^UTRK;_<_FFWO&-1;)/
-M!V3X-41U"7URG[6HR&DH+@P3:XN!"4'>28,0$LEZ:`.VX,Y4PRZIL(9](P?.
-M;,:*OB1V+0-8%QG;59'*_)/BUD\-984@VSK@*.=],^VDB51GI8K1XV$,'",E
-MN!(%S7\$E@P_"**.6H^WH$C%6<^LO`U>4O?'06(0-BF_XBA-]3=M?Q;'>XI=
-MT8ZW'Q<E(;/<YU.:]\[CJ2N-_"2_3<94>QT219:&QP?3C`!IZ>X$607%?[X3
-MDO?J&:`_;!7V$&*W3A_.2"7?(Z/)P_E)!E7&>>'!L):D%:%.D4IS.9TWS[T<
-M==877;;=#`&LKU*-C^02UL\>B]W#MDLU^JCG&E79';9F4*_R5KE,O6X/DRD-
-M61U2J;<EWRM\?*VPVU)^?VSYAO3;9UFQM5U>LAZ-/7JVW<)9B0&DF_TF'8=J
-M-Q,03T\NJ7F;FRP-SW_>4KXXBI)UY?KJ)W$]O^./<=%"+M$*I,[!+U$`,TLH
-M6O!_-68GK9SI3E^NS&5[5V44A.IFD%[-DFI^;Y$%^NL,T_"6,B>>1^48P<[M
-M67]5N&&/<EC[//-VMXE=4R`]G#]7*U+-=`DV"$TQ0]?;\?1V7O,B+T8#RM;I
-MUG_"#]#4"_*-T:'-MA0U>H=!&6UNXSQ3LJ0PKI6H0QQV6RGGA1,K3F4^Z;R+
-M`R3^GQL,2(I=#&5&C2<$G>XUF;7[*-'IN^*"20@,><_IA0)GB0>%_)V2?O(+
-MEE*GI*C<*=]B:]"@\KZPM#PW=T-I0!GV6'[KOE,(?^:KEL#K%>-0TZ?(8\S^
-M4\;T$=$C@)S347:@U'=V,=9_?O<+L2MQA^QR]5O0M@K)%*!E4IMCTSC8I_`\
-MT8+1#A7D2NF8]@#-4`@$_STA++KVA&0J$5Q0JWOR'N"%0H7?((U%57NUP.K2
-MSO:[V?^D&1KURD7`D/%,=)8<GGDLH(8C<^KR6"+@X\<T`5'Z437"%JS.8G$E
-M]WFUC*#-\.TRG@,/N5JS"TT?E-?ZYFO;*\^KZPI_1WBN7$#,L"$8\'M=CLH1
-M&TB]<(,TZ53]RU-&K,*3/B]\93"8'7PIZP3IY*#HK!JU(6G'E=>,&>WN3_5)
-M#AD7[GLC1,K^D!/M`XEE(A=3L@"W1%73&-&ES479KP>VW(C1^M!++O'IX)'6
-M&OY#7S<4)6C8D=_[/`\W,PYLTOQ3[KA.\O(</-9C^7R>G4H-IRC4,0T0:6E7
-MI\LB!%?,4$A`J?B_)NC(6))1<W+_L[]JZX!82VSJ,LHD/UQNUJ-K;XG^-'2+
-MQ^QI>%T0?CSJ>=[2UO[W^8H&S?AWXW>`!>9`AT9'%^]%5IM9D-Z=@?`@6<Z)
-M^SEX<)1"0UU86*[U0?49I2_T%58LB(&2>#ZXNL\-6(2>==F[K-./?J^%2_;Y
-M=H*1^H9G+4%I_O@4)WLB4=+1/&7J,1B6A/G^T*3]X4FL39G9:RX*.VZNR#_=
-M#,:^Y375/*P&V'*EG.[']0L9.0[O-3:U\3HXMGR//42GUWF(+8A5V&W![=B$
-M8QR&C:0^2VC?C;.3RSZUFI7\#QQ-W[6CQ,K2A@61L)1DIS30NX(_-PM%J/+^
-MFCX'29+@#A%:"#.F:.8L+`EQ9P#4@60!@?0TU*R/`S=*UM7W3#FT4H4:2:'F
-M\+>^SE,CN.+*SUQ;.]W\UW:T<X.KRI9W[I=PU#=^N<@/##&\L871C\H&A7]4
-MGI^47IRV_88!LJ]3>R#+M;;V&O.2E_1YU*%CP:J`,2RF-<QS$>'=.?"85EV.
-M;PU0)O,]UC_QW);MF7<XAITV+.K[,%9[8K&;Q&\CXJ.\-JQ^#2D/FZ%);>DT
-MI3]2$3LZ69\+6\XMZ$453&LR++,D!C_-K9_$Q'/IMRW#`W&^K+X'/<Y!V^%>
-M%$[1I!(5M/\J$@P';[3*6(KA?LLTS:##K;I22!<D%S7_O_VT__I/8Q,R>0(<
-M4-@'@R@IH'OGP6*RX6:V=U28I,_*K6E7D5[/<>=_(WCU3(L<4$9`IR"^Y-R2
-M-JW;.L3B$Q/-"?HOA-_O5G>2`&I<T%MF_B1I'\=]32L'!NS2>;;\(AXSXRH.
-M)9W4;08ZN'%:>5SKLG&L2U7Z47-18%+JN!-\::C.]\#?<X+R"\DU.*YGU8AW
-MA1U!.WP;J15_F()H@H-0BZL29R(^#IHK[PA@F%-.'QLEB']G,?1O4Y'0K5OU
-MNIDE\3D2'JU_XI.$B-?AJHVCXJ,G.:JFP;<X7S.W(DB9B#O&<@!+M)YJ%KA`
-M8TS"!`6R#L!+G;&;$P;'UK"T2I%JQ]W[#_K&-$1;C'9;%,3Q>,_MH35$CY.%
-M*&*(//=200`CMV3NEMH&!><?E+QH#>)A;X=K=V!9@P[;&`4FCZ2,>XKLW#EA
-M*NQLY5>!5`5N@>@810+8/JFU^VI4BZ<L&P.TRY)"S:,,J;VK,]Y\WX7]<,5?
-M";5.+[B:DYA3;8_5"KS)3+`&ROM0_A31J4[12!\K@XJS=YM6*^B,1NVWT$Q[
-M2[260TC6.\I7[_+G9*W-]Q5<A/'A++N0;$$?+YS72J:7'.5$'*05$:'##G4V
-M(,B@T?9V(MH:)>9H+N_Z!)TDO%M7NKC*]*Q;>A2.WQ1I-"R(K*I0OQD/(-3%
-MWU#L9*O*\D<?Z<]KIB*]#[";0XOB:B.N<_\\-U(Q\.-H]^C]U#M0JRR5D:>]
-M-T7_"(A\^`^6#@E403_=U\?E$X6M^((0&'TD0-+C2%-%:>%0SN[FS5TENQI6
-MXV?-#6.5%J*F#TYRUF$Q<F2RZ.3US?6`*^JSD:=32A9K4(>;C@&+`AJX['2V
-M_RO7#9'C6H6%_Z[D$&,!*PI5]$KB$UGWPB=-%-3FC^SX1L)IO$+4FB.'1K*;
-M]27D%Y^C`LEJ@C^UKB7FD/33GJZBE9INV6V0DDHL:WCW%"Y&5$S\+T@HKS^+
-MCN9_UWKPR:#8N:"A]9D]*48]>!BH^N6.A$,L>OWVM3G_Y$O7E=E0L0V=K!H/
-MVXD)=:?*,+[+GSFCA/P*N_.H6`1`]MFP_W*KAR2[A2O(SPNIV.]L_^(MD`TP
-MLPHS=*3^)%YR6SS,K"M#5RF4:K^(;NPW1B*8;5G#L!@G91X&"]1(%ZDFYF\I
-M<;Q6#.Z61GT/M)1O(A8^@K^Q1#ODZC.FZSF-)=1MFR82S3*@%M!-I**63;YN
-M;A7LBZWQYFGD&_OU]ISU<$QYHP5IIPG;!.,23)-C0BX-,U7AU?;>F`W87AHH
-M-''[GNK<^O@IHE7:A:I<YO#CRJ`G#(+5!X62_6<=T[0]PQTW'<BTYOCGQN;(
-MF7;TW[??G5X[M_QYR`ZD$G72AKZASKUG4\'1!SKL']GD+;9P9$A2+3+!\PH3
-MY]TARBW#!L#O\N\5!W2YZ2\:^=?)')\>H`I+OT'I=!?=]Y1+EDXX@[*1MM<9
-MEJJ/W(!"?WG1ZM'ZX1A?M)EZ(8C$7K?5[8#5L"@CY'01'UWU9%4G0AEJNMDA
-M`2C:C(PO,W-I`+6B8;6ESV)R_DQ.@\AA.1Z$]]CHE;RR%UBZ"A$H-E98]H,<
-MI0L79NFGV<Z2#\+PR^NHT#G7?/RTDT%[236?#`^HDB3>!\2T)&0T\49H,M7R
-M9);_V<'P;B7[4AR7#2'-Y-[KXKLHA933U!C5S..PCDI)T^2NHQ=(\72`4L?C
-M3-YG;N<S7+/61Z?!HQJA_M^;VW1O0\D#<N^_<:(HLEAS&I;WH<=_O2#)U0TE
-M:*F3F[R^BSV%72LBMD"C5C.`H>J-1.>]X);:+B^Q<91>,3PDIBPKE0T:$#5T
-M"]!R),7/L?><<!=$IG#8U!YV@S>&Y]<1\%?Q8CZ$,[OZMD_">%F'&M"]].6O
-M*8XME=?8H[+/B-^RF#CW'7D;`;RCO+4C?L4:R@]<?O$14+Z#TCCN\<`(!M6J
-M[A/YY]3B&UOKBD]CMRG(A2G"0+[IU`GR<%EW-H,8YQG>/H`*:+?MC$*!QSO4
-MJ]4;:KCJ^3TBP_B=3^NJ@0O8M^=ZTU72'.6HWO.N<=#6M'5[*W1RM*1+/_MX
-MLM<3D2;/W&ER#\T#3IINR*+U6RN32-V)Y8*N+=&?0)P#I6A]*^B7^.&B!$<#
-MC'!`2:\@T)I@EAM2<I?430)^HH9&U7]X!'87UY3,JY7PX"$%1N9Z^SUV#C?J
-M]B9E(>!=QWRFSZ1Y/MQXSA-0]69?T6BH$Z>=J@#.XE('O(IO5KEF`@-+4U1%
-M9$Z\'1[V>K=4CZVH`-J^_<'/,>R%=R$%P7!X?N%]=[2C?Y)<9TVRPLO"$^C/
-M<W8D_QAPHF1Q@GJYE%B02:>@<VZGVGD#6"P<RL8CL!CN4M(LXZUW!'%W,W)'
-M>W>T^660O8_WSRQ*-_S`.+1`V2TRX"'40L$SC8Q+)K1V0DJB02Q(E_X?#=/*
-M#4JRL*[FQ'I.T$;Z"T[&%#2R5*R3<X4UT%+C1/2,X1>T+)NEL26E:('EQL-'
-MUK7GT38>SG7-4N$J?Q.JDYLG%7=/6(&GWN#=:EV6V/793#L53=O9;8B&+3!U
-M,@?6`KZ<)!=R8^M!V?L7ZYNH&I;&6F=^AE8:E?+G:)04;**Q2T9($Q_1=M]O
-MA2.GRO:HZ]V&Y#HX2FFS.M&R).QM@:AY15VU[7+T).Q5USU:5WCXL=]+T>[0
-M`1]Y^I_WB5.+L'G>HV\7:EQ*0L/7A^"+;$$L:&I\#9+H4#9NFH6#4S?$E;D'
-MWBJQ)WOTD;[C7SFEB:PPN9K7J0:L@XM,A3=8)4HJ71069[^>=RO2%1U7B*,1
-M:5"W))L5?MZ7'=K9:CO&#FT6:]5$#(286L,BB:>8H\&`+&[!B;^HFVD$$C8[
-M<CYY?*1*GB;R8#MX$^E;4K/"^W17]2UCKD\_ES&79B1GPIJ)=50X[,@4AW6\
-MHMRU_BM]D=GJ/A8H`,S&"S&\>GQUHD3=5>?ZL>VLXSHS0/G^B\['4D4>7G(J
-M%H:P65E?%++?3[>GLY+1BU?*N9K4%9-'B5(WFPPA>5$D5OXA#8*9V&0>I7*S
-M>D/%*<+&56+FQR_%*KF+&.A5'[]#GS;IC]3>7&\-*0UXI;8A7F%C)@7V4@1Y
-M>TO>;;S]XLK<5(]ER"GE?_]O@_[\`P';T]9IAV<)6":V?_R7K2WS9^5GS"L1
-MF8'<=ND@&&L"N"AV5GH]$!LHI0,,A'/"X<8Q(.X4VBE.\ZND(AS5`=2,.<X?
-M3-,Q'V<F^"X)7]%QSU>C=QS@\>/;ZE6!5C@J-.Y#:IO]CRYE?/8BG%7RA<4E
-M?$=5S/TOL>I8WU97_Q:<80;N=TE&!_1('AEDYZ]]8.>0ME',W_-]%\]0)E[5
-M;R7=IN[X'S=U?/CFYT^$.K:BP5\^]ZFD.2GK4?621PAQEU<#W$X8K`-S$(=K
-MMPLM$6YQQPM#'MI@=DQA8%W(EKH[Q33Y/<'_D##4E]NM(+5+G743?KV8+0M:
-M#*0*Q<&4-36V/;]C\N!)L<:E2&8U<!,]-M;1"->&[95VK8[#VF&T?.NCA;R1
-M6'E*&5QY@2Y`(N=1=2>$A_V^/XB1^96J$I$_#U5?Z#7'*]$=L34S=@Z+IVNO
-M=!)=35;RQ,!\UI9;2"=F0_CYD9,M=(Q2$0\42:*(];-3=\BCPD0SQT*X7?M&
-MNERJ[B!-V.)DH<@;&;UV1J-S/U@I.[$+IUTI,:9_S7`.%FN3.NN.K]&[Y=SH
-MUAI+W5'FU\]B;NX\^C$,W0"I">O)(C+&,!T>69\0/7>4V(Q_">.`\LRKP;8@
-M#'W+I%/I#D,_+9EN5^M1;YQ+O(F!!<H6/OK=/5[WZMA],3C@[#316X:$2RX9
-MKXAD=:!%`%A&T>>7@IB('Q,/-?"FZ9!+>!LS\15Y>1NHJE0P;ZTK]%7/J`Q$
-M1GC2-:+XH=%3F`'G5ID1N`<IS8$GA5]VKP\*.TE9!(SLX=GRF`!OU\JH<'>"
-MJ4RRT!H6LAT_B8(K/,,S5?9F@\TXSIYQ81]6MF3ECT+7;Q0O*GT)$#\A@6KP
-M:Y.T>QSKN0#%+CM1!XY\U&J<A27`BI`]4'R$6-VDR2M(J0S8,5-(89--Y.K_
-MM,4\)J"XO=5([-=@8@H$275^_WA<6:ZXW>[.]EL&V?SG0UCV8M-DPV$3/6V]
-M[*=//@&:K&#_DF#0P--LS@9UR0F91KW+4F/U"1R05!+^:2/F0E+\^XOVLQE"
-MD+OWI5$WVM?]Q,]V1YB-%3Y-@[WE"<WGF:[@!'RQ<$..RRK[X+$GVOL#A3\2
-M=6,7!(M6N\]PT$*EN2:@W`-L3GS&(:KA?K7@@_:4&1K/JG\$]`=1D^#VM^(^
-MAM3Z%\7XH%=AMVZV0*\3/P*-S#X\>D6GV8/$E*::[/:T1HV8V*_8A`M0ZJ+J
-M*+I"MR4E-XFND"[A3L6I,T&S-',WO]\3>LR#UX9MQ^;FI7J0&>-*235%GI15
-M($,;68<1\G$/?$<#)LC:KU&BI-Y[`5+MLK\#Z0GNRWZZ42M6^N@0P-/WC2"9
-M_D08,[P.7\(`[4**=C&:%(>";1PFR2>E[$90'@Q9<ISW:#2\0=W8O^S/A:W;
-MW#AM*QV>T-4K/;DVQ2=J+4MC_/6G]F0L^\8>1P9ZRQK%]V&)F,->_0_QT:9R
-MGVLYZ/)!(4J%ZU5N)"]+2Y`&*HCNHV;`Q[CN?8$K^F6-/4'><(Z7\O,**C>E
-MR(^D(Q[-X-ON(KQ0A&A3R8];,?]`J9(SXG%`&:^)/\:\J3D9:A+.V4E0':Z\
-ML\N].)8SRSN43%/!R0+4GD1M9F4U"K<6XZ$RK\G+I''Z*;"XY3Z]W+<PW6!K
-M-.M6'5SCU-93L?+(=9U?]5&II2!!/%3Z@^%%GT9,8FY\DR0V3L`<3:[_:AOP
-M038/<$,&">Y/GY*$9"^=.1B'5PZDJ;]O,L!;"<AH<\KU_$HT%ZR\LQ((866M
-MGH:*.]J8P^X9!5'?-[$TJTOI;&C$`DVJAK@G'+N<,42^M$B;SC1WQPNW#\]?
-M"-CTIWH/V""G;S2.0>-*^TY=4=BS?7"-HE'6(#8W1)Z:M?`I8#=R\"X4J:62
-M$%$A._[#8?`/.PZ"%D^=H;<HL-VDU%:I`\0)BE_P^D:;@[;QMA?]LNKR_RN`
-M\HSN3PU/C86<K*FT;U5,)`\?+)(YJIHIRO2#YN6KENY0`C#S9?5.7T47.%PH
-MSCB'+V>(?8WP=EC-Q<PDRV-(]\R&KF)346=7_"-6O_4F0F/X]MTT@G=S^;[0
-MYI/7;<"B[4JF7%SFFC15$Z3'806:J7EU'ONM.!T\>[-8LSNQ":WO)]J?)0J(
-MMQ*;=0EA`4.,;(BGA05B1!N<;[7?H0=H1ZUAJ=9][8?[FZ)L)`G..4D@!O+S
-M9#+NC&JWAZAEI>^)ZP/[+^,S6PC&T)7:AKRLB_HWC<VO'QEZ[C<QC;D`DXY+
-M"N@$OF-"'Q9Y*%JR3S':<B1OJ%W$P(<6\A6Q>&LL"L`'9*8]^.9ER4]0*:G9
-M">Q[@UK"<-20^!PM8#35I6TTK/L4P2U]W#XCE'4(=4I!!KV"N\;$YUMOF*$/
-M#!_F9AM&U(<J!@0+WT+61#C9WIQ&#YQM`I+<Y$$H:@M>6GU^@[_8JTHH7:\D
-MS5CK*30D;)!K-/P"Y7S+1-15EUCH(]7M^_&?/\R:&[NY1Z)_8?UDCK8P6B&6
-MXNEVC@@%DD@V<[BL#S"_]E5+31CM6DBF)*XH%D7K:76^*AK.;\FO]$1T-%75
-M2#A&KPR98IME.M37+16!EYM(B'N5A]ML)3!?:9G@G"-J]R^,O89#VS"XQT1V
-MGRPC,PEO7K&5TCK24,QA^'XIB3BR!$;&Z.':.'JN0/@]^1@99Y#K'LR9`F9\
-M=L:^U/SQY=FZE\"3P;1Q8<BL"-LS+13\"H*-U*/,F*3?AP92/]I4'W?EV:UG
-MOK/9>W2=4YF+T"*/]RCP^R`;WHB@YGK&8-C."W?L"42CJZPG?^,`N"EVE#JQ
-M<*E+]Q@D=6Q&$*-55OK<$EN'XFEHPLVB+;%_H(M4HTCR\2@)<[2^S58,9\CZ
-M/Q%PC]=-3P?/.A5L'VZB:TGL+*/K)F3%<ZECNF\E3'MN8D^85-6;=N*7.K\3
-MJ*&P*.L88A7"#X\-LKX5>-?Q4*')6,5X:5UJ4G>52,\5^-,)ZFD2JA!\#/"U
-MA>%EIW:.N@9<'V)[<HOE2/,QQ(Y8?CNWOX$@!?\-0J>LF3Z7PJ.^ON*PB4$!
-M+N=DD=+[F\AV7E=@,Z_#/CJ40SW>.[?/Z8R41&=2),4=/+[\%M6NVUF!F(@O
-MLUXI>'@QO\.S])+XD9#R*K5V2CE?8N</<+7O:Y<_\IR!%$>S!'_B+QP5XVBV
-MG10N"G:,_%S^'KE<;"!V%0:=UK@I3TZBM6FZC&N>3U\=GYUWTW(1NK>7?(<I
-M-HES?L?;.BI^][,?C??];+:8S5$U2R0:,Z(LN/RX!=DWDSI4X72H/)B$INI'
-M8FL:LK2?%K^5%>/.W_(:_GT*3J$DB2\O!KZ26]+8=_'I,:-0Q;O!C-$'I)#?
-MT/?EU_RZK+NDX!G.Z40,\9:>R3X^4"!Y?ZRQO8#!ZSX)1;+(9AQ&8GFF9YNA
-M!6$1KKDM6&?)O\P8[P(`L1&A_(4ZEV`?'U40U79.4_1GS\Y0V,O+Y*P5'BST
-MR@Z/NT]6@1L+4B4NR_:>L`&EWR+U7IO=532Y$ZD(@GEED@UWW]I^A9X.;8E4
-MV>6OS>):>]?:R]DY\;7=4\\V\^J8-H@_J;FEBMV?`8<E27)&.U<9]351.>"0
-M@Z@R3WC-3^\0+_+B[<+C-`RO>/T#8>)CZ,$*!812^J?F.4N9L$9Q#7?<DXJ_
-M8#1"'A1++/.0I4&4&J7+<DB`+Y.5M"$^0<)\M*UW0VP#V('</[&$'M2W*@;K
-M($4,G)<K)M2Y<1O&>VA)W>L\O.P#OUR_L=R*FL<.DF"`^ZA;>Z((%B@%.Y1)
-M?MCIOY1,)K^"X3N6O1Q6$:T0\:.\:23D?-+AODEYM(SMZ@R5E^[@52N?$XH7
-M>E@!HH$6X@/@H%`X#Z"=%&NB3*Z)M+C^N>;'@,O&FHH5,9EA$X]"J975$6RS
-M/Z(:IVX/C7@R7V9QTOX*%7@=^$*V_#V/\F/8\9GD]IM+[A5OR&P6&P+=/?&^
-MXCYPU(V*?N']7"OZN!*R9G'XX0P(+UT-?!7**!Z8[;X*L!BCB&[LZTC[V0F+
-MA9[42Q3$KY2P/2\X0^82TT<,;*W4`U)FG^$MS+L8#=>6N*VSQ9@GC&,0-H.R
-MW^8SU3X<*^9"\7J'@"FF&\)5/8EN]-TF@SR(AV%V?8-=,:+VVEEPM(\[-N3*
-MF[LT+X8%-0^"PIO%89O>:/Q8KC7$/2A48*N.UD#!>W7_DF*&6U#R]ZF-]#:-
-ML:R<<!1C5X]V3>#>!`572E^LF)*\V/(Y*'9=\"4)J4^N?#P7MRE[AE8$87_K
-M-.')B=$O8R=5A6SBO1,PIA"/EG/5^M(DV3H"L=:/R/G-L^:]Y7OFW4@?/E33
-M;+)#ZAPNAP"0./>KC9&UBY(@FNZMTXNVS+N&CO!&:RVE3865#IH3];33!_4F
-MYF;?+H`)MZ<,3^R-IY%122A`@`"$EF.U9NH)M3Y[AG:#E8Q8_,F>^%!3A/C<
-MUFN=?@N&$H^ASPHJMR(!P-,:*@[.46ZJ]&^.1[K4<DU:JQ0EEO__<.MP-'^>
-M@1^LPK:4F]ZO)NXK6A'^'T3,5/??_+KY/1VE(SOJLE7HWD5)K`BV%CS>7/F-
-MG:*<,YR2ZO!#8"F<32YVA@^_]S*`D:/=,%3$^DK_2VL/`36T;L+,\E+ZWQ5+
-M/T5?>`<[+('6Q92VX='C*%V0$(\KQV'Q]9^9C#1DY!O<E19<E/NN&TWWK8A;
-M#A;L.(]`HR(8@[OZ)FM`I00.9@J]D_W%J"#E(C8*2IC+_2SB,M8VX@W,^UB_
-M9_DZ]Y(]]=MF0K/F/\>6XI\#_TY>20GG3#9&&L03[[/-`\_@R7?V/EMN0EID
-MQ$],*S(.`Q@N'R#S=!$\WI+TN$!K%U*W*%8J57]*%55L%](&*#_2Q>4\ZZ.5
-M-C=$EZ)(7`-IP8.;`0E,XE[LQ:+,.0@IP&7,8S#&P/:\F+A@=7U`BAV6SB1-
-M]UCU.:>1LEKYT5E7S-8;M`=LVYX>0!_8D8O#]F=46`=Z;TUD?M'?=.MA9(Z8
-M;_E*-YE:XZ@T[8-P&Y!^`@/XS65PM*-`T(_Q:.8*9T(TETP4LX?0JSIXOAG+
-M:+M9FW/PT16G#-#=.9DHR'DV\A:A&Z8_5;N;2VZ=.C2DSY4B#\RU'N4*A_<!
-MHV[+Q.?S:K+8KOP]:+)H.EL/PF$RMQ/H.'RV"I'8.1%Y8M%GT\;FL/:FVP0^
-MWX5A.-127/&ST2Q1'JGHTM0RGMAT7\8^SVH7),.W61ERU2H&>M\9QT1>IFXL
-M:($I20P'0NIW@W@-K.L$]/7+>94-@%?'J*<_[1KEN[=#9L@OT$:LTV2$)WJ3
-MG5GZ/>#PCF&@Q6.-+T#]Q&M+#M`3D'F+`2U>6>6K_R^D(H/6R0HH>?1_#6+N
-MD8A\+Y/HO7AB/G+`DCGQJ6Q#_:9?MFI:EN5KED.8Z/?M$`AVM;1U[?R]3R4T
-M9L#?67RZ5"RP=N``E0QI,W-#YS@$-S>"TM)P6.Z'%+6^T4-0TBID2KM,&[O"
-M=JEK?&H>]MI]3IMDXB!PX"6F=S6',3V`8VM$:S8J!,A/A<O"8(KO_SCU&7N0
-MZP$A:[!^B>-(F8J;I2^]WSC[$??TWX^6<'E$VD_[EA<U7Z`82*WWDHLM0%*O
-M$/0DT1.=#ZD!J?AZ<1170=767E4[G$-J\440@>A4A%6Q)E;U_GIE*K8.!;I0
-MG_IZ2VA&KQJ08)/AW"]#H*=_TPI^,#7@/!K%[,%`]ROGQS416WJ(2<X`^#?/
-M#_4_%/Q`'CHVW&?IB5]XW(EF]T-GU_RXBFLN-5HS_E?*IWO[[#.-E'_3K5M[
-MN<L`2,H=L"0IT,JCF/-D$F._1]*)1AQ>Q^Y"\@TN_3BAI=#=&`?J[Q=`%3:Z
-M?G5*_XT?BIXR(6A]"=0XL>197%@@7>`!A1D6IA@M8GFO]IZ8W(JWCG"QK=>Q
-M@FCSOZGZF/Z+8!9^!AFQ9I1W@8`SLI,"_@9G*9I>(P'9);FL?1HG9H[T25$@
-M*D[9@U*1E:,);(IY2QQ9,'_&3=HQEX'IK<@2)(1^5XX`D,5G)0&8"8F.C3T>
-M2FY*WIH%'1?!F&+I'Z@&'OR&;XNYBN8EA]WO822ZB)R_)VX\PZ]_&.+K_UMS
-M-_+/@A7N8K.Q0&C,&VND_E.)1E^D<GL65*IA=Q%`Q6V=O17U=V#L*T?6!=H!
-M!?:>N?U3GJC0D$6U/M1LO1QC0U#FZ@^(]>XM'4W-SC\XO\3)65YXM7PF4%CA
-MH,C`';DJCAUFR*G:RS[2JHBVK'S<+C1QM+_$2GG>LCOW(0)A6GOBX._G]88:
-MY#Q@F_MB:S=MF`S,(B66CU&@AKC^[UT8.J@KG2YXYN)5FF+PWQ*9QZ0F;R`&
-MQT0#)]O4X@O>9W8-PKM88M"/NET:88E9*1KNO<D.2G#G(T#;XC`5]A['=VT@
-MU7[J[3X.I^3+@/]3C105#.2D]/.T<?Y]/W4'=K0]/LM!;*80GO%\^R'#LQQY
-M"/MHM)JQJX,_31<GVJ1+'IE>$WLNY7;NO[&NTQY:5SV0>LP8P`3L!?EP?)YP
-MJ5DGNXEO25E7`R:E\]&DSF/`R&O2OM_/Q9&>A`JAT%8,_!5@LP(3;+\7_V@)
-M;ZM;T^<U,V9(X%8T.5N8#.03C;Z9"^??(,?1%?4?KK?M2&8!E'YGO%'#X],%
-M+"E*]'XMIMGE$=G/]T.:ON9CM5T65$+$_,['9R]4&+FI2;9?JW+9_R1OMV/(
-MQRRYD<M'XM(5U%3)'(H6/I-2I@DRX(M%&P2A`M#$4[.%=DGLHI$DK,EG&E1Q
-MZFT#-#R&/SY.6X*G(3SM/US$CDW$I$F4)+^H.THNK<Q.Q;*M'H[_:U1<O37W
-M8TMSK^Q1=[C;A+BL'X1^/RABII2'-*8S2)WXP/1D*7FFK?OM2<]&VN=$GTML
-M4H-:>-V"HMI'JCP>TH`DC$\%BH-+E89H#IX@):3%!-'-6T5F%DX8/S_!`3?_
-MO*F(.D\'P!;76>20^$1>6`S->K^1GAZ86K;WT%==OM^;^_QKDAJ($LS#OWKB
-M*%SK+A!.0#FEJ/TE:&RA-D@BA'>XZ<(7F)&>;=<84!6S4X#F&<T?QDDF#.S2
-M/TK[!DQ+1SZD=N/<"5().[.<0A9?4$]ZA<?G^A[[XP`?."R!7K.@U@:S_.<C
-MIB#B9JH+-%4A(+/?P?SUB0IP&%R'&'1::-14]L7I6<3"K]39*N\47RT7:]*B
-MVQPU'/',\7,1[PG[;SAYK+W2Q#;C!MZ.&TQI'H_9]#X5>((WSWI<=Q#:W*NV
-M+R2`]-O?A^5A?`EQK9GTZ.ULZX@#:E!Z1[1\J;6.+'72_([6>3Q*9"`J+^76
-M6!=_#GY<9)+E1[WR;)I7R-QG;IZO+F?%]PI5Q-;Q-H]2UYGYD$(6C.$H('.E
-M=DS/=_#*FI(Y<YZX"5'K2Q-+[7_62%Z2I'O=1E<Z53FD:5=9?Z,9AE.)I]W3
-M,MG5@$DP6&$R%SZ_<M>U5A@5`O:#A?9YCHWC9!1*WFF[?,["PL"UI8_/U"F4
-M0WK/B;$(<3689#F&:>'E.8#]S"M&,@RC"/RYV[G^U9':SB$[\CF^N+V/!;HJ
-M*EQX+\71BU4GR&\1GRAU7B0-8]5&?M&5_/==/D_GB,!AMP*4R,%[`T6_X\I1
-M@SI/["ES:S<$*DJ2_`UZ!^@><-I+_:!+<)O*9JTHS*0A=Z`3S`5CF_JE\6V6
-M\KPUGM"_$'7+2''FG:[+9D@,N3Q'-U^&5*^T:0-J4=&<5D/*T*Q?2G9"XG_F
-M^2X)F+9F@P3XI>##N5,;O$/&>=<TGD!V`0&`5K?@KK0_!Q;UK)%_#/IF`D*F
-M0`*+CM'SJ<#V_&+"VTVA#NUY6M4".I;AS#G2,"`!&M@/1D1HD4\3WN+JI/?9
-M;HS>_Z13&_4,IA"'OLI+?0HG)N'[U>9S`5\M?0@`=_E0S#,\H$IBJ:7J,5WG
-M$\/;P&\[->G/%2/?+VN!$76;T%+"TP38:.!Q/(/)2M?)5,"/HE$L'AI4<$<H
-M'D^<]+$5X+UQ%#V"I/F2"_)%JLCJ-/RXML]&;I:0S5P8!F,W1MCNAAQ)4^(<
-M+T7ST6Q=RB1?*Q'/?34G9E\HB>5$7'3TGQB]@\5.="J-47WSO*`8W\FR(-TK
-MN1#44(^V9R2DKNDRXH&E+N[YJH<"@W5`5"K;-;*&HC8:'"1$?84]D:\RO\EF
-M9M'=!$H:GT[W->G'\;/JWKD,IJURPTUV@KX)Q62[`Y8[1QHX%Y4GI.VXJR%O
-M#'"\C(WUA!:0IR(R,S0^!"FSLSEVD6T^4(8B-U%,NGOZ/DHTOD*,:'Q#[C0'
-M#A53.FF_<]S%96#8SLW%+5@50ZG3^S.<=,2<3@0&?1+AT@37'LR`I,^V]=F:
-M]Q;B@18UR\]EATL0/U7<LYANKE:@;>,+3Q.J2)0;_F\86$V_X(=`N6U$88+<
-M/5TYN*0R@X$$RQUM&8WV\,K;IW+"YYW+OC[,6(""\2Y`+P>SC:$P.YF$NWD\
-M4LY76R:NINW%%_RCZ@HT<GTR;?I)I>M0'-!L]0@Z-G>0HTD;3VPSCO?>9?)M
-MQRD9;9%5J:[N76I4+AC*_5MO2IM)1#40"I9!<N!Z1&/R$^Q^IN(N\P8F>&#M
-ML3A:&<("5>#K85DM7=C"]C20H)$+?'V/(6"N?ZT4%CL7W7K[>);E:J8:R+W6
-MA\^*".N9L.;!S:)Z#GY&#.OS$B#CO,'I<[29K3"#2SXJAI$8#,)>0&."HR[(
-MJ3?B+8_PRFH<`&):V22,L7H-I1TQ=,%DM_BMNP'3ZJF9_%*>2%>`O80A$6M^
-MOZ-Q*<?[5J74X8/V=4M8MW3BDGG$V3[IX#D9)8_E;`<8:(26TS7,>FEV#T;'
-M/[#[S")5SEVOT<J^E<ZQ@]/CK_@^,SI8FW?&M*>:JKNRC!0.[KQ\Z&Z[_,0O
-M$O)@Y%`+YOQG2^0(F7U>HP2>26)>)ND`<PX+:1CF`LU%,%<YLW71(LO7C0L^
-M+IP<L-D?92<DGRS5FSO"<)'&+$\7MND`_6V,E=\,2.N=6M&S4'TV#@X:O[Z/
-M[5A2-CQ>3:7B$;I9PZA%-I<B[0U=K25+`T<)AZ*E'9/'G<N2=-N*\7W^[)YL
-MKCY8AD=6^5J++;-VZ![+<=Z\"!H(CI/-_`R,8S/UV)`N7P`N5I6F][[<+F++
-MZ)'Z2(?ZJVU.N<Y5-_\B<0(97:`?CT8@YC:+5>NYJ-FG6+9`$U(MAKH+CL0(
-ML3E[@4%XM>WTM0:.)3;Z:7+-CZ6^]\.\JCQ+-?WTP@'CUWW]Y!HFBC+76!ZK
-M6>!TW_:U,$MNX)JV:IX[:4$P?G#&P**KMO4_ZO.7,]=F["^%!DX#?*>H++O2
-M>&5">P_]4-"/*"#-%8J`\_U;OR$;7ZX`FM6UA'FG-7CT:6`/E%>)(87P4Q.F
-M>/VL(E_8OO8:E_$\VSGP<3"KE6)LG[RTI&"SRF_Q\>@TSXHN52^Q"=8JNK5#
-MRT/'#:F'PKN'FA\UM<7R)6D0$\=F'JIKV3!I[68\^NB_6I[@*T3$=W=\/_06
-M/9DH[9/KSX7H_\X3W_*O6-/8VEI$Y]J!PZN8<5.6^:F;K2;QL;7`T(Z8]0?Q
-MPRR7*\E!@"(WV[]A"?LC@D$[<*HD>,W]?!C\&(XV':O\N'_RPJ*F=`![E1#2
-MI7]D^>"EU@=><1*55VBV1<3[S?NBL=.(VR]/:J,=+M77O2<<+/8[9,QZK%#U
-MV)L.`4+)G'V#@<*`.@?EP&^L$Q(N/]MZXR!KU^M;0B%17>J;60["AR!RB<U6
-MH`]6T<L;"[U?8X%XNU1EG:L/ON#WIENG]2P0+K=6;0./`Q;`X7+#2\^JV-C3
-MN>PZ!.2YWPS`(O+*CJ2:G%ZD,Q<9Q%35>->:6[IW0:G/*HR$[Q:RA&0NP.C(
-MX&.,OA!Y:C5X\4*43=+E*N5O0&$4T_9M"7A\O*BV@.-HEALG-[(/PA#<+MIX
-MO.8"1\E=_#&&L`:HRI\L>==->YMDU,+^TWF'$8XT]:&.1YS0;W5DFD32&FYW
-MZ=FK>^%IL`ADNQ20RL-ZQ*\1"\V_3=WK!BU&T@_-FV@+.%=(<<HPF95\PB*,
-MD$_+TR@K`3X!]9A@6O3`91-:'_]=&3+GH?$QGQ:C)^?!*B80;LF]>;L11JH&
-M8B0GNZ?,@@'N=7'^@V59PI;>H#A1>D?\U[/VYCD\(*"/^;G[!@G"2,F>[^X7
-MH]^I?3?O;+PU[N>V3('5V:V!P\[M^&+-,F(4?K,OZ72R$V1/FOWS!<BV3'E!
-M#A17#&FI$3Z@/`*.Q".Y3\39#0O[D-/).>@37`.U[(-!E=:>R>;&LK-ZO`8B
-MGP1DCXM0<"6&(KZD3^CJ3KST]H?YT@JR]3Q_%[GJ17OOI?%$54JJIS[\4V9?
-MSM_"H\[0:[<0%0_6S20WLGVR44<%??5'Q9NT=B[<*_1=Z665O.%:.N0$QV%(
-M2O,Z/-5".^+^V38!E3:/)=O+>C4//+;?70RM]N+?ZE05TA\$@&HD$@J<=*FN
-M5\JO$7DCL\O-[N7"EX1G4/DZN:$'B2\-9)>$1A'?]^,UI*$/%WQP20C[9=X:
-MYTQEM"CJ(B80D-+-"<J2,,22!/1`B?_1".6?A*/*M-7R)#?)#E*:C%=2+1X`
-M'6\S<BQ]V',VQ6TT\YV<_PYP#_Y95WZAP-LS.4%<<N-A;!8[6V*V-Z5KA["U
-MP1)9_YK2N,HCKD%'L`H(W^!V$%]LJ;/._"$`?K-P:>^,)V!D&NCXRHW!>@__
-MS(9;H=]>@@G>T).AP;83HN0RX-'?;E1.RQWN5D+"ZS9RC:2__B?MW$BRF/^'
-M>3KB50,\"[J]<T+ZK*7G^ZG%6.RG?B*=5<5@K[4RM$5CV>_UB+1FO7>F=WN`
-M#T=XUCDBG2WW8F#1#=XU%Q<0\$CD,APLD%R!KE6`69V]$3`8@QF;=>O?VV#;
-M:CS$"^%'>8K8G[.&OWR'17S;*[^G:[(L]#OR.(J,/8H<6DA]T'T[<RDX2&`N
-M'0^5P2C,E8PQGN)]U6BD1[\?[`WQ/;SJ.'&8,2YD=<:P;-JOC/ZM/KL/)],5
-M)`8^7"])!K#J7%B7%$[Q$&:R^C7'$WZU0Y<SS0UTLY3=\VCK\=SJXWL9WKIL
-M>*'##2QF=/7.<\/8X+JO2PC]7ITH\74L%DQ#)K!YK]2,ZB17<[Q4**N5LK(M
-M6L\F_7(96#YJ2Y2N?(W:F]"=<'`"+4D)C8[*%,:0-H\7`Q%(W&-$IT)9_C]/
-M2AN*;I][)#0R0"DG@=)?JO>'N<=F8<AE<2*!<0Y=(LEC^%T*@7KOFQ&T[%LE
-MT^CPQS7@2[(Q>YK+%J,*C7;$RX[Q!'MS7#I_MI49XLB3F1?6'Z]K]QC.-$0:
-M9HQ2@4[WH*0&(XI$\21VQ@#I163\!VAZUR%<ER,G3.T^2S>ZNRA0NJ\&<WR=
-MJQBSFA_$;TW1]M#TT$O:1N`PY?6]7GYKR6$YJ!5)SP&LF<L"#8(.-I.(J/*Z
-MTN!X19R\+J0P/^+<JWU5:[NK7+!)-9]!DH"^MAU9M<:`RUE6*IQ78;BW=,N1
-MUYDYVY$HW4@0'5]_I,O;-(_LZ>+MU!#M60_,FTY.;VC`*Q(>"TP-UP6#8PQL
-ME>,5U%&/,S#64&N&:!PK85RWW;@8*"<_=OR)?%^GU1@>\L:D-%.+ZX.+--2W
-MHU`_"[,6?$T.941^_;9"Y`U&8L3,=3X5NQ;\02.*K$Q=+0`CF[2NIN6E&<5Q
-M9%6NM9,`#O&/O7J9QT3Y$3"L5>,JY+BJ`%'B!Z^GKD5S0.M^E.1/U[)RJ/0$
-M<_%12N.>Z[1<`1.`1:1J]B1Z1+<@6,PRPVW?P\<JR-0(#XB(N!<RPC!M7%$W
-M)'(9I0I<QTXP!;&:NQ;@S1T`TO>@TX"=XC)1H&L4\9]W^_)CQ5(*^EZ,YI+D
-MI.O2("R?)!#1;F!-`EY@?3JI(\<NXO%I;(-N*X7-^@#B_DL\28#;R\TFL"`+
-ML\?$4XW)+_)(.K7-:E/S*TKI\)H@_=FU*I05>O[B*^#E&U-!>X&LZMOUOCAD
-M>Z"(R3%`"GUKH5\>][="7C]^$@\^,-'?($YHQ.4-Q\#.%,CA`4)#TU4-BW\:
-M9\G4<NTFNN78%%+S.:<S'EW5I!/L[<%=S+"!V%7BTKGKG)/I":($GS7"@UVQ
-M,:L>;3X/6\-\$;'^29_<SY6N50;Q#4@#F/!E_QSSP91Y$4"W`:?PSEHRB0+?
-MG/+V=2"F[^'[Q9*UMZ[O]OS^LGZOGMJ1V.;QLU:>"^@O5*0N5IC@D'M/F_15
-M'(TOV$*/DGN*[0=V[`V8CK)5]H`$J`;F)^EU[^K>&<K]GG,QA5;I0F%AR0]L
-M4LD/5A'GM8#-?.I>M_<H%3D#OX-;7TY%5IS5C@:OU#T@_8DD[AE43RH3BYJ(
-M60F`<I$-H*DSB!H1#V$RRKP`FFNZE`+L?FI@CF8!!#20=,D8O8;8NLR7<:'.
-M@TR8@KP)B;<C=W81JL>&JQ6"(^F3YP0Q_AQ6S^8-E5S'K@WH^7J^546#`_17
-MU=_G4ME>@"=5+"X3PU4K@:#!!6S>%@56FX<J?HUL!;DE=<]"<DVQ?,8C=!*\
-M)\<!HR\,.\;YNPJ4BQP_+?QZ1TA"-.^W9*\G5D=Z>/M6C.33N-LIN&^Y<-T"
-M(W>Q-\J%U&2*.W8F#,1L.:`U5T7G)+&+Z>8J"0EJ@C4RCC"\M'SJYF=.RWTX
-M7[HPO0!E<A0=4<G32_KU:[4'9^(*C_:S75:RS@`2]SKEB[=OHX?(>&)UK31.
-M5E1$;(WA^^A!JT<[:F]&B5EI2;!6TE"G'/J^G^&24"C.^4\04GK@RE.)=FP8
-M20*7L7*RMS#U!JPY1_Y%8WB(Y)/C-]R;M\F`#XQ\@W]0L7J\32=B?X;@D!RK
-M(#XE[YISQ'\,R(1>,N]=4/EBH1LH==-N@1@L.%V>+7MLI:/`E.?IY+_]6D(+
-MZ1GCDDK5K-TIF=6A(PV8)="XWX,`>P5I<$%Y(\)DK244[`\D1K=ACR/":I\.
-M-=/GP<:C:P1U>3A=1-2T=7SAB<XYVV34Q&1F(D0N%`N)I"VPN$^LF(N7-O'O
-M@[BJEP,<>J)2PI&R*0A__,97HSL&IR+G_X!YX'3UGEKC&K>P78FVN6V+D"_C
-M3"A'3:!ME2M%T_KOYPGZH%0RL"PT#`+`B>#[)GA+,MT3/5],F8I,$*:8(3A2
-MD<K]YRW/YRI/`<J5F<E5U*?!)U(0-3Y%<RPRQ'*'MM&Q&_(BL/@^RIIJ+ZEP
-M>JP!E^G!,5,2$%6R2MV3"[<<BUO_.EW-$?;[G#V%@GLE0"^8,'JT:XSI*I@0
-MRM/]`9<NF?C.JAWGR]EG><C<B,#$/7#?J#0%@$16F:J0S!4Q0M*/_I.O.;*$
-M)Q8:JH)_<L`G-_]`R=(P-D+9/$;J*"$*X%@=+I]9DUI#GL=8W.8O2R<@+VM#
-MW:6!`H%HV59!V=$=A>;2^1_OD5)O?@.TUNB0ZQE)(+],T.50<NMA!K!$(X&@
-MA!S$B+FNJ>-TH&D9*932%47KC7JUMTC>15I[4BM^<("J$/#KFK?Z*2RK%#]Y
-M/<@\+F4*SHF(NQP!0JW:T:[U-C4-B%7VMPM[QLK#W?T`8HBX*/.:BMVP85+=
-M`B$WWP]`,6646CK?5I?I#7A2O#?\+'2W[]@*P\TN4\.8V]AZ5(",C:%?;[ED
-MUMB;.JG[.JM\F.P8HD9:Q*C,3!<J>[H!7G"E@,P;RO%NBYV`L[9A*;U+8'8>
-M$=",<W*3Y5%HV,<,NS+H_KUEMGH<"<LM_$%&2*9N!<!N$P-D6%V%O-]:U.,.
-M]LJ)?&)]UCTD6GQM2;17D78>A6="3BPM.=)FKCE,GF]/Z0$>CF<;2W#MMP-?
-MXE:RCNI"3PUM?BJF@S'/-Q&DQ4LO2`&]OV7`NG89G6'*<Z=L4W%XM%5F`ZWN
-M'(Z^5LN#H-^&50LFXB%<<(%.1P_T_AO`\N@=&"K@0.<G%"_W$^*L^6(CI;`0
-M2&@U%#^8E>!%@QPX_8M&TTOU0O#6X%@X*9YN*\`0\]C3;VEO5?R7+-;,"/?1
-M3!V9+$OIHRF)%@4JVKI>MF2IK!&%#/BYK6,4"OR<*((*V!@;SKRS[5'4'UM1
-M^*X[*I@8*4H5!.LXW7ZRW0ZUL`NFT/]_"43_,+A[SY"-U+?_215PLV7W%B')
-M/?X20SA_(J$)'/OA]RM?66IW$O0&E/HV^RZQRX[3D4X&YDV<8?<M:0NLK#)Y
-M@VRPT&60"U[CT.]9F15>[8U(=?.R1)O'GS+(?[?[/>79V(2I4%M>[\B;XI(;
-M>UOH<$=:F?^K^G!)`%.^$T*R(*Q98&#;\)8LY%&KJLM;`&)9%$MF+_;\@&/_
-MZS"<^?+284P..5,KF3XW]',>>_'/=)FHMA:DUQKPWQ3ACM]%ZN12O`.,F1"B
-M%L]IZ:--PI;]C1N]DE8!W.2/.5`N49MZ/X0#LC?IY6>1Y)="8+/6U-W^E.:Q
-MP<N@='[Z,$(AYG+BC&?L`/41TH*2W--IT,&-7J1R8^V_%<GJ"GE]G.E_JS?,
-MQB9E[2XF1U`NF7T/;N!FQ[X#)9U%>$?4;L2J9E[CL<0O/?&\=W^"UZ*>\8YJ
-M1=R[JS)41[%2[N7-\(<VNZ58L%4RY+]Z/43`C4O,STW2]S[=\H4.H-Q6!5[4
-M#_QR!O=L4J?A-#=?Z^_>NBCTK41F)C=!\OC#=TG)_4%?"UZX(6Z9!^=%[!#M
-M_Y&,9\HU?"+M:LI;M/KQIRY93)J@(@5[-OY`6@DN/@5T/=QN!9X`,IM03BLZ
-M;B<@4\2VF""-2O`,:8L)Y#'QQ(:E&X]IRWB2D=`'P24^))O+/U8W9T>]Q;V?
-M0WQ2[.!DF4*'0_=()*+3W0*$I,#/])_O.X`1<9#)$!NY<SFJ[Z<,B%Z75XG;
-M/=ED0LC8J;?VO(Y&);BG7<^KS7NC)PL9B?'KX0-,,9F&9V!7.0VC&,J?B^0O
-MB`"XT8>DL<@GA=VH9(V2XG)^^U8)IL!3V64)K!^69&C8P'0<+X_9G%*`(5R9
-MP,@$.:VGB8G+S4/THHW@50$5E[[8M2J9?#N@:[YC=('E#AK/-;ZE'!/105)[
-MA3;W`^S_FXUF+G"C&RK'MO&Z@OLZ?MQ3-6\TX.O)9I:K^\)Z>"%-&>"W0^:G
-M_6K<Q&,NFR<G53QE>2ZO3S]<T[#&`LB$@1UABS&9AM0.W2_]7YJ`X)P.70_'
-MIRN8]).A+7-B/2IM!Z8^\;7!?MP`S-"BF;3/+K`5SQEH+\/AAA]X3"=BJ"SW
-M2\N[6&QMKWFB]>#B<VT>CY!YHHNT^D;"5WV?^*3H?Y;&ZT^?+#W5DFXZV>H%
-MK3N(QA?NV`2/IH,G"!T?#J0OF.),$R]C1%\644RQGU<F@C5!CZ1VBT=/RQJ%
-M&^O5Z[F0J99<2@9Y=6(^G,W+4V4UU9;P.2'V!?$/4*(S@AGG<F:\8,"J-V&'
-MS;O_`N:""3=IN$%9MO`W`(DZ$VT/V(UQC9HK].=_GOJ;IAT"IS"WS:+4@M4S
-MX174X`I57\`.?,7^$@0@_<_(VA`:T7STT54>V-)N!98\1@@BHXZX_R,"/PF6
-MWZRCBJ6S%<!50F,8`6>TU97]$PP\I_EPVNCF`=@H#N&.S:MVS&*Z^KO\5Q>C
-MAN5V0:;7-329D;ARPF6V2!Z6]N>(_WF%WKD;>%U8\&_7`9;YXP-M+#"^_Q3B
-M?8WLDM6;DI`HQLLAR!I>#IJ18V9C.EE6Y,C7_DT\;;E8,J"^^<L>8QTA0"*:
-M#24CSL<WOT:67S43;8RB%TJ^UCP6696T\Q@-T)18_27N#LH0M%"2\'DX9[(H
-M44G8!H/>EW*30NOW;(Q!`.^Z/8XUXN5$)4.P@%J]-GY<7YX7X;-8)G[E,P:&
-M"X;?TIASUU.0!W\J&R>IAV29$;:JR(=??Q`AR/^F@OP:#5075."V$:9:STB5
-MJ33+S@5HU^@M,[3A=E(B*W@VY6_*B',K+YB>1EF_AYM'+#O-+LR2@F)M7*YS
-MFZF7P*3S@9NW;U)X/:U_G7-E):['85.!$>?T,M[5B</2Q$Y?7`]`]P-*+.U*
-MOSE.GZ^*H=;4]D(#$G_1U:M+CE"%TE]%[N,7Q+)#WNC-UM+\D;GN%M->TT\D
-M*^S%><=W71IC;>;T;WB8K<R?F4:3N[!\*C[$3AJ4[Z+B;K7G=5EX"!8]?;1M
-MZGWTHH"W,IM+WWR3UI^8M)?%RW28R,_6W1W$K&YE0-8ZC7O:L:DM`JNE+16T
-MNI;F=L3+P0C9;;VV@K5H7"A-6=S/H%V*X\7P1B%VZ<&OD(O8:1@\8E]`1:C)
-MVW9"->OG`/_,%`&_".+,6[Q-;QV1PFHM4IZU[/V8"QCQ)/_P=@K\ANJ]Z!IJ
-M36&\\O7?&Y5VU,IL7LF3IZ/JW]))@FWLTQF6FNR@[8Z,#/P/&M_ICGK?+7`&
-MO71'@>&>'LL>$Z[HSQT'NE1E,/!&BMBHY,`#&6QHKX),+&I@E]68-!'4.KD^
-MB2+Q$-),>#T[@M+\:Q(T8'[,I9^CPW14-[^@VKN?L*CO%]K@0&2^G;_5".S[
-M9/F]F$!F*]3XH$$A.02;F=,?*1<#!S@]461'WP`_GFH!X`5AC*A-9>1?_')3
-MWMA\R<>?HYDHC@7[^S\0)8PD0$9PI<'7YRH<9F?@=PVC$B@-;";QZEMH_K-%
-M?=2SM@<<C1WS7>YO?\"3(6AE[`$35<&_NDS)>?NN"4#$F78>>.^E\T9K,G%6
-M((S3T\'RL+<ILE"69J2($U*$=UU(7N8+[9:\29%EOV]0Z=EH&(+-?CENEIXV
-MT\O=&O@UD+V[I;*LN`&-`^RR?>($WNUT4$5^H=?DC$3(9$B.WOMJ**U'08Y)
-M[(R3]!&,+6"/D&FI?(49Q8RT#%06P4N@V-:+K&8;!#0>B-J'_),>#*OF4ZE/
-MHO$+6_GSKPRCEK@<_]CW;.NNPP7+3@UT0YPG?=TX]$TR6CN"N\N:29NOR@+3
-MF@GH%S-*/;BVJ--4'E-GV%)0"[Q9NL*(``!AFHP7="J+:\CI^H7ZU#B<;-0<
-MI43VI06;UBE_K\SR$3J5E@HU/:$,Q;:06("EUL?II)K`$F408L1\_>IC7CJI
-M//EYLFU`YFW/>R$G8C.P/TVC<YDU-`ZR3$<1'FJG&[DZPEK1:'DYX?/V%8]?
-MGW1R[['AR3E](9PG4LPR17)RQ)<[YF0FA0('Q#/\JU?Y57]">.!R<RPS@*(.
-M7G8K6K+C)D4MQQ=54QD:<8-NN[C?(=D&YOK65UN%+=(3CC9P(X\[@,#C]2LC
-MID[&HT^JN)MS##OWA!4V0U+`%/%6O"@F9IG[!H=GPICE7\W3]4PA=DZC&R(O
-MTML#8]V#]`UYJ,(_IW;E%0.%X'*4D6:\9[K<ST&;"=V9>>[^K<]9S.4@MK9;
-MAM`YFRC^7`_O0;&9V<0D)]W)XJ@G3MXK[M@/Y4\@1DAG7@C<6RUAYP82!S9[
-MMMD<(RBB:?^JBXN&9XE3ZG@8C`W$HM\!L3K/?G\5A.M;U[K7K\<&9;*S<CK6
-M#(T!^1&-)??RE]ZA7!^JWX+.60YHRQKN<I3!WO[@EG?3@-L*?D@I\7XXI*8(
-M&G^#"#[B%IPG$#G:4G%S*B<I.4:#?E2^5@GAP+4]5@V(C%NJ>,T^]JL)A8@C
-M,O3W<.[D*=^VERR'"#!9NK=W2T@CFE,*>2>J#OO+)C3\.#(0Y(<+;EP6C7(B
-M1">.+SON/',;>Z7;MZ&]U._.YJU(&)ZX)5PB9=2JU:7GE.4/G3VL.,)6Y\;+
-M2'B^%!^LE=?/6'[."2FK?$'<2#4`S7>/NK,9GM`Q]K:6G9*ZM'PT`:USGTL:
-MCG'::2>[.(0`ORUR^U6\.Z479\P*31-O)"B4=:O@0-OE99U]R)KP'2?.11H'
-MDR%).*6*.8SQM\9[;SP\*++8Y$W"SL,_M^?*&D>7*W/6D0"0I:#R?$7'Q1:O
-M5/^N@U)V%/?Z<LR?AKI%X(FP<J^/<E%_4&!.(#*A-HEUDMYYG(+/!I@@P:O4
-M4Y9KC!MD"^]Y?6P:V5L,81Y/X!P8.-%Z\-2]9B\K-153H[#7O%E2-`:$=Q>\
-MJE<$8^ZQU.6*;5_!Y*8;D(!3A#>%P3^S?/LF%7KSJ<>6Q^#]:6.R77X*KV[.
-M063OZ^SOP(C@X<E!7U=^^"Q8,B:B);*',*(2CE*(=-Y_]3GO6M6=F7I%!SI\
-M_"GI>GX))<3;)*D<97G?/B=APU.1MN4D'\Y.P_;DI(FD@78=P(W*-$E?2S?3
-M=?1LL6Z)MJ]EW/1$K%H55C%WA[2"*(']T[]&QJ;$='7"-\Y!8N`'RNX-6+AC
-MQ(4NEHR!&E$HWFN7,W1Z$*;A40:L>29)3K;?U[5#$?8[Z7]D4JYLTJ('S/32
-M>O[5I_/9!=$8V$0>CJV3DCMD<V:BK:H_Q>S^<&\!Z\CM%5_S^\O$%C76\_5Y
-M+ZN+$2=2#))A0`,FTOZG-3)\VNT'*(ITTK;GV2Y6,CJ2WH]H.;5NX0MPMB*E
-M0D4;YGCBREB@&0K2-]'D2/<E3.RJ+(=`=HO7Z@!RVTM3@D/`N"*K4+U!V468
-M`WIAG:?Q+YIX7?O0#G67217VA[93)T]C7?Y#ZH-9"8:5&_L;<"##T[II`H$E
-M+GQ.S[%I1IB>5/C&*@47!N,6T4?OU/>?2[FV,VT;YR_E`OP[E$Z65XB<W:3Z
-MD_FE'D88*Q;]&M>EE#"6L5(NK')ILDG9\S.%JYNS(:)0PV<"6\*]%?9MZ1_+
-M)8UVQPGE@[20;R8DJZR[!S7-,PJ(&=&X?P6M.R/"GX^UU_[+C:Y:JZK?1[,G
-M5LU'3,U4N3\7)3Z)'/PP4-1N(+X5QJ(O/.?O[#DED'JI<H9:O9!-Y1B_=Z=1
-M1J$HT^R-@Y*N.0*=;#^N9,?(\\0J2I*H\IM'IJPEC2=?!#V,51GK5KWOC^(<
-M;+R1J]AY%E.G+.<I(;,HG4/\CPQEQE;C-FEWWO[M%LOC&(>K](5,+$B/NPVT
-MSB5.R\.+]\%?T#_>&O_:>)6P)A;.*0:*\$)/[`2XP1X>"$D>B94<$DT+'$*/
-MHK6B[INHZP5-U/N!E.,(M-4*D"^<G0\[Y&^UIJA9R07()'.52#X-DNDMX?@;
-M(?JWW7PO[!-\]^$\MS)V#>KTSZEN/4LF\(F!$A6Y"A!5?IH'^1-Q5$.3;`9P
-ML=E>JZB0G!/0W01R@NP<L4T`X>&)JBBVTP6&^%I+;=FP#UH&LRNNLATUY#U%
-M7S[>$OG%FQT$).%%>H(SPG+QO-<,W39(BE3@Q[MP*CK04.A*3'].KEJ0"P0H
-MZ$Z%UJF!AC@'=^N,KB.`"PAN$3IR>SRN6='Z61#OVA,\RCC4P!:BXL20V]FV
-M069A;?]+K???AT5J0AB1/78:![V2VIXAKW*[(0'S/2Y1].W]?%6LZ$:.F)@D
-M.@2HN6?$3>VO\2NG?!&;JY26;;@[4)`%N=(3QM,O@YC]4Y)!_?Q\EI=&"A#&
-M3?B4M$6;:[?0[ZYBFJ>!-574*[$(8_8^,[R@8??F^%2+[AC]2`2R:%1CLAC>
-MVB9-2:3USYY68?L0O#JCS$B'SKHB5BP^CB#Q)S2=O9`H/)<8UOU"O&1.VBJ/
-MB6,W+5`KY"6$]LIJL!M*R!MZ>LN\SRE)H0,@/)<@K9#-`?:01;4!`JY/F*^0
-M%TL),OV[5#TU2E#ZBOSP[*2X0AT8;$WP]UL_BB'<JOD+RAX/Z2Y#E;H]5C#8
-M913:N<A3!HGVE-'\01N>\K\,$L?>:-)7?_\]Z-$%+T*#B7L%K16W*3Q@KX\R
-M[=&RL[$HP*&0<'@XVX8N88`*T&9"<TW\LS/9=.VAM"#VC01STV`*8)ERPCE[
-M\=ICVJCNU/\'("G=%U=<8STI&EX0[AO`*B>DT=N"!$]9)9[+7+_QL:NB0IH,
-M7D.1X&C/6YW\`;<%HWJ(4`?0G!LXOVE,$I6P85#GIBD%M5B7\S56WQ24'VGP
-M,I%%4#P+LOL9UEM8OD;%">45A$0]"?<)=N>C<2Z3E@@>.:XJ^8SG7K)Z3?$3
-M!1$D%))Q`AI^5RD"'32JG#OR?L%EK?M2>11*LJ]O7T89/@7]%`(OAD@K#DS$
-M0Y\8MHJW4H@<K&)$3[C`W:6$4#VI1:[R'CI1,_S1PH^-F_$C\+,\F_$M)K5'
-M->]"KU,5WRP#^?J=XRJOFDGO(GWS(F`JHVMN%2,[]O0)0L\*EMM#6T9`X9+G
-MPLL@/T#LS+(EYHTO$8PI1%#O;PT07^XT,=QE0$J>^DBRK]7+^>F>@`S*W'*;
-MA)L)4D0%\[%DGPC5(`<%,_*X3J/JT1UK5*AX);JWV:WE!8CY>!H427/RG0[A
-M)A;J7^;_1/CZ:XA+.*#&BKSAGDGR`FY:4/()"GMTVR"3(LX-"A[/#:O$BM'N
-M;P$!!8,TAEHM/0*;ZX)2(@P^H)GNCS_C47C'+2<.##^Q-7+1LA9@IWB9$RQ7
-MH?EM%*=/='DIU\/!ELP]ZZ!._Y;R5U:+M+.P\*ET1Q.D(+D0@:-\R,9QN/CB
-M_#V:Y))'*25-#,2"=\H,;VR\K/EVCSG#$CT!^^=0*B,@\;$_.B+(6#A8C-QJ
-M13",G3^N+'"0EX"H8.K!;?)H[?+B+FY^?AT)BAS;'9J.V&.O&-NZ'&&<7NU6
-M0!R"=(YJ,%[%OC5;Q(;YS`V3@_K/%>[&%=VZ$=2^"-`I/Q[D@*SQZ<M!C3?+
-MYF<(P&4-@UOI!/J0'#K\D2H)A:N@Y$QKJIK'^(LN-:_A6LA_A1<+/G_J4^0T
-M*KT"X1O5>`S'L-E;5QJE,WF]?2*?J<XAH80A!`_[9'U2_*738T`,!-F(UZ!P
-MK</'M\0LO&*I@=HA+I\W7!.XT-Z3H,""A)M88XXZN_)SNG]KF6B2=<BP%A1P
-M"Z^BT(]_AU@./2O]Q::>ZAHQ.;P4@I)*"X6A<.?5'2L/F/.U>60U1^95<O-=
-M_Y4O1-Y@&?08P^P\^\D%0Z5',AU6G66,Q`O@X\)",^S9ADLCYEGLF34<UDKW
-M3(E$18C-5ECSI0VYM6[V0>SK*##L%1&,C$=0*"&W53<8F5OW*+=8NW&2<.81
-M_B#WP!A4;V1N=V$7!KKC1,EY^1U#A?HX!J1HC=3!1Q1I(1-]\57L+[>S3G0U
-MP[.9>/SN\2LW%EF/3+-;I=P.Z0;53RN&L4U$-A<*_XO6FV'2M%4H$WOU.("%
-MR>^/(5./$N$EF(;G,D1.I+5-6DG";Q1*G.L(>R+U@[-OVJP?/G;T:ZGI!-T)
-M^9L<Q=QYU?.'&`-C5)V'+8Y9:ED^K'.L5(3/EJC.S,:N)S^BRX65G?):\<_$
-MTCZ(1)473^V728!D$KCV?C%JN&TV//;]$E'QN`=]\TD(Z]>+)PRXVC]'.-+N
-M":Z&YO.^YG_@MD>^$`K"E)L5Y(O"OE--1I[QQY,,;)L7P4UIJ]QZW-VIN\O_
-MOH9AJ,DE4E";LLQN'Y>P<8'1OVXA./]1*R0W0Q>?82E-VKJI7A![FL*_MAW\
-M.^&X%2"B40I[Z5C+>5X>,@J:!?=#U98#MW*ZG&=&HW(^<X>G5$L]#7-Q"0K6
-M:Y,TKSFNN$*<ZGD@Q#FA\*^\`O+AM^2+3]%/27*K81K+UKBF#2K9$60Q@ZF2
-M^FP`%UC&]Q'76K(VAC*6)(K+8DSOZ,5?\ROZ7"R9Z'AVQN[46^G&O9Z>-K'=
-M^\905W+ZSK<,L".@#=RZT(4J-%D()85747/N\I*_SA5<H3N,32F;N\2;$[EM
-M^D*5\Y@.R0\DR8-#*)N^FG"\!WJ?IO?W9C#=NF1=+(!T15=:PUDRSZY3UP)7
-M#<&/]U[,,Y_<P9XQ<("AIR*2/-%V3$\]Y#CW2GZI'7_1"`[<XB:RZLPF2^2M
-M]WI^VK[?/.+43@1)QJ3]M$D<M$T1-0\(T']&Y!D/71^I&TRJEFMJ0NGY+Q,F
-M&DPO-[%P/E)H%OS\4EYQ^UHL6_L#%K!"8S_\=L['C4ARI9`QK-1'K8L@RZH;
-M94P[9:&HB'NVW*(<JZ00)0PF&U,>TG=51T.0Z%@[`=0'=5*CZCG@>\B'24(B
-MO+AT'&_:&CAU7C9QS<EU(_1P+AA7)@=;U,(:V`'#`1"QO.X[L)V+2R'\0^JW
-ME?K+#VX!_(W@1;K1-G`;*(:@NZ-,S7).68(?3)5R5*1\&Y1\6/TMD</VY3A*
-MRR'"TUP&:W$C:?)FW69.N)@P+MK=U1#8X311,X;JT(-&,+Z$&SX?@STP&3>>
-MCAUFI!&'YH"&LLK`#O[)1>/R>(CB3Z(Y!=]IMDZ6)D0><P%CN]@\A0<?CZ:O
-M"B;C^F"ADWFKE$I-ZMMJ/J9M&AR>)X*A\!B"#D,[TVJ1<M+6>W*P<Q*$U3'J
-M"^>)XRE*Z#"]-NW(O(/;\96:^L9WG7'U`>S4EY5)BNF46"3?#_]U$'E)M^SY
-M'Z6#DZY+.!O!VBSP,U7')F2*('I"G.E[#M#M^;M%@%;ULD['(FAKUL1%V!2<
-MPEP?6(1U<*%SZ+,B+2;("V&T!*BL7B=,!F;XZ&A,D7B7IS'N-Y*>WC8_OQ[:
-M[_I@-J*>%LIZ7>"!TV4O2GR-E@;%F;&I;).9'Q23DGYT)E*D^_J=:TWN?`ED
-M=ZV%*Y8DHVN0.#L'K52/.<':N>>%NO"#RB`VZI=PY]-7DH'0:4,/P,CHS;;]
-M1^.?:RZ_SI%]]=8MJV@$R-2"[>=B+X\`\X:B@_&S7S:]$5S*@]E:R%*$3E^U
-MW/&.FMP;EVN.P;[1>Q81YMI-!Y(_.&B,.G*J8V6D<NG07PZO1GL<H.^36FG)
-M2-<NTF"ST9`9@.?_1(E.M_G/))TF@AKD`EI5;W?89B\M&-U<#_N_XC\"Z4/&
-MEU,'MT*[@@U'#'OY">/V@I#>W^T0&#+#=1NE/V4%-135B=\J=>_;UP.Y^CMV
-MIY\J#;&84,1:R0#A!"3(AQJ^=ZYZ0(Y`?!&QJ)0$AO/Y7AA$(Q[>J9^TQ94=
-M0I.$&<>`@`)#<!GNP;4S`(@R_'L^I[13@H$MI=XF&V@O<,^_(?R'L!X.RW\H
-M3[@6K:!O!&2-\3J>T3)7K!M4&<ODGI(0/<$YWIS_=3>G#"_)?F42M&.JEA9;
-M/@E@%B;LU;.T-1DV31Z*]<E:]Y#NS/]ZVF?P1;+!LR%"H4CZCE#]B)H&]ABP
-MCF^][.&E1F'>/'(;T`YML=8^E7E:&(AA/8[`JVWB:FKN1ZRQ#]T]%,2M+)OS
-M2&"?(Y<R:$Q/.*]JGFI"<Y,T!XU,85A,.CN"&W/<OS'>GP[@7I0T+LQK9E/T
-M0'R<6*$"S[CCF*@!ADWK*?2<=I&O*$[BBCWM(5H=Y$,F<J>J&LP?C0`1LA,H
-M)I\L]H?@VIS<KWB'3!;](IBJV&,4U6-*/9$#`012#V*91S`X9BP7&4%6'MDE
-M:E8Q^GCPS=!>-7RNZN6R/UUS@:]#4YP8AV2P4HH]-'E$'J_*1S`(,GU))CVD
-M`^M,L>.\L1#A)Z?LH'3-+O@1P*TQPG%P1Q.)D6*=7515G.?OFO5G:'F=TR](
-M%B6OVS1YJ^\F+:FSB!(RU>.PK+4^V*6(;O^;<;&.^DZRJM279=B[/?KN0[0]
-M23?J`2\@;Z:Y!Z9&ITH*IBH);VUI&-J$8HUW.]DD[_BQ=)MZ.KE0B%W=%VY$
-M06X0\:L84:KY?NFR#:R%B8\KT7JC+P:GDET1+[I;F<'OERXTKD^>2!FY+P.0
-MS&O2&`^A)F9C5Q'A_FG+BC:VWML$WNA>H"]NTQ2J2T*C2%RXU_6K@ISB8E+`
-M@3V1(&%!W@@D2V]MRM.RL2E./J!(2R3;2".Y$MFVOB&A(WVN#.1I3MP3&ZHK
-M:/,<H4V/FYDDE5-):,?,_;^9BY^C.2(EY]RR(I&X<(!8"[?DT[7)')5KH)(;
-M^-?WNL_#AP[^7%N>D`6;^UZ22UV>XI9)C]7B&-A?2@\K5O6PGY1%61B]7U0?
-M9KX;>)#`@%1NY'E#@D?RGL&G@F81?!3HZDI*/./8"WQ=?"HT-`+CM`?^LD<U
-MIO0ZJU?'YI/IF4PLU*492$C(KY($/+/J=U(]"*^ELG,WIF.M!M?"96FIO0R/
-MZA[3<Q,YQR5WC\YD_=A/8+\H`P"#F.#W#>M)I@:+#6Z+-G=OF>,[PJ8*=8).
-M2V3HL/S3"T*(E>%EDH)[B.:&3]SO:*7.^.;3`(I.["/07%NQ[X`9=//R=H+Y
-M,$SDW3'4#//OEC\Q8)W8TIG^A![8H-<CV\=MDS]O1S]F<_:RL?S2;H4=+_>.
-MAP*T4[U+/?&68+@(X/_0HP1AC5_X+WB+N@0PC$-DJ%_NO*0^@CQ.MJ[-BDSX
-M_>K]WX'7QF&A8'&FX0K_94/Z@#*MZJ[M,Z(%O#'GXJ-2BC5QDOS)*C3!#=7!
-MUD)]N0K4/=J2[`WA,,>*_9Z<?J.R$_/8=-FAG*9T7\/@Q+;[G.?_N<,:X.=V
-M;"665>G#[SO(B2-7C-!;=P3?0O<P/VB3*:C:2:`'^;Z<X'W='UBGT\50@+%@
-MSD@^G3Q_RD\&NI>4/H\1)O.2R;DX?"T)NJ.,D9D"F'-'#JOTE3&HK>QL+@FY
-MAZC:08VT=@E]-A4<]<&+1/[T7!/W&T9C\`)9S/^O>K(DSQLI9OLM7E73:EJJ
-M`A^U7+J^:I;B5&MQSAXWA[[A3R&TR6Y-%TRPSM&C$,8C(;R&`-3P,ARFNR>%
-M['<!KOO[XIZ2"U<<W.Q@Y?0QS!X?N-^F=-I($$B.9;(D)<CD=&KBX@Y5`2NO
-M6>C>@%=1A&WA;(]6;;NXD>DTJ7FT]?Y-,9':4]M[`!_\YQ#E4NKBSO5I--*$
-MSJ`'UQ'8_??-^)XF<'1,K=<E"Q3B:\)VZNJ'P*'L4M?U?@<-^'K64*^^#RYM
-M&M<'9LUM(`3A-,33)#;O9>1AE,`KS/90:H)&5T.5A"*>?'`@AWB<6UC5KS%F
-M"R`)BS>1CU!\L6U1CE*+>_'JK^!+'R>IDS\CC-Q\G&>9V3)"BT0KU]3\2']E
-MT`O!A"1PL7Z8=NR67TE_J.^8=B:R7G!IQIZLT7Q/OM81H!>6%!A!.XG<0VJK
-M[<7^%4M6$>;#;_K/YD@?YK0<RBR8HBB)7K5F*65$6U;NR:U#)7FK++7/KAO/
-MU+^B`JTG9.:SIK+_;>\:0E,/9\R_C>.E05R#Y2^%PON@C2BUPWK5$7-1_8<Z
-MZX0<0Z5O>A#&Z%32OQE7*:6Z9_7PP[]/`ZY4)[K;BQ+S*D09)<O_"6`[T9G?
-MC3@Q"P.HS,)_RK:8\:`XGRH$4<%H>QR)IZ`.,4+#OY'Z!(7ZB_JQA\7O9@$A
-MGWOX)PM4$K_E!B'=<,X6&8<#J_R4.\8?SH<,H"P''&$M$/1:@*?/$D:!,M=Q
-M*J>59-/VB+Q>9RM)-0(W.L$ALXT_D+$K46'T%>:@#D8+TNGQT9]G0R]@7'H7
-MW[AHE.G\H=UAQZJG]J/\S3Y,7M+T%@99X""$-FP"<HG[8\?(I8L0S=V#*4<,
-M8X.Z[I1?>6_2@L+DIU^!:#)Q-/7TD*ME!VI*(VG`$"E_F)S:AO$P8AU,KE0M
-M*V)&!B\8A`3,;($;)@Y*]?12`;H%TLJD\)81!ZB.'%C_X4R;B[4PL%\B3)"<
-MA/VEC)5*4U6D^]$'>(2QM6>;F[$@(S=X7]-B*S5^0>)O3=*)RQ.JBXXW/>W8
-M(_G'7U'@?Y>XL3W1*7@5\"GL%?^&IDE"W8NKI@-F$?FMOI@&1%+P4#19YIF&
-M&MCKFM<W3B@4X>SYF)V97V0D<Y0-NZ`\PDZJ<+4X3D`FHQQVA&FT>E[>F'ZT
-MO-ZNO3JPA7/-$'80?R>*)^LBB]I_E9EPY2'/'=Y4H\.SHK.6T23<AQ\8:^(D
-M:LHL^][PA)F,4O4=I69&4[M+3OO:7W(TR;P)HO<!T%+$5#M:@>SD-A)?L[T%
-M)B(A_JOL*G]*J>I8,^ZI2PT\.4=8<N4BYQKO\LJZ@VLG$3?E$.!Q(]F-[I<C
-MSGLA+JM%&7%6L6/M%([/(@DTSXH:=`<\GR*-JM.>GO*?K-P]%P^+H&\.$V+K
-MA<2)%Z"ZFC%NT7G25G)P9X*%U7$CK&RE<]**F\:FDR7HB?^[7A(PV6NL']N\
-M\\TCV3L-#IM&YFP^RFX7LL[ON!AB%6ZX6K<]#A0K_!TT(EJ]!R-F&`R'+X)N
-M%M&V&)1WX4&8OJ<4NBU?62R63<M8$/K*V`PT.4`K8<W==!WRO3V;\7)W-6Z,
-MJF_&!>YGHP*8.0L<6!#?[')QR<$YZM()?;#&9'KC:<\<^YT&[\BY7WT@5)@5
-M&KXE%O@,4U_C`UEROV2PF@/:%MXWB7>0M:(^_IAY?CE"BR8>M_>>0*;M-_LR
-M%@.!&I/]O$1FV\"^+XJC!5,A'QC4NCD!DKLZ0,DV48A::&C8FR*+8*9$;JPJ
-MPTOQMAM'=X"=CF="QE&032%W0&NAJZ68VJTM9G:2A_Q>=PYD3R^U9H+>#EH'
-MW$_3XK5%MO/U5CF(\PA!8V2^;P,0:VT(#59+\7HZ3!73OG3^@EY][M>_*K3.
-M9J\,9.I,3U;SPR;O/)U;)$=N#XLSEX2%.+HWLD\L<9G5LWH6)<C3+,B#;AY>
-M#6/$)=%?%S<G%$68XR2>%9E=$FXN,MZ)#MER1T)$:.I/^$](E5BI!4->*J`<
-MZYE!E:)-Y1<24JP^(7H7X24=W,BH?(A@PM$\%6.3C9/I!_<C@^"1-B7=.PG0
-M4*V^SS0O0#+7A*ETP@E3GV$3QV:6&U"92?U.NAXR9,";Y-*[;I,W#$Y1R@&'
-M;)BF@!VI/-#^T`^$&0G2M;F[7!/[K)HW9$`KEGQ#E;@J2D_KY!\]SM<`:97)
-M_-:7^]D5@S3G?1])US8"4B>D0EDR<X]0`D84K--ZR*AJ_8QBL*#=A5QYHV+=
-M<;G/@^:"BOH4;88-(FS"$E(NPRKPO[R_/CI$1*W,O/AV096X]>Y_8L/Q<,3^
-MT,3\WK-@[I:BRL%SC&O12WO0%ZWD`C9KY_%>(1DIN[`:**V3K>%+MIRA]9CP
-M\2?%2.#ZU-E/$.*#)D5(BA(O0.+QV%Q9_L9[\8IY3_\-51XB$S98P[W12,N.
-MC'(=!NQX==7T%N,28.!W#3:;][J+%Z(?^>W)G8/&EBX$=#D%LU4*?4EXWYR=
-MI-J^?K;*I;)9^.;=/3BV3"LFM>-/A5'_(GV-[P#:;3YQ0?O<]>?A7#A+8!VV
-M?K":T;%M\=@$.K/HUO`0;7I=%",7&A\$??>;-@TJQS4K\4[]>6(XQ3@W(M)0
-MV1QO^781R7\*7F_Y7#C.9<\Z31G,.=XN2GV5A"?-.'\[LJ(>#+(VE=GZ0O,=
-M*'5(ZQ)6M(Z]_X\_-]2^7W57K2V*O!M6CEO5,2/.D`TXJ=)M>:C!BNU9BV,"
-M7@D(@JHJP/W;R'8YI>NZ)8`D^V6>4-TAF_?W53**LWW-_AO/6@#H&/]%7Z)K
-M(M]>M.^4-`BI\='%ZI"/<;K4-9LW@#ZQ?\=7S@TJA9#OR1C.>;!NB)X^S$2)
-M)N7Y@VDSGZ'=S2#\JYEZAVU.%=D$`N)E8>\*!TY>LO9TT:^I>O?,,62.%-U>
-M2Q_=<",1;9GG7Z$`,4R^\ZUZY$`%G%\<V2Z0[B*-LDDCHVUP#UVP16*S&:FX
-MLZLN#P<\<W=/<OC?;61X;T7<K5>76!/P1_<>VKUR48+X\>`F:.:0#14"27Y@
-M"%LYX^'%3[:'XQC70IC"Y,OOTK+B/NLJ2ALOJ((6:7GR:;<A)R*N7GP["0B?
-M81V^YJR6#400=LAK'XD`9GND=P1(7@X59WUWKZ1&ZN(FT<[9Q([FDJ'["LBJ
-MK:GK]1IBI`0M&;Y#O(*VMN;?4(O0IT;`+\?[;/"GXZS]QQ5;")_=91,[-E9?
-ME[;S7ZQ(I.?WE.BF]IT,P@RPVO1/.\#YIRQALW$B3QE6R,0,'^?Q*Y_%54IX
-MJ(15>2I)PGL"IE_0<IL=A6.M7Z"64H-OUSZ5M6>=#89V#;U.$WBT'+5!3A\W
-MFV:80&1R3M`&Y@3G(,`H!-]Q:3,[BN9JZ$6Z5)M.%V!L.?4YSH_OZ$(\2'[!
-MUF[WA:26DCKLP'7Z,L&!"TB4=U7Y2EYS:#C/40BS("*G0*BA@W;SMH5Y!W>/
-M&.2^%[B:#!*^VYU'6'@C7%X7&5]@1@86,_TO])ZW>^A_ZAEO4(-^2##A3R1$
-MR9PE1@7E2&K9/$Y,C?'P6N3(^,XPF"E'++\R0.53UJ<B^^Z-&%[XH$D`V#_9
-M3L.,3_]HUV&2QH7`Z^C`"OF:1>#C)#;I8&5<71SXTA$2*U0J6@4#.%@LM:.?
-M6C<:W'-Q$A_6`6?"*Q#F<N?1/L]C[:IG`M3.<"_QWTF/U2@&6U2J!RD)-('S
-M*!J9U!-F]$AXK3?'J9DX,NUL7I/'QL*&*K%4!JWWIT<`L_9+PK>O.C%<:`0[
-MR!C;F_SX/.>L:,&G?\?'-Y[M5]G$*TQ9Y4*ZTG8\^=-9%[QHD1E(MT@<8>T.
-M'G+'G5:@PC78'2DJ?8@Q1EZA;G"+ZTIUK'^HV.8DFOD7J&AP4>TG/V=`@KEV
-M^_:.7A#SQS*".LIK=[)LEK;J+'KU'>4^9IXV3V&1UA,QI&;GV,"\%RS'5F%%
-M:TXP/V%U+1-V(<*^/'R?-EA/D%;KR<)X!=MTK5L/-5=-[Y:IG"KG.]\8&P-W
-M$/?^NHM'-*O#36ZVG^E&X]&)JY:;8V>@22]"OK@G:VL;6-RCR_?6[5HD7Q+F
-MRD(.6ND*NK"KMF:"V<@)>^W<`:NW2%<!,KUWLCB9*>B'V+T2^XO4Y$9HH*`F
-M%$CDT)_H!R26<Q1'PHUX)JS_R*3C-F\K<:"L54G@'Y.P1F_N]M&C8@?J*?\]
-MH;\K5O;D\"'REFOW6=%K5EF`^G.YHG%^E!U%@MODA:@AQW<SB"2K[6]RE%41
-MG^]=M72S?$4HBK;\YNJ^KN'ID`&=H#IX>VRZ83(_&(MW"E9$HRI>[RH>C@D&
-MN&@O'&0XAH5G^16_"Z5=Z\8-?G[(JJTSNP4[3/+:B.FC=VHB.TN5T`JU85;%
-M5W\(0!C->T+*.$A,;@/Y7GPH@``B*O8\N3)UEC_K"HJA.1*A4F(A84+,X'GU
-MW)M#C$;*M\V&;+[HE-[P:9D%%O>&%Y`5H,UQ=C#GMYR=YT.++;2S8O1@/Z/L
-MC%2D(QEH$7R#:>"(45>R8T3'OLI7=9&Z=KJS!->T*7T>'<CU!DG%JG:=A?NV
-M=_N<8NBB_9?D@JE[=_&XM/(C;B%E_``)X@%"I/GQ>XQD3#95QUD,ED"W'*KE
-ML2Q5'6(8G<@_(PEW[JS$HQ-E*4P=D9(G5#V_B+/512LGFDQY0S_3.9&A4=Y,
-MM\)YDA2*]$7MA-96'\?<?N7.:>%K:KK?`=#[;FW8>P\.Y>?DD1O/J%6$<PE.
-M`"I+8DR7^*;YCW(B.E3_J@J[SVYD/'\Q7R03^%I$);W'#/7CGJ-1F.0I<F%G
-ME!QLN5Q+8+K8H6FO5(#<BE@\LD;X]4,D,FYH+(7/\ZO3@;2F>;%%4$YG*[:N
-MB]LY+ZD[=CN%GFI>3U_.Y\M8]MBV95Q(^F!3./B([&VSRXV4K</PO&X<$K,'
-M6,+&!F*%+S0Y^5#7E++[;YFJG38N^]3'=1(U5OK]F5(JX"<;>O]%-VF6RH3X
-M;P.`AAS<_X1YMRY!ZCL!.^U'-!A";Z[+=$&7!A-/'@:N\/%8G'/@CP,2(OG:
-MTQHCMI7&%!7I!Q]JKYO[G:9G64Y_->0OT?/M?<]P,,F^F1=!EQXD>/FL2Y:/
-MX:I6)Z8(/N.D1K<RD;=9T'A9084ZMIL$:+\H?/@11J]2P-*RX\AX@;,33/5)
-M*,'+F7"PZT]`1^=5%:?A%C@";^+T<5-Z4^5'JB20I4Q?76$L1987R>G%\3L.
-M-^(]GW4\.LI07S))_E\";.TQ_K%]#[WQM?^/<L;;*^'TR+VQDL^V-2I`4GLK
-M.XBD7#=*Z0PUQLL^#NZYIP9KSVZ0\LWZ:J9^5/>)Y`2<-#?,])SX0_@&A?'P
-MOA.:`X+ZMQ2T,HIR+YRT&_@.7^8T\*$[VI8[PYG1PW3JB:J,H_\>2F1+)^:9
-MJ+I2QJ/+>H'U1UN'H:&0$I$31L_XPUN-_;X]B$/>*.U3*`$FF'85I,DK3'Z4
-M(#=V(O->FQY.3A@K$U!T8[)M^/;&<3LA[_$6\O?$;??1+&<2_HH]4J3H<+A/
-MI@#MA\3]9`8TR"5NY#HNF\WVP.\,5K1)2(Y:RA+P]I!H0&9O9GCL_<<MP71C
-M<]>$Y5#MQ56!+!US!;SY_7L,'Q+/@&N:5X[(A@HOL^-GWV0@%Y/KHLI_TS&D
-MOQDKVU%3-69(2X;FH!/+J+MRY02L]#6/-%9,EPWYJ3MR'#'4JOHCM`,/;DKE
-MA4T@M-`1SD/MIR0'024^7`1O\,VK9]M61(X,.N\@;K'56L)_4=D[9L`-=^=<
-M.40.1C&.D#>P[??J$]2RP)?-GYSEX$G#XRQ=\_5I<U%F>+UO'%I_P(BS.R<S
-M*D*3;W:]9_G!UKX[Y&QG%ZI)-A$Y0%[>(WDB@A@!+.@#D[P[EH+\$N+S!B1Y
-M_#87K?-,SSDYC6HU<'`-;W\%@+]T-<5^>@&T-Y$N3*CEOBP&_7+`,7A!&'7@
-MNBI`3S/#@"LSD@JC.41(M&V6!DJ5Y93WS'>C9DS7%]%AQ2+C.!Y)JF/%\IPS
-MS*;ZNV"E>GCQ>6%6HJH/WV,;!T%I_ZD$:;4\([%E4EAGX$:3*:EX``R'K+,.
-M75,`4\GCJ8$+P&969,>R_%&8S0^O,NS6V\\[_E@=W"*6K]8UO#3%<AW=+37'
-MA5G3.Y:?T=J4T3S!;6_:02Y`GTK8U>WWX"V9`D\"]^)9".509G:&TYHDUQ#+
-M68I2LLUA5T=U,'7/JA^$4T<O`;S2#CLR'M)(/\E4L6Q5'V%N+J8]*EO!_\W[
-M#W8*OI7O+V:`G`Q].2TF9TGM[<]>7:N>@JC0MJ2(8B!TMGWTC]%*R3'1JV>7
-ME#^7DS%XVN1OY:ZIK;6)?GBCQY`3MM[GO.ZLIU$)Y:"1Q4$F]0N+H$A!ZZD%
-M0J[&CK>">H-&$6UJUU(;:YMN<N9L08LFO;).:V@R%@_MO]X6A;B_`IQ].>-X
-M;N8<+T<GOTS^],Y8@&L]9^H%T[+9DRC!^0#X+G+JOZG\?2?AK8XH->U$QS%A
-M&[Q@TY<CW<T#G6%IJ$P4RH0<%(0=H?M,W67#M5>3"NM@MYO!.(\T,R.;&J+#
-M^UO6D&KG0&VW8AG346=;/O`OP3I*:7Y44VTY2ZHPN#YJ_3A.B6B8SNQ_T,RZ
-M0)[^/*&1A\?#3;1_9`&2#D_?!K0C=J?@W;YI%)3Q2U5F[*H%NA9F=0)^7,CA
-M5]6VOO:%S#N0;T:0FK;'#H/!<1CKQ[7T7PK":A.I4A.L0X<#!+Z`RR?=:^X(
-MXA@3>>K]976/^]+<2;5$5>/B5/8N(`H2PW2]51UZ_MMM\72HLH'3IF9B>W9J
-MJXE8+J&Q66<7:QAFA"^23YL@22,;-42U31+QFM_%8[E09?(POX'3Q9>EW-;D
-MRD:C^N@W8.2N2Q,1W+<(8RPS>&;_Z5;U+6N((AQL!]K@G>GX=^E2$6_OY.S;
-M.YK79C$&A#62,+JK7+>+?SB$(6].6N.):#Y):Z?ZV=#/7K$;WOB49+<T^^H(
-M6P3DHG.CK[&OX%T#B,TS7LSXO/@/I%/Q>A">>-JJMX;7&(HD`:ZMBM(FC8F>
-M3(G$?DC/G:D<IN0B6R;J%J]@KJTQ4\E$Q@[-*MW5!9*:H8\S>P%/N_K5N>T7
-M0'TC2P[[+$J3>!<YG'S#HT1#&:B.US]#\\`)WO%!H-?JJ/(.X9F<5C%%9%\%
-M>./)/031#N%8T0UM-WD=#(38H';\*&)K(;(:/4A\*H:WU;[[[/>0P6!^$SZ=
-MBU4B\3COU,+.OQYH#RZ/O^$2@VERP><4=R!A,+ORVNN*_67WBYTI`^8O.3-^
-M4+Z?W?4(;:_+4`,BVE&*U]FYTLR:;2<6$L,VPZ)G]?@>\0QZ@HS,OQINQZ5:
-M3637F5E&]#?)[>[?X5,)L-+^[L=D&3N0>#'C>KIC`<</JIFWU=-W,F2M\-74
-M%<*51Y+[%OK@-:V9W(W:)O<TP;3@J(K^(9-[)0%)]K70T3(V`T&3^IZP=)RL
-M\%&$N*'7WQ3+/`$8\F,+4A4/'#SJPM8M+GH-OKVFQT@I3R]D?#M_)6]\,UN^
-M-I1I3IQ0QE[N413SQ07()8B-/#\<O'@.W/2,)Y,$<K2W:)/%H^E2/]'C&:PR
-MLUS9-&,;K>A4`BU#MD*X7E?Z^1,+UX5H\,UH@O[D?81E#P!PQ7#J#Y+3C@.2
-M<C+)7Q(,2SU:T^Z'_ZK9X+:MH2725LXFAU/S(?*ZJ_5`I=GE@M=M?(8V(4A@
-MD_@`1(W91*MCK&H=1=%H.('D-B<B<C"I*3,IFIVC`Z)G+Q!NRU,<_A?YB_H0
-M=87-D6C_?811W#$[I#1O3EL>*JNZ17!U&]HJZ45+^@J+K_)IH!HA^O&"W"=/
-MC-?VMUWI5TW8`:A!HU-&DE>G>T9;2AI<Z)#-9,VO]9F/59&%S2O`1EF!F"NG
-M&&X%DO0S!Y2VW`WLF:J8$`Z8(S;.HF7/_"38F]5%EQ<^(I4\O9\18<3YO;1`
-MUZP9F;PKB?93I0I`6-)N6YC"IHP,Z<%50S:MZ^S@T#CM4,L=\T>DL7EJ?=8N
-M9?0STL$XD7C"*I+!@_[&G1?9DP(`$)]+)8,7L5N\PMUZ(1DZE]&9L6`G]Y&,
-MAGS)'*SRC.Q<,HE&@5AI)U7@4]]>OXE>R7.")N+J%Q[)<Z]?3>E9(J.40-%Q
-MYX[3(&5.*<7R#:1=U1;,/4-7'Z%3*-6WM2*RJ:RWMU['VZ/"5\&=I4@MA22(
-MS1IC,A-*9./T&=!2TUCI#Q4,MS4;Z"T5(5+UF.7-OO.9$,/%\B66^2.OR"(E
-M7,Q\$?O4Y)>>G67-K"DNE^DGJ+H#,_V09^'MAA7=-H/\!>*\2_VMFXE3BZ"+
-MQ?53B$F@:<.`-D(<D"YN\QGDGRQ'V(H:=W?[;X(?TC)S>.T;4NRCX-`P2UF6
-ME&KP!Y/Q!=0Z*/'KOB$0'2Y2U0/Y]`B:W7:C+-JY\Y1<;CP,NU5`1OD%\IM.
-MC@IB8E*9M:BAW0JY&YNISC<<K8/]2'PKS?5!Q*Z;=*X<>^MJHAXF9LHC<Z##
-M<*0-U`)^$-0J`TEG]2J7WK[XH$1C$9'\+CSNIR;`*VU>J\0`Y%]X.<CX_4QJ
-M_VFTL,:C?/F]<*:NW]MY!6+B9NKBW`_J6AW%QG0[MOTV?)+U@AHIOVS*G5AQ
-M/F^D]YV*\2D21)@KCD/=>GOR]YI!D/?SG]YQ:D6R_%ISD(#((<YT`9RYLV4!
-MKIBP^\5,C8]F.[NXACO5+SP_!+.MFZ5U'IY*:3>QW/!EII;\LB>:(8W'I'#R
-MA[J-\A+M9C!`DNL0SEW!,@^X2`PER<EEVQO5FO=-<U([>CA=HDA,3O0+0@6V
-M*JJF.86W+<`?&^[7R<W=49E)<=BO[.EVJYWJA$"(2/"Z&J?JWGH-A,&]#$?R
-M[TZ9W(IIRE,]Z"Z76=NRX6&+=0,-0UVX!]>:W>KH[E5^IZ'[^Z-GXK'FR"@]
-M83;T.>**0M/.?"VM2^V[9:\I[D[<^^K-L"".F9K5`V6,M1ICG([*SK0@^P+4
-M\+25$)KACNIG#>K%SV13B@>JY"FX990[XQ<U[XH,G$_\,P]*JG;S3U'\S[SG
-M?"#EI+4T^7%10XA2&`1$/J2SPMZ2$;PM)]A5`K[W:U")8].IO#]2+HHTDP&9
-MW3)&M@2F-"*_?1)>\0?\CS/*HED;ZQU0EEG1V+!H2[`2V]R_TF8GZHWUH<4-
-M_@$F2B<9L&[$<,*G5CA"'S%,])-/,)"P"OOP7JIK&2BH;%V)`@*<1P]"#_MO
-MZ^+=?WIZ@3R;9C6Q'%T0;.[P0*%V?0YB*_VV2OW'7NU]8U[F=]IUU,DVQIL8
-M5V-;^L_QVH9X=P^ZKB7_HVYN@=Z,!A&E*YG0$YA^LR>$FU5U6@5TEQCP>4>:
-M+1KYNR%F,<IVG,C8Y@5A"P/;K,%)U$A8\.2#RG-/3';R*^I44PA>(\=%.*9$
-ML-'.GD3Q[WY0RQPGH[>>6^+34A#JSZD;OG>&0'W37.@:%_.2`^HZW+PR:E6I
-MC8P`BK%EQ)$(\DS8]72O*,WV:9P%ES^,T\>RE22Q3,SZP9.O219)E7R%9\3W
-M-JGOG%$WL+S#^0D^T^<:7/<SYKN%$BD=#2K^&*#I(_F"ZZ&G%INJ&3>A7N%,
-M$3/OK8A)7OR(/.&E@9#>C$9<J<>C':DGF#!5UAUXPQ1;:&K6V=)/1[5R8V3%
-M<JRH'$+F:TG&RQ_D1`T6VHD@=AB=?'H?DFV]>V-'VS>6\@NQEB#;+6Z1]2<+
-MTCN$408(\F2I069U-5;\QO!&^"P60JY;')WZMF9K')J$)>H5D)05.(,5A`Y#
-M@K^STGC#E09>"D3@3WS=@4@V%3]^:K=*099J]@5_ML)(2)5R%C9LR?C1."C&
-M;5>654=R$E]&>5ETG'^GNN`F_F'U,"C6;#T:?2ID7^+\ZILJ^#+]%(9G>Q.8
-M)\4@.%M&+8;Y>0"['R4ZBXPJWR[4K'[/=YL]/MFH$[RJRM16Z_VU.SXE]JQ<
-M\F[>0Y$LT0K7[<=]QY9ES#VOPS'G0[P&B%AE%91SK*XQ+5VXO`@S57^2=PP8
-M_,JJCC0VMJAYMV`2@<Q^'(!C:[YDFBJ@B+(S=V<!_2(PG@+P'=..F,=>3>%>
-M/&75%:U6=J<*8+='XB77(T%`02AU`&X3(X)V0JLH\:#+!EGN+V%7PCO223K&
-M\\<FR)^[X/E_CG[?,VHDFP+@P'-Y8'SUZO_`AJCT/]*1[9[ED.&5*J`]3D'B
-MRA.\;EG!O8"L'U(29M+*Y8O$7?]TXM[A9AIB!<BN?U*LOI)0\Q4Q4DT'#K(P
-M)PGYU7#++Q.F6MN=QS8]W#9G)V%XR-BSBG4CM]ME;)GCRZ[*L[RJ<+@-MV,^
-M_E?#H]>JHI*C*Y?QMM7J^;457+JJ"_X6GPS(8W%?K&L`_#/,/\`!NJ1)9W.U
-M@J0IZ2JBJ[IQ5J(T2)IK.<&*Q$,3\9P502-.5#@PQE'@0P&K3G(GR!O*:"<?
-MI'AG%OX8/G=6PK=Y>*&$_M'V=4>5]:>WL0B%=IBA0VW,DOQV(!`XO$&56+A%
-M-'@(UJ[#X\-%?W:Y/:-KQT?H4RU+TD$*Z0R)>L`YVI-<^_;[G@YK3UM->H"5
-M+X*'P-6R3N%1M:7SP?X);#M\3)^#[+7!(-HR(/,F*!%&*P$/)XD'`GCZ$Q)?
-MCT]9M`+^B9&M2W-3'AZ]A?BMHCUK+2^\]2,(^9&-IV3F"OS>\V7"V'E^W-J2
-M$MG4(XVPQ5/)"T[$A7E)A'GXV$#]C-YU##`-\,QX)DXMX1!ULG95@'3WLY9Y
-MPI``B$/PX6^%V)49,>^3VN9:\=23IZP?D)P&QKVC(EQT-'MTV8<HU[489=>"
-MP!J#C9R\8U5'<:R>4;('\*!2;5O'[KWXI*B6B+%2Y+@T&Q';/:?SD6VRV&E@
-M8L_OJK](9*2)%N9D-K7M`+@3$1)9)%#()WSKC.6KBMWVA+P>_\;'#@6W9-01
-M$]A]N?*&`M&EJ5WMW41!_'7?C<H85YZ-8/7EG!-[EAK1$1?,S4@^K"ZI3P6@
-MU_QNC'%Q^,<=YJHOW6Q6KR)*]`V:3]CRE(.>B6$L>IPH0TDEIC&W8$:"4/AD
-M;WE'2=7ZK8:L/]2U(31ZY!8/T;-JG#"3;(ZY'T-4:831*027\ALKKI[J.WZ`
-M<T!;:Y7\DA]SCFG;["D%MNOZ/L=U926E6),*K2>?3S$YQ?`J4LUF>^5.2-&2
-MY''&AU>5C_'7(EY66S$/UI:S'X#%UJMZBM7<L*QR/$Y$II\*^Z]]DMO&G/GT
-M;6!%H@AD^\[>X^4@)%SB'V7=04UN0'>NS4Y#Y+V;Y!08J<93JOD^MNLO_>?1
-M9I&]?(@6C9!46X9EGW`OF*()ZYQ)@.S[J=KA(_YN)GAFLU&'J+WJ-/TTWOXC
-M0UC(JA.'[U;(X]`CQ`TU]_OX9/ZGR/U,[6!V(!B4QV?HJO/-=O<*#+:7&!"6
-M"4?O6(0VY'6K/K2VXP>?SR(Y@-QUV>8BUHT^;!,3&WY(7^)_1[G^*D"-0"I0
-MC5N)?03KW9\T2K3O%5#$0[N9>0$PRQ'BC3%R)K$:JZ#S$M%$6Z*R._]:D6_6
-MD@U*%7IN\MIQK"#BY>Y;X7['"QU;ISL&-"3!#KV2]N>5J]4CBLA6S$WMO<'U
-MA]8LS7MUH?+V'`2_6L`?@Z>ALILBA(;:9=-0O7=EZ3<7^OU)1B_G,UY:_WVE
-M!J.3BW>JQW!A0!%<ZJQ<8[L<<_4-Y-A`;J+X:)4H@SJ-A4`%=(PEELL(9TH!
-MV&S-F.$5RTS=M.+K1B[+$T'F:WB7Z;H[57H'UT.UMZ@AB^T97Z.W-DGCUKD-
-MUT@76$HQ;9U_YD#*?G6LK2X!B-SK#-GN>SE''<<4.A-U-?URW/&(9R/U,(8S
-MW9H2U/*T[0VP:XAQX,&1EZA>B6E_/J$+#TBE\T$D'9H:07+X8"']M?]>]0AM
-M_$TK38WWNO%!\C?M,7,ZE;XY@:8D_C>^`L,),#@U4>5'JVL+$<,'&3F.:TN.
-M?^/3L&1S5\M6/N,QQ']`?"@4SYEP#ZN`T5RT27W"F.C+.Q]^.K;*`.]^K%)3
-M26MBJ%O[!:\@^,JTR@^OI*Q,IH$6J2*GUD-XBCNE=U4N?Z$YP!EPBM0BZ,_9
-MRC.6-=RW%<[=D111A2<A;#X*%367!!1;5"O-=WZ"GU;UQ*/FV=-)5(5FI0;L
-MN1B.!\`G[;#>UYA"V(UQ.0:)<)P_7W:O"JYV-O/W%,XY.+6;,KF1/4TM:@PR
-M&.LB[J]]5A^`XKYX='X;PV:K2^[T]!^1I1/+&*LTTY1",]X\/)[5`$'46"$0
-M-GQ!U7\SC&<<E8HXY=AH.IC:1']C2VKXZ;V_I*_&8S+?%A6DXN[DMS$U1!1&
-M*ELYNAF:L=E!TG-^&1TP'!]QO:3UTVZ<.`F_9SOO#EX#0B+S7:9S:3,CV63M
-M.I=+[+NM4A%AI1=5:7`O(*;Z<(&T12X1;("IB#-EIK8J+EK[JT[=SL[JSP)M
-M[4+OU:,'*NZ24(+&J\6^^(IW:LEYK>&F3C]VQ'FFA(OPHCYL55*NZ!JKG9NS
-M8OM#GLVQN[FL'@`E@#_7!<8*HNK*2MXU/,D!WFXD^3C<2\.GP8KSA6JW[)JY
-M>+=5(],!U76-/X">Q./TOXW"KY7A]*GI>F%[V9.@WO@UEQK].'/0#9#3QI84
-M?`?KZY.B;+[+=-53DZ58:<->"_'0MU2\%0`#K<<-=--!K/[$99-LK-F-)_PX
-MP]-N9V6=2BNL,$>H^PTPKMI'2"-T)M"WET_+AU,IK^O!O_(_AY)GP#PAW)6-
-M\KU"A)=OFIK%,-FW2G+US6^1T]7GEZA:'R#>\&VM,=V/M:Q&<S(E.$H)RQJ<
-M()A%VUA?2B&-4H%(ZLI5=`#[;+H7+Z'UW,J]:$5`]%C.$.,_W_;KIRJ*/JX^
-MG8BH_+)7/ZF*O0@G%0GSGWBWQZ?BZR$E+GIS[FE8K9T_G;#;`/X=H_1W==A7
-MPF7OXP4IAT512Q"2=+<&UX(6A]M6(I2]&'N:"G%I;M._'(>K8X")@Q+!B.(+
-M;5%AJ+/?_V.N?G83%V%7+?RR4@7*H/C>3O%3+>"#E-G[IQ1X;6^/N9.Q0YO\
-M_IAO1FP+^0>ZBSB"Z@F/?V/UQ+)3^&)^_#)LK-K-,-`PZ:$+AXV[BFO(S!;H
-M%V=B.1`YARLHR?+"C8(ZR.S0?3?\+T-6[<Z?'ROB@;3"3DH:$KDLW2OT/5%N
-M,46(PVFSG-3.;A)VKUS3G<QQ3^\"].,["3=&8,&_P`TK"C<C9?Z/X'\]KKUH
-MKHT5P>S#`644/VYJT7C+`76T93U)=^<JE4VL`/=:99$QKK)%V$2ZK/9V4N@)
-M.Z/(!G>8&WRE*BMT@O77X"!Y+$N3"I9Q0D\K%''4Z%6'&,^FPB/^J6)<0Q'U
-MQ<)?.W/>+P*9Q1RNX2WEZ&WXU>Y)S7Z=@9FR60-WCM4<F=3<YX@!BF$(S)X,
-MJS/#>><>V/G9QH7Q)&&I>ZV'<]E'7-_69GIQ)6_>/AMN_-+L1"P2+RM?3HDO
-M6A/+VO.27J92PJ1$P%^KE6OJ">3AE/Q.`J#5[<%=J<//]*IW6[XG#@$C+&CT
-M#?_0UE3$HY$GZCG_24']C1W2=9'%^78L[U:/;?4-PZ4K,VT.+:C#!R'`$^1W
-M*<"Q\(\92>\V*K[SU^0,^LL!5'NH]W39N.84')"E2H83:;\OG::'@@5%FB6"
-MRD5DZ4:::]9ZW-A7\=7&K"*K^'^D,T(Z.,=?"OUNE:_KS_C+PTI;):FV6ACY
-M@UQ68A`';(UHWY4?KQEGHA&!0LU!DGATXJ\,2??I0T<=>8N[DROXK^BKY/@Z
-MA2#_+1MZ+]7YB\^)PY)Y%M7`3"89N:&'1KO;#H]:T,%.1]X%%"7?U`S@PFA'
-MA(+@]K$;GKAD6RR3)A^-2IL-5XJIN+C837'3F:NJ0,MI/&^AF2GB71"CJ;?8
-M*15-0>DSVM3WJ]+>BMU9)KF$=D9R=GJV8&$\'ETDAR-EMC85S=8\F90%L[22
-M[H\\[7.UXIP&56XC_$*\N4N1!Q2/>\_VZ88XOL2GIN:Y4NRL0#2Q>J$-!W1-
-M#=*\#&H\0^=<U`A56[(=7*&ORY%[-IL^1XV\_,+##,^%A:<3_CI\#!84SN/O
-M"IK/`?L2.LI*II!UZ-/J)0?^`-$+DZ"K-M/'1ULAE_9GH:^QJER'C?^0`IT*
-MS04H:FKP!<$*()P:R+^L5*CX>8`I%?T)E@]@W^X(MHIDC$83E;'<TD.;-$)*
-MOWB[,R=!E!5>T6(0MYA(RZ8(C$ID)7H\B-2AQ[8&>(N(X5`ZOVN<F7%'#8V'
-MJUVZ_WU[\7")<4X8%A"TQSE?^]>[^)X/KGGC6R)9XL`K`S:O:T:V3^J`UFZZ
-M"@CS#@1OOM_1?61Q8EZ9]IHV]13+7!`<FF,B9-$G/2J1N0<SGO)96T0W'Q4=
-MX`1#B@R_1PSLYR45JS,0(FLD(QI.$L_5=QN)(5'6=8):T)DMK\I/(GFX+`^-
-M$)Q8OFU\.-9:[FUHN(.<D]*$@NG)^+:MZFDMN5M3%@!-.XQ5<Q)AZ<\4LJH'
-M\L?'L8A31D&CX0KV*R$TA'R#(R2U";H0:)8R9K4H@F<$H2_D,Y<?D^#6X^B^
-M'(U^7%=QKRM2Z(;FL6R.WLP;@@)+[V/KHZ/\UZ6'QK]^>J@37X%5C''&VD@W
-MY3CX?45HY0<MQ,2!5]2?QG>B!#^9.%"DH@46U/N-_2JRE39#+(&AIQI9U_0\
-M9Z?V("HS"R``]Q(B_YR[R,.GU9#4U=1CN6`U4=;7@;A20HVT^R68B$\.=,"5
-M0\UT,;#'$P5X3Q'3#!(A1?`=-OY37%%>`-*[V2841UCY)7L&X;2;!E`?>>==
-MFF?1[CYI<"L:"9*ZYS9?[TXPY'3^O@CE0O&D!)'3KM)?=Q.71RQ1!L&&AI,<
-MSC[[VH\!+[(R;PV^#"),)]"`VLC9@NFVZ7>C<IA\G'R:V9.R_UHA+V\VU(SF
-MBC9V#3C[0+13262VVTL`D9A+`529%Y`O[-7R(+6O)6`$D[2QKQNZ\0[Y@M=S
-MZ"XGS[[\K"?X;7X&T@O6-G!4]5?#R=UC&$RSQY*;X>G19=4D\OT)/@U8P5MR
-M=[/>[:_]I66'W+VGHV`GH)I$_',U(`\RLD(EK4N!A;:NO#VWC_4N,Z<OU+NI
-MJ0%7.@Z+>S]*83LGAZ7(BLTYPH8$6*&9P%<^DS;D6V7T:.<;/40^7RH+CREB
-M2:$W[+R#:I>!2G=&N<P?^Z5Z(X#,-P!O>@#6N.<)NC0"(9))::H[R0C03L%I
-M)A<L"%B+@FKU>@R0C#*:-ST*-0@3'ZH6R*N4L4^\5\OED]?9TJ'Y'L<6;'O<
-MLG^%'`=$W#<^R",A=$LJ7=1"3KH]UZ"^>Z?V`-5UDL_M;R^R^"UCKH3#<F>[
-MV0HGI5CV"OWF'66V5YK)/?0#U^0]MA@7ET5S(`S='DOM'0UB_2;1A'4XJD@B
-MT*N\X*$T\C!*VA!IC4WBL>M"UEP-_;S?%0J6?8(YK%IW_36Y`4J_D9G<PFD-
-M-1#T/N0M5I^U];NI((MMH'A)L(QH%W2K1;P8+MWLW,84HHB!LJ;&N<13AQB<
-MY-K#(Q?\2G>$E@Y*(F<(R?Y^H#GLEPZA_F,/#9#<U#4#N@?@/W:#RQ4<H6:S
-MA:32R1>89QOR+C<DTQ>A_GH@[:7"1#(9:`3J91G!??HL/+CP2+U:W9PE80DY
-M</6#?GKN)6GB0AE,__4L4K..$M/#(Y<=M++7ML-K%&+7`&U]GBODNT@,G6%7
-M!>O=$5$^ZIK<,MB5=5]L=)7D4"*DC&]<50;V%UKI4$U*K.Z77T!+>W<2$HG/
-M)M[?^Q@>\7-\$-B>!.#4^U^_>Z"C]N:.?,POL]ULLC>9--4;M<Y'XWV38KIU
-M`WY7J0Q.`J6L*V,N8.'[8HYZ;9A/K`*:C`!.UG05@"N;)6V0:Y4-8Y._L7;:
-M-05ZIOE^]<0,HHOYU]J/'.9`>VG?#`>*44E*EQ>Y\6.MMM8<K'U$$)F30*L+
-M@-,F&'>>^#S>35D](AA%V`M,QF,DBRTE\@ILWS46)?_(!L:!EB=BHIG@)+XJ
-M`H%;T[K[QD'ZY2FI^QIG3,8#:%)HUU[Q*R:SM[<1$CS>1<:-WM=HH#I.W'/F
-MSY[M,>F(-K2/SOB&M?`,:\GJS]A99R4$!IKX<J:[ILJ3T)QV4FD-F6<Y6W(I
-MN^RBYE(P5MO7%.6-M6LF&&-WH'N&*LNW!,2I0W_^L]^ML&O/S"4=%67)KMF=
-MK<61<^T?J1X[?FOM"V+,S_SC3NI0OW<W#7\#6=4$17-]7",2?:O**U/>0I$^
-M>Y5MO%>`XR&@HP9LIUB'!`W=JRR;;]+FP2+[*`4V2)X*2%/A8V,6F[,#-,-X
-MUNI&EY&,_:?M1'FM!Y`?I(6A,)8):X`^5:Q9[\/)'$7#EB*4&:A-:XD#'F[F
-M>:GT/XAH8=!_$8VZ::B5T(^J+%C3>];#?=%QZ>O(A8&TKGI?2->]<V@>O[2%
-MBCU?4\X."`R7/3K7`N2+NJA=+\6AV]IH@0A=I4G,"2HLEQ5*+4PC0"E\2:-%
-MQ:@X2?N@&'&CQ_OII(D'=`'7&"O+0T&=(?H)&64Y%7KQL@^^ZS8).TB;8:HN
-M$K@2;R[EP%5[<8M::3#7#_2E)@XNPS"@N7;"PU7EC12^9?/-:+Z@F3))JO8'
-MW^PGAX/)M&PX$%?#^M\V,%4$J)2EXE5,F61TOJ&Z"MIA3I+21MI8+/,WVT:,
-M4U,-\6]14&&4,]='>T+;8UZ+:?B]#X8Q_YYQ2Q6L<_?ON%'<LD%7%`1G?P+,
-MYQ%/<=4J=M>_3EU6Z4COD!7FHGZI*H7%FSC&)*QO.6AV6GYD=UE2B</HTY[4
-M9V]U2>A=J:JFFIOAM)O&RG68OA>4X2'4J21'28,VA="`J&G`L`''_RS0_;&-
-MGQAXYB?'^_=*=BQY!IR\,AQ+?SM)3R'$^=DHWE23XGJ$7!*Y9(N>Y8RSY\2-
-MW&4<P(/F;8394KC<+$@9[>'%#4,M^)-6,-$T,O9P*(8MF=%!??\T<G,J1Z<W
-M:>(M_SL9^?OZ824<['@5H-5DBKM8]N4I*'NVW$3*(54R*""+5/6<3WGNN=6[
-M>7#7FX7TH,%54GCC1.)HJYG`Y-+\*#AJ(Y&A:&&C.F&D%VE1QJ4T^,]@F&1G
-M;`<9'&#Y=MC%!O,NGNE`<_?EO577STG:Z9[^@7#5='Z4$3ZYB\SQA**X2ASN
-M68;AUZYHBK&"PW4\3UP?CU$M)]=MW4>AD"/^UG[07EGT:F>'2D8`KS74"M[?
-MZ\DL%4!5GLA0_#Y([??Q3LYWM\YX*6!&='$,O\"&*N1EQJ\F_D0VE)&"#"J+
-MZNITF6'WH1\E_\%B6=,&7ZT:&1U=V#)DHG1.H[NA[Q2)@B7<J'W7_\O.O:?X
-MEZ"./DP-\\:#ARA@%0CR(NBM3V^?)T3Y>XJ\7A9#R4SN6R$1(#H:8MZD(M;S
-MH3YI5$]L&4R!)Y=N12-[(Y*1"BW#FLERNJ-1NZ$PPEKT\&NXIE+B3](.7EO+
-M'R*^Z"R#/5L\AZ)GV#+;&1EXLXK=1ITQ'S9PXSL8Q!J8DH32W&_\5%+U0U\L
-M#"-*U"!=W9J?OBODB41O;<MX*'MX`Q)M^VY:FR/U6?,=%:FJ+NOM+_3?25V0
-MU\&U09AN(+:12_R4@$NQ,9)5!#X80S%0I)-ZE^W?D*'\C6Z+WZO9E@.L^.W'
-MW0=.<UEV+=(2V,V#GHA.!.Y.HS%Q#IZS!MTVBT"?Z(6RS69Q73#T^=V,O!DH
-M`PAOFO!1'.TJI[=0I<$Y;GGS3.=_<0@N[_7/3FP-_<HCR":KL,8.GYU'H.7?
-M#\Q6"@:YF"S]!W0R[:0;#L1#!8-VT([`<5R;P=EZ?L`C4F*\/<.."%QZ5N=A
-M(^1'*/QC=U8\1Q>+8<4S`./IB\W:N'0!WK5%'7-Q?!G*:I\('SG`,:!D_AK;
-M;]3$6>&R4DUBOSEC-H"%8B:T;$)@D#M$P3#ZB?9<TEG?*'*[3P?!W]8GX94F
-MAH/$^7C]N0$\.!]]:\'N)PQQAJ3$Z*/=C!$P31&VL(CI@,6M9Y_[$B5%WET9
-MIV;)$7[:65(MP8,#A*W03<3&&T9I1IYA?*^SE+V4#?$LH.VU9$U>OH/A@PAO
-M!?J75;``+*RG6X2*;JL@=WI>(_WL$DYNRN+X)D3.7*B<[TD+/[77?O*EZ7QC
-M-!4A]R@&Z3Q_`YX64GZ;#,33,.?6:*:65>`(KSP4'<(*'^:Q/2;+;D;+>_5Y
-MI3\\BP7F'8J[X_Y6>8(*V>O$BJ(U@ZO+<N7]L=K2TM2%:VX1T.;NFNH3^.;%
-MI21W7?I^&@9V^_@-R/7OESYG(6.IQH4L4T%7K2*\4;J/,.[BEZ?>&67C4$S>
-M0A8@JO8)&Y4B64[1P@P8D?]I:C18^F/O\:D^>>TH=I`'.6`\K#$Q_",O.ISB
-M+"BKT2?+`XSJ'4!\_+"O?8ZB_^?7<%24:,)K&\6C7>)<76_.SELA#ZV$Z\$D
-M+:`8MGW_W/'U<EC2/$C-?3OO7`@L1W?:9YN7C\BKPV`H'EW*IW'>][&R!Y9)
-M<G50XN&]36#$2+,`<^Q8$"E'>$6>U_RA']J\+`Y30+%:-G9RPW?&1#4S<[3+
-MQW,_CY+))LE3^%IJ]SE$<!*O'-9&[?U-6;UR;?N&,*`F(.^/H,\UI-11_.KE
-M,F_-RBSR\&<<9C%EQJ@*ABUA'GX36DZ0L^<;`7E6K85A2N[T&$?-"4UQ$$ET
-M.X/,YHH2I`?PEG2V5X61!1Q`9EILBG`)1NEY&9=TXOTV<J.U>E2H[&82N`%*
-M?K?]!"QH&HV#'"SW8Y=-%[>CG6O'V%"M.XLFLJ]PLSV05)ALT]3@Q.9RPE$?
-M[WP3\H=<:5PU2Z]AOLII4-<%4UQP3K0IAQ98SX4>ZN!U8C62++0:?X2`5'>8
-M6RY))A49;3?9;X;:=D\$.F/64Z_>X`7R*FKB_)$ZU$ID/P&L_UV1\_/VDR46
-MA:5,GD=[QR9^.@F._A*RS_H5NN9P\:#T(BY;348QA(2\<^6G%G36(-3^YH?G
-ML-.U3NOA-6;/N&+'3NV?H(H4H$"B8"6^-/OIVO.H<%A/I;IW!%Z[>&BR-6-J
-MF]+TGD5J;E,^,KR%G+CZ^S._3<3J1E9F>AK&)9Y=#DB;@\6M&;3P?A2X3:@S
-MP.4!N*A9>WY.W:9G;<LEVABF1L)N:_M.B6EHS2JG'W@\WMS"G/D1!Q4[+6=(
-M>';1&V"VYF]-\_M1V$L>A'#A5_1W_JH%\\%"@L"VUJ]\!HU*I3J#<74UT*OX
-MVLH^EDR#<4T\OS"%$D!Q?&EF!E:_5#=2?-YUY:_'$NZ#G:<<GP/N[*%R#=^S
-ML*PSZG6MF^NIRFJ&!UJF+PIF^F*;5#_\"EOC'AHBJ=#+$F$L0W:[109F@[(M
-M:DV\,7]1E9,Y\Y1@XL/00&>96Z?GN`.\50?ZP4Q1O=?0`S3S_'&]<3]A'QR1
-M!NV*:-9LS(D4\_5SG]G\_K<9YU;=F.T,0JZPE.4`SFADM!7H7'P(*JZ0YFO@
-MN='@-5EJ\_019!"I:8PLGDJ@\2\#.X7==PY:%8LS'R9L-<LRT1#1*1>F9M6\
-M"G\?T.X:DZM=1EI<.5-E_>!['J%>*%S-_K])EI<42[L!?N,'8(@$G'9(.Q:F
-MX;(*#8B'89B2O:P/?2KB&\M->S;L?"5['+0_#A8PJ33<.95C%3C:E4<=2>1`
-MXVO-T[/\L6D8H'U*PK@N4,T>"6:".W\LR82ZAJEX@7R/ANA-VRNX@Q[0M95D
-M8-!]J"27<3U>]C"5.*)$]-VV7M^>6E_&Q<-<.6HHEC:%?EK[B0SV1,WQ&7<*
-M3VH)=YN0NW=,OJ<1`6\B']=+7V(E4DZSAA;9.I2E98Z!:19/3;*/J]&:A0<"
-MKQ7-:L-B^T5D96E9@Q*RY6V<S7.)3&*P*2E?CAC?!X(EFUN9RF7$TP/B/3MN
-M&Q@LL"-NL$0;,Q]-=*R%*9'_VGB3D@6Y6QM!W$^2J#KR!6OI!"%.>'V!3@O`
-M?VB=>_TY_'4%:![G@].98=':@)U[EC>66`,90-YP^FX9IHR,D,7U8+A'?I?2
-MU6[SG"!HZ53-#SEO..E];]P&1?*PX\^YC,U0$NXR1K=2$:(`Q+S=FC\1!-1H
-MYAK_XTQC7OU,9V@ZSB*P5KY4E1&52=M8-'N%[8%JY^:H4:+4SHU.,PU]]LIO
-MA5DR[/+NHE*<SU-(:H%O+LT-*X5.X?"&4(4S?',+N>,&A0'&TQ]*<8",*IXK
-MS&49@WZB4J3*_W$__CB+EOQ]"!6]$2-T=-[*Q4SVFE1AST26FEW[!YT0+AQ9
-M3\S%I659Y-QXG[?BZ'C)_NY/C7(RJ;.`(4JQF%YY!;H8V7;.>'@FARV$ZU\N
-M!E4/M6<>A2**A[.\E.VBFF/^B>6DZZ-`PY_VU[08[2("U7`#4CX8QV1RVZ"S
-M\VT:?W2;6$HC<&8E[XWTG']5CN1PQ]5,46@]Y]!W4IAG2=9K=A4L52$->6!M
-MCLS,+%*(*S^6Y2UOUOA/G4-&VY;:$IHPS%8$:G'VNI07C]/I$S@H>C/,@-5L
-M?F:$\C.)Q9^DSI16U6DUP1(*12MRU<@9H0?':C2:#:H&\R-!SY)/OV//L:R\
-MAJY2%E>[&HC*DVZVS@UNF<Y?6;?*HNV+^;PMF/\D.8O"(B6B`@7XNA>-V`&]
-MN!-)(,(KP:X[X_3\*>^D!J;:IZV'GU)8U#T&IQ-*\$CVQM>BCXCO[[_IXY*7
-M7V$^V"&Y>_HJ>*3=\T`<[,NL9LIK@#8=8?@(+VK5".IE.XDIKYAH1/3!QT6Q
-MF8STG?>/NR3OZHVN3I^HC<H4?%[F^S,0"S84?,!;&R*79RF#F+W\M5>DRZ]@
-M-`RV\,1-4`<'"1GA]!<^6E0FG.[^B%:"TE1R1C"./&:XX[X9Y8\',)?!2-65
-MHTPNYJH1\)$DJG[RQ!,?$84>_JFWHS5G25[/.#05I@.PN:^F'=G/QZY&]GB)
-M"^=2\(WD_2M3:0RC'-?'P(I)`=O+)3::!OM)I+`%GYFC0OT-X7GH)?/03Z*9
-MO-.%3:DN0UVI$TG,\./DC&4R3S\#&8(N8XIXB"P-7I1IFS9FB^4B+*_)`[WT
-M7:./XKDDS`$54D"Q![])F_:;AC;:B7S>RI.]H0R3`_0.\\.1C';DOI(BETU[
-MTMEH04]Y9<SJLNQI!D8\)'^T0PMU8.]$U1XTR9TFZ!PN\*:D8'X-Z5=8^6I[
-MC7]Y&J!/ZEJGPG<[+.\(W?JGR3O-"]##UN0I7+!PF!',&VG1.[*G(+HX.G5W
-M1IT_%I3DIDS"6T&YS#!TZ\]/RZ:=_<6!IB!D,,3TU*R)D,Z"1([Z%ABNAF(!
-M#^UO\\4YBRK;.S(YFS]6G*#?:S?-"Q6/5^%^CN;4)';G$*WAQ1J!2Q#$\(Y3
-M2!N*8N^HQ%EVO,=*9)KG0<>?ZLC7;>%IZVRP9&NC:-J29#8Z8'"N2R;*N;]+
-M:!G:=M/5M`3<'">)CO1:W%'V>&=L:"J91O\TQS5,:XCLBT_XW..AD_=3V>NQ
-M`?E'JMYE<\HR![N>IIT/?W-=R_G&I#S0#PT)D%B`EXO,>&D:4BX9'7!J,PEA
-M8;X-S^L.6?8"YN3^7W:C"(L,>X\V(^HM!7SG08F#5#(=A[N';F&S85;,^WCU
-M>`/#2:_`"^7&-46<>;$N:/>IZ[%Q\[\E)9#B=VR+7']<9XLHJ;(QY$@5"O"$
-M_$<F;'F^%[+'4#ZG(^[G,D.F3D9K0"5O3273S+O'#!(W;@I9TI991WO2<<9J
-MA`1C%]AVC*2L>Q\@*-9^[19_JCA52?4I#<V_!1STJ>H:PU]LM#7O,D_".^9[
-M5/_?P]EVUEU6!5OUOHR2+VIS:1PF!D^;'9$@G*ET2\U3<3MR11!&'RME'EL"
-M6F?Y(*S2XO3VO3@J9F;N(-(.[7`]6_Z))((K#96D0=V8ZCDA3&N!L^EV<Z@#
-MH8,CIC1?-[I<VQ2L1I6G'+/%%;W=CFI$I@K&'?[V(,HZQH3X`MLQ:1ZSG#2C
-M0I]4`J<[;&450P1V,7'%&M*ZNZ[@12DR*.5*O!Y;_6CC(>.#4>.FJ'VEE*?2
-MREJ61.3PEB>#8APQJ==!F].=$(7%@:&^$IUUX>8EF)/`5+]UJ]T%GQH5YI&P
-MAF#Q3'T;^/$\3A+,SG8GNA[:LL(L#=#N;&U$Z,A_4LV]*K-,]\X`8TK5;)H%
-M$[MLS'KTT]KZ(-B22FQ!2P^QH29G-L9=\!TUSD#FI!&TR+6B/E9L8AFO1.CB
-M42%3:5H6G,0A,@T*9-[OYK:2M.-J'WR(`C#`@8CE635>7&$G7-B])KNZHD\A
-M,9R,-N#:+#?PO19:"$?3I*)-*(74\2T/0!%T#\4X3JH/C=>VJNS@W\<R5>M2
-MTF+G<Z>L8:O;-5!>6K-6NF*_L?#S=*+YC;=Q:ME9GD_7,]##K'^Z']2APP\C
-M@04C?<PEY-`6D?OS#/E%4MPBI?X80`M,HCG5&]@V[@^!"$/W]\!/3Q&#00JB
-MZTZ1,;NF[9?"9@<,/6?=QXT;^.=SD3`VSFW9LR"C.WQ75N\HYB-DR^!;,@P7
-MN3QPO/2L"6%\"RQ:L?WT-<+,ITNH#U.>O*[0_*Y#5Z+.A&S&RO`P.2.\Q2`5
-M=%VL<]41RRLKDK5(\`V/Y7ZK1__O@+WET-:!L6^Y?.+UP:5,U977F';)35B"
-M91><<`H:5^:VF:RS-8QN[N@LK)(8/KV2;%G/^-?'X3C+'7<)F3ZIQ1#^)F'A
-MIW'+P`9UVOTIB/SGJ6TO22U;ZQY2;HZNE2`2YI4"G@H$M$E9P21-*J@ZQH2N
-MPW8;,>9^[?ONGH#%.N3"(#)LQ+8ZK-?IAVC5O5]N(RUW?YU?$T;*;!EA,-4"
-MW='@</<R>(6:MR:BK/!00W\,FK'668^*/11SI[=Q8VVU]I/AS6R*K]UU[RS(
-MV0C)2J[OZVC*RHOD0+YY:NH6(07?1J6KU^-N)!K<I_"LB'\499[[L^%0HKU[
-M^P'\MYHEQ]?%+&([?DQ%766!U+9_W'[CX:(@D/^_CQ?7-)LJ?VB],H"RM^SE
-M7731B?!+MT)!')_5#^>ZC$%^!2[2I0_<6&=XG).7?54GN.7M#6?=+U#(*E,O
-MWPJSF39;698N2<Q^B4F*>7?[ML>=ES`:2^,Q=O"W14E?`_"+]=B==`I%>#SP
-MH-^Q'XBJ=QA\V9.6FC,.C_T'4H)E3!`DXPZP?8DC:O_,]B5CK'_#&,T&8,';
-M%>"HV!!@]Y;.Y=/Z/"U9M$U'&_K&[IT9TJ6ES6O@FF?*`<U*(.@+$-S=*]R?
-M9\=^]A[+PM>+\'CRX)<+\?N^8&BAVCQ9,:E.@BPX7IZXE%U.`M'[1C$5_<5Z
-M:**MMA*,8N`)C\B(6"[A.>IFBZAJ3\()D\\VI5E^9Y97@"W^R2R>VN2!R-!]
-M34Q6W`*IUV3QH[$X-'R@;S,5^(C.T<;'HWFZP]&<]K),;D#K1;$I,.)8!7&#
-M/."5X.HD$G;_)A\GVNL<'NB>/HVPZ;3X.1ZDW8]!!Q?*E`'S@XW*(PK]D73)
-M07@)M8*L@#!@1K=T'!%*[2LM\01/?@]UW:R022=.\+,)%'8>@+:SZ']B:4;5
-MR@M92A:7_.B^E7Y*/KML%B;.Q_3/.V00_"30BCU;`@:M,3&Q1RG5A3D_2>=!
-MANJ<K&IO`J08%;81G"QI"^&3ZK!XFKRW[B,\],28HR6B&>F=L&H"?3Z0*7Q<
-M*R?$:ZU?+DY4O%Y$<K/Z.+*@Z.A2I98GV3QQD(K[P&I]"#F2:%ZGPYMR61,[
-M),?9U`ZJ]V0&72V(?R,[72^MB$:"O@R-7]OE"MRDP?7\UV^U:_9F-F>V7PLA
-M%:31!!VX<1B\V?E&R*F?[BL\B?;9S*9N3AM!.AKP%0NO,K/,%E&VJB.7WEN<
-M1ODQ^%J(NQ+LZ37Y=T:0K6TH>\VK(X1661[XS5D8-3[U5#@8.,6GGS&3GSF&
-M]87!J<&D.\'8\O4TN:(&:@N07LEPQV6<<6+A[SX@FW)E",[[W%D2Y+>Z>QK6
-MS+@G?29H\*L]=M4<$R'RW>8)IPS?[%!/R='ARV6]:B;L%T@_(\[2%*ZHV=9>
-MYX5#;C)[KQ";Q=[?/E=B).ROQ-OW2$A"V34MJK0$2)=/B$M@$2(N271<'&8/
-M/!OVI:/\BLO$;(+UF]CO0]>_9;U:"Z^I\A9==]K)Q]A<%$K1P2B\75;,_<6H
-M`'1G]/#!8\C"F3DJ=C^(*Q"ZTITB!1N-ZVH\M#>$Q)MD,WYJO>24<W1*(XS*
-MF'9,K@29V%]]GQ1^2U<+W#-FZZ`N%VB]F1;\=O(83$;E#78BYC6KLXR4DH!Y
-MS,=2OU+#MN]NJ4D5<-61`8.O@RZK(Q:LL'%"')MQ?/7\ODM2ML+,E<E\;_DT
-M1Z+`VPC\Y>#^&.@HGB.RP#'(UU[0K[WWPX?24_OJ]3$C:*R+4`^'/#)*&_DC
-MWKY<Y!Q29?<<8C#5L&/7!;\13EL7PM3"3^#_2X;P4*:)!=&!J#6>K"T#[V.T
-MY,QSPD6C1*K).`)/P;/&#M@.(@^K;4FA22YK981X5@<U1OL\0'@F!#D"%8&,
-M$#"&VK=QC4+OQ^^7PU3Q//VR/FQ:2SBOYXJ"*[$8:UW4:`=P3JXG.99!$$HT
-MHXE,6Z0P#]E_Q!^KHO)N3D.D9]2;EC.O&1!^J?EW@5IZ5Q]CZ&\!-%-9NY9P
-M7'&F@,3U.79Z5$=D<G.7&Z3G]E6Y@4T_?'8<@8"W#2S(]6O]>$=>VAX@N[NZ
-M2NQ!TR$,P^Y8ZADZ>N@Z<2:WD'J)-C99IZCVBL1I/RD)(A3+N,*54KS"RTD<
-M]A6X-:1@P$4(1%E2B6!-J=M`KL,V3<#WI:8N6!_":RU@')NMZ=BR\AN=RYS`
-MDC@=_\!2W">Q.@TA!']#]^7LEA*"T.RYFT\!P'M8=(#8[Z"VGV6.H-W)Q$V+
-M<HG@<@J"ZZ`WA\8D(?BF,]@LM3*`VJS"T:`%?9-C(VTA&R_50]?=SKF,[F`O
-M"*"R?$M!`'+"\^[T0$+KV^QF]$$0CF8]_E<M9Z6!H"*'H3O2W*95DN?='(@O
-MN,KXF:.I38KU3S1$&@8@X@/XEO-F^<:318<&E=)3C+U\B*30E!*2H>HBMB:X
-M\Z288+ZIV]V>LU/5+9$//2_@SVM=Y>UST(M#]O.\M0@.!SKRKG-?K,8&_0N?
-M;$:S%0WR'@!&T#L0>C0!VB\^KH39\N5RO@!;_V(P=N^?XCO&_98\6O\^0Y82
-M5EM*H9]%2,/-'GM7%>2D7#"I!@+T"#0&[UYDL3`A]RI:=)1\ORT<.S+?"%=?
-M1X;J-KR?TK]B\!=_FO(M8YS<YQ2%<V)C6*\]`CXI>[5E/)_8_7\-:F'""SYP
-M)U![V!F^PPKD.>&*4[O:,5"OT')=UZ?C62FI*4U?#&`2_@U>KK:"GT/!.INN
-MJLY.3'Z%<L%D4J1O)YD*_LG6'X="LW<>0RYW'XS!2@JC!,#\<J,\'7J#QL]X
-M<L2(@F%VM_:8#2#][IOY@L/>)W2-Z_XA1SL53[ZFZ8UMDS+APY`;XLMI7Q8F
-M2PD8@_9TX4_(`DZ-X:9`=82#K1K!8^FCKQHC2$.!AE'D4L(1-ZEEM+_`?IG@
-M`;YN-]=M+WSYY35Y$+X#1!9H[$;@QD)\;E5.;5-4+C>:7S,##-%OYOWLA)"_
-M<BX>23U0JNZ,"\ZPL]6<VD'86@N;(,B<S94"DRV6[@K*GG9X^V&$LQKVJ+K'
-M#'4T#!<7I]'_Y:XH?'!G=H3Q'MILB^<E5,4TI"&^-Y=*&&-]V!(<29EW(H8X
-MN[M&1&"D<\J[XD=[\4,GJ@=,EHPQP-`[0''?\#Q"E_!'S(Q^!HI:;X5_E2FL
-M4F"+F8J(LS:JRV6-SYYD@LE]V)NQY.$F1;HTB3B!O`>HQDPV;7I=/-XASP2:
-M4<T=Z["4^BB\V7Q*94/&P30;E)2+CO,VGZ'CBP4QV)Q#IE6'_E5*^+?/T%NR
-M&^8$.U1*&0[G`FD:R%D29;,&/\HZ"`*5OWSNB)>FS`\P&:[A23S+]/O@V]Y7
-M+0\W(E?=&T3IC_QK^#-/X[+^;:(XR0O)DN8TN+X0CG>_:H%>^C5(>S7C?0JZ
-M]LU,[.>Y;+"2:GYJ227P0.5"'D:[-VZNRRE*3,))37(RMA8G#1R-T7T=!`D7
-M)Y<R*ARY2V/K_FF^<=!\YQ(P)[+AC`>IHU7FD5<YN>J(A*1;LFCE$[FUA?C;
-M9EF5KZMESOV>;B$7<?791I>HYEBX+OO`2$#[`I$B2.[=;>W'AAI4:%],K7Y2
-M<^!.VX`_-")B'&OM>_':]5VR.03>-##N9ON0WF@1[Q93+(JF0Y%^0O^U^S6S
-M*V]=QB7]7@8L1>C)59[Y#^"B+)[8_@5O1;N!/G:51L3#J)CFDI#ZBTDXHB5]
-MK3"67RM/F$&9,HB&![K\3<(0WY:O\GY`SOP+TBB6OG?]A]JQY_*4?1\*W->K
-MRMP:#($,#:C1"!D=Y]X-\KSQ%89U_7]LON<];'I!L0E/!K>@IUY0S"KQQ5)L
-M4_V:@RX)Z,6GSW?BP6Z^!(S,W_W<[S<FNV)#7E'1G1;=N0>:[A&N61T_P)5Y
-MJE1/;/M&NFH^=>[]LA-Z%Y[1Z3CXM9(_00&\%SMR@?E<LI%+'!'(J)^<\9O`
-MW4#0R7ORA*,1[9R1V6ME=Q#4!DHMTA6+>--]B5DHZ'"94HPPVQ[BIR92E*^<
-M43X5=A2T*B<KH:,2^-7:X1>[[6]^6B:Y6+=Y\>#12%-15FYW*5Y+^#"01O?"
-M6A6>#389L0<Y=IOTM2")3K+K<3]Y79`/)HXB<4J<M\VXS>!YA<&FNJY!L_`"
-MG9TQ<N\I6&/5N41>]JU"QZ9$0D\[I1G1X9+%Q.OW4=\/ODXJ4>88V%W#U>,@
-MY41ECU^PNA!'2GEV1H`X/_BAKG-_?0H_:E8?HOTF5>$ZOYC@$CA=2^:G_U5D
-MFN1_D4R,@@;2B1E1(*RMUV'D(PC#(RY/Y2%,M]%C<DVE%G="=[ES3NF_T59$
-M_TD3@!VCF[@%6LWM53DQ>GRU^W_-`4V;F6B9WI=N%Z)_#P$I/D1:W?ZJ%FI<
-M\O9!G&%F-*OE>-KBT\('_L#["P'N]E*647.-OI*55%/VH]GRMF('%/C"]J6:
-M(3W@TK<U=(TU$)#WHRG.3IUDLYDGXR?D6!GW+:!BU*O7L/Z26D.INU+'+X//
-MQU9?XI]3[#2\)&Q,]+[`MY"/5#H<#R>V-$O$QS1\Z]O_<A*7*BA4_J&&BWH[
-MU"?!I@<&HY4(*Y<F8AJLI?]YMIDZ\\V5(\W"G&H!O*+.::=`_==02O5$V3BW
-M$.@09ISL9^@W*@",'P*\OSVUO]=56CZ!1?(6.`/#SG2)1(=I8Y8QV?4A_].2
-M1Z//3&OS17P/VKO.S]V=K-CW[1B<%3FOIC&8FX>#!N:G%;QVNTP>=B;+9+R(
-MT--A2DDH`=HDFL+S>S'9:U=:QJ><?^0T:>5)IW7>.>1^":NP)88%YP=IY`F2
-MB4GX6X?M!D^>AI6D0T2S`CY7M#J[TDZ62><+'-:D+N@'HT.;FC9UR"@27^JC
-M]W(>?MIB(;>-^4.)-B6GKM+R[),#AYXKHM)PHB*CJ!%R)%W*"`8,;'&-O^^#
-MDWW363H).%R_AYDSI*%8*K%*B1&7Q<'H:$CDAP+G>*[FA>D8_E#2?TV=9ZVR
-MADI-IQ4P'Q+W(78W:<;.*A+CZ82:HH\T%"5_8K,$S:5^.S[+=G(SM7@]:1;#
-M)[=54<[8+EOOT]NE6U/$4_5U]9#NJ.9*H*3[R&=FRIVK/QY:R,,R:5Z*G5WN
-M6I_(Y!<6696SO1;,1:R^S:M)729`BA+SZ+)1'Y@VSQGIL02=68!\;/%SG#^+
-MX;OI?L7@5K8;24ME)!;IFVSZ79U6E_;)IO2,4JXQ#H;)+UCSE>-4"V+,89.U
-M?%0F>?[CEEC[NQX'J.KSX$-`VP=%QRY-3%C"+@D\;F$J=WQX%:YEQ<P7AZ,M
-MLZ8'_$ORJN,\S$*<X''=,`O8A/YRJG'YWQ?@88GX\R!:YM'X42T'B2=)'K-.
-M*+_;%:)N1FFY5"MC06[^[];%`RT'.FGJF<W][BG;MV-_?4^C8")*IR#`>U&G
-MP3_1K+,HV?LU']#I)HHF)GO92YJ:RL>XCVKUMBT_H3QNJ9^332,LG>*T[-_"
-MJWC?[0,QV$C<@E3C-SJN$:O)+_O?=]A?#W+K$O)"Q(?.0<[:OHE0PT+73>)@
-M"WGL(R:.,%>IJ>PVPPZPN81CK`ZM_`HTM^'L7%8W3\VTIFRZPP"EXOMYW#C9
-M!#BQ246Q:"Z^N&S=/Q)R(V]T_0W]\>4`/^`TYOYKT<U'5@J_)D+-BZ^.>OA[
-MC#H:_SMTUP>_`B7GROE9(MOXTS?7>^D;Z/D3$+>JI('UYJ#Z*RXJJ5%5!0HG
-MR-2C>*(:`P.0DA!.9MB"3U]^LQ]\]1493]PQ4,2SG$ZI@NI2!I)5F52R"370
-M_L13(H'>.0P"]3[4NHH"NUQ(+]9S2VW(0%@KN_O-RE!<?NBJW?18\XILVU/L
-MUO$&\A-.$2O))]);&6]G*/]M2=X>=]*[+FI]HX5QJ03L[7.7/#S-,=HQNI'\
-MRE7Z$.8!"R7I6K?H9.!90R5T9;24H^38X9='V!"^+!5@3%,-Y9>)T+;AQ1[^
-M",FK\!+KGKF4+BZ.T&+E1Y4%WYRNFR,"QN#-LW*6)U>NY9V!R<8A=NU)Y[67
-M;]?-&YAF;=9(!R@_>;DND7@\B1CFF<<FEQ8YSXZ`Y"!!.[^]E?.N6T.NGBTL
-M@C9`'8]-M,'0O\`1\_?%#M%\R*CD/>B=JG^*Y6*_*O9DNV"<I:WG81U)+74N
-MQ7XG^Z-9MDF1FVFSDZ3<*ZZT)L*ATBX[8WQ_3""@V$H6<D)6#6A9<$G^30Z"
-M0DJ035_W7?:[9G=6'IRY<=T=W*LKWR%!LK40U('>A2/-H%\2C*C!R]K`=5]>
-MN"J$?C330VMB2G:?795%%L!;R_$%O;I'Q5<QB()RL@094:S3,0V95+X7,$4#
-M%7-S-H5L$)XO]B#C,G>4?Z+6S-=6>1@(:-B"GX+78B-ISZ&IP4(51E+@$5I.
-MWT*#0ZRT8$SJ@)PQ.)6@HNE;ODQ4C@9`B)_FZ9Q_Y\,[,J.B!?IL!_DN<7*D
-MJOUP4!M[F4"EK@)D(KN@_T!<)\(+/KGC`<(56V.:[V^<,N3Q-^$R/"`L?9?U
-MXFB8<1>-Q7`9(0*=_0<IX"96ETH72SPZ_RS&.89YEC1U(^[*U<:OPIQS<8F*
-M#-M?[,!7+6X_BRL^RDOUFO"MPH**";Y.-3:D'6E3PUR["0U)]H@=H-?':>6=
-MTGM_(SA+!:$I(8[?]L6Q63@"UF#5(XWM$%C,IP4Y;]@S5@Y3S=-'$0GB'.B?
-MWQ+CS7OCL'W/MV7E6']C=([_SQC0ZW-MS5DV,\ST0SZ9=&/IQ].8YS6:0T0U
-M*3T=@;J"I^U5&F2&*^Y7'`K'*1,A5:PMEG92O^*XLU8$<]T!2(HUY%06)I)&
-M7,TN0P+*D:8($O;SI-"6+EY:@.#Q'W3CP_U`ETK[D3%R(=.HZW9C2HJ9)=Z@
-M^B_;!B<?2)U=U'GAY\7$XW]\/YCEE(9K#>Y/O5F#)1,%I2'1-1O$+-B11)>J
-M+R@'LDK@Y_ZE"A*,H2S_V5Y(IEOEAQ@M;ROXS7G')"221L,BI*`6QVCWC`T.
-MXA0^HI^=YA[^;'.6!T\VC87$I`^-15^]=84#,CKOV[%9.)/0Q`K5\!(E(GT2
-M9%XX,W&GSU0:B$J`FBPB/<$<!&5K"LRB[1?P]A)R</2$,=*;\M08CU)F$HF*
-MJ3ANH@9[VH0=`75J84[RKB6\B.HJY(FO%>&G`;J$EY;Z];W(Y)_'U=8!?5FD
-M6=0'0^L..T6VDI%H[S7<(NE9(/DV0XV3VNA/5\/%`ZO:&)(K>,88(W[_K*O>
-M<JD#7=`CYV&%?3V@BAHQ4+\'+2XG,D-0ODKV)8!NBW6X4B\(__&)9"Q22-[W
-M,UAD5+1>A2/'UYLK[X_[^*<U`.0'^_XR&>GV=W@P^U!DF%,M#0C9':>S`?PO
-MZJK/4$':&B148:UOF9*6?;-5E_-58Y^&1RXW*-)#%<GS^>6F90W/"&^WXD].
-M:2OL]F+7S_"?TOG;D\#X?K70QJ\\83R*FOCUJ6^FCL]N1'TV/J]KUU)5X&DM
-M^Y4P_'R#C+:;O$<1CA>4Y8Q.'Z=W.?L)%[HYJ"!$R2`6T<A^]E]7:0QKL.^"
-M8^<G^TOO1P=7_BHR@B<6:/LR&7SZ,%N[Q*424F!?5P.9R2=)F#:TDOO<+K#U
-M:=FZ0$;ESE%9*DP)HW*3C`?[:EGYG^(_%@QIR."<,7%;'YU-"J\6>-"W,:C7
-MWN*1M0.P3D(8UFG=I\6HG)$8+V+C7F'XVH)^XEI^)D"AI!]'A6B(U*\Y1Z(L
-MP7@U+(3I:9ZMOTAG8A?(9H):193*M6^TL?'W'>USC(VO*J/89=<\\@Z9R58Z
-MN16K_.A.`R+RMG[)<VX4HXF43,#!3U#$-<CK[VG;XH2DJZ*.$;&(4AB.\H?B
-MWXCOIZCK$35GS]I+YF:D]IB#//N?##%>E(M8\@"@?J.\F\G?%S.MRD*0#=Y/
-M,([Q;:WF`E7D7`+E"0*26-;7U%@AMY(J>5T*!QJYW_XJX""4V^(`]AZ$DAK@
-MF`.E'(-<(.16>XE$V1H<&/YE>$W,/]E8Q)9A!,JYLI2"?/S^/A[@YD%;5@K8
-M[]O60`(#)^%C).[@OJL_%,W@+*S>-\D0.Q<D2%T.7DU)HYS80Y6W:=^0T.%:
-MT+(0*E!=)_LBF6;;?ZS%<[6U0GM=`U'*4W<7Q:]MXK;R^[=41IM9C(S*M&#P
-M5(\?0Y7.9OZ-^"`1E!B`T&&<<,<3\-HW?Q<+;ZY/6#^E>5=1XKX)[$SFL]I]
-MB^DO*D&APRZWF"TV:KU6'6_.5E`E]T!=H98`%!]'[G#*T&S%%/U[][MBGZNK
-MY/:(]L3OU"#/!E./M:N'J9'+''CB:1G,$AQOM;.[9DL")S^*$$:.9X1$XAW,
-MJ"GEIFW2";NJ?`U($DJ?`L#5E1_-3NO;GXD9"N.=J;1[W/N@Y`#&3Z`1]DAL
-MFP'VE;E^D,(AZ:\Y`N60NB;FFH@`6W&@BN9:+?[NJQ9RG#O(W14A,0-3Q*GA
-MX1%O]I#-_<'[0?XS!EGB<FLMWDP#`:=M$*XS<<7.GJ$M]70,^Y\N&J`U`[QQ
-M%KCF!>%5-F_?7Z!^V^=5'\QDTR(5[\B"]N0B['5E%XT\+RL,:]=MCE_>W^'`
-M[2/4EQ<#CRRSJ?VX\1H!_&9BH;7AIQ_RI&ZM'8BMM;BOHAE!U&HX;145<"[9
-MUH]:[4+\^S-U"^,(0+U@-.<*L52")%!X\?U\VZ*#\(2T@K/_?$C#-_*($(AC
-MBR@UY+1V<U.H_!DI692?ICZ98]FC;&,_AO3!8S204$68K+0#OF?SA*\ZRP6.
-MV!8$#`HXWE2_#O@+N=><!97QV>5]F9$#T+3E"WS.G7ZGK_%0L[)VADS%:%V@
-M,I._<&:YFOR4#P*"*WT[N:RBT`VA6'FU&8@T6UU<B5#`JNG-6B,F;L./+0A"
-M/!A`&FK."U)^)F0?<LOO<MOXWNF5,O8FC248UX]"<07O;RPFZ8U%!0H9='LO
-M$8-.-`4.QB>*E-^&W_.1?"(#9AT0,]^=V^_J+4W!U6%\[,*4MU'-12.`,=`=
-MO&YYV8%84/DO8$6L!-CY@&BY07TX==D>ZF#>?#R"=0ZC[)P1&T6+(B2@7ZGX
-M]AIMQQ!95_+O71G>,(#!0!J:&YE8V!Z-B280@W-W_B0D@IRH(%1B<^"W!>U_
-MVA_OQM3?#_W29"=RF.W@FVXE5_V(9\`L=0L$NCQ&D-=,[PE$85E+ESO+@<.J
-M!:^#+,<W23$#,R2.$F;96W+X\BP:<];5%8!I,:X!#A26-^6BH)"X<:%.'EGI
-M;:+.<;?<UFX?X>LBQU;=&=`!'UN/NJ*A%@<C`]II^^LF.#:\7D1LAG7`,K^S
-M/=TZ`WR8U#C'_4VAFH[H,U%`[5)]/$ZRV%9C._DH\9UB*A>9+`7]KV9,-$_-
-MQ./-P#Z&W@,7W;N)G'FS5'-_D0[AP,[,9KA-BE&H.ZBKKB9AE6)IX^S!8@\=
-MQVAA]AD^)+C/5?6;=?<0*X=I`KJV:3B]FP.KVI&!GF:[Q[@)8#H-A4>]5M)+
-M47Z7[@4=?A+H%9OWORZL5!6S0XN2-^X4)VSHY,].\M:J)9%]#_(@1D%7B<UX
-M--'P\4)'/);DY28/O1I623:UIH.*`YXN4XKA;="!7FU>S%!@7K/B"6E7?7P*
-M6CY['4,N\M39@WN]DZF6,1^*]`FZ>F`F739L9CCSJ_MFMF,A;]A4!A8-/?^J
-MB1!WU$:-1[UW>3%38_VY7R$IP(27LVTHXC?^&O;UCCYD":`XP"35T$K0+=&(
-M3%:C$?]"DXQG-=T<K7$3_P2F/=7?S`H>%]L&"NOV/#M>FGD_@23B6EP;:6[T
-M>%.]6,`'!(^M>:A<7\)GMG[!8450Q0D9ND/E\[U@IQ-H7-9X%\W,.E;*5&G^
-MR:3B(XYD#6UU!\](S5NH<WC"-&3/-@CQ_TY;Q!OS$9+_\,"H,UMZ-V[.B29<
-MD/$$S1KA0'[6]#,P=X1?F`N]\<U"ZK^$1;+/MFOW7B$U:-@XHGK4HQ$=$=,@
-M_,*//_<H2CS[6"^!O30M^-B`S:>M2]W0SU?$PYP!S#,NV7";"&#<JK8^P,F-
-M=)_%$[7GW2SM@?DAUTG33"!BI2;P.@FHC%CEXDLY6JW'])]XPH17Z"2OUIMI
-M!T-P`=.@FEI"YLVDWO_BZ)C]>0"&_!(QL^.(H3^MYSG'?JF2O0<,VIA#-.]@
-M63-R+#".9$OY'OCF48'7WAL.YUY`YB0ML.3(@SD#D>HTU_WWG4!S_=O-+M(&
-MVY_[TK'?80K6MH[&"QY3<*A@<-03`QZ#V0Z!H,'E]WMN-VHK/'L\XL<H6^$O
-M6F35(?#1(`R<_X-@D+``F6!?`Z7BN$W+&APH]SPQ^)5:68^FI#`X?4?L3W4.
-M6%E7&8VH!3(?U3FO.GB=X^(9E[Z"$T^XECV8PB+7>]S3!RKW&M2C^ZVA>[D]
-MM.7J\(9;(2D=\8<.-2GOC33GYT-7,&G%;/X\L@G5-'E=^/HQ+U['B5EHH=)P
-M]G/#8P1+S,&FBZ<3"MA)HJ.CU9@R@I7?/7XYRG$OV'&5+86"G0(`*';VT]QW
-MN9**GP1RP2"[LC'-+OMN'/O2OS3VPF?=)[%5P9G$AT&)8N=+J8J'DF($M&T,
-M"_7\(O#WG._NOG[6A`/@AB!'/>>"G-#+T(:-UD27V*FV(^_/#<.+1H(PM!J_
-M/B^6D6>C-_2><,)>U':E$JA27TSZR\P.W_Y\S=4%_U&?R\&\I(>(%3\<\9';
-M_KL4!ZO7'?<\U=!1PB]F_C!'U\?F&(*IK'[#)SC#I5QR[+#(.&K8\TD$]Y)2
-M/*$O5,(#Y$$9&^OV-0P]Z*4K8P=N:EPKM>A1K?3_R._+`8O:#'8E`KUV'>.L
-M<;"Z9$\V:*YS1>CXZ2M)[P'7ZUIA+?&MT/M2*8JD3YC53]\W2=;[:4"^.\R9
-M77[NFA*H39'UV[2_3>/.H*UEPF.9XV8_9KJ7`MG*QV4>'Y8E\ZW569RSD[O;
-M`(02H.!^`?I!J8B`3&ODME/V$KSRSFXY)RB/:JA-$&3M+%+JI/C`"OYQ#"ZR
-M?'DR./?\T""$3H'JB;1IV=2F(U_8B"+UQN4G>=VK,8&EK*1854LNB9E',:WM
-M]ZEH.^&B7KP,PDA)#>T7<8+!KUG0Q3!V?5%L04=/\TEZ79RT=U!C8(O>+2XJ
-M$F@%!)M*NZ%XB8E]3RL=9U!?W9>T^<7RL:S[QM,B\=.3$-M-,`GF?G\ITAF<
-M:)(%47T&CD>D/=:NYORN]`=VJ=/"CY.9]9Y#Q`\<G2`/W9(;S#A[J==&*>"[
-MD*O<%G`;X9VQR0=!67L>>M7.B-.%EE%>ERBKD"<>^T'E=L#/(-F`-^?E]X3U
-M3SE]4NZ<QP/8=BEFAZ&*3_Q'N"7]R_;#7CL/.EI3V6[)VM:M?(8-AO"<5+@Y
-MJN4W[$=!.*67"Y0=W_R\90L=TS&[R:<J,4JJ.W!(8=E7>Y&$O54-/B[.2M*$
-M-$>-!UBY;ID<E(9=+DGCN['[L5^1FS9O#*'D3:Y+MTH%%E5&U#@?<2"]\]`!
-MEW,3/*72=;<&DA;DPXV7.!#4#4FHLP:=DI>!8JM5JDTAK(7L<-BJWF!VG=YD
-M*9.&,_)0$D5\1<&(,JYJ[[5_O$_?[*Q@:]4(:8D<$65QANG.B/!3M)NYZ<G)
-M?DVYFRD+@FJA#807R-:E]^FRV!PST99-0O0O\42&EJPL#Y\]JPQG*0OLG*^\
-MV'\57Z`T)8`S#M:ER25<5?`A8;PF9M:3&I,M[/G3(BB8_[YUICE^USZ#]!-I
-M_%W3#VW_F.46FP.231/2<;D?4*:-Z_N%^..3<>57=TA598NS^#_60J!]]??X
-M5P@3SLFX_)//[A'QY0=&_?G(*(FY^C$G"$[Z/:,_39?Y7"'.+',Z[+L/-^;$
-M=O;L5\82BEW[0&<[,I##(Z;8"K%;'&60X&O>53E\7BTG!A+@TV?.V/4T3X+)
-M;BKSZS:<`;O$CMM3C,N@*\(VE-B>]`0)7\,9=X8^W1PT\QF9P&J42YGQ[J.#
-MKOV[Z]C`U(DJILZ\-)CTTJ#)"7\6K8G5'5$5SZXDW4DXY)JV>W2!<<;T@$:?
-M,'A=/\9-GU];Q&(XYOG?SJE]HQ353V@QG-WP#=!3*C=>+67U"B2:8\F_N7ID
-M8;RFN;`^=M'T[_(C?IM.I:>R:(MR!<I+14Z/1GX90=XS;\ITT>;@+Z+QG5@`
-M2"G"=//C^%C"D\^W1E:75S+H*3,GCU>^W>P0;&7BWEM0%Y>SM*)'K_6>[XE4
-MG^`9J5I!&DI>29K9.;D0EC'+D"@C%TI4#RTMB%H,NVN$Q4J;%:>>I"GC#:><
-M:^JK$O-(U)`W?:,L?5@0\J'UY$(?&I>2#11:"`'Q&?[!4+`%]?,=%/^2'KJ4
-M(FAUR57H2!/PH7I$HV@9)FK)<RSKBIQ3@FBP\E@[5+=Y:OJUN!DL#,E5)&!4
-M_RIMZ+8?![)R00@7$.BJTG24Q_;R,]*4'F3.H.UA#")`:QJ@*]7PE8^N!2)E
-M2_.S=NBZ6%=*"L<%?N^%,A%F[%$L%T3<OH'",5<9*QQS*2$:0,*QYMYJ7MO=
-MXNL>1_`2C`@-/`@=L`FHM0"R\B;J9_PA>U4%`>DN3#WR,M3V[2E+XZ,DN^[0
-MV2;%M=^.1A%0;Z.7%>.JB0W1]?5V!2G@*UCV9XHJH$8.XNW<(O`9RA\AU/F+
-M]R6$IVKB&-CN3=DL9<C70*!D1#:=V](WU!.IY9U3><YX>A6(5022%(STL2=H
-ME<N:AY4/OR!T579`BMAX>7O8I>>]-3]IYD+G09K,JZTEQ7MH-0\LPN<78SE=
-M8`J9)L3+N9G*--`:7,P.I:B-8PWMCDKZ4#)WE(FK5X<M,5L)6E'B>HG)HXH3
-MC+P<N4I.\UTMOD?0O3E&;^FL@NZ7+?B!;PD1#9?YWK1(!9AIK>-;OY=%M/?*
-M,4"ER?VIUVQ4)K)15@YW@FZUED\'7A6E/^#KOD7=>5O\R,1`],$4/[5=E82M
-M.C`^HB^S.@>;O>9R.(Z^SP#^,3]E,HJP_Z'<UTQ+#*W5^U]),BM"FB<GS:07
-M*"+7\KOOO!(3N#M+[CP(,>-S1%[!]Y=-SA]X+XB",?-3=*11<]:__<Z6&21M
-MTE9MC4[[HB>$UOUW9B(X*%^EO=4,[!3!&Y?(<GE?)K$DFU8TL3K<<'A?8GPJ
-M-0R_PV\N8\@,L#@ECZE?F;%M2HPJL_89P::)ZI?-&UAP!.BUCU1)UGAR_KPA
-MT%I/^'ZA>F>!5*KPY-LS"Q5MT[)FSCZ$XE0(WO6[FGR*MR0YW&C;T,H2K?X9
-M'J\!C[>,!,[S*:@B&VR;-7%`V7_8XQKJ93FG)]Z;ZG"RK&T,Q)_N==IB=>JI
-MRFWG'6_3-:N?O@`_D@*;\%1@5VAF\*,ZQWM*PQAZMCMB,?;,N@4UI#1'B$CW
-MT$ZPX8%"[=UE(:GL-$IRAA?&;A$3B_!E_R;)7U[K2TJ2#OAY).W4OP%HXHK[
-M1#!I*V:GL-2"DZSD-)P";+UW\P(@0B:DJ[#&D$@I,TNE`HL&Y"+*[O$OUY_K
-M=/8A6QIIZX^HKUBH7>]+".=`S'$(\7<P`[AN2[*[6V?:#';!8<&9])6-IO(W
-M4UL$U>2%34HGD[B4;5K3O(;!GO0E\8I-SNQ^F&FO@J0MT,FZ/;362U^"/0%Z
-MU>T#*:B5X]4<(A=%AT08%'H.P1[\T_QL@TUS9@^1EF;)Q)UFMMN?=B33S:-M
-MNU<DTU[^H;W("K3M.,.N2)C#UG+#6W(]0$-TS!OQ,.U/4"TPE5V;2@?.U4Q1
-M^Y@K.D[DT56<OZ\6+:HW4):A+M9(I)S^C_$#O>,AK>E;YJLSKV`)[S4TEZ36
-MR4A1U^\^:TP$*MW$)L<$\W>Q`?E),O3MZ76YY`T"K7V25@^"A>UQ"H\P[]VQ
-M'>UZ98I;]%/@F``WO`J`TMAC-]\5:ERE+LTLHM@U4S:;AKX,`;8O_OL52<1B
-M<8W`E;S65N'^BR\.O=\H8_/?!I)=>`_+$`TRCZ::#BD(<6B2>6F4IY&C[BJ:
-MZL$3J<3X'B]T#\[@'HH7H<@Q-ONM`1YVHRZ^HO0W_C.+LAD'E0C$XR>Q#I-<
-M9750\QN.,W3G-D12.[:8Z^A+>L1@B92.OD9VC_?0P:",[O2[^IO0&/G2ANRD
-MBG'M!2U<X/<8I)%!V><K[-LOL8;BY2&Y1+=?S;+'K576;P9GG@%.3E$GO4TS
-MT>F\<?P*MY>WH4.?PE*E4`+$S("Y4!M(O?JQLWE-N4==254UTWZWC_MS`*O%
-MD[)%P@`;B&=%4#6,R@%J\V5L_#@F3PNS"X%]D\$AJ%[5X\-6-G4>0EV80CXQ
-MK]=:+!IVEYC.YS#?Q>S2RO'*[?+/`MCPPU./FC8)X)JC>AT/FQBR7;,A='\V
-MVJ()]!"+:CV4!/$Y-K:P4*1"04[/SR(/RH>"F^YU2Z^:T1[9%]D%Z5<&8!P)
-MBI&<\=JF'YW\0)J"3I+UR.M%B-<EZN73QZK#N3AD&K`RN?)PF*1=0:U=F!,!
-M@<(&B7G+?RFX7?%/@6B0'](\X.26-YY:9^W.O)\=.ZNB,C5(M=<1[\M?36)T
-M]"<F=85,'@7^+E3F!@?:/R*/37T9"D%P:;H:=1?8>AK:\]^;-S#^!(WCOQ[\
-MQ/JWY`=_#F:U/8EO(LRBC],WZ*]GFPBS.,*NSAW2@L/2T(CWGZSQ84H5#=6Y
-MPCO'VHN+?=<(AU!@+J3L42<FY9Q!!KP[BY$GI3<CS5T0[O)5_L?Y(AGF''TM
-MF]H<4,F9KC6"KLVA:C:$RJ&3`#>(3<;D:'FI7PZ-($CZXK?(M2J;N=+(V]0B
-ME5=AB2VK/;B\.C/T]]"T#DPVR9[=Z[7/5#EYD#J<]<%O.:9OED.N&L?H9XP4
-METB`N4@CJRU2ZH]X[TG>R\SY<]M[L.R]O^UB.GZ&M\3TZ'E2(4-C1O:A*`,1
-M44C+G/?G8N8W!0F$$9_J,PW-R8UPM\N+STX1N`70A%6[%M:/N<QUQV%^`%2!
-M<M'ENZ*+:T]AFP+.>W#]/3.(I/`3WQFH`7B3=$R\T,9F1"M)8C5NJL-GOTTZ
-MHM+M5K][2B(-K]\IKF$VH/)&2*?I(H(E!/R6B(L_,J;2WV(D3;DTZX8R]\M"
-M2/M:8MJ"[-@;BR"HH;SDS&WJ7=A-VIS9=0/H1,]'QZWT!G/IPP?V>-B,2$KL
-M3)MR@K3;BET&'G)G9KC/595+GYN'Z;3JMPX-ZW<OCC6-LQUR[WX9LSW7^QSA
-MB!L)G7:^T9VEO6[WC]2ES*>FZG!`U_.^-25C8DE/\J7TR.+^VA,$:B"E][6S
-M,-KN);=USVNKCX^T\HWSYKR?6I3YC'^&,?#CL]M(+BQ%)>CR)E)X.IGS(K##
-M,,WC#8>,O*P-6Q3?UU^(22&>1MM.U$E10B22_1CW_4TT%YY#J0WI9^CBN_/"
-M:B*$R'OV:O@SC8E>@>`.8O9-ZF(_3:DK#@[ZPE2BC$A,PT@TX!_M(RN=!"I^
-MSN*U3_"L":<6G^XVX_J\&N.R"`%&JKF7]K$O)[3S6R_*,-I=MJ3[J:T\ZH-(
-M_MS.E-[A%I44U,%2T/1/L]T$HSAK>,`8M\&.,DS=%,LX$\1:G[I\+@^>62J!
-M'VTXDXE\R6^"SW7"312`J.6+_V[/SK#"6"-A<^\<RB]E(V6&?L`("HL1Y@:6
-M<:AO2JQZF15RV2OZ4IRDK<<-.W[%5`>)7@","G9(^!Z`A'QJF0]?YZ&J9<K5
-M6<[U(=Y=JQ=#7-K<^O-F/]BF\D[6?@"9&U!DV6:@X/1X4Q^N,&\PFO[K4JOZ
-M2QS)-;MB=.WZ85C_G"'<Q1D<KMEAH8OH.WPZARSV675A#@GB)(,#/1RKFT["
-MGHEL$KB\&VKWDSXDO2$B%+B&\J'8KI'7C\]&58D9534/$AS-8@/GA]N%KP>3
-MDP&#ML,HX/`#[_+W>_TF<V)J3VOY"@*Q`B-)!BW5/]E6:5_4P>$Z9P5G]$`/
-M+4#^#JM).YMA<:.*J'D$J?ONKF<DA"C!=^NCTIY@.+>??*<7L2QT!..'D1B&
-MI*LZ-@G_N;/@"RQ%198\^25R4\B-TE_Q5\U7`)YW%;_6]U-U)??57HP4WX&D
-M!O6=`!]?]FMKB3J5;9)TVG-).]TTR:<\7]?,<<EGP>3&S-/VWH^^;"`AZ`>?
-M4M\7!$?7GRKZO<[R0NB8:EX69@M&WXA8?E>)C!&M5.^!H<_L1V,JD91>"L7$
-M,I]5``LA0<!MA(>/T40IO9EAWII&4"ZM^>S\"V!>\EBL4\\DZK.?V7,9A$+5
-M6-?\0W@/UM!7`163NV[Y,QKS*/KO!('R9W)H[`A&)SHG_TM[&`A)6R\:Y>]=
-MB!25:/9M5.I2F[3738,_N3D_!Z#Y9?`J-#ZRO!0'43J*#3*FFA>OZPD!WL[?
-M\#?3G[`*/0`^52;!J":^],.$_..5MBEA.P/(`]$=F[-N-D10<B.$I;79JG%2
-M.RQP6)07FM=KCJ#3#T1O,YVP'.?.2F!*K:=:=:)!C?`7X)@%JK$:^<4AGPQ2
-MG.TL4F,9&7R7^<J>I@"_?""V2M0?E6K$)'V`[8"L4_^[;0O=S?*R"%5;-+%%
-MQ5E^UWM`N:-(B\*L\=#Q_T@4_[Y1&Q.7I^FY*!(4M*6A%U57$8DPM$>'Y)=^
-M.?<^1"\$&!&JM^4&KC7""5+1J&V5O*\<F#&,&DXH*[N<]$1O!1F$80[7G8@M
-M"'(UE]G6O^A$1@4<<@FL[[GC=6(</(V>TQRH/_%J.9?@)?S+)1*W9INP5R>V
-MX\:/!V811YV@ZI&T<";%U;#;/4%G!5%F4;$M^'^.-J8!SR;!/9WM%NT[A"18
-M6`/\X((+B2`6S.*E![/4&MPN:#9I[DG#(Q^D0%Z;YLQA1`6C-VY[-YS:I>/K
-M+0\*QIPWBVQG"K?D^J]^-\"([N5.$OS?I6I$WFL0_P^#J^<K4M@'CEQ/(BFR
-MK=X;X%8/QV_-J_>.'=E!3H:UBB-K;GP3&B8MFR]5<J8M5.,BBH;WIM]R#63\
-M`,WZ46PN-%FB+3%4QI1]WSDR"FCH<X,_+E<_>N*Q_H!6ZU(7@8:>Y!D`VWQ_
-M<&7@@)3DKDBAAM3]1)FJ\Y!Y;@#3]Q5N]+#WUDS7K9YCR)R"(X7<?QTVYXC8
-M(R-2JDD!%9-,`XK%68:!H-A8L8=%%AP\%AAOK?4ZH#KIIRY$B&L47#YC(K.+
-MZKP<'0#%+]JUQ]7&ZGEYA)S5SZ--SB&HW_E+"`_[72?0H<=,X=S\<*KGH3,J
-MK0I$U^]PDY8,`[G)C@,P?L%2]6+6%!+Q)7?CIW?K2.\#.4V+KF9\F0YVL4B#
-M.:(1-1CF0,X:=UP52N[.>@8!M6G$\K<>L+R]-IIUC&/J5=4F#YJG@<E[5)+]
-MG+@#\<+2L0B5!F%5WBH;M$-7'TBV@**)A69I*^!UEF+$+/:S_I>EF\=,;;X`
-M-3;%-8;PD:*T83G;2;DAP2S.8X9815&@R_`B<&=Y/G)T[-%RKL.JY&\/6V_N
-MN&D7%B2S,7!,3W?-5DIT"`$<$V.4!;+3MDIK!NXF:':@:XHK]@!-0PLGUA=5
-M/6UV1@6F@>!>^O[^,,.,-(Z][-XSU,M_JMJ($FL!8WJ3@DQ=YR.->CTJP7`2
-M\^G`32I:8AO(?S7IO&8='X!IH/_7;!V%YPA452Q_LJ=AC?,?-,\?%\<`'&[Z
-M5<X>?'E8=O&Q?B1TM0CYR.\+24$SX=%%-X!.C9)/N?W54ELW&UO96.EX-Y0[
-MI\46:ZQWV9B%PCM^OG:KL0J@RN57,.[+^LD<>T/NME.H[:$_>A<L1P#?;*X_
-MW3&YY3Q[R4;*$F$-Z6+P+4Q"=`>=?S?:!",QYV+.KG?U].40BE\\Y4RE;3*/
-M#N/ZFU,'):10@3C\65\?IQU12CI\@N2+;DV@R"*3<'--7B\R3[EX9IT31Q3R
-M:70RL/N<O7*R?`U9V\RNVP=D(27H8+FF1K0O=3MR!.M@X#0>DK"&RNMAXV("
-MZ<-Z@F<0(E%@[IE/6#*X>C[P-IE#QONK>M*"&7Z3J'E9O=K^BW<M</M]1R=.
-M-L1>C!>K7#,.D#5D5Y"95I`D-I:1(NC6L2*E(5DN_R_MS/0U9&QPWFG)G`#P
-M:T]5IS5RB.+\IAYS0XX&P5B3*452W)K21`10(J(]3P.MON5-1B#JZ"*#>L?`
-M'WH9E%*I7#H,[4*W9,,'W6T*[+NEBN`!!&T`Q.&3^H:1]HL[F%.DGH>[T>'/
-M:QV->LMHX>;U.CDN1U8I&>HYZAIV<>3\*'@0D:G96FP$4GJ8O'*]AA-N'##W
-M+8Q`9E<NP'#]#ZX&TO;KPW*C<0[>DFL/O<6L=Y(UOY0PZSI]A@104,Y]#;?"
-M$NMLAOF33.K6M'H=;=3QL"!+?NS9G/G5O/F7?$B$.++O&O)LEU/>QS[*ZD':
-ME*$KFX-=2].4J*J)FU3@$'W>%]4PQ_:B_2#:%[%KP=&G43BYX_NZ;'<K,&L9
-MAW-@PZETR51,WAMRU6J05)N&(58]_)K(`UG8R1I-K#T%XVE+R0W-N90YX.Q`
-MX[^-`8@=9$,;O*,"QM<1E;)(?[IEW7*[(`<-=1FT2&&5W61#NASD$13.X+%3
-MNH!>E1BG/`6KW;_9E/CT>;8%N/5HYS]I(+B63C/Z$.#\#6\>:]F$VS1.;;B.
-M!6B5Z,Z*?0MO3[-?''WY.Q7J645#D!O>_^\/B$E3+TFF%;V"=)!>-;Y<^:J+
-MUB&^B5.K2P!*Y&WQRG$,3T5T(_O:[MKOV&_K@W(?.GPE?E3S;8;5J/$+_)6\
-M8^P=L>YEO@Q@GJ],EPR.._N?;7?T+Y<OQ_I'5[>R35#K2U/OJ.@G!2O%N#E[
-M-CQN8[?I"C(O[B<W+5S4[5IFO,XG>R0W,;F-#8"V`1C!0I<G+TH6D\43I+;I
-MSD%M#=+P]JKB(3>**#YQG?!S96K?8&;VW79E&UVSDO3UJC8H[,K_J:0G<9BN
-MGR+SN<+>D-O-/V(,-2Q&>5;0OIA("W!W6/*3*#CV')^?A\-!-*#B+^QC!T<H
-MXK]MJ5?=OH_.(@`/=*FJ'$A'+QAMX.?5@%E,12ZUTP:T4S33EBU4%B9>32^%
-M-^^AQH'D@6>QWM6Z)\!7%?FFG<O)F#^\1D[0A$DUC9=,OEZ^<:G2K%<&D+?M
-MMEWZ\MK4;RREHIQRY>&BVQH8'>QBGIW0TI`#$*(!KE?R%G^S#Z'G6,T/8`U6
-M^ZGLWG4<]5DIUM6D4^3R.OI<L=LCQ7TNFP-+_$X_,[8$)+A:E-W\]<-17R.Y
-M61'8;]7(T`T"T3O%>OOT,)(=(C?IE_B5`-4CP4(S0.#ZU,$EW`QIG%%N[16@
-MC2D^W'5ZO7ZLGST37!A#A29!]1/_WS^M2%AN.T*^)8Z)VY&%$A1MVF)@OS;5
-M?$8A%94<?4,W/PT%HBA\!!==US=9>QP07U%8?E^`BK6!LT&61R]NF5A2,4Q<
-MJD4>H&3PH*J[;<&WA(6EWA!,Q#`8CY["\D9F`XUQ&,D$M,1/M$]K:'G:4S@7
-MI7QT.'I.D;F(&&],_')#C7-.`5FU4P9&]"V!BMG_&,7DT5:MKDJ9L#]Y]L#.
-MNPQ]7Y5#FS+6#[+K:3M)_B#A#?7+VY`VEXWWR%&>8=Y-(?MXK1-KU6*&U?J^
-M?!>L&E<.4)9=VZ/Q_6NY4S;70979!+[@C(H9QYH""ZO,#GP+LD-PP'3*>K;%
-MD&4_G+-IV78$1TW&Y#1R1ROEM,-4#ZQ8T>\-,H;=P1(#V>*5;@&9D[)(4?V/
-ME02\2T"0@[B]*?\PTK'M)"#OE4L.1\];@5YZ?'G44N4,7;]E.(H`)8\C\&Q_
-MKOUCT!Y?-K-&>`RGU4Y&%>`I%DC"<4#05E-+^^Q>/5HMH4LAX])^M8\P"#[R
-MN!.5"*&K48=DNF,2@34*FN1(IEP#W:(8S3#*E%.WTAUP/H!A`'X`]BUHA,!%
-M<+O"05/'@DY.!Q6#[UTF2OE`$0*^A%(0!]\AU<3]->?(_]M&XUY<T9T_5,I;
-MC,F7'IDADYIN)??P`AK4+9_-0*Y`@.DC>3/-D3N%'3@$B-B$[888)CO%PC=?
-M<+D5_U57<_[,$H/<KGVEBQ`6160!G2(BH.D^BGDQAT<<G9AU?_J7.%3L>(ZP
-MM`.V(J6*C*!Z(B`;("FF$EF)1TE;\@](SP)[0JW>8KG;X5<N^[G5>1X0];$G
-METI8+;!U0J(PV.,6'L>W-V%SWNQS/\M:X3/PO?A>L\CZ'K'N_*\M>==RG_GU
-MH.:;R:2[O-'+AAG@KD[&PX2!^&R,KJ:_!=+,NDK*-]-;>?!>7=OE$1DX+K59
-M\1O`M2JHR]@9(&%LO@R"A[$OSI0JP5V`40HW(]B*K]&,>7J2>4U7GP=[]PN<
-M]'P^T9O^;FP"$8Z6E8?J;O7&3N3!BESQ1X$8=BM\I",#7):`?=-G+4DMKJ!K
-M@F9QEOS5+DU71EX9%2D@TW#0T7>LL9B)=B+D7/%3@IL]+!]?JK$T567P=,.$
-M\03QC'2).RUWEUU6.G@X;CNL]ZKNL-NN@;-50Y,MBMWO7T65R3B=H-U+5`CU
-ML[EY0!Z<N'(<<,LOH?[#`8R4#"J2D^N$`NO5,(V-J.[47,OHX-"PNH^\UXJ1
-MKI=K.L4YW4[8O4'>7-'4H72'ZUVO03[@L;]5'D7G>/U1VQ5:W%6,12_JL-5)
-M_AC'PUF7=6Z+<QKZMK;3=(A_6L^(YP6[6^>X/@E]UM9'@U.\E`^C'U0(@2K-
-M_N%M7H[D7Y1342`9>=%'HY"#&1NFVE6/+V'O\3<4R5E\I5KP)Z_B?"-SWV\Z
-M-`K0*4#`<)"F"WG9^7GH1G7P:NDU/FJW+-7EOU0@F!6"8\`!Y>62JE%:SB#3
-M4=L.@4XN+;BFZG\)^[Y?P7U%/!7J*]L:@Y-<S9H9U[\PN['G6(R9=U&V\]LH
-MPDA`^%Z+S8:7J"YS;HU$J?G!>IHF]J(JQU*A""7L53#3`>(Y*D6T*JB1G[XL
-M'@%FDI:6`(DTU,LXI1^Y`56F%/%O';682K;=6K,=_)#];ASLVDV>6%/KD[1A
-MBS('5AOW8!TP`<YG'#RO$42R,)4#(WMSA*E97?/[UAZK!O=T_.J@=U+'=>^L
-MB<-&$6_CQC;BVPV5+/XYJ2I#5M["5[ZS*SH3`7)?OWAZG25?C)N,/DFDS'(X
-M3.Y=\^JV4IUM%>J*8#ADHM^*<C`/L2B8FQ5L-(O5ZG?'C!(_)`9>5TZ(PV!J
-M&VIDPY2Z[)*3NOX._P_/@1-AGT'[1>W(X+-"D*1B+`XRQ(82P7B6CE_33T?P
-M*0@:(THTL3_;5>$@UDA)<V^GTA7#L-WNHXYYW_'L=!E,S#];S>G#4^KE\"/E
-MXJAY>V#1WIY"#^1-+0D.+4(T$)(XYP0?&\7N#F[!KK7X`>PU5Y:YG>)\[XG4
-M"N#K;PEB@FH>CW`J+3VV'_.YPJUM=(;PR?T6W7Z;`C<GG(2E@4'8G._Z#T`_
-M)J7YK%O>+>7#^T="5,T"42%@'GQ3R[&D)15$`5DBO4X;P-1UM"\E%]=4@^9%
-M(GPRGW"+/X%UC"SK+[>T]Y2DPB*1;W!\9O;B32T.^.>!N-TDN*N!1MI\:N7P
-M<K*9<Y]=L6O?X62PI/GA]J+4R\L173,6QP1Z8ETOK-B@A>&6X#W7\M,MU]2)
-MLC=RZ"G)=DF<:JBFF2U]!_DB^QT@8)`KS>2P7"4Z,$G$<G+D)"_QC*U^W*,I
-MW@23@2QJ*RR@>+'F<F/,K,A&+?]68EG>YQ[U-!)P/C0`A0NG[2D^T6+H3X74
-MIX-"J\'653J/#)`I]$5C^M00M[9^L/=5+/O>T6,];.!%+#+T9%HDP%)^#TFC
-M_Y>UZK#-]_.`X8+1#>8J'JULUE0"R7D>SH-F.`6L+FLFGFDIZJO_:_92HI:`
-M[V3?"=0.5+>J;J&;8C:]/WAVOHC\XBS7YS%)E@I22V2:NKPF;WA]M,=95EZ)
-M&S-2KP8/B[0CZO9<:C$N]*AC;B95.0[TA,)`_ROE)$3-/P-!_\3'G,M=(++K
-M'=U#:.A.#1OBAO%BRK3DO+V<U"PF#9P6#'3,2HD[@PFI&</?BEJ%H#9D/%ES
-M$Y`[+6M1EJ[784NG7M\*'LN5;(4Y>LC!I\N\XC;NQ"H_-,^HJ6]1'8#_N_L.
-MK&N"J2J[NRTXH[XU66V1^)=BT_ODUD38[-C#'DZ*&B9>&+WM?4(*&A'#13C?
-MN4N^3N)0AN52(:%FJL4#+NH%!=[%XCU6.-\+^:I_!E-!KCV7,Y#CKM<*3$KY
-M-^YNH,K74'^<K\:><=J<+-.K"DMWQAY3`BG65W0TI?FB4C"B#;N=H5K!^.B@
-MI\!NM^R7.0(3@_VW<J0CG%H'!0AQ'L#60;<5N0K@[4*BTF+TKN(W\B'BQGG4
-M'DBF<19`$75U2^=W^CE..V_11$E86-^6V:H.ZVJ-Z)/:8X7@9TFYRN]?E!N$
-M:"8^8]]+#]*(6E<7T)$V.#/G:"/QYZK$@$4\`#94G/9?WD@LV:@BW<LMTYM'
-M08>WX78[+?RL_;NN@,E?]"``;+/-=ZA.WM4+J#X7$?3FR.+):$WZHS\_VF70
-MI_4@_P43CV%V'9Z.L%E_RG_:I"ZB(NYAEJ"Q!$5\H`_RDVT3BD,9VN>RL4>9
-M@T-:"?]!D0`SWVE?L!E1WUP(/SON(IILHQ7-C3$?@<!:"ZH#=Q(YMPMZ;,_R
-M[5L%&U(1T0ZU7:YS8[D:Z`Q3`C=AK"'?;/YSMZJNNZLG%*[\F!<+E4U433VF
-MWCQ3IV(""1&_)5&IFX'K85&-B9G=W2D$/\H^5[DSAQ>H-6&J45-6D6Y[3,[G
-M-LM-I!T36W]"!PSC`J(4&---W*RMM>+VC7U>W?=XUQ=7GF0;OPP&>>V+8UIX
-M6>=/&J84@KT#,NBIGR,?;0P_W(PJ_.LI6"Y\S^@/RMA]NEN"0B+^E[Z679=G
-ME$D]\<,ITD[WQ(I%3XQ]/%'+0U*4'-O>*5BXE:DX0<]E=+DO&,[]%VM`D;%C
-M:9B`ZTTFNKSME,K*#+$%8%W:A*F]P6@*^A3Z>Y<D2&^QR9]%T1_M)&<!VBWB
-MTYA'Q'A/D]L=LE%_0X0[-Q@0?]_(@PF;^-`VIVI/@#>,::YU?:->H%L+LR>(
-M3743+1"?98<,Z71Y=87$3KHF.,-\,815Y*:F2`+YR^R7YW9/#4+`R%?7Q+]@
-M&%R6(%S<\PL:2XN2#V_=G<"%D"BJCK3H.42M=M=+R$L^I7_UT*ZNYN1(8"&T
-MM@V[7F[65C0`RPGV!03$W>-II057<]_6IH>T#XEA/"[LP)RM@O1#/"O$2N-!
-M4\VS.&'M_7X:+L)6,;RC9U8%'>0QC_Y<QCH1A-D*0E*&##C?+Y2#HQ%PV.N?
-M)<ZYRC[K&K)$3B74(<MT)B2V2+",U\YO#X-H(M$7.4H)QUPI9L+^8.QNQ34<
-M9DWUR2^)8102C]F.+`RQRPH9/%2"&QDXE&49KN5-$9_"MYG*C_D=$Z+#0O9:
-M@V5\V.3X:R\[@2VC4K"J@E'[S.?ZC4UF!=ZKJ>N$1B'#3$6P`$&MRM:]%B0P
-MI4)9X1MC=_L1#T>XA/L6MWD^<U),3'<-5NNX2JY&*[A5$>.]DJ*OBU<!RYP*
-M7IA\&64FXV\^.($V;MZU*.;:7XS7"0@7(*I%>3]]OH/1CLRFO(TVCGUE`K17
-MA;[=OKO!I9?"=3>&D!`:@:!])5C?"%/VEYEC'A9VR*F`K2<GLS+"1)[[=X_D
-M;+>&3O;=J%%'?FU*6>:NJEW)4U*`(G7UI5/(B;:G*3.S(;__>_M'EVW=)P\6
-MN<..Z?.^\]WEIM1G="0WP3B$JY8R>3!L1M;<II@2BW5,G5]U$W@Z\%MOHP(9
-M;?I'#4Y5AFV3)#KJXA,8WN0B\%^/"$#%.^[I<&?>U\[""R!B35K!GX:'V)LY
-MNX"?O0KL"6^2^8!:E9O4;0#'0<.,B5RJ,$LP)T<C$*.=5&IWN?]EX$/Q[U?_
-MMG6N*Z7W(VW:R\UTT6@@%P;?*C1#2'^6RR%H12:R&Q"G>'>&B\MKYS)<73/V
-M7`-&,;(=$JIUD-A"[UBOY0'T\8JQH8;I*/%/9\_#NF=YB;CY(XZ>?++EU"B'
-M/NMO0NWU@D=QGF6XHU8C%VD&5H%6VBP?Y[D1'&BHS1R$B?/R@.LH4!%#:]:4
-M.B+RUT,8`S7XXDV:_1F/DP?\Q)LX#/]$*JHR(>F]0WE3*'/\?Q96S\9T!(Y1
-MG!5KNIJDM0_2O\E%`OF7_D&Z',`P$Z)\7Y+\\F/I/.ZUG)I0![2^1+H9[\7P
-M5+W5-$(.C-B%SQ6:Y$X9']3]Y?X?L(3G;<^@?*;FT,UX-ELEKH-*=Y)!:RXS
-MM@'6HOD@_>\URN?MV@*L0=4W!`I5@-1/0E?21%U`SI#>U!\;:0C,VC\R8Y^V
-M&*/Q7'7%S2+RO@$3X/=)*P7Y`L`]Y3D513V#:^#7\O^'$NA[_>0-I//L)3],
-M?6&?A*=\/,Q*)N(&=Q4`*MP8H66'`)(X*D"S/<4@BX$;_<GD#<C_M,I\H%Q>
-M$QR?5PF'TTLN>3>`P(Q)J%+TPW'N$2M.Z1E.*N5Z@B1V6]'YQ$]Q79F-"G9O
-M\K77QQ+$\)]T]9.7B/V:P=>(_CG`)9!=SAR"N5A2^[>1Y(512+%?K*]`^Y03
-M(G5+/@Z(?G-Z6D.EC;4]C]+`:."U8TVK8V-=?>+Y+\2I4-ZU9[`&KW+.#VRA
-MW'9`U/+`WY'X&[ZIVZ3;@1'D@*MQ=AVZM245'SFG(GLT(`T6\Z(%FT^/LA1(
-ML%JC%9(MC6.XC)NK;3[)_:78+YD)-<2T<JQJ%D%XZM>8Y+#8K8+L[YKLW.;L
-M#\_>0>47TBG>1W#U>6*=9-+>*XJ(@1:N3[[!AD45M,TCVF:/%)!,&S'T^C/I
-MZ<KFLW-;:CQ\:-'1+"[>3]=0?6.%D5<,77M[+K&W;"46[#;=W%*A-`EH9AS!
-MT-1XQ.)R5).>FW>0*V'>.;5*H`BPS?1@QIC-^1'*^6N`<PA%>=G.T6[9-?PR
-M*10DFZ5Z`XC!6L9K'6810=RISK9NG1,VTT@.L!\&"JJ8NB]NK5^^I_3KI8M^
-M]D%7=[_X+F%.<9][Y%/^[-I50_L3-QEE`P9HMQ5'3-I2&64.Y!,;;VZ9&UI8
-M*K((WW)QK:7]M7G!R\6'X7>\8AMG)%<!=,OZTWA=69!M_KRMW=4A?Y&%.\6D
-M>D078"1C6(%C\N)_B^)L(Q&BD+X-BM9Q9V9?<:+$M"(>,,\P]$!#11>G6ZJ0
-MG7%>I_"1`N_J3+Y8Y][(>$GMY=4M>)P:0A]!W/ZBKJ?P&?@<-">3S,]R_^4L
-MTQ+A4H8BHQ[+,HP!Y#<HB+FM&]LDR-B+Q:>#)%=NN&Q^6_)S^5^0$<L,70P^
-MN'`60BTMI[1!3&M]^#A?,/W_H!E70)#[I`$%ON8@+X$P_*"ON!4.TIK'KKXQ
-M&RX6U<FC\A3*`2;?:.GS4\@REI&:CY?FTLU,`WY'M>X1>+T*SO$]Y$09--E6
-MWY9\Q=31^A`J6;Q\!['XR01MPTF(LKDM!D49'NQ).D=ZS/TVJ84$Q(K6=?DR
-MAF.L0)GR*82(9NC.N!&;7S5QD>%,6ZA+R,)P8<\7XGV?[>UN98#QOQM&'40_
-MJ!&Z5ETFM:LEUWR&@S^;B>/L.7-DE(Z>\B[S2D.BJ/'QIJ4G,#5P0%G>:97L
-M9."_:KH87F_!"<Z*T8<NZCG`L*\=10`Q&C`!E8]L@T!$AVZ$0;>?MC3:RW,N
-M?O'1TE\8.W6.DAV4?'\.OGI@7];/H\3:@`-\OX_M474]*?U.T+>#H$6DV4V?
-MXO]",$7+'`V%H0:V;DA#<M$"'7/DL.*-^1?1':#R\:WWOU^$]HK?CZ$&;28%
-MF/`0!G]87L;L",\,9\C$YC#OK=,]T/GL_#]TBUAZ/:29SY"WN3V9HI5)*Y3V
-MQ3'^H@*>V;E9I$T"CA&F$1YFV>234);XZOG>*<`.6QX[QR6O2Y4Y"=G_W7:1
-M0]-H$/[C&KK8%T2?=V55]_=!,S+17/0)L%!?[.TFG/1([EMU=;T=:MP[SO`9
-M.D0^]Y?S0>QF!>B@X^@GK,>0!Q$H50"G"H6O*FIP>%=E$U,#JPWK78AX-238
-MBW]V)3)B9[(Z3-^U55Y$,Y??5MBKL/5O]U2@QW>X""RA?843K:!Q(!&-XB[R
-MSZ*Y.8VBDP-%VZN]4,$O+@^1J'S1P'%TY5K^#\RQ%+`9,WVQFB/^O<B4D[]`
-M5>Q>&9<_\YID51L)8R@TQ@-2G]<PZ3P]'1>94[Y#QR``(B(``B(B(`B48CWT
-M#:9+`.KIL\&<+Z#?_KT56D^=!)6:W\?`5>"9Q3M^O=Y+B0\A4NW&$US#F@OX
-M?BW*3PIQ0WSUGU[HB?$6=J:C1ROH'FL7M6JB[6?N:;O1]63P]FC]DM<7'K,L
-MW#*%*PF/T"W.K9`0_E($^CS$`^1E2Z,U$81U8'#01]E^KBBL?ZKV8<7.X[]/
-M]!8<5Y0-+@'L\$$KC"J<;V_9@\9",AW,%M5O+3(<Z2A-@$Z6#;!-3%%SB:Q,
-M_.58QW]72#"I0P_^4?UN,ZBMVW(U[G$79U>TS68>R14:$9!F),WC"VA`G;+I
-MA:_NS*TQ:@V'(.X.*Z053HI;K\8GH%/QD?BEH*F^Y*BV.#/3]Q2MH<8HTZI*
-M%J5WL\3YB+=!E2H5"=XXLVT=%-"N%7CNQ]6NK9[[/%^E1JVTUJBDI;U^[I2S
-MZMH?HE\7+,=L6F-@,QZ[Z"%;N_0`=4N+KW0TR^;2S`DX8G$`,=#-"W26`CBJ
-M]*WBXFL[^;OH0GR*@<W$T=-KE9H.1KR$8N^BJ^5KZ=JF?H!K([7I&8=L]9ST
-M8F24X"G=3Z,=+]-%4(9U>.SOEZ_^&I[?LB4-G(ZW;LS<U/;@C[8.5^O$X!?_
-M%49<LS0;JQ3&X\(H'X*[0?A6`\@GPW%&'#Y4/A1X;`7UM7LJ-[KEAC1,)T7X
-MWSUIX[(I\2]C+QVR:D\=59H/=XWNE/L/&:&0O<Z@_Q;4WI0+R*AS2(Z,=AJP
-M@^JJE'V$KX2(TR`11_L38][YVP]-J+C"M-<3>Q`(<*862`6E<LI-X.BZ-\)=
-M%B_;U+3E-IOA2J/"B&+C;"4]3WTZ%ZO?0Q!9W9/9@ZNPC`S<S3'6`1@OT<QW
-MFA#C>Z*#NUL`R3716+IKE>45,`!DV96SH0J=W#6>5)U@M>AX*0!U2[.N0NW$
-M*0#=@LPHJO2V#G%2VBGIVK?`"7<E&&@0IS33&`8:/19CE]9$;4!^>>%,:$)F
-M*1\>BPP!:5_*4[FBZ(<O[J$F/ZS><W0HJ4TCU.IUC,_!4D%)M_0ZJR(1IKZ'
-ME2JJ=/L@."]HE&_1)^!G0C34=(0['`>,#2H(O-&;)]_(U+"!-)<Z-U`%`,O*
-ML-.]4_PO[R]F\#;I1*2"7_IK'XW:C!R5$IG?CB&+A]2%^T5C$:4#3I<O^0V8
-M&=$!JLOFP&`29]U,J#IMN]N]2F\C)HA--%Q[()];IBD*.$'DEK?][W3QDY^J
-MX[Y&G^V=;<'A3&+L=+0$X,SATI`XP0KS]<RBX6*X(Q?^P56HQ\G;QVM<B$3G
-MP+TB%]T=<\N03SIDZ&`LVS!&$P:=/9Z=7+J&00+:&5>%1R%V1)FA0H2G7R[*
-MM^&^WZQP&PUY+00*`A>39^'))`5<0>2:PAE+R[,A'#O5-SY0@:;8#]$6LP)*
-MR7[>Z\=<FY2(/$3_M0+FP!13$-T/!_%'7#E/*)@RNQ8=A=[/;XDV;AV26A(8
-MB#%,Z#6'"^T^0MBA)'R9.^'?V#KTA19($>%LR7KZ-*T@:WVFM&KQJ-P:>$NS
-M$EO%'."?.,_ENBAV:%ZYJRM`OWU[)">!(AB3<E+>&>/JX[1+@&^3410##33;
-M-Y`FMV?X?REOA6H*0I+@,K54R&@R,[NHCB7<-3OH&QB_F,;KU7_T%7SC@S>^
-MN07.>B@B%[*\T!$B.?*FR%K/TH9@S2^&!'+OBEB5^[17P1<YL=[;4:?VA8CS
-MAQ=#D`NRBL@\]K>@P-NK&RB0PUIT)OE%H0!=.Z-?ZJ2/,J>FK7Z#HK5J&5R'
-M?&M%W;=S%8XM273[BT>&;X)U%A5YI=R+OS5IY=9+2O8"A,F]70:F$EP[B@I`
-M=_U`,<W$2RZ8&!U:%>"L=?:-`J+6DC)O3PH%%[Y^:KAE'5^^*DT-Y9/-K,:N
-M`V=:B[PY;/'WIX%<PPE5D=$U*:,R&#S=Q,I9GF'1L&D8W)*:^Q<47!XW>=\D
-MTZ1/Y3G?A:_\NN6/OR7V1Q9Q3KF.>""FU"P'8<;6S9,NWD)C59=J_XW;A9KF
-M99IP,F!<Q!A7\KI#U`M^]#(<05M%AM:'J<09`-<:$K;$"DU=SF/H[$PE/'-W
-MZ';2K*\97,$(M&/<J76*POK7[75!Z!S,/?QDGXEFU2-1T7CV?(*#0P3TPX_Q
-M]8PH0FA_8D67T&0U`4K#<2=LUPA7I>2>5;T*]W$"8ENZ^A$8+2[Y[L"@4F0_
-M"<^,C]]&\!7V5)=^>&S5__X<=S/H`"`$:*'+(K).WAZKWC4%*W]O+G"3%ESI
-M).7VFUQDMR*2GRH#VN:M3XL]]H3#BG,7ZUNI9(8JA&NY4\>(>F;]KSJ\529X
-MY_0K;8)/(GT0!,B%&7=',L#%$T;]G363YNE31U#7S\'V7^A%E*@%Z-.+9XTO
-MO`IK'Z`@.*_R7R7DY?7\5GA4ZY8&//YA7(B*XSL=T]MD]B@@E'>;S?@N3M3>
-M*A]XGP\+-%`92I(BUR>?"6\)6U[4?)1DNH\R+#BG4;L?-D2)P4W'/'W)2$C7
-M5>H9EOG13%VST,<QSE1,#8\Y,>,K/G`UPP)B6LYU\M+6\.PL<;+_Y"88^'FX
-M5R?XZ,X@@*7Q3B(.IGC=MV7YG+1>=<O-IC+X.,-P\?YL)SQ_0@4UG>1)I'$.
-MZA]R@5KY=YFN&Q(N7["&>C-=+DOI:9/,_L#NU240B+_HI4&$N2\!J"M4?JJ(
-MNHI:67WD&7K*=UY]R;%(BEN!8NU/X'6IA,*Y7'GC;<'--G;K5#%_TEV7;]:)
-M7''T7D1<11W@YOVYRE!8LV`0\?R9VAXKF!<22L@EP)H*K_@!X>M9S]V??C%U
-M(X<F#+:V/^'PB,YLE_[XSX'RE"])I[28P]L\YLM>"JY5[4#-54QK^T1@L)%B
-MQ+L$S%1\&"-#DE2N!.K#;9"?-4GSA'7`0THA/YM;/`PZ9&+@(-&9K#7Q12!F
-MZOQ-M<QM,`U<DNEH8_PD[$J6IUP4RDGIM/)E?+9D?+'?8LR4-ZZ5SNT%+@6,
-MV_`^;NF(3Z#"K-0!*>=_0G'IG=#35>+J2XE0$#2Z^.P?_*!%_<&U8$_V/RZM
-M\F`!ZACID'V(;F%1PZ'3+VF,R))&D+[+EFWI#>H>W<#)E/*V)+@J&;_:*!34
-M[@=G&[?#@_H6(N4R'5)4]3>A'Q^&772N3.=ZOVP(=)AC`'&=[R#(_&3D8?_)
-MO<FK3+4ZB<$!XU=]KM5R!"9-MOZOF&7&.;Z0L33.T-0_E%H>Z9R+$T>O(VC>
-M>N!JA@!88!.+,J_<_!;J$X<0Z8])HC3?9MK63CEZ=+OK5-T-&+*:#=#4.ZU1
-MUQ/4*RNCZABL^@?32Q$^W$M[.OKD4FG@S>Y]Z_D[$>74B*!X]4COZ%R5E6U<
-M*+A8^M+K@3-!^E`QA-B\=ZKD")GI\LI)>C^#]R>@?$X8F^.IIL%K8Z@"$E=!
-MA-1#L'H[N`N"Q4JD2E_C2\6Z.;S,!.Y?.8<>VH63RN1,%'S8VIS7R3-"WS72
-M(M^"`@"+-X<PC'JISJ3`KCQ0OZT9"^<UL*>MWJ,H/#DF?V*BVNLA@2(NG6_W
-MLX^4@^-QY*>%N6/IW`&%J<E/XO#.<MUVH6/EDS;$9,LPE/N-*.^K4E(L/*\S
-M%"0[-H1<[L;&$-SO4R2@E]!$E&W@E0<,]PJ/U\L&+OFL;2"&7T-JF1F$$3\P
-M-INM#<G"95%YA\^85H<L-&1'L=TA6`3)PV%4]=KAMCC9X"6^QN4\AH"W(I:1
-M17"WFS6ZXN902EUKB+0`DA^?`R'5Z%G80KKPP>^YS"7K^];J4)P7XPW'HNGP
--^K_XNY(IPH2"!#,T>```
-`
-end
diff --git a/sbin/gbde/template.txt b/sbin/gbde/template.txt
deleted file mode 100644
index 3d22007befd9..000000000000
--- a/sbin/gbde/template.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-# $FreeBSD$
-#
-# Sector size is the smallest unit of data which can be read or written.
-# Making it too small decreases performance and decreases available space.
-# Making it too large may prevent filesystems from working. 512 is the
-# minimum and always safe. For UFS, use the fragment size
-#
-sector_size = 512
-
-#
-# Start and end of the encrypted section of the partition. Specify in
-# sector numbers. If none specified, "all" will be assumed, to the
-# extent the value of this can be established.
-#
-#first_sector = 0
-#last_sector = 2879
-#total_sectors = 2880
-
-#
-# An encrypted partition can have more than one key. It may be a good idea
-# to make at least two keys, and save one of them for "just in case" use.
-# The minimum is obviously one and the maximum is 4.
-#
-number_of_keys = 4
-
-#
-# Flushing the partition with random bytes prevents a brute-force attack
-# from skipping sectors which obviously contains un-encrypted data.
-# NB: This variable is boolean, if it is present it means "yes" even if
-# you set it to the value "no"
-#
-#random_flush =
diff --git a/sbin/gbde/test.sh b/sbin/gbde/test.sh
deleted file mode 100644
index 0aeb05c907c8..000000000000
--- a/sbin/gbde/test.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-set -e
-
-MD=99
-mdconfig -d -u $MD > /dev/null 2>&1 || true
-
-mdconfig -a -t malloc -s 1m -u $MD
-
-D=/dev/md$MD
-
-./gbde init $D -P foo -L /tmp/_l1
-./gbde setkey $D -p foo -l /tmp/_l1 -P bar -L /tmp/_l1
-./gbde setkey $D -p bar -l /tmp/_l1 -P foo -L /tmp/_l1
-
-./gbde setkey $D -p foo -l /tmp/_l1 -n 2 -P foo2 -L /tmp/_l2
-./gbde setkey $D -p foo2 -l /tmp/_l2 -n 3 -P foo3 -L /tmp/_l3
-./gbde setkey $D -p foo3 -l /tmp/_l3 -n 4 -P foo4 -L /tmp/_l4
-./gbde setkey $D -p foo4 -l /tmp/_l4 -n 1 -P foo1 -L /tmp/_l1
-
-./gbde nuke $D -p foo1 -l /tmp/_l1 -n 4
-if ./gbde nuke $D -p foo4 -l /tmp/_l4 -n 3 ; then false ; fi
-./gbde destroy $D -p foo2 -l /tmp/_l2
-if ./gbde destroy $D -p foo2 -l /tmp/_l2 ; then false ; fi
-
-./gbde nuke $D -p foo1 -l /tmp/_l1 -n -1
-if ./gbde nuke $D -p foo1 -l /tmp/_l1 -n -1 ; then false ; fi
-if ./gbde nuke $D -p foo2 -l /tmp/_l2 -n -1 ; then false ; fi
-if ./gbde nuke $D -p foo3 -l /tmp/_l3 -n -1 ; then false ; fi
-if ./gbde nuke $D -p foo4 -l /tmp/_l4 -n -1 ; then false ; fi
-
-rm -f /tmp/_l1 /tmp/_l2 /tmp/_l3 /tmp/_l4
-
-./gbde init $D -P foo
-./gbde setkey $D -p foo -P bar
-./gbde setkey $D -p bar -P foo
-
-./gbde setkey $D -p foo -n 2 -P foo2
-./gbde setkey $D -p foo2 -n 3 -P foo3
-./gbde setkey $D -p foo3 -n 4 -P foo4
-./gbde setkey $D -p foo4 -n 1 -P foo1
-
-mdconfig -d -u $MD
-
-mdconfig -a -t malloc -s 1m -u $MD
-if [ -f image.uu ] ; then
- uudecode -p image.uu | bzcat > $D
-else
- uudecode -p ${1}/image.uu | bzcat > $D
-fi
-
-if [ `md5 < $D` != "a4066a739338d451b919e63f9ee4a12c" ] ; then
- echo "Failed to set up md(4) device correctly"
- exit 2
-fi
-
-./gbde attach $D -p foo
-fsck_ffs ${D}.bde
-./gbde detach $D
-mdconfig -d -u $MD
-
-
-echo "***********"
-echo "Test passed"
-echo "***********"
-exit 0
diff --git a/sbin/geom/Makefile b/sbin/geom/Makefile
index 0c6e6e2b95c8..61561ef1ff1b 100644
--- a/sbin/geom/Makefile
+++ b/sbin/geom/Makefile
@@ -1,17 +1,15 @@
-# $FreeBSD$
-
.include <src.opts.mk>
.PATH: ${.CURDIR}/core ${.CURDIR}/misc
-PACKAGE=runtime
+PACKAGE=geom
PROG= geom
SRCS= geom.c subr.c
MAN= geom.8
CFLAGS+= -I${.CURDIR} -I${.CURDIR}/core
CFLAGS+= -DGEOM_CLASS_DIR=\"${GEOM_CLASS_DIR}\"
-LIBADD= geom util
+LIBADD= geom util xo
.if defined(RESCUE)
.PATH: ${SRCTOP}/lib/geom/part \
diff --git a/sbin/geom/Makefile.depend b/sbin/geom/Makefile.depend
index 343e67f6d84d..08cfc713d335 100644
--- a/sbin/geom/Makefile.depend
+++ b/sbin/geom/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
@@ -7,9 +6,7 @@ DIRDEPS = \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
lib/libgeom \
- lib/libsbuf \
lib/libutil \
diff --git a/sbin/geom/core/Makefile.depend b/sbin/geom/core/Makefile.depend
index 3f477bc3f8b0..de2127d53ae8 100644
--- a/sbin/geom/core/Makefile.depend
+++ b/sbin/geom/core/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/geom/core/geom.8 b/sbin/geom/core/geom.8
index db0556fb9505..b864b3b238f5 100644
--- a/sbin/geom/core/geom.8
+++ b/sbin/geom/core/geom.8
@@ -1,3 +1,6 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
.\" Copyright (c) 2004-2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
.\" All rights reserved.
.\"
@@ -22,14 +25,12 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd January 19, 2022
+.Dd May 9, 2023
.Dt GEOM 8
.Os
.Sh NAME
.Nm geom
-.Nd "universal control utility for GEOM classes"
+.Nd universal control utility for GEOM classes
.Sh SYNOPSIS
.Nm
.Ar class
@@ -62,13 +63,13 @@ The
.Nm
utility is used to control various GEOM classes.
A class has to be aware of
-.Xr geom 8
+.Nm
communication methods, but there are also some standard commands
which can be used for existing
-.Xr geom 8
+.Nm
unaware classes.
Here is the list of standard commands:
-.Bl -tag -width ".Cm status"
+.Bl -tag -width indent
.It Cm help
List all available commands for the given class.
.It Cm list
@@ -76,7 +77,7 @@ Print detailed information (within the given class) about all geoms
(if no additional arguments were specified) or the given geoms.
This command is only available if the given class exists in the kernel.
Additional options include:
-.Bl -tag -width ".Fl a"
+.Bl -tag -width "-a"
.It Fl a
Print information for geoms without providers.
.El
@@ -86,9 +87,11 @@ Print general information (within the given class) about all geoms
This command is only available if the given class exists in the kernel.
.Pp
Additional options include:
-.Bl -tag -width ".Fl s"
+.Bl -tag -width "-s"
.It Fl a
-When used with -g, print status for geoms without providers.
+When used with
+.Fl g ,
+print status for geoms without providers.
.It Fl g
Report statuses for geoms instead of providers.
.It Fl s
@@ -109,7 +112,7 @@ kernel module.
.El
.Pp
Additional options include:
-.Bl -tag -width ".Cm status"
+.Bl -tag -width indent
.It Fl p Ar provider-name
Print detailed information about the geom which provides
.Ar provider-name .
@@ -127,8 +130,9 @@ When a class-specific shared library exists, a direct utility should also be
available under the name of
.Nm g Ns Ar class .
.Pp
-Currently available classes which are aware of
-.Xr geom 8 :
+Currently, classes aware of
+.Nm
+are:
.Pp
.Bl -bullet -offset indent -compact
.It
@@ -169,7 +173,7 @@ VIRSTOR
.Sh ENVIRONMENT
The following environment variables affect the execution of
.Nm :
-.Bl -tag -width ".Ev GEOM_LIBRARY_PATH"
+.Bl -tag -width "GEOM_LIBRARY_PATH"
.It Ev GEOM_LIBRARY_PATH
Specifies the path where shared libraries are stored instead of
.Pa /lib/geom/ .
@@ -182,7 +186,10 @@ The following example shows how to set up a stripe on three disks for automatic
configuration:
.Bd -literal -offset indent
geom stripe label -v -s 65536 data /dev/da0 /dev/da1 /dev/da2
+.Ed
+.Pp
or:
+.Bd -literal -offset indent
gstripe label -v -s 65536 data /dev/da0 /dev/da1 /dev/da2
.Ed
.Pp
@@ -209,7 +216,6 @@ geom md unload
.Xr gnop 8 ,
.Xr gpart 8 ,
.Xr graid3 8 ,
-.Xr gsched 8 ,
.Xr gshsec 8 ,
.Xr gstripe 8 ,
.Xr gunion 8 ,
diff --git a/sbin/geom/core/geom.c b/sbin/geom/core/geom.c
index 9b43910b88f9..2de696ce6a43 100644
--- a/sbin/geom/core/geom.c
+++ b/sbin/geom/core/geom.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004-2009 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/module.h>
@@ -52,9 +49,12 @@ __FBSDID("$FreeBSD$");
#include <assert.h>
#include <libgeom.h>
#include <geom.h>
+#include <libxo/xo.h>
#include "misc/subr.h"
+#define GEOM_XO_VERSION "1"
+
#ifdef STATIC_GEOM_CLASSES
extern uint32_t gpart_version;
extern struct g_command gpart_class_commands[];
@@ -252,7 +252,7 @@ static void
set_option(struct gctl_req *req, struct g_option *opt, const char *val)
{
const char *optname;
- uint64_t number;
+ int64_t number;
void *ptr;
if (G_OPT_ISMULTI(opt)) {
@@ -503,7 +503,10 @@ run_command(int argc, char *argv[])
}
if (errstr != NULL && errstr[0] != '\0') {
warnx("%s", errstr);
- if (strncmp(errstr, "warning: ", strlen("warning: ")) != 0) {
+ /* Suppress EXIT_FAILURE for warnings */
+ if (strncmp(errstr, "warning: ", strlen("warning: ")) == 0)
+ req->nerror = 0;
+ if (req->nerror != 0) {
gctl_free(req);
exit(EXIT_FAILURE);
}
@@ -513,6 +516,7 @@ run_command(int argc, char *argv[])
gctl_free(req);
if (verbose)
printf("Done.\n");
+ xo_finish();
exit(EXIT_SUCCESS);
}
@@ -810,6 +814,10 @@ main(int argc, char *argv[])
provider_name = NULL;
tflag = false;
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return (argc);
+
if (strcmp(getprogname(), "geom") == 0) {
while ((ch = getopt(argc, argv, "hp:t")) != -1) {
switch (ch) {
@@ -831,6 +839,7 @@ main(int argc, char *argv[])
* Don't adjust argc and argv, it would break get_class().
*/
}
+ xo_set_version(GEOM_XO_VERSION);
if (tflag && provider_name != NULL) {
errx(EXIT_FAILURE,
@@ -839,6 +848,7 @@ main(int argc, char *argv[])
if (provider_name != NULL) {
list_one_geom_by_provider(provider_name);
+ xo_finish();
return (0);
}
@@ -882,29 +892,33 @@ find_geom(struct gclass *classp, const char *name)
}
static void
-list_one_provider(struct gprovider *pp, const char *prefix)
+list_one_provider(struct gprovider *pp, const char *padding)
{
struct gconfig *conf;
char buf[5];
- printf("Name: %s\n", pp->lg_name);
+ xo_emit("{Lcw:Name}{:Name}\n", pp->lg_name);
humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
- printf("%sMediasize: %jd (%s)\n", prefix, (intmax_t)pp->lg_mediasize,
- buf);
- printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
+ xo_emit("{P:/%s}{Lcw:Mediasize}{:Mediasize/%jd} ({N:/%s})\n",
+ padding, (intmax_t)pp->lg_mediasize, buf);
+ xo_emit("{P:/%s}{Lcw:Sectorsize}{:Sectorsize/%u} \n",
+ padding, pp->lg_sectorsize);
if (pp->lg_stripesize > 0 || pp->lg_stripeoffset > 0) {
- printf("%sStripesize: %ju\n", prefix, pp->lg_stripesize);
- printf("%sStripeoffset: %ju\n", prefix, pp->lg_stripeoffset);
+ xo_emit("{P:/%s}{Lcw:Stripesize}{Stripesize/%ju}\n",
+ padding, pp->lg_stripesize);
+ xo_emit("{P:/%s}{Lcw:Stripeoffset}{Stripeoffset/%ju}\n",
+ padding, pp->lg_stripeoffset);
}
- printf("%sMode: %s\n", prefix, pp->lg_mode);
+ xo_emit("{P:/%s}{Lcw:Mode}{Mode}\n", padding, pp->lg_mode);
LIST_FOREACH(conf, &pp->lg_config, lg_config) {
- printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
+ xo_emit("{P:/%s}{Lcwa:}{a:}\n", padding, conf->lg_name,
+ conf->lg_name, conf->lg_val);
}
}
static void
-list_one_consumer(struct gconsumer *cp, const char *prefix)
+list_one_consumer(struct gconsumer *cp, const char *padding)
{
struct gprovider *pp;
struct gconfig *conf;
@@ -915,20 +929,24 @@ list_one_consumer(struct gconsumer *cp, const char *prefix)
else {
char buf[5];
- printf("Name: %s\n", pp->lg_name);
+ xo_emit("{Lcw:Name}{:Name}\n", pp->lg_name);
humanize_number(buf, sizeof(buf), (int64_t)pp->lg_mediasize, "",
HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
- printf("%sMediasize: %jd (%s)\n", prefix,
- (intmax_t)pp->lg_mediasize, buf);
- printf("%sSectorsize: %u\n", prefix, pp->lg_sectorsize);
+ xo_emit("{P:/%s}{Lcw:Mediasize}{:Mediasize/%jd} ({N:/%s})\n",
+ padding, (intmax_t)pp->lg_mediasize, buf);
+ xo_emit("{P:/%s}{Lcw:Sectorsize}{:Sectorsize/%u}\n",
+ padding, pp->lg_sectorsize);
if (pp->lg_stripesize > 0 || pp->lg_stripeoffset > 0) {
- printf("%sStripesize: %ju\n", prefix, pp->lg_stripesize);
- printf("%sStripeoffset: %ju\n", prefix, pp->lg_stripeoffset);
+ xo_emit("{P:/%s}{Lcw:Stripesize}{:Stripesize/%ju}\n",
+ padding, pp->lg_stripesize);
+ xo_emit("{P:/%s}{Lcw:Stripeoffset}{:Stripesize/%ju}\n",
+ padding, pp->lg_stripeoffset);
}
- printf("%sMode: %s\n", prefix, cp->lg_mode);
+ xo_emit("{P:/%s}{Lcw:Mode}{:Mode}\n", padding, pp->lg_mode);
}
LIST_FOREACH(conf, &cp->lg_config, lg_config) {
- printf("%s%s: %s\n", prefix, conf->lg_name, conf->lg_val);
+ xo_emit("{P:/%s}{Lcwa:}{a:}\n", padding, conf->lg_name,
+ conf->lg_name, conf->lg_val);
}
}
@@ -940,27 +958,36 @@ list_one_geom(struct ggeom *gp)
struct gconfig *conf;
unsigned n;
- printf("Geom name: %s\n", gp->lg_name);
+ xo_emit("{Lcw:Geom name}{:Name}\n", gp->lg_name);
LIST_FOREACH(conf, &gp->lg_config, lg_config) {
- printf("%s: %s\n", conf->lg_name, conf->lg_val);
+ xo_emit("{Lcwa:}{a:}\n", conf->lg_name, conf->lg_name,
+ conf->lg_val);
}
if (!LIST_EMPTY(&gp->lg_provider)) {
- printf("Providers:\n");
+ xo_open_list("Providers");
+ xo_emit("{Tc:Providers}\n");
n = 1;
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
- printf("%u. ", n++);
+ xo_emit("{T:/%u}. ", n++);
+ xo_open_instance("provider");
list_one_provider(pp, " ");
+ xo_close_instance("provider");
}
+ xo_close_list("Providers");
}
if (!LIST_EMPTY(&gp->lg_consumer)) {
- printf("Consumers:\n");
+ xo_open_list("Consumers");
+ xo_emit("{Tc:Consumers}\n");
n = 1;
LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
- printf("%u. ", n++);
+ xo_emit("{T:/%u}. ", n++);
+ xo_open_instance("consumer");
list_one_consumer(cp, " ");
+ xo_close_instance("consumer");
}
+ xo_close_list("Consumers");
}
- printf("\n");
+ xo_emit("\n");
}
static void
@@ -978,8 +1005,10 @@ list_one_geom_by_provider(const char *provider_name)
if (gp == NULL)
errx(EXIT_FAILURE, "Cannot find provider '%s'.", provider_name);
- printf("Geom class: %s\n", gp->lg_class->lg_name);
+ xo_open_container("Geom");
+ xo_emit("{Lwc:Geom class}{:Class}\n", gp->lg_class->lg_name);
list_one_geom(gp);
+ xo_close_container("Geom");
}
static void
@@ -1038,14 +1067,20 @@ std_list(struct gctl_req *req, unsigned flags __unused)
"an instance named '%s'.",
gclass_name, name);
}
+ xo_open_container("Geom");
list_one_geom(gp);
+ xo_close_container("Geom");
}
} else {
+ xo_open_list("Geoms");
LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
if (LIST_EMPTY(&gp->lg_provider) && !all)
continue;
+ xo_open_instance("geom");
list_one_geom(gp);
+ xo_close_instance("geom");
}
+ xo_close_list("Geoms");
}
geom_deletetree(&mesh);
}
@@ -1115,34 +1150,24 @@ status_update_len_prs(struct ggeom *gp, int *name_len, int *status_len)
}
static char *
-status_one_consumer(struct gconsumer *cp)
+status_one_consumer(struct gconsumer *cp, const char *value)
{
- static char buf[256];
struct gprovider *pp;
struct gconfig *conf;
- const char *state, *syncr;
+ char *ret;
pp = cp->lg_provider;
if (pp == NULL)
return (NULL);
- state = NULL;
- syncr = NULL;
+ ret = NULL;
LIST_FOREACH(conf, &cp->lg_config, lg_config) {
- if (strcasecmp(conf->lg_name, "state") == 0)
- state = conf->lg_val;
- if (strcasecmp(conf->lg_name, "synchronized") == 0)
- syncr = conf->lg_val;
+ if (strcasecmp(conf->lg_name, value) == 0)
+ ret = conf->lg_val;
}
- if (state == NULL && syncr == NULL)
- snprintf(buf, sizeof(buf), "%s", pp->lg_name);
- else if (state != NULL && syncr != NULL) {
- snprintf(buf, sizeof(buf), "%s (%s, %s)", pp->lg_name,
- state, syncr);
- } else {
- snprintf(buf, sizeof(buf), "%s (%s)", pp->lg_name,
- state ? state : syncr);
- }
- return (buf);
+
+ if (ret == NULL)
+ return (NULL);
+ return (ret);
}
static void
@@ -1150,8 +1175,8 @@ status_one_geom(struct ggeom *gp, int script, int name_len, int status_len)
{
struct gconsumer *cp;
struct gconfig *conf;
- const char *name, *status, *component;
- int gotone;
+ const char *name, *status, *cstate, *csyncr;
+ int gotone, len;
name = gp->lg_name;
status = "N/A";
@@ -1161,21 +1186,53 @@ status_one_geom(struct ggeom *gp, int script, int name_len, int status_len)
break;
}
}
- gotone = 0;
+ gotone = len = 0;
+ xo_open_instance("status");
LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
- component = status_one_consumer(cp);
- if (component == NULL)
+ if (cp->lg_provider == NULL)
continue;
+
+ cstate = status_one_consumer(cp, "state");
+ csyncr = status_one_consumer(cp, "synchronized");
+ if (!gotone || script) {
+ if (!gotone) {
+ xo_emit("{:name/%*s} {:status/%*s} ",
+ name_len, name, status_len, status);
+ } else {
+ xo_emit("{d:name/%*s} {d:status/%*s} ",
+ name_len, name, status_len, status);
+ }
+ xo_open_list("components");
+ }
+
+ xo_open_instance("components");
+ if (cstate != NULL && csyncr != NULL) {
+ xo_emit("{P:/%*s}{:component} ({:state}, {:synchronized})\n",
+ len, "", cp->lg_provider->lg_name, cstate, csyncr);
+ } else if (cstate != NULL) {
+ xo_emit("{P:/%*s}{:component} ({:state})\n",
+ len, "", cp->lg_provider->lg_name, cstate);
+ } else if (csyncr != NULL) {
+ xo_emit("{P:/%*s}{:component} ({:synchronized})\n",
+ len, "", cp->lg_provider->lg_name, csyncr);
+ } else {
+ xo_emit("{P:/%*s}{:component}\n",
+ len, "", cp->lg_provider->lg_name);
+ }
+ xo_close_instance("components");
gotone = 1;
- printf("%*s %*s %s\n", name_len, name, status_len, status,
- component);
- if (!script)
- name = status = "";
+ if (!len && !script)
+ len = name_len + status_len + 4;
}
if (!gotone) {
- printf("%*s %*s %s\n", name_len, name, status_len, status,
- "N/A");
+ xo_emit("{:name/%*s} {:status/%*s} ", name_len, name, status_len, status);
+ xo_open_list("components");
+ xo_open_instance("components");
+ xo_emit("{P:/%*s}{d:component}\n", len, "", "N/A");
+ xo_close_instance("components");
}
+ xo_close_list("components");
+ xo_close_instance("status");
}
static void
@@ -1184,9 +1241,10 @@ status_one_geom_prs(struct ggeom *gp, int script, int name_len, int status_len)
struct gprovider *pp;
struct gconsumer *cp;
struct gconfig *conf;
- const char *name, *status, *component;
- int gotone;
+ const char *name, *status, *cstate, *csyncr;
+ int gotone, len;
+ xo_open_instance("status");
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
name = pp->lg_name;
status = "N/A";
@@ -1202,22 +1260,53 @@ status_one_geom_prs(struct ggeom *gp, int script, int name_len, int status_len)
break;
}
}
- gotone = 0;
+ gotone = len = 0;
LIST_FOREACH(cp, &gp->lg_consumer, lg_consumer) {
- component = status_one_consumer(cp);
- if (component == NULL)
+ if (cp->lg_provider == NULL)
continue;
+
+ cstate = status_one_consumer(cp, "state");
+ csyncr = status_one_consumer(cp, "synchronized");
+ if (!gotone || script) {
+ if (!gotone) {
+ xo_emit("{:name/%*s} {:status/%*s} ",
+ name_len, name, status_len, status);
+ } else {
+ xo_emit("{d:name/%*s} {d:status/%*s} ",
+ name_len, name, status_len, status);
+ }
+ xo_open_list("components");
+ }
+
+ xo_open_instance("component");
+ if (cstate != NULL && csyncr != NULL) {
+ xo_emit("{P:/%*s}{:component} ({:state}, {:synchronized})\n",
+ len, "", cp->lg_provider->lg_name, cstate, csyncr);
+ } else if (cstate != NULL) {
+ xo_emit("{P:/%*s}{:component} ({:state})\n",
+ len, "", cp->lg_provider->lg_name, cstate);
+ } else if (csyncr != NULL) {
+ xo_emit("{P:/%*s}{:component} ({:synchronized})\n",
+ len, "", cp->lg_provider->lg_name, csyncr);
+ } else {
+ xo_emit("{P:/%*s}{:component}\n",
+ len, "", cp->lg_provider->lg_name);
+ }
+ xo_close_instance("component");
gotone = 1;
- printf("%*s %*s %s\n", name_len, name,
- status_len, status, component);
- if (!script)
- name = status = "";
+ if (!len && !script)
+ len = name_len + status_len + 4;
}
if (!gotone) {
- printf("%*s %*s %s\n", name_len, name,
- status_len, status, "N/A");
+ xo_emit("{:name/%*s} {:status/%*s} ", name_len, name, status_len, status);
+ xo_open_list("components");
+ xo_open_instance("components");
+ xo_emit("{P:/%*s}{d:component}\n", len, "", "N/A");
+ xo_close_instance("components");
}
+ xo_close_list("components");
}
+ xo_close_instance("status");
}
static void
@@ -1240,13 +1329,9 @@ std_status(struct gctl_req *req, unsigned flags __unused)
all = gctl_get_int(req, "all");
geoms = gctl_get_int(req, "geoms");
script = gctl_get_int(req, "script");
- if (script) {
- name_len = 0;
- status_len = 0;
- } else {
- name_len = strlen("Name");
- status_len = strlen("Status");
- }
+ name_len = strlen("Name");
+ status_len = strlen("Status");
+
if (nargs > 0) {
for (i = 0, n = 0; i < nargs; i++) {
name = gctl_get_ascii(req, "arg%d", i);
@@ -1282,9 +1367,10 @@ std_status(struct gctl_req *req, unsigned flags __unused)
goto end;
}
if (!script) {
- printf("%*s %*s %s\n", name_len, "Name", status_len, "Status",
- "Components");
+ xo_emit("{T:/%*s} {T:/%*s} {T:Components}\n",
+ name_len, "Name", status_len, "Status");
}
+ xo_open_list("status");
if (nargs > 0) {
for (i = 0; i < nargs; i++) {
name = gctl_get_ascii(req, "arg%d", i);
@@ -1312,6 +1398,7 @@ std_status(struct gctl_req *req, unsigned flags __unused)
}
}
}
+ xo_close_list("status");
end:
geom_deletetree(&mesh);
}
diff --git a/sbin/geom/core/geom.h b/sbin/geom/core/geom.h
index a76021c8aca5..93a5ee72d9ad 100644
--- a/sbin/geom/core/geom.h
+++ b/sbin/geom/core/geom.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 _GEOM_H_
diff --git a/sbin/geom/misc/subr.c b/sbin/geom/misc/subr.c
index 3985ae56edc6..18bac7108ed0 100644
--- a/sbin/geom/misc/subr.c
+++ b/sbin/geom/misc/subr.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/endian.h>
@@ -398,6 +395,8 @@ gctl_error(struct gctl_req *req, const char *error, ...)
fprintf(stderr, "\n");
}
va_end(ap);
+ if (req != NULL && req->nerror == 0)
+ req->nerror = EINVAL;
}
static void *
diff --git a/sbin/geom/misc/subr.h b/sbin/geom/misc/subr.h
index 579c94c21491..708abf5f8767 100644
--- a/sbin/geom/misc/subr.h
+++ b/sbin/geom/misc/subr.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 _SUBR_H_
diff --git a/sbin/ggate/Makefile b/sbin/ggate/Makefile
index 22532cc18512..753e0bd0ddbb 100644
--- a/sbin/ggate/Makefile
+++ b/sbin/ggate/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.include <src.opts.mk>
SUBDIR= ggatec \
diff --git a/sbin/ggate/Makefile.inc b/sbin/ggate/Makefile.inc
index 265f86d1ed55..01b5f23410c8 100644
--- a/sbin/ggate/Makefile.inc
+++ b/sbin/ggate/Makefile.inc
@@ -1,3 +1 @@
-# $FreeBSD$
-
.include "../Makefile.inc"
diff --git a/sbin/ggate/ggatec/Makefile b/sbin/ggate/ggatec/Makefile
index 84db486472b1..9ea38ceb87d4 100644
--- a/sbin/ggate/ggatec/Makefile
+++ b/sbin/ggate/ggatec/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.PATH: ${.CURDIR:H}/shared
PROG= ggatec
diff --git a/sbin/ggate/ggatec/Makefile.depend b/sbin/ggate/ggatec/Makefile.depend
index 4fb720d36316..8c3aa5e6e9a2 100644
--- a/sbin/ggate/ggatec/Makefile.depend
+++ b/sbin/ggate/ggatec/Makefile.depend
@@ -1,17 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
lib/libgeom \
- lib/libsbuf \
lib/libthr \
lib/libutil \
diff --git a/sbin/ggate/ggatec/ggatec.8 b/sbin/ggate/ggatec/ggatec.8
index 6f761dcfd99b..99f9bcab5964 100644
--- a/sbin/ggate/ggatec/ggatec.8
+++ b/sbin/ggate/ggatec/ggatec.8
@@ -22,8 +22,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 8, 2016
.Dt GGATEC 8
.Os
@@ -36,6 +34,7 @@
.Op Fl n
.Op Fl v
.Op Fl o Cm ro | wo | rw
+.Op Fl o Cm direct
.Op Fl p Ar port
.Op Fl q Ar queue_size
.Op Fl R Ar rcvbuf
@@ -50,6 +49,7 @@
.Op Fl n
.Op Fl v
.Op Fl o Cm ro | wo | rw
+.Op Fl o Cm direct
.Op Fl p Ar port
.Op Fl R Ar rcvbuf
.Op Fl S Ar sndbuf
@@ -110,13 +110,21 @@ provider (cancels all pending requests).
Do not use
.Dv TCP_NODELAY
option on TCP sockets.
-.It Fl o Cm ro | wo | rw
-Specify permissions to use when opening the file or device: read-only
-.Pq Cm ro ,
+.It Fl o Ar option
+Specify permissions and options to use when opening the file or device.
+.Bl -tag -width indent
+.It Cm ro
+read-only
+.It Cm wo
write-only
-.Pq Cm wo ,
-or read-write
-.Pq Cm rw .
+.It Cm rw
+read-write
+.It Cm direct
+open with
+.Dv O_DIRECT
+option on the file
+.El
+.Pp
Default is
.Cm rw .
.It Fl p Ar port
@@ -162,11 +170,14 @@ Use a CD-ROM device on a remote host.
.Bd -literal -offset indent
server# cat /etc/gg.exports
client RO /dev/cd0
+client RW /tmp/image
server# ggated
client# ggatec create -o ro server /dev/cd0
ggate0
client# mount_cd9660 /dev/ggate0 /cdrom
+client# ggatec create -o rw -o direct server /tmp/image
+ggate1
.Ed
.Sh SEE ALSO
.Xr geom 4 ,
diff --git a/sbin/ggate/ggatec/ggatec.c b/sbin/ggate/ggatec/ggatec.c
index 0de8504ce3c4..b6f248c05290 100644
--- a/sbin/ggate/ggatec/ggatec.c
+++ b/sbin/ggate/ggatec/ggatec.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 <stdio.h>
@@ -54,7 +52,6 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
-#include <geom/gate/g_gate.h>
#include "ggate.h"
@@ -64,6 +61,7 @@ static const char *path = NULL;
static const char *host = NULL;
static int unit = G_GATE_UNIT_AUTO;
static unsigned flags = 0;
+static int direct_flag = 0;
static int force = 0;
static unsigned queue_size = G_GATE_QUEUE_SIZE;
static unsigned port = G_GATE_PORT;
@@ -80,10 +78,12 @@ static void
usage(void)
{
- fprintf(stderr, "usage: %s create [-nv] [-o <ro|wo|rw>] [-p port] "
+ fprintf(stderr, "usage: %s create [-nv] [-o <ro|wo|rw>] "
+ "[-o <direct>] [-p port] "
"[-q queue_size] [-R rcvbuf] [-S sndbuf] [-s sectorsize] "
"[-t timeout] [-u unit] <host> <path>\n", getprogname());
- fprintf(stderr, " %s rescue [-nv] [-o <ro|wo|rw>] [-p port] "
+ fprintf(stderr, " %s rescue [-nv] [-o <ro|wo|rw>] "
+ "[-o <direct>] [-p port] "
"[-R rcvbuf] [-S sndbuf] <-u unit> <host> <path>\n", getprogname());
fprintf(stderr, " %s destroy [-f] <-u unit>\n", getprogname());
fprintf(stderr, " %s list [-v] [-u unit]\n", getprogname());
@@ -363,7 +363,7 @@ handshake(int dir)
close(sfd);
return (-1);
}
- cinit.gc_flags = flags | dir;
+ cinit.gc_flags = flags | direct_flag | dir;
cinit.gc_token = token;
cinit.gc_nconn = 2;
g_gate_swap2n_cinit(&cinit);
@@ -587,6 +587,8 @@ main(int argc, char *argv[])
flags = G_GATE_FLAG_WRITEONLY;
else if (strcasecmp("rw", optarg) == 0)
flags = 0;
+ else if (strcasecmp("direct", optarg) == 0)
+ direct_flag = GGATE_FLAG_DIRECT;
else {
errx(EXIT_FAILURE,
"Invalid argument for '-o' option.");
diff --git a/sbin/ggate/ggated/Makefile b/sbin/ggate/ggated/Makefile
index 1c53cf2c2efb..629d6aded308 100644
--- a/sbin/ggate/ggated/Makefile
+++ b/sbin/ggate/ggated/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.PATH: ${.CURDIR:H}/shared
PROG= ggated
diff --git a/sbin/ggate/ggated/Makefile.depend b/sbin/ggate/ggated/Makefile.depend
index 408a62870b41..8c3aa5e6e9a2 100644
--- a/sbin/ggate/ggated/Makefile.depend
+++ b/sbin/ggate/ggated/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
diff --git a/sbin/ggate/ggated/ggated.8 b/sbin/ggate/ggated/ggated.8
index fc4fb0326bb2..8e3ad68d1db0 100644
--- a/sbin/ggate/ggated/ggated.8
+++ b/sbin/ggate/ggated/ggated.8
@@ -22,8 +22,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 8, 2016
.Dt GGATED 8
.Os
@@ -87,10 +85,51 @@ An alternate location for the exports file.
.Pp
The format of an exports file is as follows:
.Bd -literal -offset indent
-1.2.3.4 RO /dev/cd0
-1.2.3.0/24 RW /tmp/test.img
-hostname WO /tmp/image
+1.2.3.4 RO /dev/cd0
+1.2.3.0/24 RW /tmp/test.img
+hostname WO /tmp/image
+hostname RW,DIRECT /tmp/direct-image
+hostname RW,NODIRECT /tmp/nodirect-image
.Ed
+.Pp
+The first colunm specifies the ip, network with netmask, or the hostname
+that the export applies to.
+.Pp
+The next column is the access flags that apply to the export
+.Bl -tag -width ".Cm NODIRECT"
+.It Cm RO
+Read-Only the path specified will be exported to the client read only.
+.It Cm WO
+Write-Only the path specified will be exported to the client write only.
+.It Cm RW
+Read-Write the path specified will be exported to the client read-write.
+.It Cm DIRECT
+The path specified will always be opened with O_DIRECT for clients.
+.It Cm NODIRECT
+The path specified will never be opened with O_DIRECT for clients.
+.El
+.Pp
+The final column specifies the path to export.
+.Pp
+Files are opened with the least common flags between the client and the
+server. A client may request read or write only to a read-write export
+and the server will honor the client request and open the file in the
+requested mode. A client requesting greater access than permissions listed
+in the file will be rejected.
+.Pp
+DIRECT and NODIRECT are used to coerce the use of the O_DIRECT flag to
+.Xr open 2 when the specified path is opened. If DIRECT is specified the
+path is always opened with O_DIRECT. If NODIRECT is specified the path is
+never opened with O_DIRECT. DIRECT access limits the cache effects of
+IO operaions on the file. This has the effect of having clients accessing
+exports to not impact the cache of the local machine, however it
+will cause greater IO utilization to the devices on which the files reside.
+.Pp
+If neither is specified the server will use
+the preference specified by the client, with the default to not use O_DIRECT.
+If the client specifies a preference against the server's configuration the
+client preference will be silently ignored.
+.Pp
.Sh FILES
.Bl -tag -width ".Pa /var/run/ggated.pid" -compact
.It Pa /var/run/ggated.pid
@@ -106,13 +145,18 @@ should be called with the
.Fl v
option.
.Sh EXAMPLES
-Export CD-ROM device and a file:
+Export CD-ROM device, a file, and a file with
+.Dv O_DIRECT
+option:
.Bd -literal -offset indent
# echo "1.2.3.0/24 RO /dev/cd0" > /etc/gg.exports
# echo "client RW /image" >> /etc/gg.exports
+# echo "client RW,DIRECT /image2" >> /etc/gg.exports
+# echo "client RW,NODIRECT /image3" >> /etc/gg.exports
# ggated
.Ed
.Sh SEE ALSO
+.Xr open 2 ,
.Xr geom 4 ,
.Xr ggatec 8 ,
.Xr ggatel 8
diff --git a/sbin/ggate/ggated/ggated.c b/sbin/ggate/ggated/ggated.c
index 7cacbf58037e..ef7b61cb13c4 100644
--- a/sbin/ggate/ggated/ggated.c
+++ b/sbin/ggate/ggated/ggated.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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>
@@ -66,7 +64,7 @@
struct ggd_connection {
off_t c_mediasize;
unsigned c_sectorsize;
- unsigned c_flags; /* flags (RO/RW) */
+ int c_flags; /* flags (RO/RW) */
int c_diskfd;
int c_sendfd;
int c_recvfd;
@@ -87,11 +85,18 @@ struct ggd_request {
#define r_length r_hdr.gh_length
#define r_error r_hdr.gh_error
+#define EFLAGS_RDONLY 0x0000
+#define EFLAGS_WRONLY 0x0001
+#define EFLAGS_RDWR 0x0002
+#define EFLAGS_ACCMODE 0x0003
+#define EFLAGS_DIRECT 0x0004
+#define EFLAGS_NODIRECT 0x0008
+
struct ggd_export {
char *e_path; /* path to device/file */
in_addr_t e_ip; /* remote IP address */
in_addr_t e_mask; /* IP mask */
- unsigned e_flags; /* flags (RO/RW) */
+ int e_flags; /* flags (WO/RO/RW/DIRECT/NODIRECT) */
SLIST_ENTRY(ggd_export) e_next;
};
@@ -148,20 +153,61 @@ countmask(unsigned m)
return (mask);
}
+static int
+parse_flags(const char *flagsstr, int lineno)
+{
+ char *flagscpy;
+ char *word, *brkf;
+ int access_flags = -1;
+ int direct_flags = 0;
+
+ flagscpy = strdup(flagsstr);
+ if (flagscpy == NULL) {
+ g_gate_xlog("Not enough memory.");
+ }
+
+ for (word = strtok_r(flagscpy, ",", &brkf);
+ word != NULL;
+ word = strtok_r(NULL, ",", &brkf)) {
+ if (strcasecmp("ro", word) == 0 ||
+ strcasecmp("rd", word) == 0) {
+ access_flags = EFLAGS_RDONLY;
+ } else if (strcasecmp("wo", word) == 0) {
+ access_flags = EFLAGS_WRONLY;
+ } else if (strcasecmp("rw", word) == 0) {
+ access_flags = EFLAGS_RDWR;
+ } else if (strcasecmp("direct", word) == 0) {
+ direct_flags = EFLAGS_DIRECT;
+ } else if (strcasecmp("nodirect", word) == 0) {
+ direct_flags = EFLAGS_NODIRECT;
+ } else {
+ g_gate_xlog("Invalid value (%s) in flags field at "
+ "line %u.", word, lineno);
+ }
+ }
+ free(flagscpy);
+ if (access_flags == -1) {
+ g_gate_xlog("Invalid value (%s) in flags field at "
+ "line %u.", flagsstr, lineno);
+ }
+ return (direct_flags | access_flags);
+}
+
static void
line_parse(char *line, unsigned lineno)
{
struct ggd_export *ex;
- char *word, *path, *sflags;
- unsigned flags, i, vmask;
+ char *word, *path, *sflags, *brkl;
+ unsigned i, vmask;
+ int flags;
in_addr_t ip, mask;
ip = mask = flags = vmask = 0;
path = NULL;
sflags = NULL;
- for (i = 0, word = strtok(line, " \t"); word != NULL;
- i++, word = strtok(NULL, " \t")) {
+ for (i = 0, word = strtok_r(line, " \t", &brkl); word != NULL;
+ i++, word = strtok_r(NULL, " \t", &brkl)) {
switch (i) {
case 0: /* IP address or host name */
ip = g_gate_str2ip(strsep(&word, "/"));
@@ -187,17 +233,7 @@ line_parse(char *line, unsigned lineno)
mask = countmask(vmask);
break;
case 1: /* flags */
- if (strcasecmp("rd", word) == 0 ||
- strcasecmp("ro", word) == 0) {
- flags = O_RDONLY;
- } else if (strcasecmp("wo", word) == 0) {
- flags = O_WRONLY;
- } else if (strcasecmp("rw", word) == 0) {
- flags = O_RDWR;
- } else {
- g_gate_xlog("Invalid value in flags field at "
- "line %u.", lineno);
- }
+ flags = parse_flags(word, lineno);
sflags = word;
break;
case 2: /* path */
@@ -308,13 +344,16 @@ exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit,
struct ggd_connection *conn)
{
char ipmask[32]; /* 32 == strlen("xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx")+1 */
- int error = 0, flags;
+ int error = 0, flags, access_flags, direct_flags = 0;
strlcpy(ipmask, ip2str(ex->e_ip), sizeof(ipmask));
strlcat(ipmask, "/", sizeof(ipmask));
strlcat(ipmask, ip2str(ex->e_mask), sizeof(ipmask));
+
+ access_flags = ex->e_flags & EFLAGS_ACCMODE;
+
if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) {
- if (ex->e_flags == O_WRONLY) {
+ if (access_flags == EFLAGS_WRONLY) {
g_gate_log(LOG_WARNING, "Read-only access requested, "
"but %s (%s) is exported write-only.", ex->e_path,
ipmask);
@@ -323,7 +362,7 @@ exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit,
conn->c_flags |= GGATE_FLAG_RDONLY;
}
} else if ((cinit->gc_flags & GGATE_FLAG_WRONLY) != 0) {
- if (ex->e_flags == O_RDONLY) {
+ if (access_flags == EFLAGS_RDONLY) {
g_gate_log(LOG_WARNING, "Write-only access requested, "
"but %s (%s) is exported read-only.", ex->e_path,
ipmask);
@@ -332,24 +371,41 @@ exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit,
conn->c_flags |= GGATE_FLAG_WRONLY;
}
} else {
- if (ex->e_flags == O_RDONLY) {
+ if (access_flags == EFLAGS_RDONLY) {
g_gate_log(LOG_WARNING, "Read-write access requested, "
"but %s (%s) is exported read-only.", ex->e_path,
ipmask);
return (EPERM);
- } else if (ex->e_flags == O_WRONLY) {
+ } else if (access_flags == EFLAGS_WRONLY) {
g_gate_log(LOG_WARNING, "Read-write access requested, "
"but %s (%s) is exported write-only.", ex->e_path,
ipmask);
return (EPERM);
}
}
+
+ if ((cinit->gc_flags & GGATE_FLAG_DIRECT) != 0) {
+ if (ex->e_flags & EFLAGS_NODIRECT) {
+ g_gate_log(LOG_WARNING, "Direct IO requested, "
+ "but %s (%s) is exported NODIRECT.", ex->e_path,
+ ipmask);
+ } else {
+ conn->c_flags |= GGATE_FLAG_DIRECT;
+ direct_flags = O_DIRECT;
+ }
+ }
+
+ if (ex->e_flags & EFLAGS_DIRECT) {
+ direct_flags = O_DIRECT;
+ }
+
if ((conn->c_flags & GGATE_FLAG_RDONLY) != 0)
flags = O_RDONLY;
else if ((conn->c_flags & GGATE_FLAG_WRONLY) != 0)
flags = O_WRONLY;
else
flags = O_RDWR;
+ flags |= direct_flags;
if (conn->c_diskfd != -1) {
if (strcmp(conn->c_path, ex->e_path) != 0) {
g_gate_log(LOG_ERR, "old %s and new %s: "
diff --git a/sbin/ggate/ggatel/Makefile b/sbin/ggate/ggatel/Makefile
index 13fb7c2fcf43..eb9ff9a675ce 100644
--- a/sbin/ggate/ggatel/Makefile
+++ b/sbin/ggate/ggatel/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.PATH: ${.CURDIR:H}/shared
PROG= ggatel
diff --git a/sbin/ggate/ggatel/Makefile.depend b/sbin/ggate/ggatel/Makefile.depend
index 1096cf51d094..d483b342de4b 100644
--- a/sbin/ggate/ggatel/Makefile.depend
+++ b/sbin/ggate/ggatel/Makefile.depend
@@ -1,17 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
lib/libgeom \
- lib/libsbuf \
lib/libutil \
diff --git a/sbin/ggate/ggatel/ggatel.8 b/sbin/ggate/ggatel/ggatel.8
index 7facee0c5369..512e4ab9d187 100644
--- a/sbin/ggate/ggatel/ggatel.8
+++ b/sbin/ggate/ggatel/ggatel.8
@@ -22,8 +22,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 8, 2016
.Dt GGATEL 8
.Os
@@ -34,7 +32,7 @@
.Nm
.Cm create
.Op Fl v
-.Op Fl o Cm ro | wo | rw
+.Oo Fl o option Oc ...
.Op Fl s Ar sectorsize
.Op Fl t Ar timeout
.Op Fl u Ar unit
@@ -50,7 +48,7 @@
.Nm
.Cm rescue
.Op Fl v
-.Op Fl o Cm ro | wo | rw
+.Oo Fl o option Oc ...
.Fl u Ar unit
.Ar path
.Sh DESCRIPTION
@@ -94,13 +92,21 @@ Available options:
Forcibly destroy
.Nm ggate
provider (cancels all pending requests).
-.It Fl o Cm ro | wo | rw
-Specify permissions to use when opening the file or device: read-only
-.Pq Cm ro ,
+.It Fl o Ar option
+Specify permissions and options to use when opening the file or device.
+.Bl -tag -width indent
+.It Cm ro
+read-only
+.It Cm wo
write-only
-.Pq Cm wo ,
-or read-write
-.Pq Cm rw .
+.It Cm rw
+read-write
+.It Cm direct
+open with
+.Dv O_DIRECT
+option on the file
+.El
+.Pp
Default is
.Cm rw .
.It Fl s Ar sectorsize
@@ -127,27 +133,8 @@ To get details about the failure,
should be called with the
.Fl v
option.
-.Sh EXAMPLES
-.Dq GEOMify
-the
-.Dq Li fd0
-device and use
-.Xr gbde 8
-to encrypt data on a floppy disk.
-.Bd -literal -offset indent
-ggatel create -u 5 /dev/fd0
-gbde init /dev/ggate5
-gbde attach ggate5
-newfs /dev/ggate5.bde
-mount /dev/ggate5.bde /secret
-cp /private/foo /secret/
-umount /secret
-gbde detach ggate5
-ggatel destroy -u 5
-.Ed
.Sh SEE ALSO
.Xr geom 4 ,
-.Xr gbde 8 ,
.Xr ggatec 8 ,
.Xr ggated 8 ,
.Xr mount 8 ,
diff --git a/sbin/ggate/ggatel/ggatel.c b/sbin/ggate/ggatel/ggatel.c
index 4659cacbee17..1cbb6af28b7e 100644
--- a/sbin/ggate/ggatel/ggatel.c
+++ b/sbin/ggate/ggatel/ggatel.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 <stdio.h>
@@ -45,7 +43,6 @@
#include <sys/stat.h>
#include <sys/syslog.h>
-#include <geom/gate/g_gate.h>
#include "ggate.h"
@@ -54,6 +51,7 @@ static enum { UNSET, CREATE, DESTROY, LIST, RESCUE } action = UNSET;
static const char *path = NULL;
static int unit = G_GATE_UNIT_AUTO;
static unsigned flags = 0;
+static int direct_flag = 0;
static int force = 0;
static unsigned sectorsize = 0;
static unsigned timeout = G_GATE_TIMEOUT;
@@ -62,24 +60,30 @@ static void
usage(void)
{
- fprintf(stderr, "usage: %s create [-v] [-o <ro|wo|rw>] "
+ fprintf(stderr, "usage: %s create [-v] [-o option] ... "
"[-s sectorsize] [-t timeout] [-u unit] <path>\n", getprogname());
- fprintf(stderr, " %s rescue [-v] [-o <ro|wo|rw>] <-u unit> "
+ fprintf(stderr, " %s rescue [-v] [-o option] ... <-u unit> "
"<path>\n", getprogname());
fprintf(stderr, " %s destroy [-f] <-u unit>\n", getprogname());
fprintf(stderr, " %s list [-v] [-u unit]\n", getprogname());
+ fprintf(stderr, " option = {ro, wo, rw, direct}\n");
exit(EXIT_FAILURE);
}
static int
g_gate_openflags(unsigned ggflags)
{
+ int openflags = O_RDWR;
if ((ggflags & G_GATE_FLAG_READONLY) != 0)
- return (O_RDONLY);
+ openflags = O_RDONLY;
else if ((ggflags & G_GATE_FLAG_WRITEONLY) != 0)
- return (O_WRONLY);
- return (O_RDWR);
+ openflags = O_WRONLY;
+
+ if (direct_flag)
+ openflags |= O_DIRECT;
+
+ return (openflags);
}
static void
@@ -250,6 +254,8 @@ main(int argc, char *argv[])
flags = G_GATE_FLAG_WRITEONLY;
else if (strcasecmp("rw", optarg) == 0)
flags = 0;
+ else if (strcasecmp("direct", optarg) == 0)
+ direct_flag = 1;
else {
errx(EXIT_FAILURE,
"Invalid argument for '-o' option.");
diff --git a/sbin/ggate/shared/ggate.c b/sbin/ggate/shared/ggate.c
index 2f544f7a2c9c..456027b1bbe3 100644
--- a/sbin/ggate/shared/ggate.c
+++ b/sbin/ggate/shared/ggate.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 <stdio.h>
diff --git a/sbin/ggate/shared/ggate.h b/sbin/ggate/shared/ggate.h
index d399b247cd75..78488a24c3fa 100644
--- a/sbin/ggate/shared/ggate.h
+++ b/sbin/ggate/shared/ggate.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,13 +24,12 @@
* 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 _GGATE_H_
#define _GGATE_H_
+#include <geom/gate/g_gate.h>
#include <sys/endian.h>
#include <stdarg.h>
@@ -44,8 +43,8 @@
#define GGATE_MAGIC "GEOM_GATE "
#define GGATE_VERSION 0
-#define GGATE_FLAG_RDONLY 0x0001
-#define GGATE_FLAG_WRONLY 0x0002
+#define GGATE_FLAG_RDONLY G_GATE_FLAG_READONLY
+#define GGATE_FLAG_WRONLY G_GATE_FLAG_WRITEONLY
/*
* If neither the GGATE_FLAG_SEND nor the GGATE_FLAG_RECV flag is
* set - this is initial connection.
@@ -55,6 +54,8 @@
#define GGATE_FLAG_SEND 0x0004
#define GGATE_FLAG_RECV 0x0008
+#define GGATE_FLAG_DIRECT 0x0010
+
#define GGATE_CMD_READ 0
#define GGATE_CMD_WRITE 1
#define GGATE_CMD_FLUSH 3
diff --git a/sbin/growfs/Makefile b/sbin/growfs/Makefile
index 8aeb9d77509e..b5b3d99f287d 100644
--- a/sbin/growfs/Makefile
+++ b/sbin/growfs/Makefile
@@ -1,18 +1,12 @@
-# @(#)Makefile 8.8 (Berkeley) 6/21/2000
-#
# $TSHeader: src/sbin/growfs/Makefile,v 1.4 2000/12/05 19:45:24 tomsoft Exp $
-# $FreeBSD$
#
.include <src.opts.mk>
-.PATH: ${.CURDIR:H}/mount
-
-PACKAGE=runtime
+PACKAGE=ufs
PROG= growfs
-SRCS= growfs.c getmntopts.c
+SRCS= growfs.c
MAN= growfs.8
-CFLAGS+=-I${.CURDIR:H}/mount
.if defined(GFSDBG)
SRCS+= debug.c
diff --git a/sbin/growfs/Makefile.depend b/sbin/growfs/Makefile.depend
index 51f2384d1c84..2e61386bc0cc 100644
--- a/sbin/growfs/Makefile.depend
+++ b/sbin/growfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/growfs/debug.c b/sbin/growfs/debug.c
index e0dfc997fcf6..3fe7e26e3e50 100644
--- a/sbin/growfs/debug.c
+++ b/sbin/growfs/debug.c
@@ -41,11 +41,6 @@
*
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <limits.h>
@@ -62,7 +57,7 @@ static FILE *dbg_log = NULL;
static unsigned int indent = 0;
/*
- * prototypes not done here, as they come with debug.h
+ * prototypes are not done here, as they come with debug.h
*/
/*
@@ -310,8 +305,6 @@ dbg_dump_fs(struct fs *sb, const char *comment)
sb->fs_avgfilesize);
fprintf(dbg_log, "avgfpdir int32_t 0x%08x\n",
sb->fs_avgfpdir);
- fprintf(dbg_log, "save_cgsize int32_t 0x%08x\n",
- sb->fs_save_cgsize);
fprintf(dbg_log, "flags int32_t 0x%08x\n",
sb->fs_flags);
fprintf(dbg_log, "contigsumsize int32_t 0x%08x\n",
diff --git a/sbin/growfs/debug.h b/sbin/growfs/debug.h
index 068e89c3441f..527f4ed63b73 100644
--- a/sbin/growfs/debug.h
+++ b/sbin/growfs/debug.h
@@ -38,7 +38,6 @@
* SUCH DAMAGE.
*
* $TSHeader: src/sbin/growfs/debug.h,v 1.2 2000/11/16 18:43:50 tom Exp $
- * $FreeBSD$
*
*/
diff --git a/sbin/growfs/growfs.8 b/sbin/growfs/growfs.8
index 334881369405..f23817b0afbe 100644
--- a/sbin/growfs/growfs.8
+++ b/sbin/growfs/growfs.8
@@ -35,9 +35,8 @@
.\" SUCH DAMAGE.
.\"
.\" $TSHeader: src/sbin/growfs/growfs.8,v 1.3 2000/12/12 19:31:00 tomsoft Exp $
-.\" $FreeBSD$
.\"
-.Dd December 13, 2017
+.Dd January 23, 2025
.Dt GROWFS 8
.Os
.Sh NAME
@@ -56,22 +55,15 @@ Before running
.Nm
the partition or slice containing the file system must be extended using
.Xr gpart 8 .
-If you are using volumes you must enlarge them by using
-.Xr gvinum 8 .
The
.Nm
utility extends the size of the file system on the specified special file.
The following options are available:
-.Bl -tag -width indent
+.Bl -tag -width "-s size"
.It Fl N
.Dq Test mode .
Causes the new file system parameters to be printed out without actually
enlarging the file system.
-.It Fl y
-Causes
-.Nm
-to assume yes
-as the answer to all operator questions.
.It Fl s Ar size
Determines the
.Ar size
@@ -88,7 +80,16 @@ This value defaults to the size of the raw partition specified in
(in other words,
.Nm
will enlarge the file system to the size of the entire partition).
+.It Fl y
+Causes
+.Nm
+to assume yes
+as the answer to all operator questions.
.El
+.Sh EXIT STATUS
+Exit status is 0 on success, and >= 1 on errors.
+Errors recoverable by user action are indicated by 2.
+OS errors, which are usually not recoverable, are indicated by 3 or greater.
.Sh EXAMPLES
Expand root file system to fill up available space:
.Dl growfs /
diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c
index 69e6f04dd4c2..9a48287107e7 100644
--- a/sbin/growfs/growfs.c
+++ b/sbin/growfs/growfs.c
@@ -45,16 +45,6 @@
*
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\
-Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\
-All rights reserved.\n";
-#endif /* not lint */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
@@ -118,7 +108,6 @@ static void updjcg(int, time_t, int, int, unsigned int);
static void updcsloc(time_t, int, int, unsigned int);
static void frag_adjust(ufs2_daddr_t, int);
static void updclst(int);
-static void mount_reload(const struct statfs *stfs);
static void cgckhash(struct cg *);
/*
@@ -150,7 +139,7 @@ growfs(int fsi, int fso, unsigned int Nflag)
*/
fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize);
if (fscs == NULL)
- errx(1, "calloc failed");
+ errx(3, "calloc failed");
memcpy(fscs, osblock.fs_csp, osblock.fs_cssize);
free(osblock.fs_csp);
osblock.fs_csp = NULL;
@@ -243,7 +232,7 @@ growfs(int fsi, int fso, unsigned int Nflag)
*
* We probably should rather change the summary for the cylinder group
* statistics here to the value of what would be in there, if the file
- * system were created initially with the new size. Therefor we still
+ * system were created initially with the new size. Therefore we still
* need to find an easy way of calculating that.
* Possibly we can try to read the first superblock copy and apply the
* "diffed" stats between the old and new superblock by still copying
@@ -262,7 +251,7 @@ growfs(int fsi, int fso, unsigned int Nflag)
* and all the alternates back to disk.
*/
if (!Nflag && sbput(fso, &sblock, sblock.fs_ncg) != 0)
- errc(2, EIO, "could not write updated superblock");
+ errc(3, EIO, "could not write updated superblock");
DBG_PRINT0("fscs written\n");
#ifdef FS_DEBUG
@@ -339,7 +328,7 @@ initcg(int cylno, time_t modtime, int fso, unsigned int Nflag)
acg.cg_ndblk = dmax - cbase;
if (sblock.fs_contigsumsize > 0)
acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
- start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
+ start = sizeof(acg);
if (sblock.fs_magic == FS_UFS2_MAGIC) {
acg.cg_iusedoff = start;
} else {
@@ -690,7 +679,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
sblock.fs_frag);
} else {
/*
- * Lets rejoin a possible partially growed
+ * Lets rejoin a possible partially grown
* fragment.
*/
k = 0;
@@ -716,7 +705,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
j++;
}
/*
- * Lets rejoin a possible partially growed fragment.
+ * Lets rejoin a possible partially grown fragment.
*/
k = 0;
while (isset(cg_blksfree(&acg), i) &&
@@ -744,7 +733,7 @@ updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag)
}
/*
- * Handle the last new block if there are stll some new fragments left.
+ * Handle the last new block if there are still some new fragments left.
* Here we don't have to bother about the cluster summary or the even
* the rotational layout table.
*/
@@ -1263,76 +1252,11 @@ is_dev(const char *name)
return (1);
}
-/*
- * Return mountpoint on which the device is currently mounted.
- */
-static const struct statfs *
-dev_to_statfs(const char *dev)
-{
- struct stat devstat, mntdevstat;
- struct statfs *mntbuf, *statfsp;
- char device[MAXPATHLEN];
- char *mntdevname;
- int i, mntsize;
-
- /*
- * First check the mounted filesystems.
- */
- if (stat(dev, &devstat) != 0)
- return (NULL);
- if (!S_ISCHR(devstat.st_mode) && !S_ISBLK(devstat.st_mode))
- return (NULL);
-
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
- mntdevname = statfsp->f_mntfromname;
- if (*mntdevname != '/') {
- strcpy(device, _PATH_DEV);
- strcat(device, mntdevname);
- mntdevname = device;
- }
- if (stat(mntdevname, &mntdevstat) == 0 &&
- mntdevstat.st_rdev == devstat.st_rdev)
- return (statfsp);
- }
-
- return (NULL);
-}
-
static const char *
-mountpoint_to_dev(const char *mountpoint)
-{
- struct statfs *mntbuf, *statfsp;
- struct fstab *fs;
- int i, mntsize;
-
- /*
- * First check the mounted filesystems.
- */
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = 0; i < mntsize; i++) {
- statfsp = &mntbuf[i];
-
- if (strcmp(statfsp->f_mntonname, mountpoint) == 0)
- return (statfsp->f_mntfromname);
- }
-
- /*
- * Check the fstab.
- */
- fs = getfsfile(mountpoint);
- if (fs != NULL)
- return (fs->fs_spec);
-
- return (NULL);
-}
-
-static const char *
-getdev(const char *name)
+getdev(const char *name, struct statfs *statfsp)
{
static char device[MAXPATHLEN];
- const char *cp, *dev;
+ const char *cp;
if (is_dev(name))
return (name);
@@ -1344,9 +1268,8 @@ getdev(const char *name)
return (device);
}
- dev = mountpoint_to_dev(name);
- if (dev != NULL && is_dev(dev))
- return (dev);
+ if (statfsp != NULL)
+ return (statfsp->f_mntfromname);
return (NULL);
}
@@ -1378,7 +1301,7 @@ main(int argc, char **argv)
DBG_FUNC("main")
struct fs *fs;
const char *device;
- const struct statfs *statfsp;
+ struct statfs *statfsp;
uint64_t size = 0;
off_t mediasize;
int error, j, fsi, fso, ch, ret, Nflag = 0, yflag = 0;
@@ -1408,7 +1331,7 @@ main(int argc, char **argv)
size <<= 30;
size <<= 10;
} else
- errx(1, "unknown suffix on -s argument");
+ errx(2, "unknown suffix on -s argument");
break;
case 'v': /* for compatibility to newfs */
break;
@@ -1430,44 +1353,43 @@ main(int argc, char **argv)
/*
* Now try to guess the device name.
*/
- device = getdev(*argv);
+ statfsp = getmntpoint(*argv);
+ device = getdev(*argv, statfsp);
if (device == NULL)
- errx(1, "cannot find special device for %s", *argv);
-
- statfsp = dev_to_statfs(device);
+ errx(2, "cannot find special device for %s", *argv);
fsi = open(device, O_RDONLY);
if (fsi < 0)
- err(1, "%s", device);
+ err(3, "%s", device);
/*
* Try to guess the slice size if not specified.
*/
if (ioctl(fsi, DIOCGMEDIASIZE, &mediasize) == -1)
- err(1,"DIOCGMEDIASIZE");
+ err(3,"DIOCGMEDIASIZE");
/*
* Check if that partition is suitable for growing a file system.
*/
if (mediasize < 1)
- errx(1, "partition is unavailable");
+ errx(2, "partition is unavailable");
/*
* Read the current superblock, and take a backup.
*/
- if ((ret = sbget(fsi, &fs, STDSB)) != 0) {
+ if ((ret = sbget(fsi, &fs, UFS_STDSB, 0)) != 0) {
switch (ret) {
case ENOENT:
- errx(1, "superblock not recognized");
+ errx(2, "superblock not recognized");
default:
- errc(1, ret, "unable to read superblock");
+ errc(3, ret, "unable to read superblock");
}
}
/*
* Check for filesystem that was unclean at mount time.
*/
if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) != 0)
- errx(1, "%s is not clean - run fsck.\n", *argv);
+ errx(2, "%s is not clean - run fsck.\n", *argv);
memcpy(&osblock, fs, fs->fs_sbsize);
free(fs);
memcpy((void *)&fsun1, (void *)&fsun2, osblock.fs_sbsize);
@@ -1488,7 +1410,7 @@ main(int argc, char **argv)
mediasize,
"B", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
- errx(1, "requested size %s is larger "
+ errx(2, "requested size %s is larger "
"than the available %s", oldsizebuf, newsizebuf);
}
}
@@ -1509,7 +1431,7 @@ main(int argc, char **argv)
if (size == (uint64_t)(osblock.fs_size * osblock.fs_fsize))
errx(0, "requested size %s is equal to the current "
"filesystem size %s", newsizebuf, oldsizebuf);
- errx(1, "requested size %s is smaller than the current "
+ errx(2, "requested size %s is smaller than the current "
"filesystem size %s", newsizebuf, oldsizebuf);
}
@@ -1521,7 +1443,7 @@ main(int argc, char **argv)
* Are we really growing?
*/
if (osblock.fs_size >= sblock.fs_size) {
- errx(1, "we are not growing (%jd->%jd)",
+ errx(3, "we are not growing (%jd->%jd)",
(intmax_t)osblock.fs_size, (intmax_t)sblock.fs_size);
}
@@ -1531,7 +1453,7 @@ main(int argc, char **argv)
if (yflag == 0) {
for (j = 0; j < FSMAXSNAP; j++) {
if (sblock.fs_snapinum[j]) {
- errx(1, "active snapshot found in file system; "
+ errx(2, "active snapshot found in file system; "
"please remove all snapshots before "
"using growfs");
}
@@ -1576,14 +1498,14 @@ main(int argc, char **argv)
if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) {
fso = open(_PATH_UFSSUSPEND, O_RDWR);
if (fso == -1)
- err(1, "unable to open %s", _PATH_UFSSUSPEND);
+ err(3, "unable to open %s", _PATH_UFSSUSPEND);
error = ioctl(fso, UFSSUSPEND, &statfsp->f_fsid);
if (error != 0)
- err(1, "UFSSUSPEND");
+ err(3, "UFSSUSPEND");
} else {
fso = open(device, O_WRONLY);
if (fso < 0)
- err(1, "%s", device);
+ err(3, "%s", device);
}
}
@@ -1592,7 +1514,7 @@ main(int argc, char **argv)
*/
testbuf = malloc(sblock.fs_fsize);
if (testbuf == NULL)
- err(1, "malloc");
+ err(3, "malloc");
rdfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE),
sblock.fs_fsize, testbuf, fsi);
wtfs((ufs2_daddr_t)((size - sblock.fs_fsize) / DEV_BSIZE),
@@ -1647,7 +1569,7 @@ main(int argc, char **argv)
fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
if (osblock.fs_size >= sblock.fs_size)
- errx(1, "not enough new space");
+ errx(3, "not enough new space");
DBG_PRINT0("sblock calculated\n");
@@ -1661,13 +1583,14 @@ main(int argc, char **argv)
if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) == 0) {
error = ioctl(fso, UFSRESUME);
if (error != 0)
- err(1, "UFSRESUME");
+ err(3, "UFSRESUME");
}
error = close(fso);
if (error != 0)
- err(1, "close");
- if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0)
- mount_reload(statfsp);
+ err(3, "close");
+ if (statfsp != NULL && (statfsp->f_flags & MNT_RDONLY) != 0 &&
+ chkdoreload(statfsp, warn) != 0)
+ exit(9);
}
DBG_CLOSE;
@@ -1734,29 +1657,6 @@ updclst(int block)
return;
}
-static void
-mount_reload(const struct statfs *stfs)
-{
- char errmsg[255];
- struct iovec *iov;
- int iovlen;
-
- iov = NULL;
- iovlen = 0;
- *errmsg = '\0';
- build_iovec(&iov, &iovlen, "fstype", __DECONST(char *, "ffs"), 4);
- build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, stfs->f_mntonname), (size_t)-1);
- build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
- build_iovec(&iov, &iovlen, "update", NULL, 0);
- build_iovec(&iov, &iovlen, "reload", NULL, 0);
-
- if (nmount(iov, iovlen, stfs->f_flags) < 0) {
- errmsg[sizeof(errmsg) - 1] = '\0';
- err(9, "%s: cannot reload filesystem%s%s", stfs->f_mntonname,
- *errmsg != '\0' ? ": " : "", errmsg);
- }
-}
-
/*
* Calculate the check-hash of the cylinder group.
*/
diff --git a/sbin/growfs/tests/Makefile b/sbin/growfs/tests/Makefile
index 6a3208d9c441..a23b430f58fa 100644
--- a/sbin/growfs/tests/Makefile
+++ b/sbin/growfs/tests/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
TAP_TESTS_PERL= legacy_test
.include <bsd.test.mk>
diff --git a/sbin/growfs/tests/Makefile.depend b/sbin/growfs/tests/Makefile.depend
index f80275d86ab1..11aba52f82cf 100644
--- a/sbin/growfs/tests/Makefile.depend
+++ b/sbin/growfs/tests/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/growfs/tests/legacy_test.pl b/sbin/growfs/tests/legacy_test.pl
index 931a57b6dde4..e2b145fa7f35 100755
--- a/sbin/growfs/tests/legacy_test.pl
+++ b/sbin/growfs/tests/legacy_test.pl
@@ -1,4 +1,3 @@
-# $FreeBSD$
use strict;
use warnings;
@@ -31,9 +30,9 @@ sub fsck_md {
sub setsize {
my ($partszMB, $unitszMB) = @_;
- open my $fd, "|-", "bsdlabel -R md$unit /dev/stdin" or die;
- print $fd "a: ", ($partszMB * BLKS_PER_MB), " 0 4.2BSD 1024 8192\n";
- print $fd "c: ", ($unitszMB * BLKS_PER_MB), " 0 unused 0 0\n";
+ open my $fd, "|-", "gpart restore -F md$unit" or die;
+ print $fd "BSD 8\n";
+ print $fd "1 freebsd-ufs 0 ", ($partszMB * BLKS_PER_MB), "\n";
close $fd;
}
diff --git a/sbin/gvinum/Makefile b/sbin/gvinum/Makefile
deleted file mode 100644
index 18550053228a..000000000000
--- a/sbin/gvinum/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# $FreeBSD$
-
-PACKAGE=runtime
-PROG= gvinum
-SRCS= gvinum.c gvinum.h geom_vinum_share.c
-MAN= gvinum.8
-
-WARNS?= 2
-CFLAGS+= -I${SRCTOP}/sys -I${SYSROOT:U${DESTDIR}}/${INCLUDEDIR}/edit
-
-LIBADD= edit geom
-
-.PATH: ${SRCTOP}/sys/geom/vinum
-
-.include <bsd.prog.mk>
diff --git a/sbin/gvinum/Makefile.depend b/sbin/gvinum/Makefile.depend
deleted file mode 100644
index bc5225ea2a80..000000000000
--- a/sbin/gvinum/Makefile.depend
+++ /dev/null
@@ -1,23 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libedit \
- lib/libedit/edit/readline \
- lib/libexpat \
- lib/libgeom \
- lib/libsbuf \
- lib/ncurses/ncursesw \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/sbin/gvinum/gvinum.8 b/sbin/gvinum/gvinum.8
deleted file mode 100644
index a8135e9bf4a2..000000000000
--- a/sbin/gvinum/gvinum.8
+++ /dev/null
@@ -1,462 +0,0 @@
-.\" Copyright (c) 2005 Chris Jones
-.\" All rights reserved.
-.\"
-.\" This software was developed for the FreeBSD Project by Chris Jones
-.\" thanks to the support of Google's Summer of Code program and
-.\" mentoring by Lukas Ertl.
-.\"
-.\" 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd March 28, 2021
-.Dt GVINUM 8
-.Os
-.Sh NAME
-.Nm gvinum
-.Nd Logical Volume Manager control program
-.Sh DEPRECATION NOTICE
-.Nm
-and associated
-.Xr geom 4
-kernel support is deprecated, and may not be available in
-.Fx 14.0
-and later.
-Users are advised to migrate to
-.Xr gconcat 8 ,
-.Xr gmirror 8 ,
-.Xr gstripe 8 ,
-.Xr graid 8 ,
-or
-.Xr ZFS 8 .
-More information is available at
-.Pa https://wiki.freebsd.org/DeprecationPlan/gvinum .
-.Sh SYNOPSIS
-.Nm
-.Op Ar command
-.Op Fl options
-.Sh COMMANDS
-.Bl -tag -width indent
-.It Ic attach Ar plex volume Op Cm rename
-.It Ic attach Ar subdisk plex Oo Ar offset Oc Op Cm rename
-Attach a plex to a volume, or a subdisk to a plex.
-If offset is specified, the subdisk will be attached to the given offset within
-the plex.
-If rename is specified, the subdisk or plex will change name according to the
-object it attaches to.
-.It Ic checkparity Oo Fl f Oc Ar plex
-Check the parity blocks of a RAID-5 plex.
-The parity check will start at the
-beginning of the plex if the
-.Fl f
-flag is specified, or otherwise at the location of the parity check pointer,
-the first location at which plex's parity is incorrect.
-All subdisks in the
-plex must be up for a parity check.
-.It Ic concat Oo Fl fv Oc Oo Fl n Ar name Oc Ar drives
-Create a concatenated volume from the specified drives.
-If no name is specified, a unique name will be set by
-.Ic gvinum .
-.It Ic create Oo Fl f Oc Op Ar description-file
-Create a volume as described in
-.Ar description-file .
-If no
-.Ar description-file
-provided, opens an editor and provides the current
-.Nm
-configuration for editing.
-The
-.Fl f
-flag will make gvinum ignore any errors regarding creating objects that already
-exists.
-However, in contrast to vinum, objects that are not properly named in the
-.Ar description-file
-will not be created when the
-.Fl f
-flag is given.
-.It Ic detach Oo Fl f Oc Op Ar plex | subdisk
-Detach a plex or subdisk from the volume or plex to which it is
-attached.
-.It Ic grow Ar plex device
-Grow a plex by creating a gvinum drive and subdisk on device and attach it to
-the plex.
-If required by the plex organization, it will be put into the growable state.
-.It Ic help
-Provides a synopsis of
-.Nm
-commands and arguments.
-.It Ic l | list Oo Fl rvV Oc Op Ar volume | plex | subdisk
-.It Ic ld Oo Fl rvV Oc Op Ar drive ...
-.It Ic ls Oo Fl rvV Oc Op Ar subdisk ...
-.It Ic lp Oo Fl rvV Oc Op Ar plex ...
-.It Ic lv Oo Fl rvV Oc Op Ar volume ...
-List information about the relevant object(s).
-The
-.Fl r
-flag provides recursive display, showing each object's subordinate objects in
-proper relation.
-The
-.Fl v
-and
-.Fl V
-flags provide progressively more detailed output.
-.It Ic mirror Oo Fl fsv Oc Oo Fl n Ar name Oc Ar drives
-Create a mirrored volume from the specified drives.
-It requires at least a multiple of 2 drives.
-If no name is specified, a unique name will be set by gvinum.
-If the
-.Fl s
-flag is specified, a striped mirror will be created, and thus requires a
-multiple of 4 drives.
-.It Ic move | mv Fl f Ar drive subdisk Op Ar ...
-Move the subdisk(s) to the specified drive.
-The
-.Fl f
-flag is required, as all data on the indicated subdisk(s) will be destroyed as
-part of the move.
-This can currently only be done when the subdisk is
-not being accessed.
-.Pp
-If a single subdisk is moved, and it forms a part of a RAID-5 plex, the moved
-subdisks will need to be set to the
-.Dq stale
-state, and the plex will require a
-.Ic start
-command.
-If multiple subdisk(s) is moved, and form part of a RAID-5 plex, the
-moved disk(s) will need to be set to the
-.Dq up
-state and the plex will require a
-.Ic rebuildparity
-command.
-If the subdisk(s) form part of a plex that is mirrored with other
-plexes, the plex will require restarting and will sync once restarted.
-Moving
-more than one subdisk in a RAID-5 plex or subdisks from both sides of a
-mirrored plex volume will destroy data.
-Note that parity rebuilds and syncing
-must be started manually after a move.
-.It Ic printconfig
-Write a copy of the current configuration to standard output.
-.It Ic quit
-Exit
-.Nm
-when running in interactive mode.
-Normally this would be done by entering the
-EOF character.
-.It Ic raid5 Oo Fl fv Oc Oo Fl s Ar stripesize Oc Oo Fl n Ar name Oc Ar drives
-Create a RAID-5 volume from the specified drives.
-If no name is specified, a unique name will be set by
-.Ic gvinum .
-This organization requires at least three drives.
-.It Ic rename Oo Fl r Oc Ar drive | subdisk | plex | volume newname
-Change the name of the specified object.
-The
-.Fl r
-flag will recursively rename subordinate objects.
-.Pp
-Note that device nodes will not be renamed until
-.Nm
-is restarted.
-.It Ic rebuildparity Oo Fl f Oc Ar plex
-Rebuild the parity blocks of a RAID-5 plex.
-The parity rebuild will start at
-the beginning of the plex if the
-.Fl f
-flag is specified, or otherwise at the location of the parity check pointer.
-All subdisks in the plex must be up for a parity check.
-.It Ic resetconfig Oo Fl f Oc
-Reset the complete
-.Nm
-configuration.
-.It Ic rm Oo Fl r Oc Ar volume | plex | subdisk
-Remove an object and, if
-.Fl r
-is specified, its subordinate objects.
-.It Ic saveconfig
-Save
-.Nm
-configuration to disk after configuration failures.
-.It Ic setstate Oo Fl f Oc Ar state volume | plex | subdisk | drive
-Set state without influencing other objects, for diagnostic purposes
-only.
-The
-.Fl f
-flag forces state changes regardless of whether they are legal.
-.It Ic start
-Read configuration from all vinum drives.
-.It Ic start Oo Fl S Ar size Oc Ar volume | plex | subdisk
-Allow the system to access the objects.
-If necessary, plexes will be synced and rebuilt.
-If a subdisk was added to a running RAID-5 or striped plex, gvinum will
-expand into this subdisk and grow the whole RAID-5 array.
-This can be done without unmounting your filesystem.
-The
-.Fl S
-flag is currently ignored.
-.It Ic stop Oo Fl f Oc Op Ar volume | plex | subdisk
-Terminate access to the objects, or stop
-.Nm
-if no parameters are specified.
-.It Ic stripe Oo Fl fv Oc Oo Fl n Ar name Oc Ar drives
-Create a striped volume from the specified drives.
-If no name is specified, a unique name will be set by
-.Ic gvinum .
-This organization requires at least two drives.
-.El
-.Sh DESCRIPTION
-The
-.Nm
-utility communicates with the kernel component of the GVinum logical volume
-manager.
-It is designed either for interactive use, when started without
-command line arguments, or to execute a single command if the command is
-supplied on the command line.
-In interactive mode,
-.Nm
-maintains a command line history.
-.Sh OPTIONS
-The
-.Nm
-commands may be followed by an option.
-.Bl -tag -width indent
-.It Fl f
-The
-.Fl f
-.Pq Dq force
-option overrides safety checks.
-It should be used with extreme caution.
-This
-option is required in order to use the
-.Ic move
-command.
-.It Fl r
-The
-.Fl r
-.Pq Dq recursive
-option applies the command recursively to subordinate objects.
-For example, in
-conjunction with the
-.Ic lv
-command, the
-.Fl r
-option will also show information about the plexes and subdisks belonging to
-the volume.
-It is also used by the
-.Ic rename
-command to indicate that subordinate objects such as subdisks should be renamed
-to match the object(s) specified and by the
-.Ic rm
-command to delete plexes belonging to a volume and so on.
-.It Fl v
-The
-.Fl v
-.Pq Dq verbose
-option provides more detailed output.
-.It Fl V
-The
-.Fl V
-.Pq Dq "very verbose"
-option provides even more detailed output than
-.Fl v .
-.El
-.Sh ENVIRONMENT
-.Bl -tag -width ".Ev EDITOR"
-.It Ev EDITOR
-The name of the editor to use for editing configuration files, by
-default
-.Xr vi 1
-is invoked.
-.El
-.Sh FILES
-.Bl -tag -width ".Pa /dev/gvinum/plex"
-.It Pa /dev/gvinum
-directory with device nodes for
-.Nm
-objects
-.El
-.Sh EXAMPLES
-To create a mirror on disks /dev/ada1 and /dev/ada2, create a filesystem,
-mount, unmount and then stop
-.Ic gvinum :
-.Pp
-.Dl "gvinum mirror /dev/ada1 /dev/ada2"
-.Dl "newfs /dev/gvinum/gvinumvolume0"
-.Dl "mount /dev/gvinum/gvinumvolume0 /mnt"
-.Dl "..."
-.Dl "unmount /mnt"
-.Dl "gvinum stop"
-.Pp
-To create a striped mirror on disks /dev/ada1 /dev/ada2 /dev/ada3 and
-/dev/ada4 named "data" and create a filesystem:
-.Pp
-.Dl "gvinum mirror -s -n data /dev/ada1 /dev/ada2 /dev/ada3 /dev/ada4"
-.Dl "newfs /dev/gvinum/data"
-.Pp
-To create a raid5 array on disks /dev/ada1 /dev/ada2 and /dev/ada3,
-with stripesize 493k you can use the raid5 command:
-.Pp
-.Dl "gvinum raid5 -s 493k /dev/ada1 /dev/ada2 /dev/ada3"
-.Pp
-Then the volume will be created automatically.
-Afterwards, you have to initialize the volume:
-.Pp
-.Dl "gvinum start myraid5vol"
-.Pp
-The initialization will start, and the states will be updated when it's
-finished.
-The list command will give you information about its progress.
-.Pp
-Imagine that one of the drives fails, and the output of 'printconfig' looks
-something like this:
-.Pp
-.Dl "drive gvinumdrive1 device /dev/ada2"
-.Dl "drive gvinumdrive2 device /dev/???"
-.Dl "drive gvinumdrive0 device /dev/ada1"
-.Dl "volume myraid5vol"
-.Dl "plex name myraid5vol.p0 org raid5 986s vol myraid5vol"
-.Dl "sd name myraid5vol.p0.s2 drive gvinumdrive2 len 32538s driveoffset 265s"
-.Dl "plex myraid5vol.p0 plexoffset 1972s"
-.Dl "sd name myraid5vol.p0.s1 drive gvinumdrive1 len 32538s driveoffset 265s"
-.Dl "plex myraid5vol.p0 plexoffset 986s"
-.Dl "sd name myraid5vol.p0.s0 drive gvinumdrive0 len 32538s driveoffset 265s"
-.Dl "plex myraid5vol.p0 plexoffset 0s"
-.Pp
-Create a new drive with this configuration:
-.Pp
-.Dl "drive gdrive4 device /dev/ada4"
-.Pp
-Then move the stale subdisk to the new drive:
-.Pp
-.Dl "gvinum move gdrive4 myraid5vol.p0.s2"
-.Pp
-Then, initiate the rebuild:
-.Pp
-.Dl "gvinum start myraid5vol.p0"
-.Pp
-The plex will go up form degraded mode after the rebuild is finished.
-The plex can still be used while the rebuild is in progress, although requests
-might be delayed.
-.Pp
-Given the configuration as in the previous example, growing a RAID-5 or STRIPED
-array is accomplished by using the grow command:
-.Pp
-.Dl "gvinum grow myraid5vol.p0 /dev/ada4"
-.Pp
-If everything went ok, the plex state should now be set to growable.
-You can then start the growing with the
-.Ic start
-command:
-.Pp
-.Dl "gvinum start myraid5vol.p0"
-.Pp
-As with rebuilding, you can watch the progress using the
-.Ic list
-command.
-.Pp
-For a more advanced usage and detailed explanation of gvinum, the
-handbook is recommended.
-.Sh SEE ALSO
-.Xr geom 4 ,
-.Xr geom 8
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Fx 5.3 .
-The
-.Nm vinum
-utility, on which
-.Nm
-is based, was written by
-.An "Greg Lehey" .
-.Pp
-The
-.Nm
-utility
-was written by
-.An "Lukas Ertl" .
-The
-.Ic move
-and
-.Ic rename
-commands and
-documentation were added by
-.An "Chris Jones"
-through the 2005 Google Summer
-of Code program.
-A partial rewrite of gvinum was done by
-.An "Lukas Ertl"
-and
-.An "Ulf Lilleengen"
-through the 2007 Google Summer of Code program.
-The documentation have been updated to reflect the new functionality.
-.Sh AUTHORS
-.An Lukas Ertl Aq Mt le@FreeBSD.org
-.An Chris Jones Aq Mt soc-cjones@FreeBSD.org
-.An Ulf Lilleengen Aq Mt lulf@FreeBSD.org
-.Sh BUGS
-Currently,
-.Nm
-does not rename devices in
-.Pa /dev/gvinum
-until reloaded.
-.Pp
-The
-.Fl S
-initsize flag to
-.Ic start
-is ignored.
-.Pp
-Moving subdisks that are not part of a mirrored or RAID-5 volume will
-destroy data.
-It is perhaps a bug to permit this.
-.Pp
-Plexes in which subdisks have been moved do not automatically sync or
-rebuild parity.
-This may leave data unprotected and is perhaps unwise.
-.Pp
-Currently,
-.Nm
-does not yet fully implement all of the functions found in
-.Nm vinum .
-Specifically, the following commands from
-.Nm vinum
-are not supported:
-.Bl -tag -width indent
-.It Ic debug
-Cause the volume manager to enter the kernel debugger.
-.It Ic debug Ar flags
-Set debugging flags.
-.It Ic dumpconfig Op Ar drive ...
-List the configuration information stored on the specified drives, or all
-drives in the system if no drive names are specified.
-.It Ic info Op Fl vV
-List information about volume manager state.
-.It Ic label Ar volume
-Create a volume label.
-.It Ic resetstats Oo Fl r Oc Op Ar volume | plex | subdisk
-Reset statistics counters for the specified objects, or for all objects if none
-are specified.
-.It Ic setdaemon Op Ar value
-Set daemon configuration.
-.El
diff --git a/sbin/gvinum/gvinum.c b/sbin/gvinum/gvinum.c
deleted file mode 100644
index 5a081e92a8df..000000000000
--- a/sbin/gvinum/gvinum.c
+++ /dev/null
@@ -1,1452 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2004 Lukas Ertl
- * Copyright (c) 2005 Chris Jones
- * Copyright (c) 2007 Ulf Lilleengen
- * All rights reserved.
- *
- * Portions of this software were developed for the FreeBSD Project
- * by Chris Jones thanks to the support of Google's Summer of Code
- * program and mentoring by Lukas Ertl.
- *
- * 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.
- *
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/linker.h>
-#include <sys/lock.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/queue.h>
-#include <sys/utsname.h>
-
-#include <geom/vinum/geom_vinum_var.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <libgeom.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <paths.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-#include <unistd.h>
-
-#include "gvinum.h"
-
-static void gvinum_attach(int, char * const *);
-static void gvinum_concat(int, char * const *);
-static void gvinum_create(int, char * const *);
-static void gvinum_detach(int, char * const *);
-static void gvinum_grow(int, char * const *);
-static void gvinum_help(void);
-static void gvinum_list(int, char * const *);
-static void gvinum_move(int, char * const *);
-static void gvinum_mirror(int, char * const *);
-static void gvinum_parityop(int, char * const * , int);
-static void gvinum_printconfig(int, char * const *);
-static void gvinum_raid5(int, char * const *);
-static void gvinum_rename(int, char * const *);
-static void gvinum_resetconfig(int, char * const *);
-static void gvinum_rm(int, char * const *);
-static void gvinum_saveconfig(void);
-static void gvinum_setstate(int, char * const *);
-static void gvinum_start(int, char * const *);
-static void gvinum_stop(int, char * const *);
-static void gvinum_stripe(int, char * const *);
-static void parseline(int, char * const *);
-static void printconfig(FILE *, const char *);
-
-static char *create_drive(const char *);
-static void create_volume(int, char * const * , const char *);
-static char *find_name(const char *, int, int);
-static const char *find_pattern(char *, const char *);
-static void copy_device(struct gv_drive *, const char *);
-#define find_drive() \
- find_name("gvinumdrive", GV_TYPE_DRIVE, GV_MAXDRIVENAME)
-
-int
-main(int argc, char **argv)
-{
- int tokens;
- char buffer[BUFSIZ], *inputline, *token[GV_MAXARGS];
-
- /* Load the module if necessary. */
- if (modfind(GVINUMMOD) < 0) {
- if (kldload(GVINUMKLD) < 0 && modfind(GVINUMMOD) < 0)
- err(1, GVINUMKLD ": Kernel module not available");
- }
-
- /* Arguments given on the command line. */
- if (argc > 1) {
- argc--;
- argv++;
- parseline(argc, argv);
-
- /* Interactive mode. */
- } else {
- for (;;) {
- inputline = readline("gvinum -> ");
- if (inputline == NULL) {
- if (ferror(stdin)) {
- err(1, "can't read input");
- } else {
- printf("\n");
- exit(0);
- }
- } else if (*inputline) {
- add_history(inputline);
- strcpy(buffer, inputline);
- free(inputline);
- tokens = gv_tokenize(buffer, token, GV_MAXARGS);
- if (tokens)
- parseline(tokens, token);
- }
- }
- }
- exit(0);
-}
-
-/* Attach a plex to a volume or a subdisk to a plex. */
-static void
-gvinum_attach(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- int rename;
- off_t offset;
-
- rename = 0;
- offset = -1;
- if (argc < 3) {
- warnx("usage:\tattach <subdisk> <plex> [rename] "
- "[<plexoffset>]\n"
- "\tattach <plex> <volume> [rename]");
- return;
- }
- if (argc > 3) {
- if (!strcmp(argv[3], "rename")) {
- rename = 1;
- if (argc == 5)
- offset = strtol(argv[4], NULL, 0);
- } else
- offset = strtol(argv[3], NULL, 0);
- }
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "attach");
- gctl_ro_param(req, "child", -1, argv[1]);
- gctl_ro_param(req, "parent", -1, argv[2]);
- gctl_ro_param(req, "offset", sizeof(off_t), &offset);
- gctl_ro_param(req, "rename", sizeof(int), &rename);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("attach failed: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_create(int argc, char * const *argv)
-{
- struct gctl_req *req;
- struct gv_drive *d;
- struct gv_plex *p;
- struct gv_sd *s;
- struct gv_volume *v;
- FILE *tmp;
- int drives, errors, fd, flags, i, line, plexes, plex_in_volume;
- int sd_in_plex, status, subdisks, tokens, undeffd, volumes;
- const char *errstr;
- char buf[BUFSIZ], buf1[BUFSIZ], commandline[BUFSIZ], *sdname;
- const char *ed;
- char original[BUFSIZ], tmpfile[20], *token[GV_MAXARGS];
- char plex[GV_MAXPLEXNAME], volume[GV_MAXVOLNAME];
-
- tmp = NULL;
- flags = 0;
- for (i = 1; i < argc; i++) {
- /* Force flag used to ignore already created drives. */
- if (!strcmp(argv[i], "-f")) {
- flags |= GV_FLAG_F;
- /* Else it must be a file. */
- } else {
- if ((tmp = fopen(argv[i], "r")) == NULL) {
- warn("can't open '%s' for reading", argv[i]);
- return;
- }
- }
- }
-
- /* We didn't get a file. */
- if (tmp == NULL) {
- snprintf(tmpfile, sizeof(tmpfile), "/tmp/gvinum.XXXXXX");
-
- if ((fd = mkstemp(tmpfile)) == -1) {
- warn("temporary file not accessible");
- return;
- }
- if ((tmp = fdopen(fd, "w")) == NULL) {
- warn("can't open '%s' for writing", tmpfile);
- return;
- }
- printconfig(tmp, "# ");
- fclose(tmp);
-
- ed = getenv("EDITOR");
- if (ed == NULL)
- ed = _PATH_VI;
-
- snprintf(commandline, sizeof(commandline), "%s %s", ed,
- tmpfile);
- status = system(commandline);
- if (status != 0) {
- warn("couldn't exec %s; status: %d", ed, status);
- return;
- }
-
- if ((tmp = fopen(tmpfile, "r")) == NULL) {
- warn("can't open '%s' for reading", tmpfile);
- return;
- }
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "create");
- gctl_ro_param(req, "flags", sizeof(int), &flags);
-
- drives = volumes = plexes = subdisks = 0;
- plex_in_volume = sd_in_plex = undeffd = 0;
- plex[0] = '\0';
- errors = 0;
- line = 1;
- while ((fgets(buf, BUFSIZ, tmp)) != NULL) {
-
- /* Skip empty lines and comments. */
- if (*buf == '\0' || *buf == '#') {
- line++;
- continue;
- }
-
- /* Kill off the newline. */
- buf[strlen(buf) - 1] = '\0';
-
- /*
- * Copy the original input line in case we need it for error
- * output.
- */
- strlcpy(original, buf, sizeof(original));
-
- tokens = gv_tokenize(buf, token, GV_MAXARGS);
- if (tokens <= 0) {
- line++;
- continue;
- }
-
- /* Volume definition. */
- if (!strcmp(token[0], "volume")) {
- v = gv_new_volume(tokens, token);
- if (v == NULL) {
- warnx("line %d: invalid volume definition",
- line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- /* Reset plex count for this volume. */
- plex_in_volume = 0;
-
- /*
- * Set default volume name for following plex
- * definitions.
- */
- strlcpy(volume, v->name, sizeof(volume));
-
- snprintf(buf1, sizeof(buf1), "volume%d", volumes);
- gctl_ro_param(req, buf1, sizeof(*v), v);
- volumes++;
-
- /* Plex definition. */
- } else if (!strcmp(token[0], "plex")) {
- p = gv_new_plex(tokens, token);
- if (p == NULL) {
- warnx("line %d: invalid plex definition", line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- /* Reset subdisk count for this plex. */
- sd_in_plex = 0;
-
- /* Default name. */
- if (strlen(p->name) == 0) {
- snprintf(p->name, sizeof(p->name), "%s.p%d",
- volume, plex_in_volume++);
- }
-
- /* Default volume. */
- if (strlen(p->volume) == 0) {
- snprintf(p->volume, sizeof(p->volume), "%s",
- volume);
- }
-
- /*
- * Set default plex name for following subdisk
- * definitions.
- */
- strlcpy(plex, p->name, sizeof(plex));
-
- snprintf(buf1, sizeof(buf1), "plex%d", plexes);
- gctl_ro_param(req, buf1, sizeof(*p), p);
- plexes++;
-
- /* Subdisk definition. */
- } else if (!strcmp(token[0], "sd")) {
- s = gv_new_sd(tokens, token);
- if (s == NULL) {
- warnx("line %d: invalid subdisk "
- "definition:", line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- /* Default name. */
- if (strlen(s->name) == 0) {
- if (strlen(plex) == 0) {
- sdname = find_name("gvinumsubdisk.p",
- GV_TYPE_SD, GV_MAXSDNAME);
- snprintf(s->name, sizeof(s->name),
- "%s.s%d", sdname, undeffd++);
- free(sdname);
- } else {
- snprintf(s->name, sizeof(s->name),
- "%s.s%d",plex, sd_in_plex++);
- }
- }
-
- /* Default plex. */
- if (strlen(s->plex) == 0)
- snprintf(s->plex, sizeof(s->plex), "%s", plex);
-
- snprintf(buf1, sizeof(buf1), "sd%d", subdisks);
- gctl_ro_param(req, buf1, sizeof(*s), s);
- subdisks++;
-
- /* Subdisk definition. */
- } else if (!strcmp(token[0], "drive")) {
- d = gv_new_drive(tokens, token);
- if (d == NULL) {
- warnx("line %d: invalid drive definition:",
- line);
- warnx("line %d: '%s'", line, original);
- errors++;
- line++;
- continue;
- }
-
- snprintf(buf1, sizeof(buf1), "drive%d", drives);
- gctl_ro_param(req, buf1, sizeof(*d), d);
- drives++;
-
- /* Everything else is bogus. */
- } else {
- warnx("line %d: invalid definition:", line);
- warnx("line %d: '%s'", line, original);
- errors++;
- }
- line++;
- }
-
- fclose(tmp);
- unlink(tmpfile);
-
- if (!errors && (volumes || plexes || subdisks || drives)) {
- gctl_ro_param(req, "volumes", sizeof(int), &volumes);
- gctl_ro_param(req, "plexes", sizeof(int), &plexes);
- gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("create failed: %s", errstr);
- }
- gctl_free(req);
-}
-
-/* Create a concatenated volume. */
-static void
-gvinum_concat(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage:\tconcat [-fv] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "concat");
-}
-
-/* Create a drive quick and dirty. */
-static char *
-create_drive(const char *device)
-{
- struct gv_drive *d;
- struct gctl_req *req;
- const char *errstr;
- char *drivename, *dname;
- int drives, i, flags, volumes, subdisks, plexes;
- int found = 0;
-
- flags = plexes = subdisks = volumes = 0;
- drives = 1;
- dname = NULL;
-
- drivename = find_drive();
- if (drivename == NULL)
- return (NULL);
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "create");
- d = gv_alloc_drive();
- if (d == NULL)
- err(1, "unable to allocate for gv_drive object");
-
- strlcpy(d->name, drivename, sizeof(d->name));
- copy_device(d, device);
- gctl_ro_param(req, "drive0", sizeof(*d), d);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- gctl_ro_param(req, "volumes", sizeof(int), &volumes);
- gctl_ro_param(req, "plexes", sizeof(int), &plexes);
- gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("error creating drive: %s", errstr);
- drivename = NULL;
- } else {
- /* XXX: This is needed because we have to make sure the drives
- * are created before we return. */
- /* Loop until it's in the config. */
- for (i = 0; i < 100000; i++) {
- dname = find_name("gvinumdrive", GV_TYPE_DRIVE,
- GV_MAXDRIVENAME);
- /* If we got a different name, quit. */
- if (dname == NULL)
- continue;
- if (strcmp(dname, drivename))
- found = 1;
- free(dname);
- dname = NULL;
- if (found)
- break;
- usleep(100000); /* Sleep for 0.1s */
- }
- if (found == 0) {
- warnx("error creating drive");
- drivename = NULL;
- }
- }
- gctl_free(req);
- return (drivename);
-}
-
-/*
- * General routine for creating a volume. Mainly for use by concat, mirror,
- * raid5 and stripe commands.
- */
-static void
-create_volume(int argc, char * const *argv, const char *verb)
-{
- struct gctl_req *req;
- const char *errstr;
- char buf[BUFSIZ], *drivename, *volname;
- int drives, flags, i;
- off_t stripesize;
-
- flags = 0;
- drives = 0;
- volname = NULL;
- stripesize = 262144;
-
- /* XXX: Should we check for argument length? */
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
-
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-f")) {
- flags |= GV_FLAG_F;
- } else if (!strcmp(argv[i], "-n")) {
- volname = argv[++i];
- } else if (!strcmp(argv[i], "-v")) {
- flags |= GV_FLAG_V;
- } else if (!strcmp(argv[i], "-s")) {
- flags |= GV_FLAG_S;
- if (!strcmp(verb, "raid5"))
- stripesize = gv_sizespec(argv[++i]);
- } else {
- /* Assume it's a drive. */
- snprintf(buf, sizeof(buf), "drive%d", drives++);
-
- /* First we create the drive. */
- drivename = create_drive(argv[i]);
- if (drivename == NULL)
- goto bad;
- /* Then we add it to the request. */
- gctl_ro_param(req, buf, -1, drivename);
- }
- }
-
- gctl_ro_param(req, "stripesize", sizeof(off_t), &stripesize);
-
- /* Find a free volume name. */
- if (volname == NULL)
- volname = find_name("gvinumvolume", GV_TYPE_VOL, GV_MAXVOLNAME);
-
- /* Then we send a request to actually create the volumes. */
- gctl_ro_param(req, "verb", -1, verb);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- gctl_ro_param(req, "name", -1, volname);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("creating %s volume failed: %s", verb, errstr);
-bad:
- gctl_free(req);
-}
-
-/* Parse a line of the config, return the word after <pattern>. */
-static const char *
-find_pattern(char *line, const char *pattern)
-{
- char *ptr;
-
- ptr = strsep(&line, " ");
- while (ptr != NULL) {
- if (!strcmp(ptr, pattern)) {
- /* Return the next. */
- ptr = strsep(&line, " ");
- return (ptr);
- }
- ptr = strsep(&line, " ");
- }
- return (NULL);
-}
-
-/* Find a free name for an object given a prefix. */
-static char *
-find_name(const char *prefix, int type, int namelen)
-{
- struct gctl_req *req;
- char comment[1], buf[GV_CFG_LEN - 1], *sname, *ptr;
- const char *errstr, *name;
- int i, n, begin, len, conflict;
- char line[1024];
-
- comment[0] = '\0';
- buf[0] = '\0';
-
- /* Find a name. Fetch out configuration first. */
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "getconfig");
- gctl_ro_param(req, "comment", -1, comment);
- gctl_add_param(req, "config", sizeof(buf), buf,
- GCTL_PARAM_WR | GCTL_PARAM_ASCII);
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't get configuration: %s", errstr);
- return (NULL);
- }
- gctl_free(req);
-
- begin = 0;
- len = strlen(buf);
- i = 0;
- sname = malloc(namelen + 1);
-
- /* XXX: Max object setting? */
- for (n = 0; n < 10000; n++) {
- snprintf(sname, namelen, "%s%d", prefix, n);
- conflict = 0;
- begin = 0;
- /* Loop through the configuration line by line. */
- for (i = 0; i < len; i++) {
- if (buf[i] == '\n' || buf[i] == '\0') {
- ptr = buf + begin;
- strlcpy(line, ptr, (i - begin) + 1);
- begin = i + 1;
- switch (type) {
- case GV_TYPE_DRIVE:
- name = find_pattern(line, "drive");
- break;
- case GV_TYPE_VOL:
- name = find_pattern(line, "volume");
- break;
- case GV_TYPE_PLEX:
- case GV_TYPE_SD:
- name = find_pattern(line, "name");
- break;
- default:
- printf("Invalid type given\n");
- continue;
- }
- if (name == NULL)
- continue;
- if (!strcmp(sname, name)) {
- conflict = 1;
- /* XXX: Could quit the loop earlier. */
- }
- }
- }
- if (!conflict)
- return (sname);
- }
- free(sname);
- return (NULL);
-}
-
-static void
-copy_device(struct gv_drive *d, const char *device)
-{
-
- if (strncmp(device, "/dev/", 5) == 0)
- strlcpy(d->device, (device + 5), sizeof(d->device));
- else
- strlcpy(d->device, device, sizeof(d->device));
-}
-
-/* Detach a plex or subdisk from its parent. */
-static void
-gvinum_detach(int argc, char * const *argv)
-{
- const char *errstr;
- struct gctl_req *req;
- int flags, i;
-
- flags = 0;
- optreset = 1;
- optind = 1;
- while ((i = getopt(argc, argv, "f")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- default:
- warn("invalid flag: %c", i);
- return;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc != 1) {
- warnx("usage: detach [-f] <subdisk> | <plex>");
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "detach");
- gctl_ro_param(req, "object", -1, argv[0]);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
-
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("detach failed: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_help(void)
-{
-
- printf("COMMANDS\n"
- "checkparity [-f] plex\n"
- " Check the parity blocks of a RAID-5 plex.\n"
- "create [-f] description-file\n"
- " Create as per description-file or open editor.\n"
- "attach plex volume [rename]\n"
- "attach subdisk plex [offset] [rename]\n"
- " Attach a plex to a volume, or a subdisk to a plex\n"
- "concat [-fv] [-n name] drives\n"
- " Create a concatenated volume from the specified drives.\n"
- "detach [-f] [plex | subdisk]\n"
- " Detach a plex or a subdisk from the volume or plex to\n"
- " which it is attached.\n"
- "grow plex drive\n"
- " Grow plex by creating a properly sized subdisk on drive\n"
- "l | list [-r] [-v] [-V] [volume | plex | subdisk]\n"
- " List information about specified objects.\n"
- "ld [-r] [-v] [-V] [volume]\n"
- " List information about drives.\n"
- "ls [-r] [-v] [-V] [subdisk]\n"
- " List information about subdisks.\n"
- "lp [-r] [-v] [-V] [plex]\n"
- " List information about plexes.\n"
- "lv [-r] [-v] [-V] [volume]\n"
- " List information about volumes.\n"
- "mirror [-fsv] [-n name] drives\n"
- " Create a mirrored volume from the specified drives.\n"
- "move | mv -f drive object ...\n"
- " Move the object(s) to the specified drive.\n"
- "quit Exit the vinum program when running in interactive mode."
- " Nor-\n"
- " mally this would be done by entering the EOF character.\n"
- "raid5 [-fv] [-s stripesize] [-n name] drives\n"
- " Create a RAID-5 volume from the specified drives.\n"
- "rename [-r] [drive | subdisk | plex | volume] newname\n"
- " Change the name of the specified object.\n"
- "rebuildparity plex [-f]\n"
- " Rebuild the parity blocks of a RAID-5 plex.\n"
- "resetconfig [-f]\n"
- " Reset the complete gvinum configuration\n"
- "rm [-r] [-f] volume | plex | subdisk | drive\n"
- " Remove an object.\n"
- "saveconfig\n"
- " Save vinum configuration to disk after configuration"
- " failures.\n"
- "setstate [-f] state [volume | plex | subdisk | drive]\n"
- " Set state without influencing other objects, for"
- " diagnostic pur-\n"
- " poses only.\n"
- "start [-S size] volume | plex | subdisk\n"
- " Allow the system to access the objects.\n"
- "stripe [-fv] [-n name] drives\n"
- " Create a striped volume from the specified drives.\n"
- );
-}
-
-static void
-gvinum_setstate(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int flags, i;
- const char *errstr;
-
- flags = 0;
-
- optreset = 1;
- optind = 1;
-
- while ((i = getopt(argc, argv, "f")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case '?':
- default:
- warn("invalid flag: %c", i);
- return;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (argc != 2) {
- warnx("usage: setstate [-f] <state> <obj>");
- return;
- }
-
- /*
- * XXX: This hack is needed to avoid tripping over (now) invalid
- * 'classic' vinum states and will go away later.
- */
- if (strcmp(argv[0], "up") && strcmp(argv[0], "down") &&
- strcmp(argv[0], "stale")) {
- warnx("invalid state '%s'", argv[0]);
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "setstate");
- gctl_ro_param(req, "state", -1, argv[0]);
- gctl_ro_param(req, "object", -1, argv[1]);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
-
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("%s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_list(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int flags, i, j;
- const char *errstr;
- char buf[20], config[GV_CFG_LEN + 1];
- const char *cmd;
-
- flags = 0;
- cmd = "list";
-
- if (argc) {
- optreset = 1;
- optind = 1;
- cmd = argv[0];
- while ((j = getopt(argc, argv, "rsvV")) != -1) {
- switch (j) {
- case 'r':
- flags |= GV_FLAG_R;
- break;
- case 's':
- flags |= GV_FLAG_S;
- break;
- case 'v':
- flags |= GV_FLAG_V;
- break;
- case 'V':
- flags |= GV_FLAG_V;
- flags |= GV_FLAG_VV;
- break;
- case '?':
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- }
-
- config[0] = '\0';
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "list");
- gctl_ro_param(req, "cmd", -1, cmd);
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_add_param(req, "config", sizeof(config), config,
- GCTL_PARAM_WR | GCTL_PARAM_ASCII);
- if (argc) {
- for (i = 0; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- }
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't get configuration: %s", errstr);
- gctl_free(req);
- return;
- }
-
- printf("%s", config);
- gctl_free(req);
-}
-
-/* Create a mirrored volume. */
-static void
-gvinum_mirror(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage\tmirror [-fsv] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "mirror");
-}
-
-/* Note that move is currently of form '[-r] target object [...]' */
-static void
-gvinum_move(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- char buf[20];
- int flags, i, j;
-
- flags = 0;
- if (argc) {
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "f")) != -1) {
- switch (j) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case '?':
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
- }
-
- switch (argc) {
- case 0:
- warnx("no destination or object(s) to move specified");
- return;
- case 1:
- warnx("no object(s) to move specified");
- return;
- default:
- break;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "move");
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "destination", -1, argv[0]);
- for (i = 1; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("can't move object(s): %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_printconfig(int argc __unused, char * const *argv __unused)
-{
-
- printconfig(stdout, "");
-}
-
-static void
-gvinum_parityop(int argc, char * const *argv, int rebuild)
-{
- struct gctl_req *req;
- int flags, i;
- const char *errstr;
- const char *op;
-
- if (rebuild) {
- op = "rebuildparity";
- } else {
- op = "checkparity";
- }
-
- optreset = 1;
- optind = 1;
- flags = 0;
- while ((i = getopt(argc, argv, "fv")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case 'v':
- flags |= GV_FLAG_V;
- break;
- default:
- warnx("invalid flag '%c'", i);
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 1) {
- warn("usage: %s [-f] [-v] <plex>", op);
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, op);
- gctl_ro_param(req, "rebuild", sizeof(int), &rebuild);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "plex", -1, argv[0]);
-
- errstr = gctl_issue(req);
- if (errstr)
- warnx("%s\n", errstr);
- gctl_free(req);
-}
-
-/* Create a RAID-5 volume. */
-static void
-gvinum_raid5(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage:\traid5 [-fv] [-s stripesize] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "raid5");
-}
-
-static void
-gvinum_rename(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- int flags, j;
-
- flags = 0;
-
- if (argc) {
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "r")) != -1) {
- switch (j) {
- case 'r':
- flags |= GV_FLAG_R;
- break;
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
- }
-
- switch (argc) {
- case 0:
- warnx("no object to rename specified");
- return;
- case 1:
- warnx("no new name specified");
- return;
- case 2:
- break;
- default:
- warnx("more than one new name specified");
- return;
- }
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "rename");
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "object", -1, argv[0]);
- gctl_ro_param(req, "newname", -1, argv[1]);
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("can't rename object: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_rm(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int flags, i, j;
- const char *errstr;
- char buf[20];
-
- flags = 0;
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "rf")) != -1) {
- switch (j) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- case 'r':
- flags |= GV_FLAG_R;
- break;
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "remove");
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- if (argc) {
- for (i = 0; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- }
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't remove: %s", errstr);
- gctl_free(req);
- return;
- }
- gctl_free(req);
-}
-
-static void
-gvinum_resetconfig(int argc, char * const *argv)
-{
- struct gctl_req *req;
- const char *errstr;
- char reply[32];
- int flags, i;
-
- flags = 0;
- while ((i = getopt(argc, argv, "f")) != -1) {
- switch (i) {
- case 'f':
- flags |= GV_FLAG_F;
- break;
- default:
- warn("invalid flag: %c", i);
- return;
- }
- }
- if ((flags & GV_FLAG_F) == 0) {
- if (!isatty(STDIN_FILENO)) {
- warn("Please enter this command from a tty device\n");
- return;
- }
- printf(" WARNING! This command will completely wipe out"
- " your gvinum configuration.\n"
- " All data will be lost. If you really want to do this,"
- " enter the text\n\n"
- " NO FUTURE\n"
- " Enter text -> ");
- fgets(reply, sizeof(reply), stdin);
- if (strcmp(reply, "NO FUTURE\n")) {
- printf("\n No change\n");
- return;
- }
- }
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "resetconfig");
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't reset config: %s", errstr);
- gctl_free(req);
- return;
- }
- gctl_free(req);
- printf("gvinum configuration obliterated\n");
-}
-
-static void
-gvinum_saveconfig(void)
-{
- struct gctl_req *req;
- const char *errstr;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "saveconfig");
- errstr = gctl_issue(req);
- if (errstr != NULL)
- warnx("can't save configuration: %s", errstr);
- gctl_free(req);
-}
-
-static void
-gvinum_start(int argc, char * const *argv)
-{
- struct gctl_req *req;
- int i, initsize, j;
- const char *errstr;
- char buf[20];
-
- /* 'start' with no arguments is a no-op. */
- if (argc == 1)
- return;
-
- initsize = 0;
-
- optreset = 1;
- optind = 1;
- while ((j = getopt(argc, argv, "S")) != -1) {
- switch (j) {
- case 'S':
- initsize = atoi(optarg);
- break;
- default:
- return;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (!initsize)
- initsize = 512;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "start");
- gctl_ro_param(req, "argc", sizeof(int), &argc);
- gctl_ro_param(req, "initsize", sizeof(int), &initsize);
- if (argc) {
- for (i = 0; i < argc; i++) {
- snprintf(buf, sizeof(buf), "argv%d", i);
- gctl_ro_param(req, buf, -1, argv[i]);
- }
- }
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't start: %s", errstr);
- gctl_free(req);
- return;
- }
-
- gctl_free(req);
-}
-
-static void
-gvinum_stop(int argc __unused, char * const *argv __unused)
-{
- int err, fileid;
-
- fileid = kldfind(GVINUMKLD);
- if (fileid == -1) {
- if (modfind(GVINUMMOD) < 0)
- warn("cannot find " GVINUMKLD);
- return;
- }
-
- /*
- * This little hack prevents that we end up in an infinite loop in
- * g_unload_class(). gv_unload() will return EAGAIN so that the GEOM
- * event thread will be free for the g_wither_geom() call from
- * gv_unload(). It's silly, but it works.
- */
- printf("unloading " GVINUMKLD " kernel module... ");
- fflush(stdout);
- if ((err = kldunload(fileid)) != 0 && (errno == EAGAIN)) {
- sleep(1);
- err = kldunload(fileid);
- }
- if (err != 0) {
- printf(" failed!\n");
- warn("cannot unload " GVINUMKLD);
- return;
- }
-
- printf("done\n");
- exit(0);
-}
-
-/* Create a striped volume. */
-static void
-gvinum_stripe(int argc, char * const *argv)
-{
-
- if (argc < 2) {
- warnx("usage:\tstripe [-fv] [-n name] drives\n");
- return;
- }
- create_volume(argc, argv, "stripe");
-}
-
-/* Grow a subdisk by adding disk backed by provider. */
-static void
-gvinum_grow(int argc, char * const *argv)
-{
- struct gctl_req *req;
- char *drive, *sdname;
- char sdprefix[GV_MAXSDNAME];
- struct gv_drive *d;
- struct gv_sd *s;
- const char *errstr;
- int drives, volumes, plexes, subdisks, flags;
-
- flags = 0;
- drives = volumes = plexes = subdisks = 0;
- if (argc < 3) {
- warnx("usage:\tgrow plex drive\n");
- return;
- }
-
- s = gv_alloc_sd();
- if (s == NULL) {
- warn("unable to create subdisk");
- return;
- }
- d = gv_alloc_drive();
- if (d == NULL) {
- warn("unable to create drive");
- free(s);
- return;
- }
- /* Lookup device and set an appropriate drive name. */
- drive = find_drive();
- if (drive == NULL) {
- warn("unable to find an appropriate drive name");
- free(s);
- free(d);
- return;
- }
- strlcpy(d->name, drive, sizeof(d->name));
- copy_device(d, argv[2]);
-
- drives = 1;
-
- /* We try to use the plex name as basis for the subdisk name. */
- snprintf(sdprefix, sizeof(sdprefix), "%s.s", argv[1]);
- sdname = find_name(sdprefix, GV_TYPE_SD, GV_MAXSDNAME);
- if (sdname == NULL) {
- warn("unable to find an appropriate subdisk name");
- free(s);
- free(d);
- free(drive);
- return;
- }
- strlcpy(s->name, sdname, sizeof(s->name));
- free(sdname);
- strlcpy(s->plex, argv[1], sizeof(s->plex));
- strlcpy(s->drive, d->name, sizeof(s->drive));
- subdisks = 1;
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "create");
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "volumes", sizeof(int), &volumes);
- gctl_ro_param(req, "plexes", sizeof(int), &plexes);
- gctl_ro_param(req, "subdisks", sizeof(int), &subdisks);
- gctl_ro_param(req, "drives", sizeof(int), &drives);
- gctl_ro_param(req, "drive0", sizeof(*d), d);
- gctl_ro_param(req, "sd0", sizeof(*s), s);
- errstr = gctl_issue(req);
- free(drive);
- if (errstr != NULL) {
- warnx("unable to grow plex: %s", errstr);
- free(s);
- free(d);
- return;
- }
- gctl_free(req);
-}
-
-static void
-parseline(int argc, char * const *argv)
-{
-
- if (argc <= 0)
- return;
-
- if (!strcmp(argv[0], "create"))
- gvinum_create(argc, argv);
- else if (!strcmp(argv[0], "exit") || !strcmp(argv[0], "quit"))
- exit(0);
- else if (!strcmp(argv[0], "attach"))
- gvinum_attach(argc, argv);
- else if (!strcmp(argv[0], "detach"))
- gvinum_detach(argc, argv);
- else if (!strcmp(argv[0], "concat"))
- gvinum_concat(argc, argv);
- else if (!strcmp(argv[0], "grow"))
- gvinum_grow(argc, argv);
- else if (!strcmp(argv[0], "help"))
- gvinum_help();
- else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "l"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "ld"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "lp"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "ls"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "lv"))
- gvinum_list(argc, argv);
- else if (!strcmp(argv[0], "mirror"))
- gvinum_mirror(argc, argv);
- else if (!strcmp(argv[0], "move"))
- gvinum_move(argc, argv);
- else if (!strcmp(argv[0], "mv"))
- gvinum_move(argc, argv);
- else if (!strcmp(argv[0], "printconfig"))
- gvinum_printconfig(argc, argv);
- else if (!strcmp(argv[0], "raid5"))
- gvinum_raid5(argc, argv);
- else if (!strcmp(argv[0], "rename"))
- gvinum_rename(argc, argv);
- else if (!strcmp(argv[0], "resetconfig"))
- gvinum_resetconfig(argc, argv);
- else if (!strcmp(argv[0], "rm"))
- gvinum_rm(argc, argv);
- else if (!strcmp(argv[0], "saveconfig"))
- gvinum_saveconfig();
- else if (!strcmp(argv[0], "setstate"))
- gvinum_setstate(argc, argv);
- else if (!strcmp(argv[0], "start"))
- gvinum_start(argc, argv);
- else if (!strcmp(argv[0], "stop"))
- gvinum_stop(argc, argv);
- else if (!strcmp(argv[0], "stripe"))
- gvinum_stripe(argc, argv);
- else if (!strcmp(argv[0], "checkparity"))
- gvinum_parityop(argc, argv, 0);
- else if (!strcmp(argv[0], "rebuildparity"))
- gvinum_parityop(argc, argv, 1);
- else
- printf("unknown command '%s'\n", argv[0]);
-}
-
-/*
- * The guts of printconfig. This is called from gvinum_printconfig and from
- * gvinum_create when called without an argument, in order to give the user
- * something to edit.
- */
-static void
-printconfig(FILE *of, const char *comment)
-{
- struct gctl_req *req;
- struct utsname uname_s;
- const char *errstr;
- time_t now;
- char buf[GV_CFG_LEN + 1];
-
- uname(&uname_s);
- time(&now);
- buf[0] = '\0';
-
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "getconfig");
- gctl_ro_param(req, "comment", -1, comment);
- gctl_add_param(req, "config", sizeof(buf), buf,
- GCTL_PARAM_WR | GCTL_PARAM_ASCII);
- errstr = gctl_issue(req);
- if (errstr != NULL) {
- warnx("can't get configuration: %s", errstr);
- return;
- }
- gctl_free(req);
-
- fprintf(of, "# Vinum configuration of %s, saved at %s",
- uname_s.nodename,
- ctime(&now));
-
- if (*comment != '\0')
- fprintf(of, "# Current configuration:\n");
-
- fprintf(of, "%s", buf);
-}
diff --git a/sbin/gvinum/gvinum.h b/sbin/gvinum/gvinum.h
deleted file mode 100644
index e9c112a5e936..000000000000
--- a/sbin/gvinum/gvinum.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-4-Clause
- *
- * Copyright (c) 1997, 1998
- * Nan Yang Computer Services Limited. All rights reserved.
- *
- * This software is distributed under the so-called ``Berkeley
- * License'':
- *
- * 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 Nan Yang Computer
- * Services Limited.
- * 4. Neither the name of the Company 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 ``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 company 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$ */
-
-#define GVINUMMOD "g_vinum"
-#define GVINUMKLD "geom_vinum"
diff --git a/sbin/hastctl/Makefile b/sbin/hastctl/Makefile
index 00c89ef4f743..36152dc835a6 100644
--- a/sbin/hastctl/Makefile
+++ b/sbin/hastctl/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=hast
@@ -7,7 +5,6 @@ PACKAGE=hast
PROG= hastctl
SRCS= activemap.c
-SRCS+= crc32.c
SRCS+= ebuf.c
SRCS+= hast_checksum.c hast_compression.c hast_proto.c hastctl.c
SRCS+= lzf.c
@@ -33,7 +30,7 @@ CFLAGS+=-DINET6
CFLAGS+=-DYY_NO_UNPUT
CFLAGS+=-DYY_NO_INPUT
-LIBADD= md util
+LIBADD= md util z
YFLAGS+=-v
diff --git a/sbin/hastctl/Makefile.depend b/sbin/hastctl/Makefile.depend
index 371ab3746dcc..0fe9592e761a 100644
--- a/sbin/hastctl/Makefile.depend
+++ b/sbin/hastctl/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
@@ -11,6 +9,7 @@ DIRDEPS = \
lib/libcompiler_rt \
lib/libmd \
lib/libutil \
+ lib/libz \
usr.bin/yacc.host \
diff --git a/sbin/hastctl/hastctl.8 b/sbin/hastctl/hastctl.8
index 0b8204d00b99..f696858a8071 100644
--- a/sbin/hastctl/hastctl.8
+++ b/sbin/hastctl/hastctl.8
@@ -1,5 +1,4 @@
.\" Copyright (c) 2010 The FreeBSD Foundation
-.\" All rights reserved.
.\"
.\" This software was developed by Pawel Jakub Dawidek under sponsorship from
.\" the FreeBSD Foundation.
@@ -25,8 +24,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 8, 2016
.Dt HASTCTL 8
.Os
diff --git a/sbin/hastctl/hastctl.c b/sbin/hastctl/hastctl.c
index 162ba2610991..fe37dcaa1b58 100644
--- a/sbin/hastctl/hastctl.c
+++ b/sbin/hastctl/hastctl.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -29,9 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <err.h>
diff --git a/sbin/hastd/Makefile b/sbin/hastd/Makefile
index d3854850d3b3..8a79320fb665 100644
--- a/sbin/hastd/Makefile
+++ b/sbin/hastd/Makefile
@@ -1,11 +1,9 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=hast
PROG= hastd
SRCS= activemap.c
-SRCS+= control.c crc32.c
+SRCS+= control.c
SRCS+= ebuf.c event.c
SRCS+= hast_checksum.c hast_compression.c hast_proto.c hastd.c hooks.c
SRCS+= lzf.c
@@ -31,7 +29,7 @@ CFLAGS+=-DINET
CFLAGS+=-DINET6
.endif
-LIBADD= geom md pthread util
+LIBADD= geom md pthread util z
YFLAGS+=-v
diff --git a/sbin/hastd/Makefile.depend b/sbin/hastd/Makefile.depend
index 9a828fd8932d..c254576c1d8c 100644
--- a/sbin/hastd/Makefile.depend
+++ b/sbin/hastd/Makefile.depend
@@ -1,20 +1,17 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
lib/libgeom \
lib/libmd \
- lib/libsbuf \
lib/libthr \
lib/libutil \
+ lib/libz \
usr.bin/yacc.host \
diff --git a/sbin/hastd/activemap.c b/sbin/hastd/activemap.c
index 73577d2764e9..d693d08d524e 100644
--- a/sbin/hastd/activemap.c
+++ b/sbin/hastd/activemap.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -29,9 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h> /* powerof2() */
#include <sys/queue.h>
diff --git a/sbin/hastd/activemap.h b/sbin/hastd/activemap.h
index e42a37e0d96f..ff598f841909 100644
--- a/sbin/hastd/activemap.h
+++ b/sbin/hastd/activemap.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _ACTIVEMAP_H_
diff --git a/sbin/hastd/control.c b/sbin/hastd/control.c
index 52e567a52879..0a9befcc4358 100644
--- a/sbin/hastd/control.c
+++ b/sbin/hastd/control.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -29,9 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/wait.h>
diff --git a/sbin/hastd/control.h b/sbin/hastd/control.h
index 18096162eb65..ad7fb7978597 100644
--- a/sbin/hastd/control.h
+++ b/sbin/hastd/control.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _CONTROL_H_
diff --git a/sbin/hastd/crc32.c b/sbin/hastd/crc32.c
deleted file mode 100644
index e8bc74a97f2b..000000000000
--- a/sbin/hastd/crc32.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- * code or tables extracted from it, as desired without restriction.
- */
-
-/*
- * First, the polynomial itself and its table of feedback terms. The
- * polynomial is
- * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
- *
- * Note that we take it "backwards" and put the highest-order term in
- * the lowest-order bit. The X^32 term is "implied"; the LSB is the
- * X^31 term, etc. The X^0 term (usually shown as "+1") results in
- * the MSB being 1
- *
- * Note that the usual hardware shift register implementation, which
- * is what we're using (we're merely optimizing it by doing eight-bit
- * chunks at a time) shifts bits into the lowest-order term. In our
- * implementation, that means shifting towards the right. Why do we
- * do it this way? Because the calculated CRC must be transmitted in
- * order from highest-order term to lowest-order term. UARTs transmit
- * characters in order from LSB to MSB. By storing the CRC this way
- * we hand it to the UART in the order low-byte to high-byte; the UART
- * sends each low-bit to hight-bit; and the result is transmission bit
- * by bit from highest- to lowest-order term without requiring any bit
- * shuffling on our part. Reception works similarly
- *
- * The feedback terms table consists of 256, 32-bit entries. Notes
- *
- * The table can be generated at runtime if desired; code to do so
- * is shown later. It might not be obvious, but the feedback
- * terms simply represent the results of eight shift/xor opera
- * tions for all combinations of data and CRC register values
- *
- * The values must be right-shifted by eight bits by the "updcrc
- * logic; the shift must be unsigned (bring in zeroes). On some
- * hardware you could probably optimize the shift in assembler by
- * using byte-swap instructions
- * polynomial $edb88320
- *
- *
- * CRC32 code derived from work by Gary S. Brown.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdint.h>
-
-#include <crc32.h>
-
-uint32_t crc32_tab[] = {
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
- 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
- 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
- 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
- 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
- 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
- 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
- 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
- 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
- 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
- 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
- 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
- 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
- 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
- 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
- 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
- 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
- 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
- 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
- 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
- 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
- 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-/*
- * A function that calculates the CRC-32 based on the table above is
- * given below for documentation purposes. An equivalent implementation
- * of this function that's actually used in the kernel can be found
- * in sys/libkern.h, where it can be inlined.
- *
- * uint32_t
- * crc32(const void *buf, size_t size)
- * {
- * const uint8_t *p = buf;
- * uint32_t crc;
- *
- * crc = ~0U;
- * while (size--)
- * crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
- * return crc ^ ~0U;
- * }
- */
diff --git a/sbin/hastd/crc32.h b/sbin/hastd/crc32.h
deleted file mode 100644
index 3812a83f971f..000000000000
--- a/sbin/hastd/crc32.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-
- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
- * code or tables extracted from it, as desired without restriction.
- *
- * $FreeBSD$
- */
-
-#ifndef _CRC32_H_
-#define _CRC32_H_
-
-#include <stdint.h> /* uint32_t */
-#include <stdlib.h> /* size_t */
-
-extern uint32_t crc32_tab[];
-
-static __inline uint32_t
-crc32(const void *buf, size_t size)
-{
- const uint8_t *p = buf;
- uint32_t crc;
-
- crc = ~0U;
- while (size--)
- crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
- return (crc ^ ~0U);
-}
-
-#endif /* !_CRC32_H_ */
diff --git a/sbin/hastd/ebuf.c b/sbin/hastd/ebuf.c
index 83f99f834288..1ec8dd672c35 100644
--- a/sbin/hastd/ebuf.c
+++ b/sbin/hastd/ebuf.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -29,9 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <errno.h>
diff --git a/sbin/hastd/ebuf.h b/sbin/hastd/ebuf.h
index 83500ed7f646..a4a2b30f4cb4 100644
--- a/sbin/hastd/ebuf.h
+++ b/sbin/hastd/ebuf.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _EBUF_H_
diff --git a/sbin/hastd/event.c b/sbin/hastd/event.c
index 105939f123bf..aff8018dd49c 100644
--- a/sbin/hastd/event.c
+++ b/sbin/hastd/event.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -27,8 +27,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <errno.h>
#include "hast.h"
diff --git a/sbin/hastd/event.h b/sbin/hastd/event.h
index c3773298794d..f6d7d1a73130 100644
--- a/sbin/hastd/event.h
+++ b/sbin/hastd/event.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 _EVENT_H_
diff --git a/sbin/hastd/hast.conf.5 b/sbin/hastd/hast.conf.5
index 9267e368f8d3..66ca2efdffa1 100644
--- a/sbin/hastd/hast.conf.5
+++ b/sbin/hastd/hast.conf.5
@@ -26,8 +26,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd January 25, 2012
.Dt HAST.CONF 5
.Os
diff --git a/sbin/hastd/hast.h b/sbin/hastd/hast.h
index b1e2537a51f3..d0f9dd874c56 100644
--- a/sbin/hastd/hast.h
+++ b/sbin/hastd/hast.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -28,8 +28,6 @@
* 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 _HAST_H_
diff --git a/sbin/hastd/hast_checksum.c b/sbin/hastd/hast_checksum.c
index f7ef6a64b4e1..ea3113b01849 100644
--- a/sbin/hastd/hast_checksum.c
+++ b/sbin/hastd/hast_checksum.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
* All rights reserved.
@@ -27,16 +27,14 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <errno.h>
#include <string.h>
#include <strings.h>
-#include <crc32.h>
#include <hast.h>
#include <nv.h>
#include <sha256.h>
+#include <zlib.h>
#include <pjdlog.h>
#include "hast_checksum.h"
@@ -49,7 +47,9 @@ hast_crc32_checksum(const unsigned char *data, size_t size,
{
uint32_t crc;
- crc = crc32(data, size);
+ crc = crc32(0L, Z_NULL, 0);
+ crc = crc32(crc, data, size);
+
/* XXXPJD: Do we have to use htole32() on crc first? */
bcopy(&crc, hash, sizeof(crc));
*hsizep = sizeof(crc);
diff --git a/sbin/hastd/hast_checksum.h b/sbin/hastd/hast_checksum.h
index ea37a2ff1a1a..4b00e19b45ae 100644
--- a/sbin/hastd/hast_checksum.h
+++ b/sbin/hastd/hast_checksum.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 _HAST_CHECKSUM_H_
diff --git a/sbin/hastd/hast_compression.c b/sbin/hastd/hast_compression.c
index e6a2192c6a53..769fd1d2676e 100644
--- a/sbin/hastd/hast_compression.c
+++ b/sbin/hastd/hast_compression.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
* All rights reserved.
@@ -27,8 +27,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/endian.h>
#include <errno.h>
diff --git a/sbin/hastd/hast_compression.h b/sbin/hastd/hast_compression.h
index b7ea66290bdd..430d9248f4e2 100644
--- a/sbin/hastd/hast_compression.h
+++ b/sbin/hastd/hast_compression.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 _HAST_COMPRESSION_H_
diff --git a/sbin/hastd/hast_proto.c b/sbin/hastd/hast_proto.c
index 81dd01a21f17..d9f231e7b007 100644
--- a/sbin/hastd/hast_proto.c
+++ b/sbin/hastd/hast_proto.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -31,8 +31,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/endian.h>
#include <errno.h>
diff --git a/sbin/hastd/hast_proto.h b/sbin/hastd/hast_proto.h
index 3a0a3fbdc884..0158aa4ccee6 100644
--- a/sbin/hastd/hast_proto.h
+++ b/sbin/hastd/hast_proto.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _HAST_PROTO_H_
diff --git a/sbin/hastd/hastd.8 b/sbin/hastd/hastd.8
index 2b5c7784e5be..05a2d9b5e4e9 100644
--- a/sbin/hastd/hastd.8
+++ b/sbin/hastd/hastd.8
@@ -1,5 +1,4 @@
.\" Copyright (c) 2010 The FreeBSD Foundation
-.\" All rights reserved.
.\"
.\" This software was developed by Pawel Jakub Dawidek under sponsorship from
.\" the FreeBSD Foundation.
@@ -25,8 +24,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd December 21, 2019
.Dt HASTD 8
.Os
diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c
index be58411b7ec7..c62b85fd1925 100644
--- a/sbin/hastd/hastd.c
+++ b/sbin/hastd/hastd.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2010-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/module.h>
diff --git a/sbin/hastd/hastd.h b/sbin/hastd/hastd.h
index 965a63d1cb6d..a54ef316f37a 100644
--- a/sbin/hastd/hastd.h
+++ b/sbin/hastd/hastd.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _HASTD_H_
diff --git a/sbin/hastd/hooks.c b/sbin/hastd/hooks.c
index 13890b5fcb10..43ba6f06851a 100644
--- a/sbin/hastd/hooks.c
+++ b/sbin/hastd/hooks.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 The FreeBSD Foundation
* Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
diff --git a/sbin/hastd/hooks.h b/sbin/hastd/hooks.h
index 3ace6d35a7af..215f5e518422 100644
--- a/sbin/hastd/hooks.h
+++ b/sbin/hastd/hooks.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 The FreeBSD Foundation
* Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
@@ -28,8 +28,6 @@
* 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 _HOOKS_H_
diff --git a/sbin/hastd/lzf.c b/sbin/hastd/lzf.c
index 687cd0847cb5..371dee3a037b 100644
--- a/sbin/hastd/lzf.c
+++ b/sbin/hastd/lzf.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>
*
@@ -118,7 +118,7 @@ lzf_compress (const void *const in_data, unsigned int in_len,
/* off requires a type wide enough to hold a general pointer difference.
* ISO C doesn't have that (size_t might not be enough and ptrdiff_t only
* works for differences within a single object). We also assume that no
- * no bit pattern traps. Since the only platform that is both non-POSIX
+ * bit pattern traps. Since the only platform that is both non-POSIX
* and fails to support both assumptions is windows 64 bit, we make a
* special workaround for it.
*/
diff --git a/sbin/hastd/lzf.h b/sbin/hastd/lzf.h
index b3a3b0979e6b..d54e8eb66ae3 100644
--- a/sbin/hastd/lzf.h
+++ b/sbin/hastd/lzf.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>
*
@@ -160,7 +160,7 @@ lzf_decompress (const void *const in_data, unsigned int in_len,
#endif
/*
- * Wether to pass the LZF_STATE variable as argument, or allocate it
+ * Whether to pass the LZF_STATE variable as argument, or allocate it
* on the stack. For small-stack environments, define this to 1.
* NOTE: this breaks the prototype in lzf.h.
*/
@@ -169,7 +169,7 @@ lzf_decompress (const void *const in_data, unsigned int in_len,
#endif
/*
- * Wether to add extra checks for input validity in lzf_decompress
+ * Whether to add extra checks for input validity in lzf_decompress
* and return EINVAL if the input stream has been corrupted. This
* only shields against overflowing the input buffer and will not
* detect most corrupted streams.
diff --git a/sbin/hastd/metadata.c b/sbin/hastd/metadata.c
index 2d998b706c5a..5318d9f6aee5 100644
--- a/sbin/hastd/metadata.c
+++ b/sbin/hastd/metadata.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -30,8 +29,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <errno.h>
#include <fcntl.h>
#include <string.h>
diff --git a/sbin/hastd/metadata.h b/sbin/hastd/metadata.h
index 4efd13ff7b87..6d8c593f0a46 100644
--- a/sbin/hastd/metadata.h
+++ b/sbin/hastd/metadata.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _METADATA_H_
diff --git a/sbin/hastd/nv.c b/sbin/hastd/nv.c
index 81def8aeb5cd..16ab95cf0dc6 100644
--- a/sbin/hastd/nv.c
+++ b/sbin/hastd/nv.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -29,9 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/endian.h>
@@ -101,7 +97,7 @@ struct nvhdr {
} __packed;
#define NVH_DATA(nvh) ((unsigned char *)nvh + NVH_HSIZE(nvh))
#define NVH_HSIZE(nvh) \
- (sizeof(struct nvhdr) + roundup2((nvh)->nvh_namesize, 8))
+ (sizeof(struct nvhdr) + roundup2((size_t)(nvh)->nvh_namesize, 8))
#define NVH_DSIZE(nvh) \
(((nvh)->nvh_type & NV_ORDER_MASK) == NV_ORDER_HOST ? \
(nvh)->nvh_dsize : \
@@ -251,11 +247,8 @@ nv_validate(struct nv *nv, size_t *extrap)
break;
}
dsize = NVH_DSIZE(nvh);
- if (dsize == 0) {
- error = EINVAL;
- break;
- }
- if (size < NVH_SIZE(nvh)) {
+ if (roundup2(dsize, 8) == 0 ||
+ roundup2(dsize, 8) > size - NVH_HSIZE(nvh)) {
error = EINVAL;
break;
}
diff --git a/sbin/hastd/nv.h b/sbin/hastd/nv.h
index 7d93a71b2a47..657a66fe38eb 100644
--- a/sbin/hastd/nv.h
+++ b/sbin/hastd/nv.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _NV_H_
diff --git a/sbin/hastd/parse.y b/sbin/hastd/parse.y
index 4e7687c8d23d..6cba61d74738 100644
--- a/sbin/hastd/parse.y
+++ b/sbin/hastd/parse.y
@@ -1,6 +1,6 @@
%{
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -29,8 +29,6 @@
* 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> /* MAXHOSTNAMELEN */
diff --git a/sbin/hastd/pjdlog.c b/sbin/hastd/pjdlog.c
index 9ac9a69b75da..3dbbe163812e 100644
--- a/sbin/hastd/pjdlog.c
+++ b/sbin/hastd/pjdlog.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
diff --git a/sbin/hastd/pjdlog.h b/sbin/hastd/pjdlog.h
index 6a1833db0187..ee77f9ffee0f 100644
--- a/sbin/hastd/pjdlog.h
+++ b/sbin/hastd/pjdlog.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org>
@@ -28,8 +28,6 @@
* 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 _PJDLOG_H_
diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c
index 620cb6e72720..5d166a088b9b 100644
--- a/sbin/hastd/primary.c
+++ b/sbin/hastd/primary.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009 The FreeBSD Foundation
* Copyright (c) 2010-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/time.h>
#include <sys/bio.h>
@@ -101,7 +98,7 @@ struct hio {
*/
refcnt_t hio_writecount;
/*
- * Memsync request was acknowleged by remote.
+ * Memsync request was acknowledged by remote.
*/
bool hio_memsyncacked;
/*
diff --git a/sbin/hastd/proto.c b/sbin/hastd/proto.c
index 249da7d5e4ea..70166271a747 100644
--- a/sbin/hastd/proto.c
+++ b/sbin/hastd/proto.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -29,9 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/socket.h>
diff --git a/sbin/hastd/proto.h b/sbin/hastd/proto.h
index b7f2d44adfd2..729daa518d9d 100644
--- a/sbin/hastd/proto.h
+++ b/sbin/hastd/proto.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _PROTO_H_
diff --git a/sbin/hastd/proto_common.c b/sbin/hastd/proto_common.c
index 5a927f563637..39ef696f5b69 100644
--- a/sbin/hastd/proto_common.c
+++ b/sbin/hastd/proto_common.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
diff --git a/sbin/hastd/proto_impl.h b/sbin/hastd/proto_impl.h
index 2d035beee8b0..0a0074545f38 100644
--- a/sbin/hastd/proto_impl.h
+++ b/sbin/hastd/proto_impl.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _PROTO_IMPL_H_
diff --git a/sbin/hastd/proto_socketpair.c b/sbin/hastd/proto_socketpair.c
index 9c4e9f1b12c9..59ac9553ff6e 100644
--- a/sbin/hastd/proto_socketpair.c
+++ b/sbin/hastd/proto_socketpair.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -29,9 +28,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
diff --git a/sbin/hastd/proto_tcp.c b/sbin/hastd/proto_tcp.c
index d2bf98318af5..aeec887433f8 100644
--- a/sbin/hastd/proto_tcp.c
+++ b/sbin/hastd/proto_tcp.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h> /* MAXHOSTNAMELEN */
#include <sys/socket.h>
diff --git a/sbin/hastd/proto_uds.c b/sbin/hastd/proto_uds.c
index 5c18a2c43fcb..acb61a360180 100644
--- a/sbin/hastd/proto_uds.c
+++ b/sbin/hastd/proto_uds.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -30,8 +29,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/* UDS - UNIX Domain Socket */
#include <sys/types.h>
diff --git a/sbin/hastd/rangelock.c b/sbin/hastd/rangelock.c
index 129b82bedbfc..26025d1169ac 100644
--- a/sbin/hastd/rangelock.c
+++ b/sbin/hastd/rangelock.c
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -30,8 +29,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/queue.h>
#include <stdbool.h>
diff --git a/sbin/hastd/rangelock.h b/sbin/hastd/rangelock.h
index 93281a382a26..4847887b6b7a 100644
--- a/sbin/hastd/rangelock.h
+++ b/sbin/hastd/rangelock.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _RANGELOCK_H_
diff --git a/sbin/hastd/refcnt.h b/sbin/hastd/refcnt.h
index 8001570b7c85..f44229d4fcf7 100644
--- a/sbin/hastd/refcnt.h
+++ b/sbin/hastd/refcnt.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2005 John Baldwin <jhb@FreeBSD.org>
*
@@ -23,8 +23,6 @@
* 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 __REFCNT_H__
diff --git a/sbin/hastd/secondary.c b/sbin/hastd/secondary.c
index fa3142eb0d21..6bf889bba657 100644
--- a/sbin/hastd/secondary.c
+++ b/sbin/hastd/secondary.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/bio.h>
diff --git a/sbin/hastd/subr.c b/sbin/hastd/subr.c
index 51e0a55e4191..084ea50dae7c 100644
--- a/sbin/hastd/subr.c
+++ b/sbin/hastd/subr.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -30,9 +30,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
@@ -159,7 +156,6 @@ drop_privs(const struct hast_resource *res)
struct passwd *pw;
uid_t ruid, euid, suid;
gid_t rgid, egid, sgid;
- gid_t gidset[1];
bool capsicum, jailed;
/*
@@ -210,10 +206,8 @@ drop_privs(const struct hast_resource *res)
}
}
PJDLOG_VERIFY(chdir("/") == 0);
- gidset[0] = pw->pw_gid;
- if (setgroups(1, gidset) == -1) {
- pjdlog_errno(LOG_ERR, "Unable to set groups to gid %u",
- (unsigned int)pw->pw_gid);
+ if (setgroups(0, NULL) == -1) {
+ pjdlog_errno(LOG_ERR, "Unable to drop supplementary groups");
return (-1);
}
if (setgid(pw->pw_gid) == -1) {
@@ -289,9 +283,7 @@ drop_privs(const struct hast_resource *res)
PJDLOG_VERIFY(rgid == pw->pw_gid);
PJDLOG_VERIFY(egid == pw->pw_gid);
PJDLOG_VERIFY(sgid == pw->pw_gid);
- PJDLOG_VERIFY(getgroups(0, NULL) == 1);
- PJDLOG_VERIFY(getgroups(1, gidset) == 1);
- PJDLOG_VERIFY(gidset[0] == pw->pw_gid);
+ PJDLOG_VERIFY(getgroups(0, NULL) == 0);
pjdlog_debug(1,
"Privileges successfully dropped using %s%s+setgid+setuid.",
diff --git a/sbin/hastd/subr.h b/sbin/hastd/subr.h
index 93e344d0b181..0603cdf18099 100644
--- a/sbin/hastd/subr.h
+++ b/sbin/hastd/subr.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -28,8 +28,6 @@
* 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 _SUBR_H_
diff --git a/sbin/hastd/synch.h b/sbin/hastd/synch.h
index 2644e54cebdc..32463f836bd0 100644
--- a/sbin/hastd/synch.h
+++ b/sbin/hastd/synch.h
@@ -1,8 +1,7 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
- * All rights reserved.
*
* This software was developed by Pawel Jakub Dawidek under sponsorship from
* the FreeBSD Foundation.
@@ -27,8 +26,6 @@
* 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 _SYNCH_H_
diff --git a/sbin/hastd/token.l b/sbin/hastd/token.l
index bc423e17b6e5..6476862e0bc1 100644
--- a/sbin/hastd/token.l
+++ b/sbin/hastd/token.l
@@ -1,6 +1,6 @@
%{
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009-2010 The FreeBSD Foundation
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>
@@ -29,8 +29,6 @@
* 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 <stdio.h>
diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile
index c48375b8c6d9..2553e61b5e9e 100644
--- a/sbin/ifconfig/Makefile
+++ b/sbin/ifconfig/Makefile
@@ -1,6 +1,3 @@
-# From: @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=runtime
@@ -71,10 +68,15 @@ LIBADD+= jail
.endif
LIBADD+= nv
+.if ${MK_NETLINK_SUPPORT} != "no"
+SRCS+= ifconfig_netlink.c
+.else
+CFLAGS+=-DWITHOUT_NETLINK
+.endif
+
MAN= ifconfig.8
CFLAGS+= -Wall -Wmissing-prototypes -Wcast-qual -Wwrite-strings -Wnested-externs
-WARNS?= 2
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/sbin/ifconfig/Makefile.depend b/sbin/ifconfig/Makefile.depend
index 896ebc6ade5f..da0504014f9d 100644
--- a/sbin/ifconfig/Makefile.depend
+++ b/sbin/ifconfig/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
@@ -8,8 +7,9 @@ DIRDEPS = \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
- lib/libsbuf \
+ lib/libifconfig \
+ lib/libnv \
+ lib/libutil \
lib/msun \
diff --git a/sbin/ifconfig/Makefile.depend.options b/sbin/ifconfig/Makefile.depend.options
index 91c60b1a0b29..8dc0fcbc30de 100644
--- a/sbin/ifconfig/Makefile.depend.options
+++ b/sbin/ifconfig/Makefile.depend.options
@@ -1,4 +1,3 @@
-# $FreeBSD$
# This file is not autogenerated - take care!
DIRDEPS_OPTIONS= JAIL WIRELESS_SUPPORT
diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
index c5c40de155d6..4fd74d481b3a 100644
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -29,11 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -53,23 +48,35 @@ static const char rcsid[] =
#include <netdb.h>
#include "ifconfig.h"
+#include "ifconfig_netlink.h"
+#ifdef WITHOUT_NETLINK
static struct in_aliasreq in_addreq;
static struct ifreq in_ridreq;
+#else
+struct in_px {
+ struct in_addr addr;
+ int plen;
+ bool addrset;
+ bool maskset;
+};
+struct in_pdata {
+ struct in_px addr;
+ struct in_px dst_addr;
+ struct in_px brd_addr;
+ uint32_t flags;
+ uint32_t vhid;
+};
+static struct in_pdata in_add, in_del;
+#endif
+
static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/
extern char *f_inet, *f_addr;
static void
-in_status(int s __unused, const struct ifaddrs *ifa)
+print_addr(struct sockaddr_in *sin)
{
- struct sockaddr_in *sin, null_sin;
int error, n_flags;
-
- memset(&null_sin, 0, sizeof(null_sin));
-
- sin = (struct sockaddr_in *)ifa->ifa_addr;
- if (sin == NULL)
- return;
if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
n_flags = 0;
@@ -85,15 +92,28 @@ in_status(int s __unused, const struct ifaddrs *ifa)
inet_ntop(AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf));
printf("\tinet %s", addr_buf);
+}
+
+#ifdef WITHOUT_NETLINK
+static void
+in_status(if_ctx *ctx __unused, const struct ifaddrs *ifa)
+{
+ struct sockaddr_in *sin, null_sin = {};
+
+ sin = satosin(ifa->ifa_addr);
+ if (sin == NULL)
+ return;
+
+ print_addr(sin);
if (ifa->ifa_flags & IFF_POINTOPOINT) {
- sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
+ sin = satosin(ifa->ifa_dstaddr);
if (sin == NULL)
sin = &null_sin;
printf(" --> %s", inet_ntoa(sin->sin_addr));
}
- sin = (struct sockaddr_in *)ifa->ifa_netmask;
+ sin = satosin(ifa->ifa_netmask);
if (sin == NULL)
sin = &null_sin;
if (f_inet != NULL && strcmp(f_inet, "cidr") == 0) {
@@ -114,16 +134,62 @@ in_status(int s __unused, const struct ifaddrs *ifa)
printf(" netmask 0x%lx", (unsigned long)ntohl(sin->sin_addr.s_addr));
if (ifa->ifa_flags & IFF_BROADCAST) {
- sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
+ sin = satosin(ifa->ifa_broadaddr);
if (sin != NULL && sin->sin_addr.s_addr != 0)
printf(" broadcast %s", inet_ntoa(sin->sin_addr));
}
- print_vhid(ifa, " ");
+ print_vhid(ifa);
putchar('\n');
}
+#else
+static struct in_addr
+get_mask(int plen)
+{
+ struct in_addr a;
+
+ a.s_addr = htonl(plen ? ~((1 << (32 - plen)) - 1) : 0);
+
+ return (a);
+}
+
+static void
+in_status_nl(if_ctx *ctx __unused, if_link_t *link, if_addr_t *ifa)
+{
+ struct sockaddr_in *sin = satosin(ifa->ifa_local);
+ int plen = ifa->ifa_prefixlen;
+
+ print_addr(sin);
+
+ if (link->ifi_flags & IFF_POINTOPOINT) {
+ struct sockaddr_in *dst = satosin(ifa->ifa_address);
+
+ printf(" --> %s", inet_ntoa(dst->sin_addr));
+ }
+ if (f_inet != NULL && strcmp(f_inet, "cidr") == 0) {
+ printf("/%d", plen);
+ } else if (f_inet != NULL && strcmp(f_inet, "dotted") == 0)
+ printf(" netmask %s", inet_ntoa(get_mask(plen)));
+ else
+ printf(" netmask 0x%lx", (unsigned long)ntohl(get_mask(plen).s_addr));
+
+ if ((link->ifi_flags & IFF_BROADCAST) && plen != 0) {
+ struct sockaddr_in *brd = satosin(ifa->ifa_broadcast);
+ if (brd != NULL)
+ printf(" broadcast %s", inet_ntoa(brd->sin_addr));
+ }
+
+ if (ifa->ifaf_vhid != 0)
+ printf(" vhid %d", ifa->ifaf_vhid);
+
+ putchar('\n');
+}
+#endif
+
+
+#ifdef WITHOUT_NETLINK
#define SIN(x) ((struct sockaddr_in *) &(x))
static struct sockaddr_in *sintab[] = {
SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
@@ -131,6 +197,12 @@ static struct sockaddr_in *sintab[] = {
};
static void
+in_copyaddr(if_ctx *ctx __unused, int to, int from)
+{
+ memcpy(sintab[to], sintab[from], sizeof(struct sockaddr_in));
+}
+
+static void
in_getaddr(const char *s, int which)
{
struct sockaddr_in *sin = sintab[which];
@@ -146,7 +218,7 @@ in_getaddr(const char *s, int which)
if((p = strrchr(s, '/')) != NULL) {
const char *errstr;
/* address is `name/masklen' */
- int masklen;
+ int masklen = 0;
struct sockaddr_in *min = sintab[MASK];
*p = '\0';
if (!isdigit(*(p + 1)))
@@ -175,18 +247,221 @@ in_getaddr(const char *s, int which)
errx(1, "%s: bad value", s);
}
+#else
+
+static struct in_px *sintab_nl[] = {
+ &in_del.addr, /* RIDADDR */
+ &in_add.addr, /* ADDR */
+ NULL, /* MASK */
+ &in_add.dst_addr, /* DSTADDR*/
+ &in_add.brd_addr, /* BRDADDR*/
+};
+
+static void
+in_copyaddr(if_ctx *ctx __unused, int to, int from)
+{
+ sintab_nl[to]->addr = sintab_nl[from]->addr;
+ sintab_nl[to]->addrset = sintab_nl[from]->addrset;
+}
+
+static void
+in_getip(const char *addr_str, struct in_addr *ip)
+{
+ struct hostent *hp;
+ struct netent *np;
+
+ if (inet_aton(addr_str, ip))
+ return;
+ if ((hp = gethostbyname(addr_str)) != NULL)
+ bcopy(hp->h_addr, (char *)ip,
+ MIN((size_t)hp->h_length, sizeof(ip)));
+ else if ((np = getnetbyname(addr_str)) != NULL)
+ *ip = inet_makeaddr(np->n_net, INADDR_ANY);
+ else
+ errx(1, "%s: bad value", addr_str);
+}
+
+static void
+in_getaddr(const char *s, int which)
+{
+ struct in_px *px = sintab_nl[which];
+
+ if (which == MASK) {
+ struct in_px *px_addr = sintab_nl[ADDR];
+ struct in_addr mask = {};
+
+ in_getip(s, &mask);
+ px_addr->plen = __bitcount32(mask.s_addr);
+ px_addr->maskset = true;
+ return;
+ }
+
+ if (which == ADDR) {
+ char *p = NULL;
+
+ if((p = strrchr(s, '/')) != NULL) {
+ const char *errstr;
+ /* address is `name/masklen' */
+ int masklen;
+ *p = '\0';
+ if (!isdigit(*(p + 1)))
+ errstr = "invalid";
+ else
+ masklen = (int)strtonum(p + 1, 0, 32, &errstr);
+ if (errstr != NULL) {
+ *p = '/';
+ errx(1, "%s: bad value (width %s)", s, errstr);
+ }
+ px->plen = masklen;
+ px->maskset = true;
+ }
+ }
+
+ in_getip(s, &px->addr);
+ px->addrset = true;
+}
+
+/*
+ * Deletes the first found IPv4 interface address for the interface.
+ *
+ * This function provides SIOCDIFADDR semantics missing in Netlink.
+ * When no valid IPv4 address is specified (sin_family or sin_len is wrong) to
+ * the SIOCDIFADDR call, it deletes the first found IPv4 address on the interface.
+ * 'ifconfig IFNAME inet addr/prefix' relies on that behavior, as it
+ * executes empty SIOCDIFADDR before adding a new address.
+ */
+static int
+in_delete_first_nl(if_ctx *ctx)
+{
+ struct nlmsghdr *hdr;
+ struct ifaddrmsg *ifahdr;
+ uint32_t nlmsg_seq;
+ struct in_addr addr;
+ struct snl_writer nw = {};
+ struct snl_errmsg_data e = {};
+ struct snl_state *ss = ctx->io_ss;
+ bool found = false;
+
+ uint32_t ifindex = if_nametoindex_nl(ss, ctx->ifname);
+ if (ifindex == 0) {
+ /* No interface with the desired name, nothing to delete */
+ return (EADDRNOTAVAIL);
+ }
+
+ snl_init_writer(ss, &nw);
+ hdr = snl_create_msg_request(&nw, NL_RTM_GETADDR);
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg);
+ ifahdr->ifa_family = AF_INET;
+ ifahdr->ifa_index = ifindex;
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
+ return (EINVAL);
+
+ nlmsg_seq = hdr->nlmsg_seq;
+ while ((hdr = snl_read_reply_multi(ss, nlmsg_seq, &e)) != NULL) {
+ struct snl_parsed_addr attrs = {};
+ if (snl_parse_nlmsg(ss, hdr, &snl_rtm_addr_parser, &attrs)) {
+ addr = satosin(attrs.ifa_local)->sin_addr;
+ ifindex = attrs.ifa_index;
+ found = true;
+ break;
+ } else
+ return (EINVAL);
+ }
+ if (e.error != 0) {
+ if (e.error_str != NULL)
+ warnx("%s(): %s", __func__, e.error_str);
+ return (e.error);
+ }
+
+ if (!found)
+ return (0);
+
+ /* Try to delete the found address */
+ snl_init_writer(ss, &nw);
+ hdr = snl_create_msg_request(&nw, NL_RTM_DELADDR);
+ ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg);
+ ifahdr->ifa_family = AF_INET;
+ ifahdr->ifa_index = ifindex;
+ snl_add_msg_attr_ip4(&nw, IFA_LOCAL, &addr);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
+ return (EINVAL);
+ memset(&e, 0, sizeof(e));
+ snl_read_reply_code(ss, hdr->nlmsg_seq, &e);
+ if (e.error_str != NULL)
+ warnx("%s(): %s", __func__, e.error_str);
+
+ return (e.error);
+}
+
+
+static int
+in_exec_nl(if_ctx *ctx, unsigned long action, void *data)
+{
+ struct in_pdata *pdata = (struct in_pdata *)data;
+ struct snl_writer nw = {};
+
+ if (action == NL_RTM_DELADDR && !pdata->addr.addrset)
+ return (in_delete_first_nl(ctx));
+
+ snl_init_writer(ctx->io_ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, action);
+ struct ifaddrmsg *ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg);
+
+ ifahdr->ifa_family = AF_INET;
+ ifahdr->ifa_prefixlen = pdata->addr.plen;
+ ifahdr->ifa_index = if_nametoindex_nl(ctx->io_ss, ctx->ifname);
+
+ snl_add_msg_attr_ip4(&nw, IFA_LOCAL, &pdata->addr.addr);
+ if (action == NL_RTM_NEWADDR && pdata->dst_addr.addrset)
+ snl_add_msg_attr_ip4(&nw, IFA_ADDRESS, &pdata->dst_addr.addr);
+ if (action == NL_RTM_NEWADDR && pdata->brd_addr.addrset)
+ snl_add_msg_attr_ip4(&nw, IFA_BROADCAST, &pdata->brd_addr.addr);
+
+ int off = snl_add_msg_attr_nested(&nw, IFA_FREEBSD);
+ snl_add_msg_attr_u32(&nw, IFAF_FLAGS, pdata->flags);
+ if (pdata->vhid != 0)
+ snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid);
+ snl_end_attr_nested(&nw, off);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ctx->io_ss, hdr))
+ return (0);
+
+ struct snl_errmsg_data e = {};
+ snl_read_reply_code(ctx->io_ss, hdr->nlmsg_seq, &e);
+ if (e.error_str != NULL)
+ warnx("%s(): %s", __func__, e.error_str);
+
+ return (e.error);
+}
+#endif
+
+static void
+err_nomask(int ifflags)
+{
+ if ((ifflags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
+ errx(1, "ERROR: setting interface address without mask is no longer supported.");
+ }
+}
+
static void
-in_postproc(int s, const struct afswtch *afp, int newaddr, int ifflags)
+in_postproc(if_ctx *ctx __unused, int newaddr, int ifflags)
{
- if (sintab[ADDR]->sin_len != 0 && sintab[MASK]->sin_len == 0 &&
- newaddr && (ifflags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
- warnx("WARNING: setting interface address without mask "
- "is deprecated,\ndefault mask may not be correct.");
+#ifdef WITHOUT_NETLINK
+ if (sintab[ADDR]->sin_len != 0 && sintab[MASK]->sin_len == 0 && newaddr) {
+ err_nomask(ifflags);
}
+#else
+ if (sintab_nl[ADDR]->addrset && !sintab_nl[ADDR]->maskset && newaddr) {
+ err_nomask(ifflags);
+ }
+#endif
}
static void
-in_status_tunnel(int s)
+in_status_tunnel(if_ctx *ctx)
{
char src[NI_MAXHOST];
char dst[NI_MAXHOST];
@@ -194,16 +469,16 @@ in_status_tunnel(int s)
const struct sockaddr *sa = (const struct sockaddr *) &ifr.ifr_addr;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, IFNAMSIZ);
+ strlcpy(ifr.ifr_name, ctx->ifname, IFNAMSIZ);
- if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx(ctx, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0)
return;
if (sa->sa_family != AF_INET)
return;
if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0)
src[0] = '\0';
- if (ioctl(s, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx(ctx, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0)
return;
if (sa->sa_family != AF_INET)
return;
@@ -214,31 +489,56 @@ in_status_tunnel(int s)
}
static void
-in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
+in_set_tunnel(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres)
{
struct in_aliasreq addreq;
memset(&addreq, 0, sizeof(addreq));
- strlcpy(addreq.ifra_name, name, IFNAMSIZ);
+ strlcpy(addreq.ifra_name, ctx->ifname, IFNAMSIZ);
memcpy(&addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len);
- if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0)
+ if (ioctl_ctx(ctx, SIOCSIFPHYADDR, &addreq) < 0)
warn("SIOCSIFPHYADDR");
}
+static void
+in_set_vhid(int vhid)
+{
+#ifdef WITHOUT_NETLINK
+ in_addreq.ifra_vhid = vhid;
+#else
+ in_add.vhid = (uint32_t)vhid;
+#endif
+}
+
static struct afswtch af_inet = {
.af_name = "inet",
.af_af = AF_INET,
+#ifdef WITHOUT_NETLINK
.af_status = in_status,
+#else
+ .af_status = in_status_nl,
+#endif
.af_getaddr = in_getaddr,
+ .af_copyaddr = in_copyaddr,
.af_postproc = in_postproc,
.af_status_tunnel = in_status_tunnel,
.af_settunnel = in_set_tunnel,
+ .af_setvhid = in_set_vhid,
+#ifdef WITHOUT_NETLINK
.af_difaddr = SIOCDIFADDR,
.af_aifaddr = SIOCAIFADDR,
.af_ridreq = &in_ridreq,
.af_addreq = &in_addreq,
+ .af_exec = af_exec_ioctl,
+#else
+ .af_difaddr = NL_RTM_DELADDR,
+ .af_aifaddr = NL_RTM_NEWADDR,
+ .af_ridreq = &in_del,
+ .af_addreq = &in_add,
+ .af_exec = in_exec_nl,
+#endif
};
static __constructor void
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index 08902b934ad8..9386f5eaf513 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -29,11 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -57,53 +52,98 @@ static const char rcsid[] =
#include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */
#include "ifconfig.h"
+#include "ifconfig_netlink.h"
+
+#ifndef WITHOUT_NETLINK
+struct in6_px {
+ struct in6_addr addr;
+ int plen;
+ bool set;
+};
+struct in6_pdata {
+ struct in6_px addr;
+ struct in6_px dst_addr;
+ struct in6_addrlifetime lifetime;
+ uint32_t flags;
+ uint32_t vhid;
+};
+static struct in6_pdata in6_del;
+static struct in6_pdata in6_add = {
+ .lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME },
+};
+#else
static struct in6_ifreq in6_ridreq;
static struct in6_aliasreq in6_addreq =
{ .ifra_flags = 0,
.ifra_lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } };
+#endif
static int ip6lifetime;
+#ifdef WITHOUT_NETLINK
static int prefix(void *, int);
+#endif
static char *sec2str(time_t);
static int explicit_prefix = 0;
extern char *f_inet6, *f_addr;
-extern void setnd6flags(const char *, int, int, const struct afswtch *);
-extern void setnd6defif(const char *, int, int, const struct afswtch *);
-extern void nd6_status(int);
+extern void setnd6flags(if_ctx *, const char *, int);
+extern void setnd6defif(if_ctx *,const char *, int);
+extern void nd6_status(if_ctx *);
static char addr_buf[NI_MAXHOST]; /*for getnameinfo()*/
static void
-setifprefixlen(const char *addr, int dummy __unused, int s,
- const struct afswtch *afp)
+setifprefixlen(if_ctx *ctx __netlink_unused, const char *addr, int dummy __unused)
{
+#ifdef WITHOUT_NETLINK
+ const struct afswtch *afp = ctx->afp;
+
if (afp->af_getprefix != NULL)
afp->af_getprefix(addr, MASK);
+#else
+ int plen = strtol(addr, NULL, 10);
+
+ if ((plen < 0) || (plen > 128))
+ errx(1, "%s: bad value", addr);
+ in6_add.addr.plen = plen;
+#endif
explicit_prefix = 1;
}
static void
-setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused,
- const struct afswtch *afp)
+setip6flags(if_ctx *ctx, const char *dummyaddr __unused, int flag)
{
+ const struct afswtch *afp = ctx->afp;
+
if (afp->af_af != AF_INET6)
err(1, "address flags can be set only for inet6 addresses");
+#ifdef WITHOUT_NETLINK
if (flag < 0)
in6_addreq.ifra_flags &= ~(-flag);
else
in6_addreq.ifra_flags |= flag;
+#else
+ if (flag < 0)
+ in6_add.flags &= ~(-flag);
+ else
+ in6_add.flags |= flag;
+#endif
}
static void
-setip6lifetime(const char *cmd, const char *val, int s,
- const struct afswtch *afp)
+setip6lifetime(if_ctx *ctx, const char *cmd, const char *val)
{
+ const struct afswtch *afp = ctx->afp;
struct timespec now;
time_t newval;
char *ep;
+#ifdef WITHOUT_NETLINK
+ struct in6_addrlifetime *lifetime = &in6_addreq.ifra_lifetime;
+#else
+ struct in6_addrlifetime *lifetime = &in6_add.lifetime;
+#endif
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
newval = (time_t)strtoul(val, &ep, 0);
@@ -112,32 +152,30 @@ setip6lifetime(const char *cmd, const char *val, int s,
if (afp->af_af != AF_INET6)
errx(1, "%s not allowed for the AF", cmd);
if (strcmp(cmd, "vltime") == 0) {
- in6_addreq.ifra_lifetime.ia6t_expire = now.tv_sec + newval;
- in6_addreq.ifra_lifetime.ia6t_vltime = newval;
+ lifetime->ia6t_expire = now.tv_sec + newval;
+ lifetime->ia6t_vltime = newval;
} else if (strcmp(cmd, "pltime") == 0) {
- in6_addreq.ifra_lifetime.ia6t_preferred = now.tv_sec + newval;
- in6_addreq.ifra_lifetime.ia6t_pltime = newval;
+ lifetime->ia6t_preferred = now.tv_sec + newval;
+ lifetime->ia6t_pltime = newval;
}
}
static void
-setip6pltime(const char *seconds, int dummy __unused, int s,
- const struct afswtch *afp)
+setip6pltime(if_ctx *ctx, const char *seconds, int dummy __unused)
{
- setip6lifetime("pltime", seconds, s, afp);
+ setip6lifetime(ctx, "pltime", seconds);
}
static void
-setip6vltime(const char *seconds, int dummy __unused, int s,
- const struct afswtch *afp)
+setip6vltime(if_ctx *ctx, const char *seconds, int dummy __unused)
{
- setip6lifetime("vltime", seconds, s, afp);
+ setip6lifetime(ctx, "vltime", seconds);
}
static void
-setip6eui64(const char *cmd, int dummy __unused, int s,
- const struct afswtch *afp)
+setip6eui64(if_ctx *ctx, const char *cmd, int dummy __unused)
{
+ const struct afswtch *afp = ctx->afp;
struct ifaddrs *ifap, *ifa;
const struct sockaddr_in6 *sin6 = NULL;
const struct in6_addr *lladdr = NULL;
@@ -145,15 +183,19 @@ setip6eui64(const char *cmd, int dummy __unused, int s,
if (afp->af_af != AF_INET6)
errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
+#ifdef WITHOUT_NETLINK
in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr;
+#else
+ in6 = &in6_add.addr.addr;
+#endif
if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0)
errx(EXIT_FAILURE, "interface index is already filled");
if (getifaddrs(&ifap) != 0)
err(EXIT_FAILURE, "getifaddrs");
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if (ifa->ifa_addr->sa_family == AF_INET6 &&
- strcmp(ifa->ifa_name, name) == 0) {
- sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
+ strcmp(ifa->ifa_name, ctx->ifname) == 0) {
+ sin6 = (const struct sockaddr_in6 *)satosin6(ifa->ifa_addr);
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
lladdr = &sin6->sin6_addr;
break;
@@ -169,25 +211,94 @@ setip6eui64(const char *cmd, int dummy __unused, int s,
}
static void
-in6_status(int s __unused, const struct ifaddrs *ifa)
+print_addr(struct sockaddr_in6 *sin)
+{
+ int error, n_flags;
+
+ if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
+ n_flags = 0;
+ else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
+ n_flags = NI_NOFQDN;
+ else
+ n_flags = NI_NUMERICHOST;
+ error = getnameinfo((struct sockaddr *)sin, sin->sin6_len,
+ addr_buf, sizeof(addr_buf), NULL, 0,
+ n_flags);
+ if (error != 0)
+ inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
+ sizeof(addr_buf));
+ printf("\tinet6 %s", addr_buf);
+}
+
+static void
+print_p2p(struct sockaddr_in6 *sin)
+{
+ int error;
+
+ error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf,
+ sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
+
+ if (error != 0)
+ inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, sizeof(addr_buf));
+ printf(" --> %s", addr_buf);
+}
+
+static void
+print_mask(int plen)
+{
+ if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0)
+ printf("/%d", plen);
+ else
+ printf(" prefixlen %d", plen);
+}
+
+static void
+print_flags(int flags6)
{
- struct sockaddr_in6 *sin, null_sin;
+ if ((flags6 & IN6_IFF_ANYCAST) != 0)
+ printf(" anycast");
+ if ((flags6 & IN6_IFF_TENTATIVE) != 0)
+ printf(" tentative");
+ if ((flags6 & IN6_IFF_DUPLICATED) != 0)
+ printf(" duplicated");
+ if ((flags6 & IN6_IFF_DETACHED) != 0)
+ printf(" detached");
+ if ((flags6 & IN6_IFF_DEPRECATED) != 0)
+ printf(" deprecated");
+ if ((flags6 & IN6_IFF_AUTOCONF) != 0)
+ printf(" autoconf");
+ if ((flags6 & IN6_IFF_TEMPORARY) != 0)
+ printf(" temporary");
+ if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0)
+ printf(" prefer_source");
+
+}
+
+static void
+print_lifetime(const char *prepend, time_t px_time, struct timespec *now)
+{
+ printf(" %s", prepend);
+ if (px_time == 0)
+ printf(" infty");
+
+ printf(" %s", px_time < now->tv_sec ? "0" : sec2str(px_time - now->tv_sec));
+}
+
+#ifdef WITHOUT_NETLINK
+static void
+in6_status(if_ctx *ctx, const struct ifaddrs *ifa)
+{
+ struct sockaddr_in6 *sin, null_sin = {};
struct in6_ifreq ifr6;
int s6;
u_int32_t flags6;
struct in6_addrlifetime lifetime;
- struct timespec now;
- int error, n_flags;
- clock_gettime(CLOCK_MONOTONIC_FAST, &now);
-
- memset(&null_sin, 0, sizeof(null_sin));
-
- sin = (struct sockaddr_in6 *)ifa->ifa_addr;
+ sin = satosin6(ifa->ifa_addr);
if (sin == NULL)
return;
- strlcpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
+ strlcpy(ifr6.ifr_name, ctx->ifname, sizeof(ifr6.ifr_name));
if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
warn("socket(AF_INET6,SOCK_DGRAM)");
return;
@@ -209,101 +320,202 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
lifetime = ifr6.ifr_ifru.ifru_lifetime;
close(s6);
- if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
- n_flags = 0;
- else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
- n_flags = NI_NOFQDN;
- else
- n_flags = NI_NUMERICHOST;
- error = getnameinfo((struct sockaddr *)sin, sin->sin6_len,
- addr_buf, sizeof(addr_buf), NULL, 0,
- n_flags);
- if (error != 0)
- inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
- sizeof(addr_buf));
- printf("\tinet6 %s", addr_buf);
+ print_addr(sin);
if (ifa->ifa_flags & IFF_POINTOPOINT) {
- sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
+ sin = satosin6(ifa->ifa_dstaddr);
/*
* some of the interfaces do not have valid destination
* address.
*/
- if (sin != NULL && sin->sin6_family == AF_INET6) {
- int error;
-
- error = getnameinfo((struct sockaddr *)sin,
- sin->sin6_len, addr_buf,
- sizeof(addr_buf), NULL, 0,
- NI_NUMERICHOST);
- if (error != 0)
- inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
- sizeof(addr_buf));
- printf(" --> %s", addr_buf);
- }
+ if (sin != NULL && sin->sin6_family == AF_INET6)
+ print_p2p(sin);
}
- sin = (struct sockaddr_in6 *)ifa->ifa_netmask;
+ sin = satosin6(ifa->ifa_netmask);
if (sin == NULL)
sin = &null_sin;
- if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0)
- printf("/%d", prefix(&sin->sin6_addr,
- sizeof(struct in6_addr)));
- else
- printf(" prefixlen %d", prefix(&sin->sin6_addr,
- sizeof(struct in6_addr)));
+ print_mask(prefix(&sin->sin6_addr, sizeof(struct in6_addr)));
- if ((flags6 & IN6_IFF_ANYCAST) != 0)
- printf(" anycast");
- if ((flags6 & IN6_IFF_TENTATIVE) != 0)
- printf(" tentative");
- if ((flags6 & IN6_IFF_DUPLICATED) != 0)
- printf(" duplicated");
- if ((flags6 & IN6_IFF_DETACHED) != 0)
- printf(" detached");
- if ((flags6 & IN6_IFF_DEPRECATED) != 0)
- printf(" deprecated");
- if ((flags6 & IN6_IFF_AUTOCONF) != 0)
- printf(" autoconf");
- if ((flags6 & IN6_IFF_TEMPORARY) != 0)
- printf(" temporary");
- if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0)
- printf(" prefer_source");
+ print_flags(flags6);
- if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id)
+ if ((satosin6(ifa->ifa_addr))->sin6_scope_id)
printf(" scopeid 0x%x",
- ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id);
+ (satosin6(ifa->ifa_addr))->sin6_scope_id);
if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) {
- printf(" pltime");
- if (lifetime.ia6t_preferred) {
- printf(" %s", lifetime.ia6t_preferred < now.tv_sec
- ? "0" :
- sec2str(lifetime.ia6t_preferred - now.tv_sec));
- } else
- printf(" infty");
-
- printf(" vltime");
- if (lifetime.ia6t_expire) {
- printf(" %s", lifetime.ia6t_expire < now.tv_sec
- ? "0" :
- sec2str(lifetime.ia6t_expire - now.tv_sec));
- } else
- printf(" infty");
+ struct timespec now;
+
+ clock_gettime(CLOCK_MONOTONIC_FAST, &now);
+ print_lifetime("pltime", lifetime.ia6t_preferred, &now);
+ print_lifetime("vltime", lifetime.ia6t_expire, &now);
+ }
+
+ print_vhid(ifa);
+
+ putchar('\n');
+}
+
+#else
+static void
+show_lifetime(struct ifa_cacheinfo *ci)
+{
+ struct timespec now;
+ uint32_t pl, vl;
+
+ if (ci == NULL)
+ return;
+
+ int count = ci->ifa_prefered != ND6_INFINITE_LIFETIME;
+ count += ci->ifa_valid != ND6_INFINITE_LIFETIME;
+ if (count == 0)
+ return;
+
+ pl = (ci->ifa_prefered == ND6_INFINITE_LIFETIME) ? 0 : ci->ifa_prefered;
+ vl = (ci->ifa_valid == ND6_INFINITE_LIFETIME) ? 0 : ci->ifa_valid;
+
+ clock_gettime(CLOCK_MONOTONIC_FAST, &now);
+ print_lifetime("pltime", pl + now.tv_sec, &now);
+ print_lifetime("vltime", vl + now.tv_sec, &now);
+}
+
+static void
+in6_status_nl(if_ctx *ctx __unused, if_link_t *link __unused, if_addr_t *ifa)
+{
+ int plen = ifa->ifa_prefixlen;
+ uint32_t scopeid;
+
+ if (ifa->ifa_local == NULL) {
+ /* Non-P2P address */
+ scopeid = satosin6(ifa->ifa_address)->sin6_scope_id;
+ print_addr(satosin6(ifa->ifa_address));
+ } else {
+ scopeid = satosin6(ifa->ifa_local)->sin6_scope_id;
+ print_addr(satosin6(ifa->ifa_local));
+ print_p2p(satosin6(ifa->ifa_address));
}
- print_vhid(ifa, " ");
+ print_mask(plen);
+ print_flags(ifa->ifaf_flags);
+
+ if (scopeid != 0)
+ printf(" scopeid 0x%x", scopeid);
+
+ show_lifetime(ifa->ifa_cacheinfo);
+
+ if (ifa->ifaf_vhid != 0)
+ printf(" vhid %d", ifa->ifaf_vhid);
putchar('\n');
}
-#define SIN6(x) ((struct sockaddr_in6 *) &(x))
+static struct in6_px *sin6tab_nl[] = {
+ &in6_del.addr, /* RIDADDR */
+ &in6_add.addr, /* ADDR */
+ NULL, /* MASK */
+ &in6_add.dst_addr, /* DSTADDR*/
+};
+
+static void
+in6_copyaddr(if_ctx *ctx __unused, int to, int from)
+{
+ sin6tab_nl[to]->addr = sin6tab_nl[from]->addr;
+ sin6tab_nl[to]->set = sin6tab_nl[from]->set;
+}
+
+static void
+in6_getaddr(const char *addr_str, int which)
+{
+ struct in6_px *px = sin6tab_nl[which];
+
+ if (which == MASK)
+ errx(1, "netmask: invalid option for inet6");
+ if (which == BRDADDR)
+ errx(1, "broadcast: invalid option for inet6");
+
+ px->set = true;
+ px->plen = 128;
+ if (which == ADDR) {
+ char *p = NULL;
+ if((p = strrchr(addr_str, '/')) != NULL) {
+ *p = '\0';
+ int plen = strtol(p + 1, NULL, 10);
+ if (plen < 0 || plen > 128)
+ errx(1, "%s: bad value", p + 1);
+ px->plen = plen;
+ explicit_prefix = 1;
+ }
+ }
+
+ struct addrinfo hints = { .ai_family = AF_INET6 };
+ struct addrinfo *res;
+
+ int error = getaddrinfo(addr_str, NULL, &hints, &res);
+ if (error != 0) {
+ if (inet_pton(AF_INET6, addr_str, &px->addr) != 1)
+ errx(1, "%s: bad value", addr_str);
+ } else {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr;
+ px->addr = sin6->sin6_addr;
+ freeaddrinfo(res);
+ }
+}
+
+static int
+in6_exec_nl(if_ctx *ctx, unsigned long action, void *data)
+{
+ struct in6_pdata *pdata = (struct in6_pdata *)data;
+ struct snl_writer nw = {};
+
+ snl_init_writer(ctx->io_ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, action);
+ struct ifaddrmsg *ifahdr = snl_reserve_msg_object(&nw, struct ifaddrmsg);
+
+ ifahdr->ifa_family = AF_INET6;
+ ifahdr->ifa_prefixlen = pdata->addr.plen;
+ ifahdr->ifa_index = if_nametoindex_nl(ctx->io_ss, ctx->ifname);
+
+ snl_add_msg_attr_ip6(&nw, IFA_LOCAL, &pdata->addr.addr);
+ if (action == NL_RTM_NEWADDR && pdata->dst_addr.set)
+ snl_add_msg_attr_ip6(&nw, IFA_ADDRESS, &pdata->dst_addr.addr);
+
+ struct ifa_cacheinfo ci = {
+ .ifa_prefered = pdata->lifetime.ia6t_pltime,
+ .ifa_valid = pdata->lifetime.ia6t_vltime,
+ };
+ snl_add_msg_attr(&nw, IFA_CACHEINFO, sizeof(ci), &ci);
+
+ int off = snl_add_msg_attr_nested(&nw, IFA_FREEBSD);
+ snl_add_msg_attr_u32(&nw, IFAF_FLAGS, pdata->flags);
+ if (pdata->vhid != 0)
+ snl_add_msg_attr_u32(&nw, IFAF_VHID, pdata->vhid);
+ snl_end_attr_nested(&nw, off);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ctx->io_ss, hdr))
+ return (0);
+
+ struct snl_errmsg_data e = {};
+ snl_read_reply_code(ctx->io_ss, hdr->nlmsg_seq, &e);
+
+ return (e.error);
+}
+#endif
+
+#ifdef WITHOUT_NETLINK
static struct sockaddr_in6 *sin6tab[] = {
- SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
- SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)
+ &in6_ridreq.ifr_addr, &in6_addreq.ifra_addr,
+ &in6_addreq.ifra_prefixmask, &in6_addreq.ifra_dstaddr
};
static void
+in6_copyaddr(if_ctx *ctx __unused, int to, int from)
+{
+ memcpy(sin6tab[to], sin6tab[from], sizeof(struct sockaddr_in6));
+}
+
+static void
in6_getprefix(const char *plen, int which)
{
struct sockaddr_in6 *sin = sin6tab[which];
@@ -332,8 +544,6 @@ in6_getaddr(const char *s, int which)
struct addrinfo hints, *res;
int error = -1;
- newaddr &= 1;
-
sin->sin6_len = sizeof(*sin);
if (which != MASK)
sin->sin6_family = AF_INET6;
@@ -384,6 +594,7 @@ prefix(void *val, int size)
return(0);
return (plen);
}
+#endif
static char *
sec2str(time_t total)
@@ -419,20 +630,20 @@ sec2str(time_t total)
}
static void
-in6_postproc(int s, const struct afswtch *afp, int newaddr __unused,
+in6_postproc(if_ctx *ctx, int newaddr __unused,
int ifflags __unused)
{
if (explicit_prefix == 0) {
/* Aggregatable address architecture defines all prefixes
are 64. So, it is convenient to set prefixlen to 64 if
it is not specified. */
- setifprefixlen("64", 0, s, afp);
+ setifprefixlen(ctx, "64", 0);
/* in6_getprefix("64", MASK) if MASK is available here... */
}
}
static void
-in6_status_tunnel(int s)
+in6_status_tunnel(if_ctx *ctx)
{
char src[NI_MAXHOST];
char dst[NI_MAXHOST];
@@ -440,9 +651,9 @@ in6_status_tunnel(int s)
const struct sockaddr *sa = (const struct sockaddr *) &in6_ifr.ifr_addr;
memset(&in6_ifr, 0, sizeof(in6_ifr));
- strlcpy(in6_ifr.ifr_name, name, sizeof(in6_ifr.ifr_name));
+ strlcpy(in6_ifr.ifr_name, ctx->ifname, sizeof(in6_ifr.ifr_name));
- if (ioctl(s, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0)
+ if (ioctl_ctx(ctx, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0)
return;
if (sa->sa_family != AF_INET6)
return;
@@ -450,7 +661,7 @@ in6_status_tunnel(int s)
NI_NUMERICHOST) != 0)
src[0] = '\0';
- if (ioctl(s, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr) < 0)
+ if (ioctl_ctx(ctx, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr) < 0)
return;
if (sa->sa_family != AF_INET6)
return;
@@ -462,20 +673,29 @@ in6_status_tunnel(int s)
}
static void
-in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
+in6_set_tunnel(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres)
{
- struct in6_aliasreq in6_addreq;
+ struct in6_aliasreq in6_req = {};
- memset(&in6_addreq, 0, sizeof(in6_addreq));
- strlcpy(in6_addreq.ifra_name, name, sizeof(in6_addreq.ifra_name));
- memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
- memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr,
+ strlcpy(in6_req.ifra_name, ctx->ifname, sizeof(in6_req.ifra_name));
+ memcpy(&in6_req.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
+ memcpy(&in6_req.ifra_dstaddr, dstres->ai_addr,
dstres->ai_addr->sa_len);
- if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0)
+ if (ioctl_ctx(ctx, SIOCSIFPHYADDR_IN6, &in6_req) < 0)
warn("SIOCSIFPHYADDR_IN6");
}
+static void
+in6_set_vhid(int vhid)
+{
+#ifdef WITHOUT_NETLINK
+ in6_addreq.ifra_vhid = vhid;
+#else
+ in6_add.vhid = (uint32_t)vhid;
+#endif
+}
+
static struct cmd inet6_cmds[] = {
DEF_CMD_ARG("prefixlen", setifprefixlen),
DEF_CMD("anycast", IN6_IFF_ANYCAST, setip6flags),
@@ -506,6 +726,8 @@ static struct cmd inet6_cmds[] = {
DEF_CMD_ARG("pltime", setip6pltime),
DEF_CMD_ARG("vltime", setip6vltime),
DEF_CMD("eui64", 0, setip6eui64),
+ DEF_CMD("stableaddr", ND6_IFF_STABLEADDR, setnd6flags),
+ DEF_CMD("-stableaddr", -ND6_IFF_STABLEADDR, setnd6flags),
#ifdef EXPERIMENTAL
DEF_CMD("ipv6_only", ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags),
DEF_CMD("-ipv6_only", -ND6_IFF_IPV6_ONLY_MANUAL,setnd6flags),
@@ -515,21 +737,38 @@ static struct cmd inet6_cmds[] = {
static struct afswtch af_inet6 = {
.af_name = "inet6",
.af_af = AF_INET6,
+#ifdef WITHOUT_NETLINK
.af_status = in6_status,
+#else
+ .af_status = in6_status_nl,
+#endif
.af_getaddr = in6_getaddr,
+ .af_copyaddr = in6_copyaddr,
+#ifdef WITHOUT_NETLINK
.af_getprefix = in6_getprefix,
+#endif
.af_other_status = nd6_status,
.af_postproc = in6_postproc,
.af_status_tunnel = in6_status_tunnel,
.af_settunnel = in6_set_tunnel,
+ .af_setvhid = in6_set_vhid,
+#ifdef WITHOUT_NETLINK
.af_difaddr = SIOCDIFADDR_IN6,
.af_aifaddr = SIOCAIFADDR_IN6,
- .af_ridreq = &in6_addreq,
+ .af_ridreq = &in6_ridreq,
.af_addreq = &in6_addreq,
+ .af_exec = af_exec_ioctl,
+#else
+ .af_difaddr = NL_RTM_DELADDR,
+ .af_aifaddr = NL_RTM_NEWADDR,
+ .af_ridreq = &in6_del,
+ .af_addreq = &in6_add,
+ .af_exec = in6_exec_nl,
+#endif
};
static void
-in6_Lopt_cb(const char *optarg __unused)
+in6_Lopt_cb(const char *arg __unused)
{
ip6lifetime++; /* print IPv6 address lifetime */
}
diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c
index fb7a235b2f49..55b75d847c16 100644
--- a/sbin/ifconfig/af_link.c
+++ b/sbin/ifconfig/af_link.c
@@ -29,11 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -51,39 +46,80 @@ static const char rcsid[] =
#include <net/ethernet.h>
#include "ifconfig.h"
+#include "ifconfig_netlink.h"
static struct ifreq link_ridreq;
extern char *f_ether;
static void
-link_status(int s __unused, const struct ifaddrs *ifa)
+print_ether(const struct ether_addr *addr, const char *prefix)
{
- /* XXX no const 'cuz LLADDR is defined wrong */
- struct sockaddr_dl *sdl;
- char *ether_format, *format_char;
- struct ifreq ifr;
- int n, rc, sock_hw;
- static const u_char laggaddr[6] = {0};
+ char *ether_format = ether_ntoa(addr);
- sdl = (struct sockaddr_dl *) ifa->ifa_addr;
- if (sdl == NULL || sdl->sdl_alen == 0)
- return;
+ if (f_ether != NULL) {
+ if (strcmp(f_ether, "dash") == 0) {
+ char *format_char;
- if ((sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_L2VLAN ||
- sdl->sdl_type == IFT_BRIDGE) && sdl->sdl_alen == ETHER_ADDR_LEN) {
- ether_format = ether_ntoa((struct ether_addr *)LLADDR(sdl));
- if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
- while ((format_char = strchr(ether_format, ':')) !=
- NULL) {
+ while ((format_char = strchr(ether_format, ':')) != NULL) {
*format_char = '-';
}
+ } else if (strcmp(f_ether, "dotted") == 0) {
+ /* Indices 0 and 1 is kept as is. */
+ ether_format[ 2] = ether_format[ 3];
+ ether_format[ 3] = ether_format[ 4];
+ ether_format[ 4] = '.';
+ ether_format[ 5] = ether_format[ 6];
+ ether_format[ 6] = ether_format[ 7];
+ ether_format[ 7] = ether_format[ 9];
+ ether_format[ 8] = ether_format[10];
+ ether_format[ 9] = '.';
+ ether_format[10] = ether_format[12];
+ ether_format[11] = ether_format[13];
+ ether_format[12] = ether_format[15];
+ ether_format[13] = ether_format[16];
+ ether_format[14] = '\0';
}
- printf("\tether %s\n", ether_format);
+ }
+ printf("\t%s %s\n", prefix, ether_format);
+}
+
+static void
+print_lladdr(struct sockaddr_dl *sdl)
+{
+ if (match_ether(sdl)) {
+ print_ether((struct ether_addr *)LLADDR(sdl), "ether");
} else {
- n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
+ int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
printf("\tlladdr %s\n", link_ntoa(sdl) + n);
}
+}
+
+static void
+print_pcp(if_ctx *ctx)
+{
+ struct ifreq ifr = {};
+
+ if (ioctl_ctx_ifr(ctx, SIOCGLANPCP, &ifr) == 0 &&
+ ifr.ifr_lan_pcp != IFNET_PCP_NONE)
+ printf("\tpcp %d\n", ifr.ifr_lan_pcp);
+}
+
+#ifdef WITHOUT_NETLINK
+static void
+link_status(if_ctx *ctx, const struct ifaddrs *ifa)
+{
+ /* XXX no const 'cuz LLADDR is defined wrong */
+ struct sockaddr_dl *sdl;
+ struct ifreq ifr;
+ int rc, sock_hw;
+ static const u_char laggaddr[6] = {0};
+
+ sdl = satosdl(ifa->ifa_addr);
+ if (sdl == NULL || sdl->sdl_alen == 0)
+ return;
+
+ print_lladdr(sdl);
/*
* Best-effort (i.e. failures are silent) to get original
@@ -118,21 +154,37 @@ link_status(int s __unused, const struct ifaddrs *ifa)
memcmp(ifr.ifr_addr.sa_data, LLADDR(sdl), sdl->sdl_alen) == 0)
goto pcp;
- ether_format = ether_ntoa((const struct ether_addr *)
- &ifr.ifr_addr.sa_data);
- if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
- for (format_char = strchr(ether_format, ':');
- format_char != NULL;
- format_char = strchr(ether_format, ':'))
- *format_char = '-';
- }
- printf("\thwaddr %s\n", ether_format);
-
+ print_ether((const struct ether_addr *)&ifr.ifr_addr.sa_data, "hwaddr");
pcp:
- if (ioctl(s, SIOCGLANPCP, (caddr_t)&ifr) == 0 &&
- ifr.ifr_lan_pcp != IFNET_PCP_NONE)
- printf("\tpcp %d\n", ifr.ifr_lan_pcp);
+ print_pcp(ctx);
+}
+
+#else
+
+static void
+link_status_nl(if_ctx *ctx, if_link_t *link, if_addr_t *ifa __unused)
+{
+ if (link->ifla_address != NULL) {
+ struct sockaddr_dl sdl = {
+ .sdl_len = sizeof(struct sockaddr_dl),
+ .sdl_family = AF_LINK,
+ .sdl_type = convert_iftype(link->ifi_type),
+ .sdl_alen = NLA_DATA_LEN(link->ifla_address),
+ };
+ memcpy(LLADDR(&sdl), NLA_DATA(link->ifla_address), sdl.sdl_alen);
+ print_lladdr(&sdl);
+
+ if (link->iflaf_orig_hwaddr != NULL) {
+ struct nlattr *hwaddr = link->iflaf_orig_hwaddr;
+
+ if (memcmp(NLA_DATA(hwaddr), NLA_DATA(link->ifla_address), sdl.sdl_alen))
+ print_ether((struct ether_addr *)NLA_DATA(hwaddr), "hwaddr");
+ }
+ }
+ if (convert_iftype(link->ifi_type) == IFT_ETHER)
+ print_pcp(ctx);
}
+#endif
static void
link_getaddr(const char *addr, int which)
@@ -158,7 +210,8 @@ link_getaddr(const char *addr, int which)
temp[0] = ':';
strcpy(temp + 1, addr);
sdl.sdl_len = sizeof(sdl);
- link_addr(temp, &sdl);
+ if (link_addr(temp, &sdl) == -1)
+ errx(1, "malformed link-level address");
free(temp);
}
if (sdl.sdl_alen > sizeof(sa->sa_data))
@@ -171,26 +224,41 @@ link_getaddr(const char *addr, int which)
static struct afswtch af_link = {
.af_name = "link",
.af_af = AF_LINK,
+#ifdef WITHOUT_NETLINK
.af_status = link_status,
+#else
+ .af_status = link_status_nl,
+#endif
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
+ .af_exec = af_exec_ioctl,
};
static struct afswtch af_ether = {
.af_name = "ether",
.af_af = AF_LINK,
+#ifdef WITHOUT_NETLINK
.af_status = link_status,
+#else
+ .af_status = link_status_nl,
+#endif
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
+ .af_exec = af_exec_ioctl,
};
static struct afswtch af_lladdr = {
.af_name = "lladdr",
.af_af = AF_LINK,
+#ifdef WITHOUT_NETLINK
.af_status = link_status,
+#else
+ .af_status = link_status_nl,
+#endif
.af_getaddr = link_getaddr,
.af_aifaddr = SIOCSIFLLADDR,
.af_addreq = &link_ridreq,
+ .af_exec = af_exec_ioctl,
};
static __constructor void
diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c
index b6cda30dc06d..fb7e72028e2e 100644
--- a/sbin/ifconfig/af_nd6.c
+++ b/sbin/ifconfig/af_nd6.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009 Hiroki Sato. All rights reserved.
*
@@ -25,11 +25,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -57,34 +52,37 @@ static const char rcsid[] =
#include "ifconfig.h"
#define MAX_SYSCTL_TRY 5
+static const char *ND6BITS[] = {
+ [0] = "PERFORMNUD",
+ [1] = "ACCEPT_RTADV",
+ [2] = "PREFER_SOURCE",
+ [3] = "IFDISABLED",
+ [4] = "DONT_SET_IFROUTE",
+ [5] = "AUTO_LINKLOCAL",
+ [6] = "NO_RADR",
+ [7] = "NO_PREFER_IFACE",
+ [8] = "NO_DAD",
#ifdef DRAFT_IETF_6MAN_IPV6ONLY_FLAG
-#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
- "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
- "\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD" \
- "\012IPV6_ONLY\013IPV6_ONLY_MANUAL" \
- "\020DEFAULTIF"
-#else
-#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
- "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
- "\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD\020DEFAULTIF"
+ [9] = "IPV6_ONLY",
+ [10] = "IPV6_ONLY_MANUAL",
#endif
+ [11] = "STABLEADDR",
+ [15] = "DEFAULTIF",
+};
-static int isnd6defif(int);
-void setnd6flags(const char *, int, int, const struct afswtch *);
-void setnd6defif(const char *, int, int, const struct afswtch *);
-void nd6_status(int);
+static int isnd6defif(if_ctx *ctx, int s);
+void setnd6flags(if_ctx *, const char *, int);
+void setnd6defif(if_ctx *,const char *, int);
+void nd6_status(if_ctx *);
void
-setnd6flags(const char *dummyaddr __unused,
- int d, int s,
- const struct afswtch *afp)
+setnd6flags(if_ctx *ctx, const char *dummyaddr __unused, int d)
{
- struct in6_ndireq nd;
+ struct in6_ndireq nd = {};
int error;
- memset(&nd, 0, sizeof(nd));
- strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
- error = ioctl(s, SIOCGIFINFO_IN6, &nd);
+ strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname));
+ error = ioctl_ctx(ctx, SIOCGIFINFO_IN6, &nd);
if (error) {
warn("ioctl(SIOCGIFINFO_IN6)");
return;
@@ -93,25 +91,22 @@ setnd6flags(const char *dummyaddr __unused,
nd.ndi.flags &= ~(-d);
else
nd.ndi.flags |= d;
- error = ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd);
+ error = ioctl_ctx(ctx, SIOCSIFINFO_IN6, (caddr_t)&nd);
if (error)
warn("ioctl(SIOCSIFINFO_IN6)");
}
void
-setnd6defif(const char *dummyaddr __unused,
- int d, int s,
- const struct afswtch *afp)
+setnd6defif(if_ctx *ctx, const char *dummyaddr __unused, int d)
{
- struct in6_ndifreq ndifreq;
+ struct in6_ndifreq ndifreq = {};
int ifindex;
int error;
- memset(&ndifreq, 0, sizeof(ndifreq));
- strlcpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+ strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname));
if (d < 0) {
- if (isnd6defif(s)) {
+ if (isnd6defif(ctx, ctx->io_s)) {
/* ifindex = 0 means to remove default if */
ifindex = 0;
} else
@@ -122,20 +117,19 @@ setnd6defif(const char *dummyaddr __unused,
}
ndifreq.ifindex = ifindex;
- error = ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq);
+ error = ioctl_ctx(ctx, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq);
if (error)
warn("ioctl(SIOCSDEFIFACE_IN6)");
}
static int
-isnd6defif(int s)
+isnd6defif(if_ctx *ctx, int s)
{
- struct in6_ndifreq ndifreq;
+ struct in6_ndifreq ndifreq = {};
unsigned int ifindex;
int error;
- memset(&ndifreq, 0, sizeof(ndifreq));
- strlcpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+ strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname));
ifindex = if_nametoindex(ndifreq.ifname);
error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq);
@@ -147,15 +141,15 @@ isnd6defif(int s)
}
void
-nd6_status(int s)
+nd6_status(if_ctx *ctx)
{
- struct in6_ndireq nd;
+ struct in6_ndireq nd = {};
int s6;
int error;
int isdefif;
+ uint32_t bits;
- memset(&nd, 0, sizeof(nd));
- strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+ strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname));
if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
warn("socket(AF_INET6, SOCK_DGRAM)");
@@ -168,11 +162,12 @@ nd6_status(int s)
close(s6);
return;
}
- isdefif = isnd6defif(s6);
+ isdefif = isnd6defif(ctx, s6);
close(s6);
if (nd.ndi.flags == 0 && !isdefif)
return;
- printb("\tnd6 options",
- (unsigned int)(nd.ndi.flags | (isdefif << 15)), ND6BITS);
+ bits = (nd.ndi.flags | (isdefif << 15));
+ printf("\tnd6 options=%x", bits);
+ print_bits("options", &bits, 1, ND6BITS, nitems(ND6BITS));
putchar('\n');
}
diff --git a/sbin/ifconfig/carp.c b/sbin/ifconfig/carp.c
index 23a119e3b9d7..7c7398f92d48 100644
--- a/sbin/ifconfig/carp.c
+++ b/sbin/ifconfig/carp.c
@@ -1,8 +1,7 @@
-/* $FreeBSD$ */
/* from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
* Copyright (c) 2003 Ryan McBride. All rights reserved.
@@ -42,13 +41,17 @@
#include <netinet/in_var.h>
#include <netinet/ip_carp.h>
+#include <arpa/inet.h>
+
#include <ctype.h>
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
+#include <netdb.h>
#include <libifconfig.h>
@@ -56,41 +59,58 @@
static const char *carp_states[] = { CARP_STATES };
-static void carp_status(int s);
-static void setcarp_vhid(const char *, int, int, const struct afswtch *rafp);
-static void setcarp_callback(int, void *);
-static void setcarp_advbase(const char *,int, int, const struct afswtch *rafp);
-static void setcarp_advskew(const char *, int, int, const struct afswtch *rafp);
-static void setcarp_passwd(const char *, int, int, const struct afswtch *rafp);
+static void setcarp_callback(if_ctx *, void *);
static int carpr_vhid = -1;
static int carpr_advskew = -1;
static int carpr_advbase = -1;
static int carpr_state = -1;
+static struct in_addr carp_addr;
+static struct in6_addr carp_addr6;
static unsigned char const *carpr_key;
+static carp_version_t carpr_version;
+static uint8_t carpr_vrrp_prio;
+static uint16_t carpr_vrrp_adv_inter;
static void
-carp_status(int s)
+carp_status(if_ctx *ctx)
{
- struct carpreq carpr[CARP_MAXVHID];
+ struct ifconfig_carp carpr[CARP_MAXVHID];
+ char addr_buf[NI_MAXHOST];
- if (ifconfig_carp_get_info(lifh, name, carpr, CARP_MAXVHID) == -1)
+ if (ifconfig_carp_get_info(lifh, ctx->ifname, carpr, CARP_MAXVHID) == -1)
return;
for (size_t i = 0; i < carpr[0].carpr_count; i++) {
- printf("\tcarp: %s vhid %d advbase %d advskew %d",
- carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid,
- carpr[i].carpr_advbase, carpr[i].carpr_advskew);
- if (printkeys && carpr[i].carpr_key[0] != '\0')
- printf(" key \"%s\"\n", carpr[i].carpr_key);
- else
- printf("\n");
+ switch (carpr[i].carpr_version) {
+ case CARP_VERSION_CARP:
+ printf("\tcarp: %s vhid %d advbase %d advskew %d",
+ carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid,
+ carpr[i].carpr_advbase, carpr[i].carpr_advskew);
+ if (ctx->args->printkeys && carpr[i].carpr_key[0] != '\0')
+ printf(" key \"%s\"\n", carpr[i].carpr_key);
+ else
+ printf("\n");
+
+ inet_ntop(AF_INET6, &carpr[i].carpr_addr6, addr_buf,
+ sizeof(addr_buf));
+
+ printf("\t peer %s peer6 %s\n",
+ inet_ntoa(carpr[i].carpr_addr), addr_buf);
+ break;
+ case CARP_VERSION_VRRPv3:
+ printf("\tvrrp: %s vrid %d prio %d interval %d\n",
+ carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid,
+ carpr[i].carpr_vrrp_prio, carpr[i].carpr_vrrp_adv_inter);
+ break;
+ }
}
}
static void
-setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_vhid(if_ctx *ctx, const char *val, int dummy __unused)
{
+ const struct afswtch *afp = ctx->afp;
carpr_vhid = atoi(val);
@@ -98,47 +118,23 @@ setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp)
errx(1, "vhid must be greater than 0 and less than %u",
CARP_MAXVHID);
- switch (afp->af_af) {
-#ifdef INET
- case AF_INET:
- {
- struct in_aliasreq *ifra;
-
- ifra = (struct in_aliasreq *)afp->af_addreq;
- ifra->ifra_vhid = carpr_vhid;
- break;
- }
-#endif
-#ifdef INET6
- case AF_INET6:
- {
- struct in6_aliasreq *ifra;
-
- ifra = (struct in6_aliasreq *)afp->af_addreq;
- ifra->ifra_vhid = carpr_vhid;
- break;
- }
-#endif
- default:
+ if (afp->af_setvhid == NULL)
errx(1, "%s doesn't support carp(4)", afp->af_name);
- }
-
+ afp->af_setvhid(carpr_vhid);
callback_register(setcarp_callback, NULL);
}
static void
-setcarp_callback(int s, void *arg __unused)
+setcarp_callback(if_ctx *ctx, void *arg __unused)
{
- struct carpreq carpr;
-
- bzero(&carpr, sizeof(struct carpreq));
- carpr.carpr_vhid = carpr_vhid;
- carpr.carpr_count = 1;
- ifr.ifr_data = (caddr_t)&carpr;
+ struct ifconfig_carp carpr = { };
- if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1 && errno != ENOENT)
- err(1, "SIOCGVH");
+ if (ifconfig_carp_get_vhid(lifh, ctx->ifname, &carpr, carpr_vhid) == -1) {
+ if (ifconfig_err_errno(lifh) != ENOENT)
+ return;
+ }
+ carpr.carpr_vhid = carpr_vhid;
if (carpr_key != NULL)
/* XXX Should hash the password into the key here? */
strlcpy(carpr.carpr_key, carpr_key, CARP_KEY_LEN);
@@ -148,13 +144,24 @@ setcarp_callback(int s, void *arg __unused)
carpr.carpr_advbase = carpr_advbase;
if (carpr_state > -1)
carpr.carpr_state = carpr_state;
-
- if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
+ if (carp_addr.s_addr != INADDR_ANY)
+ carpr.carpr_addr = carp_addr;
+ if (! IN6_IS_ADDR_UNSPECIFIED(&carp_addr6))
+ memcpy(&carpr.carpr_addr6, &carp_addr6,
+ sizeof(carp_addr6));
+ if (carpr_version != 0)
+ carpr.carpr_version = carpr_version;
+ if (carpr_vrrp_prio != 0)
+ carpr.carpr_vrrp_prio = carpr_vrrp_prio;
+ if (carpr_vrrp_adv_inter != 0)
+ carpr.carpr_vrrp_adv_inter = carpr_vrrp_adv_inter;
+
+ if (ifconfig_carp_set_info(lifh, ctx->ifname, &carpr))
err(1, "SIOCSVH");
}
static void
-setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_passwd(if_ctx *ctx __unused, const char *val, int dummy __unused)
{
if (carpr_vhid == -1)
@@ -164,7 +171,7 @@ setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
}
static void
-setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_advskew(if_ctx *ctx __unused, const char *val, int dummy __unused)
{
if (carpr_vhid == -1)
@@ -174,7 +181,7 @@ setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
}
static void
-setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_advbase(if_ctx *ctx __unused, const char *val, int dummy __unused)
{
if (carpr_vhid == -1)
@@ -184,7 +191,7 @@ setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
}
static void
-setcarp_state(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_state(if_ctx *ctx __unused, const char *val, int dummy __unused)
{
int i;
@@ -200,12 +207,81 @@ setcarp_state(const char *val, int d, int s, const struct afswtch *afp)
errx(1, "unknown state");
}
+static void
+setcarp_peer(if_ctx *ctx __unused, const char *val, int dummy __unused)
+{
+ carp_addr.s_addr = inet_addr(val);
+}
+
+static void
+setcarp_mcast(if_ctx *ctx __unused, const char *val __unused, int dummy __unused)
+{
+ carp_addr.s_addr = htonl(INADDR_CARP_GROUP);
+}
+
+static void
+setcarp_peer6(if_ctx *ctx __unused, const char *val, int dummy __unused)
+{
+ struct addrinfo hints, *res;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if (getaddrinfo(val, NULL, &hints, &res) != 0)
+ errx(1, "Invalid IPv6 address %s", val);
+
+ memcpy(&carp_addr6, &(satosin6(res->ai_addr))->sin6_addr, sizeof(carp_addr6));
+ freeaddrinfo(res);
+}
+
+static void
+setcarp_mcast6(if_ctx *ctx __unused, const char *val __unused, int dummy __unused)
+{
+ bzero(&carp_addr6, sizeof(carp_addr6));
+ carp_addr6.s6_addr[0] = 0xff;
+ carp_addr6.s6_addr[1] = 0x02;
+ carp_addr6.s6_addr[15] = 0x12;
+}
+
+static void
+setcarp_version(if_ctx *ctx __unused, const char *val, int dummy __unused)
+{
+ carpr_version = atoi(val);
+
+ if (carpr_version != CARP_VERSION_CARP && carpr_version != CARP_VERSION_VRRPv3)
+ errx(1, "version must be %d or %d", CARP_VERSION_CARP,
+ CARP_VERSION_VRRPv3);
+}
+
+static void
+setvrrp_prio(if_ctx *ctx __unused, const char *val, int dummy __unused)
+{
+ carpr_vrrp_prio = atoi(val);
+}
+
+static void
+setvrrp_interval(if_ctx *ctx __unused, const char *val, int dummy __unused)
+{
+ carpr_vrrp_adv_inter = atoi(val);
+
+ if (carpr_vrrp_adv_inter == 0 || carpr_vrrp_adv_inter > VRRP_MAX_INTERVAL)
+ errx(1, "vrrpinterval must be greater than 0 and less than %d", VRRP_MAX_INTERVAL);
+}
+
static struct cmd carp_cmds[] = {
DEF_CMD_ARG("advbase", setcarp_advbase),
DEF_CMD_ARG("advskew", setcarp_advskew),
DEF_CMD_ARG("pass", setcarp_passwd),
DEF_CMD_ARG("vhid", setcarp_vhid),
DEF_CMD_ARG("state", setcarp_state),
+ DEF_CMD_ARG("peer", setcarp_peer),
+ DEF_CMD("mcast", 0, setcarp_mcast),
+ DEF_CMD_ARG("peer6", setcarp_peer6),
+ DEF_CMD("mcast6", 0, setcarp_mcast6),
+ DEF_CMD_ARG("carpver", setcarp_version),
+ DEF_CMD_ARG("vrrpprio", setvrrp_prio),
+ DEF_CMD_ARG("vrrpinterval", setvrrp_interval),
};
static struct afswtch af_carp = {
.af_name = "af_carp",
@@ -216,9 +292,7 @@ static struct afswtch af_carp = {
static __constructor void
carp_ctor(void)
{
- int i;
-
- for (i = 0; i < nitems(carp_cmds); i++)
+ for (size_t i = 0; i < nitems(carp_cmds); i++)
cmd_register(&carp_cmds[i]);
af_register(&af_carp);
}
diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
index 2bd9c96f2489..eff443447c13 100644
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -35,11 +35,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -65,6 +60,10 @@ static const char rcsid[] =
#include "ifconfig.h"
+static int parse_vlans(ifbvlan_set_t *set, const char *str);
+static int get_val(const char *cp, u_long *valp);
+static int get_vlan_id(const char *cp, ether_vlanid_t *valp);
+
static const char *stpstates[] = { STP_STATES };
static const char *stpproto[] = { STP_PROTOS };
static const char *stproles[] = { STP_ROLES };
@@ -85,28 +84,40 @@ get_val(const char *cp, u_long *valp)
}
static int
-do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
+get_vlan_id(const char *cp, ether_vlanid_t *valp)
{
- struct ifdrv ifd;
+ u_long val;
+
+ if (get_val(cp, &val) == -1)
+ return (-1);
+ if (val < DOT1Q_VID_MIN || val > DOT1Q_VID_MAX)
+ return (-1);
- memset(&ifd, 0, sizeof(ifd));
+ *valp = (ether_vlanid_t)val;
+ return (0);
+}
+
+static int
+do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set)
+{
+ struct ifdrv ifd = {};
- strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
+ strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name));
ifd.ifd_cmd = op;
ifd.ifd_len = argsize;
ifd.ifd_data = arg;
- return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
+ return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
}
static void
-do_bridgeflag(int sock, const char *ifs, int flag, int set)
+do_bridgeflag(if_ctx *ctx, const char *ifs, int flag, int set)
{
struct ifbreq req;
strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname));
- if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0)
+ if (do_cmd(ctx, BRDGGIFFLGS, &req, sizeof(req), 0) < 0)
err(1, "unable to get bridge flags");
if (set)
@@ -114,17 +125,17 @@ do_bridgeflag(int sock, const char *ifs, int flag, int set)
else
req.ifbr_ifsflags &= ~flag;
- if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGSIFFLGS, &req, sizeof(req), 1) < 0)
err(1, "unable to set bridge flags");
}
static void
-bridge_addresses(int s, const char *prefix)
+bridge_addresses(if_ctx *ctx, const char *prefix)
{
struct ifbaconf ifbac;
struct ifbareq *ifba;
char *inbuf = NULL, *ninbuf;
- int i, len = 8192;
+ size_t len = 8192;
struct ether_addr ea;
for (;;) {
@@ -133,14 +144,14 @@ bridge_addresses(int s, const char *prefix)
err(1, "unable to allocate address buffer");
ifbac.ifbac_len = len;
ifbac.ifbac_buf = inbuf = ninbuf;
- if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0)
+ if (do_cmd(ctx, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0)
err(1, "unable to get address cache");
if ((ifbac.ifbac_len + sizeof(*ifba)) < len)
break;
len *= 2;
}
- for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
+ for (unsigned long i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
ifba = ifbac.ifbac_req + i;
memcpy(ea.octet, ifba->ifba_dst,
sizeof(ea.octet));
@@ -154,7 +165,52 @@ bridge_addresses(int s, const char *prefix)
}
static void
-bridge_status(int s)
+print_vlans(ifbvlan_set_t *vlans)
+{
+ unsigned printed = 0;
+
+ for (unsigned vlan = DOT1Q_VID_MIN; vlan <= DOT1Q_VID_MAX;) {
+ unsigned last;
+
+ if (!BRVLAN_TEST(vlans, vlan)) {
+ ++vlan;
+ continue;
+ }
+
+ last = vlan;
+ while (last < DOT1Q_VID_MAX && BRVLAN_TEST(vlans, last + 1))
+ ++last;
+
+ if (printed == 0)
+ printf(" tagged ");
+ else
+ printf(",");
+
+ printf("%u", vlan);
+ if (last != vlan)
+ printf("-%u", last);
+ ++printed;
+ vlan = last + 1;
+ }
+}
+
+static char const *
+vlan_proto_name(uint16_t proto)
+{
+ switch (proto) {
+ case 0:
+ return "none";
+ case ETHERTYPE_VLAN:
+ return "802.1q";
+ case ETHERTYPE_QINQ:
+ return "802.1ad";
+ default:
+ return "unknown";
+ }
+}
+
+static void
+bridge_status(if_ctx *ctx)
{
struct ifconfig_bridge_status *bridge;
struct ifbropreq *params;
@@ -162,7 +218,7 @@ bridge_status(int s)
uint8_t lladdr[ETHER_ADDR_LEN];
uint16_t bprio;
- if (ifconfig_bridge_get_bridge_status(lifh, name, &bridge) == -1)
+ if (ifconfig_bridge_get_bridge_status(lifh, ctx->ifname, &bridge) == -1)
return;
params = bridge->params;
@@ -186,6 +242,11 @@ bridge_status(int s)
params->ifbop_root_path_cost,
params->ifbop_root_port & 0xfff);
+ printb("\tbridge flags", bridge->flags, IFBRFBITS);
+ if (bridge->defpvid)
+ printf(" defuntagged=%u", (unsigned) bridge->defpvid);
+ printf("\n");
+
prefix = "\tmember: ";
pad = "\t ";
for (size_t i = 0; i < bridge->members_count; ++i) {
@@ -194,8 +255,9 @@ bridge_status(int s)
printf("%s%s ", prefix, member->ifbr_ifsname);
printb("flags", member->ifbr_ifsflags, IFBIFBITS);
printf("\n%s", pad);
- printf("ifmaxaddr %u port %u priority %u path cost %u",
- member->ifbr_addrmax,
+ if (member->ifbr_addrmax != 0)
+ printf("ifmaxaddr %u ", member->ifbr_addrmax);
+ printf("port %u priority %u path cost %u",
member->ifbr_portno,
member->ifbr_priority,
member->ifbr_path_cost);
@@ -218,231 +280,319 @@ bridge_status(int s)
else
printf(" <unknown state %d>", state);
}
+ if (member->ifbr_vlanproto != 0)
+ printf(" vlan protocol %s",
+ vlan_proto_name(member->ifbr_vlanproto));
+ if (member->ifbr_pvid != 0)
+ printf(" untagged %u", (unsigned)member->ifbr_pvid);
+ print_vlans(&bridge->member_vlans[i]);
printf("\n");
}
ifconfig_bridge_free_bridge_status(bridge);
}
-static void
-setbridge_add(const char *val, int d, int s, const struct afswtch *afp)
+static int
+setbridge_add(if_ctx *ctx, int argc, const char *const *argv)
{
struct ifbreq req;
+ struct ifbif_vlan_req vlreq;
+ int oargc = argc;
memset(&req, 0, sizeof(req));
- strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
- if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0)
- err(1, "BRDGADD %s", val);
+ memset(&vlreq, 0, sizeof(vlreq));
+
+ if (argc < 1)
+ errx(1, "usage: addm <interface> [opts ...]");
+
+ strlcpy(req.ifbr_ifsname, argv[0], sizeof(req.ifbr_ifsname));
+ --argc; ++argv;
+
+ while (argc) {
+ if (strcmp(argv[0], "untagged") == 0) {
+ if (argc < 2)
+ errx(1, "usage: untagged <vlan id>");
+
+ if (get_vlan_id(argv[1], &req.ifbr_pvid) < 0)
+ errx(1, "invalid VLAN identifier: %s", argv[1]);
+
+ argc -= 2;
+ argv += 2;
+ } else if (strcmp(argv[0], "tagged") == 0) {
+ if (argc < 2)
+ errx(1, "usage: tagged <vlan set>");
+
+ vlreq.bv_op = BRDG_VLAN_OP_SET;
+ strlcpy(vlreq.bv_ifname, req.ifbr_ifsname,
+ sizeof(vlreq.bv_ifname));
+ if (parse_vlans(&vlreq.bv_set, argv[1]) != 0)
+ errx(1, "invalid vlan set: %s", argv[1]);
+
+ argc -= 2;
+ argv += 2;
+ } else {
+ break;
+ }
+ }
+
+ if (do_cmd(ctx, BRDGADD, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGADD %s", req.ifbr_ifsname);
+
+ if (req.ifbr_pvid != 0 &&
+ do_cmd(ctx, BRDGSIFPVID, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFPVID %s %u", req.ifbr_ifsname,
+ (unsigned)req.ifbr_pvid);
+
+ if (vlreq.bv_op != 0 &&
+ do_cmd(ctx, BRDGSIFVLANSET, &vlreq, sizeof(vlreq), 1) < 0)
+ err(1, "BRDGSIFVLANSET %s", req.ifbr_ifsname);
+
+ return (oargc - argc);
}
static void
-setbridge_delete(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_delete(if_ctx *ctx, const char *val, int dummy __unused)
{
struct ifbreq req;
memset(&req, 0, sizeof(req));
strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
- if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGDEL, &req, sizeof(req), 1) < 0)
err(1, "BRDGDEL %s", val);
}
static void
-setbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_discover(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_DISCOVER, 1);
+ do_bridgeflag(ctx, val, IFBIF_DISCOVER, 1);
}
static void
-unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_discover(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_DISCOVER, 0);
+ do_bridgeflag(ctx, val, IFBIF_DISCOVER, 0);
}
static void
-setbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_learn(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_LEARNING, 1);
+ do_bridgeflag(ctx, val, IFBIF_LEARNING, 1);
}
static void
-unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_learn(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_LEARNING, 0);
+ do_bridgeflag(ctx, val, IFBIF_LEARNING, 0);
}
static void
-setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_sticky(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_STICKY, 1);
+ do_bridgeflag(ctx, val, IFBIF_STICKY, 1);
}
static void
-unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_sticky(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_STICKY, 0);
+ do_bridgeflag(ctx, val, IFBIF_STICKY, 0);
}
static void
-setbridge_span(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_span(if_ctx *ctx, const char *val, int dummy __unused)
{
struct ifbreq req;
memset(&req, 0, sizeof(req));
strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
- if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGADDS, &req, sizeof(req), 1) < 0)
err(1, "BRDGADDS %s", val);
}
static void
-unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_span(if_ctx *ctx, const char *val, int dummy __unused)
{
struct ifbreq req;
memset(&req, 0, sizeof(req));
strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
- if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGDELS, &req, sizeof(req), 1) < 0)
err(1, "BRDGDELS %s", val);
}
static void
-setbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_stp(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_STP, 1);
+ do_bridgeflag(ctx, val, IFBIF_STP, 1);
}
static void
-unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_stp(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_STP, 0);
+ do_bridgeflag(ctx, val, IFBIF_STP, 0);
}
static void
-setbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_edge(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_EDGE, 1);
}
static void
-unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_edge(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_EDGE, 0);
}
static void
-setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_autoedge(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOEDGE, 1);
}
static void
-unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_autoedge(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOEDGE, 0);
}
static void
-setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_ptp(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_PTP, 1);
}
static void
-unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_ptp(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_PTP, 0);
}
static void
-setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_autoptp(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOPTP, 1);
}
static void
-unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_autoptp(if_ctx *ctx, const char *val, int dummy __unused)
{
- do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0);
+ do_bridgeflag(ctx, val, IFBIF_BSTP_AUTOPTP, 0);
}
static void
-setbridge_flush(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_flush(if_ctx *ctx, const char *val __unused, int dummy __unused)
{
struct ifbreq req;
memset(&req, 0, sizeof(req));
req.ifbr_ifsflags = IFBF_FLUSHDYN;
- if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGFLUSH, &req, sizeof(req), 1) < 0)
err(1, "BRDGFLUSH");
}
static void
-setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_flushall(if_ctx *ctx, const char *val __unused, int dummy __unused)
{
struct ifbreq req;
memset(&req, 0, sizeof(req));
req.ifbr_ifsflags = IFBF_FLUSHALL;
- if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGFLUSH, &req, sizeof(req), 1) < 0)
err(1, "BRDGFLUSH");
}
-static void
-setbridge_static(const char *val, const char *mac, int s,
- const struct afswtch *afp)
+static int
+setbridge_static(if_ctx *ctx, int argc, const char *const *argv)
{
struct ifbareq req;
struct ether_addr *ea;
+ int arg;
+
+ if (argc < 2)
+ errx(1, "usage: static <interface> <address> [vlan <id>]");
+ arg = 0;
memset(&req, 0, sizeof(req));
- strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname));
+ req.ifba_flags = IFBAF_STATIC;
- ea = ether_aton(mac);
- if (ea == NULL)
- errx(1, "%s: invalid address: %s", val, mac);
+ strlcpy(req.ifba_ifsname, argv[arg], sizeof(req.ifba_ifsname));
+ ++arg;
+ ea = ether_aton(argv[arg]);
+ if (ea == NULL)
+ errx(1, "invalid address: %s", argv[arg]);
memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
- req.ifba_flags = IFBAF_STATIC;
- req.ifba_vlan = 1; /* XXX allow user to specify */
+ ++arg;
+
+ req.ifba_vlan = 0;
+ if (argc > 2 && strcmp(argv[arg], "vlan") == 0) {
+ if (argc < 3)
+ errx(1, "usage: static <interface> <address> "
+ "[vlan <id>]");
+ ++arg;
+
+ if (get_vlan_id(argv[arg], &req.ifba_vlan) < 0)
+ errx(1, "invalid vlan id: %s", argv[arg]);
+ ++arg;
+ }
- if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0)
- err(1, "BRDGSADDR %s", val);
+ if (do_cmd(ctx, BRDGSADDR, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSADDR");
+ return arg;
}
-static void
-setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp)
+static int
+setbridge_deladdr(if_ctx *ctx, int argc, const char *const *argv)
{
struct ifbareq req;
struct ether_addr *ea;
+ int arg;
+
+ if (argc < 1)
+ errx(1, "usage: deladdr <address> [vlan <id>]");
+ arg = 0;
memset(&req, 0, sizeof(req));
- ea = ether_aton(val);
+ ea = ether_aton(argv[arg]);
if (ea == NULL)
- errx(1, "invalid address: %s", val);
-
+ errx(1, "invalid address: %s", argv[arg]);
memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
+ ++arg;
+
+ req.ifba_vlan = 0;
+ if (argc >= 2 && strcmp(argv[arg], "vlan") == 0) {
+ if (argc < 3)
+ errx(1, "usage: deladdr <address> [vlan <id>]");
+ ++arg;
+
+ if (get_vlan_id(argv[arg], &req.ifba_vlan) < 0)
+ errx(1, "invalid vlan id: %s", argv[arg]);
+ ++arg;
+ }
+
+ if (do_cmd(ctx, BRDGDADDR, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGDADDR");
- if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0)
- err(1, "BRDGDADDR %s", val);
+ return arg;
}
static void
-setbridge_addr(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_addr(if_ctx *ctx, const char *val __unused, int dummy __unused)
{
-
- bridge_addresses(s, "");
+ bridge_addresses(ctx, "");
}
static void
-setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_maxaddr(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
u_long val;
@@ -452,12 +602,12 @@ setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
param.ifbrp_csize = val & 0xffffffff;
- if (do_cmd(s, BRDGSCACHE, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSCACHE, &param, sizeof(param), 1) < 0)
err(1, "BRDGSCACHE %s", arg);
}
static void
-setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_hellotime(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
u_long val;
@@ -467,12 +617,12 @@ setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp)
param.ifbrp_hellotime = val & 0xff;
- if (do_cmd(s, BRDGSHT, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSHT, &param, sizeof(param), 1) < 0)
err(1, "BRDGSHT %s", arg);
}
static void
-setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_fwddelay(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
u_long val;
@@ -482,12 +632,12 @@ setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp)
param.ifbrp_fwddelay = val & 0xff;
- if (do_cmd(s, BRDGSFD, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSFD, &param, sizeof(param), 1) < 0)
err(1, "BRDGSFD %s", arg);
}
static void
-setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_maxage(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
u_long val;
@@ -497,12 +647,12 @@ setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp)
param.ifbrp_maxage = val & 0xff;
- if (do_cmd(s, BRDGSMA, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSMA, &param, sizeof(param), 1) < 0)
err(1, "BRDGSMA %s", arg);
}
static void
-setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_priority(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
u_long val;
@@ -512,12 +662,12 @@ setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp)
param.ifbrp_prio = val & 0xffff;
- if (do_cmd(s, BRDGSPRI, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSPRI, &param, sizeof(param), 1) < 0)
err(1, "BRDGSPRI %s", arg);
}
static void
-setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_protocol(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
@@ -529,12 +679,12 @@ setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp)
errx(1, "unknown stp protocol");
}
- if (do_cmd(s, BRDGSPROTO, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSPROTO, &param, sizeof(param), 1) < 0)
err(1, "BRDGSPROTO %s", arg);
}
static void
-setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_holdcount(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
u_long val;
@@ -544,13 +694,12 @@ setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp)
param.ifbrp_txhc = val & 0xff;
- if (do_cmd(s, BRDGSTXHC, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSTXHC, &param, sizeof(param), 1) < 0)
err(1, "BRDGSTXHC %s", arg);
}
static void
-setbridge_ifpriority(const char *ifn, const char *pri, int s,
- const struct afswtch *afp)
+setbridge_ifpriority(if_ctx *ctx, const char *ifn, const char *pri)
{
struct ifbreq req;
u_long val;
@@ -563,13 +712,12 @@ setbridge_ifpriority(const char *ifn, const char *pri, int s,
strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
req.ifbr_priority = val & 0xff;
- if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGSIFPRIO, &req, sizeof(req), 1) < 0)
err(1, "BRDGSIFPRIO %s", pri);
}
static void
-setbridge_ifpathcost(const char *ifn, const char *cost, int s,
- const struct afswtch *afp)
+setbridge_ifpathcost(if_ctx *ctx, const char *ifn, const char *cost)
{
struct ifbreq req;
u_long val;
@@ -582,13 +730,41 @@ setbridge_ifpathcost(const char *ifn, const char *cost, int s,
strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
req.ifbr_path_cost = val;
- if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGSIFCOST, &req, sizeof(req), 1) < 0)
err(1, "BRDGSIFCOST %s", cost);
}
static void
-setbridge_ifmaxaddr(const char *ifn, const char *arg, int s,
- const struct afswtch *afp)
+setbridge_ifuntagged(if_ctx *ctx, const char *ifn, const char *vlanid)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+
+ if (get_vlan_id(vlanid, &req.ifbr_pvid) < 0)
+ errx(1, "invalid VLAN identifier: %s", vlanid);
+
+ if (do_cmd(ctx, BRDGSIFPVID, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFPVID %s", vlanid);
+}
+
+static void
+unsetbridge_ifuntagged(if_ctx *ctx, const char *ifn, int dummy __unused)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+
+ strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+ req.ifbr_pvid = 0;
+
+ if (do_cmd(ctx, BRDGSIFPVID, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFPVID");
+}
+
+static void
+setbridge_ifmaxaddr(if_ctx *ctx, const char *ifn, const char *arg)
{
struct ifbreq req;
u_long val;
@@ -601,12 +777,12 @@ setbridge_ifmaxaddr(const char *ifn, const char *arg, int s,
strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
req.ifbr_addrmax = val & 0xffffffff;
- if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, BRDGSIFAMAX, &req, sizeof(req), 1) < 0)
err(1, "BRDGSIFAMAX %s", arg);
}
static void
-setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_timeout(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifbrparam param;
u_long val;
@@ -616,26 +792,199 @@ setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp)
param.ifbrp_ctime = val & 0xffffffff;
- if (do_cmd(s, BRDGSTO, &param, sizeof(param), 1) < 0)
+ if (do_cmd(ctx, BRDGSTO, &param, sizeof(param), 1) < 0)
err(1, "BRDGSTO %s", arg);
}
static void
-setbridge_private(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_private(if_ctx *ctx, const char *val, int dummy __unused)
{
+ do_bridgeflag(ctx, val, IFBIF_PRIVATE, 1);
+}
- do_bridgeflag(s, val, IFBIF_PRIVATE, 1);
+static void
+unsetbridge_private(if_ctx *ctx, const char *val, int dummy __unused)
+{
+ do_bridgeflag(ctx, val, IFBIF_PRIVATE, 0);
+}
+
+static int
+parse_vlans(ifbvlan_set_t *set, const char *str)
+{
+ char *s, *token;
+
+ /* "none" means the empty vlan set */
+ if (strcmp(str, "none") == 0) {
+ __BIT_ZERO(BRVLAN_SETSIZE, set);
+ return (0);
+ }
+
+ /* "all" means all vlans, except for 0 and 4095 which are reserved */
+ if (strcmp(str, "all") == 0) {
+ __BIT_FILL(BRVLAN_SETSIZE, set);
+ BRVLAN_CLR(set, DOT1Q_VID_NULL);
+ BRVLAN_CLR(set, DOT1Q_VID_RSVD_IMPL);
+ return (0);
+ }
+
+ if ((s = strdup(str)) == NULL)
+ return (-1);
+
+ while ((token = strsep(&s, ",")) != NULL) {
+ unsigned long first, last;
+ char *p, *lastp;
+
+ if ((lastp = strchr(token, '-')) != NULL)
+ *lastp++ = '\0';
+
+ first = last = strtoul(token, &p, 10);
+ if (*p != '\0')
+ goto err;
+ if (first < DOT1Q_VID_MIN || first > DOT1Q_VID_MAX)
+ goto err;
+
+ if (lastp) {
+ last = strtoul(lastp, &p, 10);
+ if (*p != '\0')
+ goto err;
+ if (last < DOT1Q_VID_MIN || last > DOT1Q_VID_MAX ||
+ last < first)
+ goto err;
+ }
+
+ for (unsigned vlan = first; vlan <= last; ++vlan)
+ BRVLAN_SET(set, vlan);
+ }
+
+ free(s);
+ return (0);
+
+err:
+ free(s);
+ return (-1);
+}
+
+static void
+set_bridge_vlanset(if_ctx *ctx, const char *ifn, const char *vlans, int op)
+{
+ struct ifbif_vlan_req req;
+
+ memset(&req, 0, sizeof(req));
+
+ if (parse_vlans(&req.bv_set, vlans) != 0)
+ errx(1, "invalid vlan set: %s", vlans);
+
+ strlcpy(req.bv_ifname, ifn, sizeof(req.bv_ifname));
+ req.bv_op = op;
+
+ if (do_cmd(ctx, BRDGSIFVLANSET, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFVLANSET %s", vlans);
+}
+
+static void
+setbridge_iftagged(if_ctx *ctx, const char *ifn, const char *vlans)
+{
+ set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_SET);
+}
+
+static void
+addbridge_iftagged(if_ctx *ctx, const char *ifn, const char *vlans)
+{
+ set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_ADD);
+}
+
+static void
+delbridge_iftagged(if_ctx *ctx, const char *ifn, const char *vlans)
+{
+ set_bridge_vlanset(ctx, ifn, vlans, BRDG_VLAN_OP_DEL);
+}
+
+static void
+setbridge_flags(if_ctx *ctx, const char *val __unused, int newflags)
+{
+ struct ifbrparam req;
+
+ if (do_cmd(ctx, BRDGGFLAGS, &req, sizeof(req), 0) < 0)
+ err(1, "BRDGGFLAGS");
+
+ req.ifbrp_flags |= (uint32_t)newflags;
+
+ if (do_cmd(ctx, BRDGSFLAGS, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSFLAGS");
}
static void
-unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_flags(if_ctx *ctx, const char *val __unused, int newflags)
{
+ struct ifbrparam req;
+
+ if (do_cmd(ctx, BRDGGFLAGS, &req, sizeof(req), 0) < 0)
+ err(1, "BRDGGFLAGS");
+
+ req.ifbrp_flags &= ~(uint32_t)newflags;
+
+ if (do_cmd(ctx, BRDGSFLAGS, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSFLAGS");
+}
+
+static void
+setbridge_defuntagged(if_ctx *ctx, const char *arg, int dummy __unused)
+{
+ struct ifbrparam req;
+
+ memset(&req, 0, sizeof(req));
+ if (get_vlan_id(arg, &req.ifbrp_defpvid) < 0)
+ errx(1, "invalid vlan id: %s", arg);
+
+ if (do_cmd(ctx, BRDGSDEFPVID, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSDEFPVID");
+}
+
+static void
+unsetbridge_defuntagged(if_ctx *ctx, const char *val __unused, int dummy __unused)
+{
+ struct ifbrparam req;
+
+ memset(&req, 0, sizeof(req));
+ req.ifbrp_defpvid = 0;
- do_bridgeflag(s, val, IFBIF_PRIVATE, 0);
+ if (do_cmd(ctx, BRDGSDEFPVID, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSDEFPVID");
+}
+
+static void
+setbridge_qinq(if_ctx *ctx, const char *val, int dummy __unused)
+{
+ do_bridgeflag(ctx, val, IFBIF_QINQ, 1);
+}
+
+static void
+unsetbridge_qinq(if_ctx *ctx, const char *val, int dummy __unused)
+{
+ do_bridgeflag(ctx, val, IFBIF_QINQ, 0);
+}
+
+static void
+setbridge_ifvlanproto(if_ctx *ctx, const char *ifname, const char *proto)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.ifbr_ifsname, ifname, sizeof(req.ifbr_ifsname));
+
+ if (strcmp(proto, "802.1q") == 0)
+ req.ifbr_vlanproto = ETHERTYPE_VLAN;
+ else if (strcmp(proto, "802.1ad") == 0)
+ req.ifbr_vlanproto = ETHERTYPE_QINQ;
+ else
+ errx(1, "unrecognised VLAN protocol: %s", proto);
+
+ if (do_cmd(ctx, BRDGSIFVLANPROTO, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFVLANPROTO");
}
static struct cmd bridge_cmds[] = {
- DEF_CMD_ARG("addm", setbridge_add),
+ DEF_CMD_VARG("addm", setbridge_add),
DEF_CMD_ARG("deletem", setbridge_delete),
DEF_CMD_ARG("discover", setbridge_discover),
DEF_CMD_ARG("-discover", unsetbridge_discover),
@@ -657,8 +1006,8 @@ static struct cmd bridge_cmds[] = {
DEF_CMD_ARG("-autoptp", unsetbridge_autoptp),
DEF_CMD("flush", 0, setbridge_flush),
DEF_CMD("flushall", 0, setbridge_flushall),
- DEF_CMD_ARG2("static", setbridge_static),
- DEF_CMD_ARG("deladdr", setbridge_deladdr),
+ DEF_CMD_VARG("static", setbridge_static),
+ DEF_CMD_VARG("deladdr", setbridge_deladdr),
DEF_CMD("addr", 1, setbridge_addr),
DEF_CMD_ARG("maxaddr", setbridge_maxaddr),
DEF_CMD_ARG("hellotime", setbridge_hellotime),
@@ -670,10 +1019,29 @@ static struct cmd bridge_cmds[] = {
DEF_CMD_ARG2("ifpriority", setbridge_ifpriority),
DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost),
DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr),
+ DEF_CMD_ARG2("ifuntagged", setbridge_ifuntagged),
+ DEF_CMD_ARG("-ifuntagged", unsetbridge_ifuntagged),
+ DEF_CMD_ARG2("iftagged", setbridge_iftagged),
+ DEF_CMD_ARG2("+iftagged", addbridge_iftagged),
+ DEF_CMD_ARG2("-iftagged", delbridge_iftagged),
+ DEF_CMD_ARG2("ifvlanproto", setbridge_ifvlanproto),
DEF_CMD_ARG("timeout", setbridge_timeout),
DEF_CMD_ARG("private", setbridge_private),
DEF_CMD_ARG("-private", unsetbridge_private),
+ DEF_CMD("vlanfilter", (int32_t)IFBRF_VLANFILTER,
+ setbridge_flags),
+ DEF_CMD("-vlanfilter", (int32_t)IFBRF_VLANFILTER,
+ unsetbridge_flags),
+ DEF_CMD_ARG("defuntagged", setbridge_defuntagged),
+ DEF_CMD("-defuntagged", 0, unsetbridge_defuntagged),
+ DEF_CMD("defqinq", (int32_t)IFBRF_DEFQINQ,
+ setbridge_flags),
+ DEF_CMD("-defqinq", (int32_t)IFBRF_DEFQINQ,
+ unsetbridge_flags),
+ DEF_CMD_ARG("qinq", setbridge_qinq),
+ DEF_CMD_ARG("-qinq", unsetbridge_qinq),
};
+
static struct afswtch af_bridge = {
.af_name = "af_bridge",
.af_af = AF_UNSPEC,
@@ -683,9 +1051,7 @@ static struct afswtch af_bridge = {
static __constructor void
bridge_ctor(void)
{
- int i;
-
- for (i = 0; i < nitems(bridge_cmds); i++)
+ for (size_t i = 0; i < nitems(bridge_cmds); i++)
cmd_register(&bridge_cmds[i]);
af_register(&af_bridge);
}
diff --git a/sbin/ifconfig/ifclone.c b/sbin/ifconfig/ifclone.c
index 9cacff239967..f44d052c97ad 100644
--- a/sbin/ifconfig/ifclone.c
+++ b/sbin/ifconfig/ifclone.c
@@ -29,11 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/queue.h>
@@ -118,13 +113,12 @@ clone_setdefcallback_filter(clone_match_func *filter, clone_callback_func *p)
* no parameters.
*/
static void
-ifclonecreate(int s, void *arg)
+ifclonecreate(if_ctx *ctx, void *arg __unused)
{
- struct ifreq ifr;
+ struct ifreq ifr = {};
struct clone_defcb *dcp;
- memset(&ifr, 0, sizeof(ifr));
- (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
/* Try to find a default callback by filter */
SLIST_FOREACH(dcp, &clone_defcbh, next) {
@@ -145,32 +139,24 @@ ifclonecreate(int s, void *arg)
if (dcp == NULL || dcp->clone_cb == NULL) {
/* NB: no parameters */
- ioctl_ifcreate(s, &ifr);
+ ifcreate_ioctl(ctx, &ifr);
} else {
- dcp->clone_cb(s, &ifr);
- }
-
- /*
- * If we get a different name back than we put in, update record and
- * indicate it should be printed later.
- */
- if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) {
- strlcpy(name, ifr.ifr_name, sizeof(name));
- printifname = 1;
+ dcp->clone_cb(ctx, &ifr);
}
}
-static
-DECL_CMD_FUNC(clone_create, arg, d)
+static void
+clone_create(if_ctx *ctx __unused, const char *cmd __unused, int d __unused)
{
callback_register(ifclonecreate, NULL);
}
-static
-DECL_CMD_FUNC(clone_destroy, arg, d)
+static void
+clone_destroy(if_ctx *ctx, const char *cmd __unused, int d __unused)
{
- (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
+ struct ifreq ifr = {};
+
+ if (ioctl_ctx_ifr(ctx, SIOCIFDESTROY, &ifr) < 0)
err(1, "SIOCIFDESTROY");
}
@@ -182,7 +168,7 @@ static struct cmd clone_cmds[] = {
};
static void
-clone_Copt_cb(const char *optarg __unused)
+clone_Copt_cb(const char *arg __unused)
{
list_cloners();
exit(exit_code);
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index e059c172dd5c..d4f8d2b5747a 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -1,3 +1,6 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -25,10 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
-.\" $FreeBSD$
-.\"
-.Dd June 24, 2022
+.Dd October 12, 2025
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -36,7 +36,8 @@
.Nd configure network interface parameters
.Sh SYNOPSIS
.Nm
-.Op Fl kLmn
+.Op Fl j Ar jid
+.Op Fl DkLmn
.Op Fl f Ar type Ns Cm \&: Ns Ar format
.Ar interface
.Op Cm create
@@ -49,11 +50,13 @@
.Oc
.Op Ar parameters
.Nm
+.Op Fl j Ar jid
.Ar interface
.Cm destroy
.Nm
+.Op Fl j Ar jid
.Fl a
-.Op Fl dkLmuv
+.Op Fl dDkLmuv
.Op Fl f Ar type Ns Cm \&: Ns Ar format
.Op Fl G Ar groupname
.Op Fl g Ar groupname
@@ -61,13 +64,16 @@
.Nm
.Fl C
.Nm
+.Op Fl j Ar jid
.Fl g Ar groupname
.Nm
+.Op Fl j Ar jid
.Fl l
.Op Fl du
.Op Fl g Ar groupname
.Op Ar address_family
.Nm
+.Op Fl j Ar jid
.Op Fl dkLmuv
.Op Fl f Ar type Ns Cm \&: Ns Ar format
.Sh DESCRIPTION
@@ -99,6 +105,12 @@ with no additional information.
Use of this flag is mutually exclusive with all other flags and commands.
.It Fl d
Display only the interfaces that are down.
+.It Fl D
+Include the driver name and unit number of the interface in the output.
+This is normally the original name of the interface,
+even if it has been renamed; it may differ from the original name
+in some cases, such as
+.Xr epair 4 .
.It Fl f Xo
.Ar type Ns Cm \&: Ns Ar format Ns
.Op Cm \&, Ns Ar type Ns Cm \&: Ns Ar format Ar ...
@@ -126,7 +138,7 @@ and their associated
.Ar format
strings are:
.Pp
-.Bl -tag -width ether
+.Bl -tag -width default
.It Cm addr
Adjust the display of inet and inet6 addresses:
.Pp
@@ -150,6 +162,9 @@ Adjust the display of link-level ethernet (MAC) addresses:
Separate address segments with a colon
.It Cm dash
Separate address segments with a dash
+.It Cm dotted
+Dotted notation, for example:
+.Ql 5254.0015.4a3b
.It Cm default
Default format,
.Cm colon
@@ -188,15 +203,24 @@ Integer format, for example:
.Ql prefixlen 64
.El
.El
+.Pp
+In addition, the following shortcuts are accepted:
+.Bl -tag -width default
+.It Cm default
+Resets all formats to their default values.
+.It Cm cidr
+Shortcut notation for
+.Cm inet:cidr,inet6:cidr .
+.El
+.Pp
.It Fl G Ar groupname
Exclude members of the specified
.Ar groupname
from the output.
-.Ar groupname .
.Pp
-Only one option
+Only one
.Fl G
-should be specified as later override previous ones
+option should be specified as later ones override earlier ones.
.Ar groupname
may contain shell patterns in which case it should be quoted.
.Pp
@@ -222,9 +246,9 @@ lists names of interfaces belonging to
.Ar groupname .
Any other flags and arguments are ignored in this case.
.Pp
-Only one option
+Only one
.Fl g
-should be specified as later override previous ones
+option should be specified as later ones override earlier ones.
.Ar groupname
may contain shell patterns in which case it should be quoted.
.Pp
@@ -233,6 +257,22 @@ Setting
to
.Cm all
selects all interfaces.
+.It Fl j Ar jid
+Perform the actions inside the jail specified by
+.Ar jid ,
+which may be either a jail name or a numeric jail ID.
+.Pp
+The
+.Nm
+utility will attach to the specified jail immediately upon
+encountering the option on the command line.
+The option may be specified multiple times to attach to a nested jail
+(jail within a jail).
+.Pp
+This makes it possible to configure network interfaces within a vnet
+jail even if the
+.Nm
+binary is not available inside the jail.
.It Fl k
Print keying information for the
.Ar interface ,
@@ -408,11 +448,10 @@ of specifying the host portion, removing all NS addresses will
allow you to respecify the host portion.
.It Cm anycast
(Inet6 only.)
-Specify that the address configured is an anycast address.
-Based on the current specification,
-only routers may configure anycast addresses.
-Anycast address will not be used as source address of any of outgoing
-IPv6 packets.
+Specify that the address configured is an anycast address,
+as described in RFC 4291 section 2.6.
+Anycast addresses will not be used as source address of any outgoing
+IPv6 packets unless an application explicitly binds to the address.
.It Cm arp
Enable the use of the Address Resolution Protocol
.Pq Xr arp 4
@@ -434,13 +473,17 @@ sending out requests and listening for replies.
.It Cm stickyarp
Enable the so-called sticky ARP mode for the interface.
If this option is enabled on the given interface, any resolved address is
-marked as a static one and never expires. This may be used to increase
+marked as a static one and never expires.
+This may be used to increase
security of the network by preventing ARP spoofing or to reduce latency for
high-performance Ethernet networks where the time needed for ARP resolution is
-too high. Please note that a similar feature is also provided for bridges. See
+too high.
+Please note that a similar feature is also provided for bridges.
+See
the sticky option in the
.Sx Bridge Interface Parameters
-section. Enabling this
+section.
+Enabling this
option may impact techniques which rely on ARP expiration/overwriting feature
such as load-balancers or high-availabity solutions such as
.Xr carp 4 .
@@ -458,6 +501,10 @@ Enable driver dependent debugging code; usually, this turns on
extra console error logging.
.It Fl debug
Disable driver dependent debugging code.
+.It Cm allmulti
+Enable promiscuous mode for multicast packets.
+.It Fl allmulti
+Disable promiscuous mode for multicast packets.
.It Cm promisc
Put interface into permanently promiscuous mode.
.It Fl promisc
@@ -484,16 +531,16 @@ This action does not automatically disable routes using the interface.
.It Cm group Ar groupname
Assign the interface to a
.Dq group .
+The
+.Ar groupname
+may not be longer than 15 characters and must not end in a digit.
Any interface can be in multiple groups.
.Pp
Cloned interfaces are members of their interface family group by default.
-For example, a PPP interface such as
-.Em ppp0
-is a member of the PPP interface family group,
-.Em ppp .
-.\" The interface(s) the default route(s) point to are members of the
-.\" .Em egress
-.\" interface group.
+For example, a VLAN interface such as
+.Em vlan10
+is a member of the VLAN interface family group,
+.Em vlan .
.It Cm -group Ar groupname
Remove the interface from the given
.Dq group .
@@ -520,9 +567,11 @@ Specify tunnel FIB.
A FIB
.Ar fib_number
is assigned to all packets encapsulated by tunnel interface, e.g.,
-.Xr gif 4
+.Xr gif 4 ,
+.Xr gre 4 ,
+.Xr vxlan 4 ,
and
-.Xr gre 4 .
+.Xr wg 4 .
.It Cm maclabel Ar label
If Mandatory Access Control support is enabled in the kernel,
set the MAC label to
@@ -682,7 +731,7 @@ buffers, enable them on the interface.
.It Fl mextpg
If the driver supports extended multi-page
.Xr mbuf 9
-biffers, disable them on the interface.
+buffers, disable them on the interface.
.It Cm wol , wol_ucast , wol_mcast , wol_magic
Enable Wake On Lan (WOL) support, if available.
WOL is a facility whereby a machine in a low power state may be woken
@@ -955,6 +1004,36 @@ Set a flag to disable Duplicate Address Detection.
.It Cm -no_dad
Clear a flag
.Cm no_dad .
+.It Cm stableaddr
+Set a flag to create SLAAC addresses using a stable algorithm according to RFC 7217
+The
+.Xr sysctl 8
+variable
+.Va net.inet6.ip6.use_stableaddr
+controls whether this flag is set by default or not for newly created interfaces.
+To get consistent defaults for interfaces created at boot it should be set as a tunable via loader.conf(8).
+The
+.Xr sysctl 8
+variable
+.Va net.inet6.ip6.stableaddr_maxretries
+sets the maximum number of retries to generate a unique IPv6 address to be performed in case of DAD failures.
+This defaults to 3 which is also the reccommended minimum value.
+The interface ID source can be configured using the
+.Xr sysctl 8
+variable
+.Va net.inet6.ip6.stableaddr_netifsource:
+.Bl -tag -compact
+.It Cm 0
+uses the interface name string (the default)
+.It Cm 1
+uses the interface ID
+.It Cm 2
+uses the MAC address of the interface (if one can be obtained for it)
+.El
+.Pp
+.It Cm -stableaddr
+Clear the flag
+.Cm stableaddr .
.El
.Ss IPv6 Parameters
The following parameters are specific for IPv6 addresses.
@@ -1039,7 +1118,7 @@ Legacy
.Cm wds
devices have a fixed peer relationship and do not, for example, roam
if their peer stops communicating.
-For completeness a Dynamic WDS (DWDS) interface may marked as
+For completeness a Dynamic WDS (DWDS) interface may be marked as
.Fl wdslegacy .
.It Cm bssid
Request a unique local mac address for the cloned device.
@@ -1196,8 +1275,8 @@ Set the interval at which beacon frames are sent when operating in
ad-hoc or ap mode.
The
.Ar interval
-parameter is specified in TU's (1024 usecs).
-By default beacon frames are transmitted every 100 TU's.
+parameter is specified in TUs (1024 usecs).
+By default beacon frames are transmitted every 100 TUs.
.It Cm bmissthreshold Ar count
Set the number of consecutive missed beacons at which the station
will attempt to roam (i.e., search for a new access point).
@@ -1854,8 +1933,8 @@ Use
.Fl powersave
to disable powersave operation when operating as a client.
.It Cm powersavesleep Ar sleep
-Set the desired max powersave sleep time in TU's (1024 usecs).
-By default the max powersave sleep time is 100 TU's.
+Set the desired max powersave sleep time in TUs (1024 usecs).
+By default the max powersave sleep time is 100 TUs.
.It Cm protmode Ar technique
For interfaces operating in 802.11g, use the specified
.Ar technique
@@ -2445,12 +2524,27 @@ compatibility.
.Ss Bridge Interface Parameters
The following parameters are specific to bridge interfaces:
.Bl -tag -width indent
-.It Cm addm Ar interface
+.It Cm addm Ar interface Op Ar options ...
Add the interface named by
.Ar interface
as a member of the bridge.
The interface is put into promiscuous mode
so that it can receive every packet sent on the network.
+.Pp
+The interface name may be followed by one or more of the following
+.Ar options :
+.Bl -tag -width ".Cm untagged Ar vlan-id"
+.It Cm untagged Ar vlan-id
+Set the untagged VLAN identifier for the interface.
+This is equivalent to the
+.Cm ifuntagged
+command.
+.It Cm tagged Ar vlan-set
+Set the allowed VLAN list for the interface.
+This is equivalent to the
+.Cm iftagged
+command.
+.El
.It Cm deletem Ar interface
Remove the interface named by
.Ar interface
@@ -2471,15 +2565,23 @@ is zero, then address cache entries will not be expired.
The default is 1200 seconds.
.It Cm addr
Display the addresses that have been learned by the bridge.
-.It Cm static Ar interface-name Ar address
-Add a static entry into the address cache pointing to
+.It Cm static Ar interface-name Ar address Op Cm vlan Ar vlan-id
+Add a static entry into the address cache for pointing to
.Ar interface-name .
+If
+.Ar vlan-id
+is specified, the entry is added for that VLAN, otherwise it is added
+for VLAN 0.
+.Pp
Static entries are never aged out of the cache or re-placed, even if the
address is seen on a different interface.
-.It Cm deladdr Ar address
+.It Cm deladdr Ar address Op Cm vlan Ar vlan-id
Delete
.Ar address
-from the address cache.
+from the address cache. If
+.Ar vlan-id
+is specified, the entry is deleted from that VLAN's address table,
+otherwise it is deleted from the VLAN 0 address table.
.It Cm flush
Delete all dynamically-learned addresses from the address cache.
.It Cm flushall
@@ -2646,6 +2748,103 @@ Set the maximum number of hosts allowed from an interface, packets with unknown
source addresses are dropped until an existing host cache entry expires or is
removed.
Set to 0 to disable.
+.It Cm vlanfilter
+Enable VLAN filtering on the bridge.
+Incoming frames on member interfaces will be dropped unless the frame
+is explicitly permitted by the interface's
+.Cm ifuntagged
+or
+.Cm iftagged
+configuration.
+.It Cm -vlanfilter
+Disable VLAN filtering on the bridge.
+This is the default.
+.It Cm iftagged Ar interface Ar vlan-list
+Set the interface's VLAN access list to the provided list of VLANs.
+The list should be a comma-separated list of one or more VLAN IDs
+or ranges formatted as
+.Ar first-last ,
+the value
+.Dq none
+meaning the empty set,
+or the value
+.Dq all
+meaning all VLANs (1-4094).
+.Pp
+This option is only meaningful if the
+.Cm vlanfilter
+option is enabled for the bridge;
+otherwise, all VLANs will be permitted.
+.It Cm +iftagged Ar interface Ar vlan-list
+Add the provided list of VLAN IDs to the interface's VLAN access list.
+The list should be formatted as described for
+.Cm iftagged .
+.Pp
+This option is only meaningful if the
+.Cm vlanfilter
+option is enabled for the bridge;
+otherwise, all VLANs will be permitted.
+.It Cm -iftagged Ar interface Ar vlan-list
+Remove the provided list of VLAN IDs from the interface's VLAN access
+list.
+The list should be formatted as described for
+.Cm iftagged .
+.Pp
+This option is only meaningful if the
+.Cm vlanfilter
+option is enabled for the bridge;
+otherwise, all VLANs will be permitted.
+.It Cm ifuntagged Ar interface Ar vlan-id
+Set the untagged VLAN identifier for an interface.
+Frames received on this interface without an 802.1Q tag will be assigned
+to this VLAN instead of the default VLAN 0,
+and outgoing frames on this VLAN will have their 802.1Q tag removed.
+.It Cm -ifuntagged Ar interface
+Clear the untagged VLAN identifier for an interface.
+.It Cm defuntagged Ar vlan-id
+Enable the
+.Cm untagged
+option by default on newly added members.
+.It Cm -defuntagged
+Do not enable the
+.Cm untagged
+option by default on newly added members.
+This is the default.
+.It Cm qinq Ar interface
+Allow this interface to send 802.1ad
+.Dq Q-in-Q
+frames.
+This option is only meaningful if the
+.Cm vlanfilter
+option is enabled for the bridge;
+otherwise, Q-in-Q frames are always allowed.
+.It Cm -qinq Ar interface
+Do not allow this interface to send 802.1ad
+.Dq Q-in-Q
+frames.
+This is the default if the
+.Cm vlanfilter
+option is enabled.
+.It Cm defqinq
+Enable the
+.Cm qinq
+option by default on newly added members.
+.It Cm -defqinq
+Do not enable the
+.Cm qinq
+option by default on newly added members.
+This is the default.
+.It Cm ifvlanproto Ar interface Ar proto
+Set the VLAN encapsulation protocol on
+.Ar interface
+to
+.Ar proto ,
+which must be either
+.Dq 802.1q
+or
+.Dq 802.1ad .
+The default is
+.Dq 802.1q .
.El
.Ss Link Aggregation and Link Failover Parameters
The following parameters are specific to lagg interfaces:
@@ -2720,19 +2919,19 @@ Hash is calculated by using flowid bits in a packet header mbuf
which are shifted by the number of this parameter.
.It Cm use_numa
Enable selection of egress ports based on the native
-.Xr NUMA 4
+.Xr numa 4
domain for the packets being transmitted.
This is currently only implemented for lacp mode.
This works only on
-.Xr NUMA 4
+.Xr numa 4
hardware, running a kernel compiled with the
-.Xr NUMA 4
+.Xr numa 4
option, and when interfaces from multiple
-.Xr NUMA 4
+.Xr numa 4
domains are ports of the aggregation interface.
.It Cm -use_numa
Disable selection of egress ports based on the native
-.Xr NUMA 4
+.Xr numa 4
domain for the packets being transmitted.
.It Cm lacp_fast_timeout
Enable lacp fast-timeout on the interface.
@@ -2778,34 +2977,26 @@ interfaces previously configured with
Another name for the
.Fl tunnel
parameter.
-.It Cm accept_rev_ethip_ver
-Set a flag to accept both correct EtherIP packets and ones
-with reversed version field.
-Enabled by default.
-This is for backward compatibility with
-.Fx 6.1 ,
-6.2, 6.3, 7.0, and 7.1.
-.It Cm -accept_rev_ethip_ver
-Clear a flag
-.Cm accept_rev_ethip_ver .
+.It Cm noclamp
+This flag prevents the MTU from being clamped to 1280 bytes, the
+minimum MTU for IPv6, when the outer protocol is IPv6. When the
+flag is set, the MTU value configured on the interface will be
+used instead of the fixed length of 1280 bytes. For more details,
+please refer to the
+.Ar MTU Configuration and Path MTU Discovery
+section in
+.Xr gif 4 .
+.It Cm -noclamp
+Clear the flag
+.Cm noclamp .
.It Cm ignore_source
Set a flag to accept encapsulated packets destined to this host
independently from source address.
This may be useful for hosts, that receive encapsulated packets
from the load balancers.
.It Cm -ignore_source
-Clear a flag
+Clear the flag
.Cm ignore_source .
-.It Cm send_rev_ethip_ver
-Set a flag to send EtherIP packets with reversed version
-field intentionally.
-Disabled by default.
-This is for backward compatibility with
-.Fx 6.1 ,
-6.2, 6.3, 7.0, and 7.1.
-.It Cm -send_rev_ethip_ver
-Clear a flag
-.Cm send_rev_ethip_ver .
.El
.Ss GRE Tunnel Parameters
The following parameters apply to GRE tunnel interfaces,
@@ -2845,12 +3036,24 @@ to send and receive pfsync state synchronisation messages.
.It Fl syncdev
Stop sending pfsync state synchronisation messages over the network.
.It Cm syncpeer Ar peer_address
-Make the pfsync link point-to-point rather than using
-multicast to broadcast the state synchronisation messages.
-The peer_address is the IP address of the other host taking part in
-the pfsync cluster.
+Set the destination address for the state synchronization messages sent.
+The
+.Ar peer_address
+is normally the IPv4 or IPv6 address of the other host taking
+part in the pfsync cluster.
+.Pp
+When the
+.Ar peer_address
+is set to a unicast IP address, the pfsync link will behave
+as point-to-point rather than using multicast to broadcast the messages.
+.Pp
+When the
+.Ar peer_address
+is set to ff12::f0, the state synchronization
+messages will be broadcast using multicast over IPv6.
.It Fl syncpeer
-Broadcast the packets using multicast.
+Unset the syncpeer.
+Packets will then be broadcast using multicast over IPv4.
.It Cm maxupd Ar n
Set the maximum number of updates for a single state which
can be collapsed into one.
@@ -2861,6 +3064,11 @@ acknowledged that the associated state has been inserted.
.It Fl defer
Do not defer the first packet in a state.
This is the default.
+.It Fl version Ar n
+Configure message format for compatibility with older versions of FreeBSD.
+Refer to
+.Xr pfsync 4
+for details.
.El
.Ss VLAN Parameters
The following parameters are specific to
@@ -2882,17 +3090,15 @@ must both be set at the same time.
.It Cm vlanproto Ar vlan_proto
Set the VLAN encapsulation protocol to
.Ar vlan_proto .
-Supported encapsulation protocols are currently
-.Dq 802.1Q
-and
-.Dq 802.1ad .
-The default encapsulation protocol is
-.Dq 802.1Q .
-The
-.Dq 802.1ad
-protocol is also commonly known as
-.Dq QinQ ;
-either name can be used.
+Supported encapsulation protocols are currently:
+.Bl -tag
+.It Cm 802.1Q
+Default.
+.It Cm 802.1ad
+.It Cm QinQ
+Same as
+.Cm 802.1ad .
+.El
.It Cm vlanpcp Ar priority_code_point
Priority code point
.Pq Dv PCP
@@ -3090,6 +3296,36 @@ The following states are recognized:
.Cm MASTER
and
.Cm BACKUP .
+.It Cm peer Ar address
+Set the address to send (IPv4)
+.Xr carp 4
+announcements to.
+.It Cm mcast
+Restore the default destination address for (IPv4)
+.Xr carp 4
+announcements, which is 224.0.0.18.
+.It Cm peer6 Ar address
+Set the address to send (IPv6)
+.Xr carp 4
+announcements to.
+.It Cm mcast6
+Restore the default destination address for (IPv4)
+.Xr carp 4
+announcements, which is ff02::12.
+.It Cm carpver
+Set the protocol version.
+Valid choices are 2 (for
+.Xr carp 4)
+and 3 (for VRRPv3).
+This can only be set when
+.Xr carp 4
+is initiated.
+.It Cm vrrpprio
+Set the VRRPv3 priority.
+Valid values are 1-255.
+.It Cm vrrpinterval
+Set the VRRPv3 Master Advertisement Interval.
+Values are in centiseconds.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of
@@ -3231,6 +3467,16 @@ tried to alter an interface's configuration.
.Xr rc 8 ,
.Xr routed 8 ,
.Xr sysctl 8
+.Rs
+.%R RFC 3484
+.%D February 2003
+.%T "Default Address Selection for Internet Protocol version 6 (IPv6)"
+.Re
+.Rs
+.%R RFC 4291
+.%D February 2006
+.%T "IP Version 6 Addressing Architecture"
+.Re
.Sh HISTORY
The
.Nm
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index ec8a3fd52803..9aeb4a09ef49 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -29,19 +29,11 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1983, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#if 0
-static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
+#ifdef JAIL
+#include <sys/jail.h>
+#endif
#include <sys/module.h>
#include <sys/linker.h>
#include <sys/nv.h>
@@ -52,6 +44,7 @@ static const char rcsid[] =
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_dl.h>
+#include <net/if_strings.h>
#include <net/if_types.h>
#include <net/route.h>
@@ -82,48 +75,34 @@ static const char rcsid[] =
ifconfig_handle_t *lifh;
-/*
- * Since "struct ifreq" is composed of various union members, callers
- * should pay special attention to interpret the value.
- * (.e.g. little/big endian difference in the structure.)
- */
-struct ifreq ifr;
-
-char name[IFNAMSIZ];
-char *descr = NULL;
-size_t descrlen = 64;
-int setaddr;
-int setmask;
-int doalias;
-int clearaddr;
-int newaddr = 1;
-int verbose;
-int noload;
-int printifname = 0;
-
-int supmedia = 0;
-int printkeys = 0; /* Print keying material for interfaces. */
+#ifdef WITHOUT_NETLINK
+static char *descr = NULL;
+static size_t descrlen = 64;
+#endif
+static int setaddr;
+static int setmask;
+static int doalias;
+static int clearaddr;
+static int newaddr = 1;
+
int exit_code = 0;
+static char ifname_to_print[IFNAMSIZ]; /* Helper for printifnamemaybe() */
+
/* Formatter Strings */
char *f_inet, *f_inet6, *f_ether, *f_addr;
-static bool group_member(const char *ifname, const char *match,
- const char *nomatch);
-static int ifconfig(int argc, char *const *argv, int iscreate,
- const struct afswtch *afp);
-static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
+#ifdef WITHOUT_NETLINK
+static void list_interfaces_ioctl(if_ctx *ctx);
+static void status(if_ctx *ctx, const struct sockaddr_dl *sdl,
struct ifaddrs *ifa);
-static void tunnel_status(int s);
+#endif
static _Noreturn void usage(void);
+static void Perrorc(const char *cmd, int error);
static int getifflags(const char *ifname, int us, bool err_ok);
static struct afswtch *af_getbyname(const char *name);
-static struct afswtch *af_getbyfamily(int af);
-static void af_other_status(int);
-
-void printifnamemaybe(void);
static struct option *opts = NULL;
@@ -190,29 +169,59 @@ usage(void)
}
fprintf(stderr,
- "usage: ifconfig [-f type:format] %sinterface address_family\n"
+ "usage: ifconfig [-j jail] [-f type:format] %sinterface address_family\n"
" [address [dest_address]] [parameters]\n"
- " ifconfig interface create\n"
- " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
- " ifconfig -l [-d] [-u] [address_family]\n"
- " ifconfig %s[-d] [-m] [-u] [-v]\n",
+ " ifconfig [-j jail] interface create\n"
+ " ifconfig [-j jail] -a %s[-d] [-m] [-u] [-v] [address_family]\n"
+ " ifconfig [-j jail] -l [-d] [-u] [address_family]\n"
+ " ifconfig [-j jail] %s[-d] [-m] [-u] [-v]\n",
options, options, options);
exit(1);
}
+static void
+ifname_update(if_ctx *ctx, const char *name)
+{
+ strlcpy(ctx->_ifname_storage_ioctl, name, sizeof(ctx->_ifname_storage_ioctl));
+ ctx->ifname = ctx->_ifname_storage_ioctl;
+
+ strlcpy(ifname_to_print, name, sizeof(ifname_to_print));
+}
+
+static void
+ifr_set_name(struct ifreq *ifr, const char *name)
+{
+ strlcpy(ifr->ifr_name, name, sizeof(ifr->ifr_name));
+}
+
+int
+ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr)
+{
+ ifr_set_name(ifr, ctx->ifname);
+ return (ioctl_ctx(ctx, cmd, ifr));
+}
+
void
-ioctl_ifcreate(int s, struct ifreq *ifr)
+ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr)
{
- if (ioctl(s, SIOCIFCREATE2, ifr) < 0) {
+ char ifname_orig[IFNAMSIZ];
+
+ strlcpy(ifname_orig, ifr->ifr_name, sizeof(ifname_orig));
+
+ if (ioctl(ctx->io_s, SIOCIFCREATE2, ifr) < 0) {
switch (errno) {
case EEXIST:
errx(1, "interface %s already exists", ifr->ifr_name);
default:
- err(1, "SIOCIFCREATE2");
+ err(1, "SIOCIFCREATE2 (%s)", ifr->ifr_name);
}
}
+
+ if (strncmp(ifname_orig, ifr->ifr_name, sizeof(ifname_orig)) != 0)
+ ifname_update(ctx, ifr->ifr_name);
}
+#ifdef WITHOUT_NETLINK
static int
calcorders(struct ifaddrs *ifa, struct ifa_queue *q)
{
@@ -299,18 +308,15 @@ cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q)
return (0);
}
+#endif
static void freeformat(void)
{
- if (f_inet != NULL)
- free(f_inet);
- if (f_inet6 != NULL)
- free(f_inet6);
- if (f_ether != NULL)
- free(f_ether);
- if (f_addr != NULL)
- free(f_addr);
+ free(f_inet);
+ free(f_inet6);
+ free(f_ether);
+ free(f_addr);
}
static void setformat(char *input)
@@ -320,9 +326,18 @@ static void setformat(char *input)
formatstr = strdup(input);
while ((category = strsep(&formatstr, ",")) != NULL) {
modifier = strchr(category, ':');
- if (modifier == NULL || modifier[1] == '\0') {
- warnx("Skipping invalid format specification: %s\n",
- category);
+ if (modifier == NULL) {
+ if (strcmp(category, "default") == 0) {
+ freeformat();
+ } else if (strcmp(category, "cidr") == 0) {
+ free(f_inet);
+ f_inet = strdup(category);
+ free(f_inet6);
+ f_inet6 = strdup(category);
+ } else {
+ warnx("Skipping invalid format: %s\n",
+ category);
+ }
continue;
}
@@ -330,18 +345,24 @@ static void setformat(char *input)
modifier[0] = '\0';
modifier++;
- if (strcmp(category, "addr") == 0)
+ if (strcmp(category, "addr") == 0) {
+ free(f_addr);
f_addr = strdup(modifier);
- else if (strcmp(category, "ether") == 0)
+ } else if (strcmp(category, "ether") == 0) {
+ free(f_ether);
f_ether = strdup(modifier);
- else if (strcmp(category, "inet") == 0)
+ } else if (strcmp(category, "inet") == 0) {
+ free(f_inet);
f_inet = strdup(modifier);
- else if (strcmp(category, "inet6") == 0)
+ } else if (strcmp(category, "inet6") == 0) {
+ free(f_inet6);
f_inet6 = strdup(modifier);
+ }
}
free(formatstr);
}
+#ifdef WITHOUT_NETLINK
static struct ifaddrs *
sortifaddrs(struct ifaddrs *list,
int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *),
@@ -396,59 +417,71 @@ sortifaddrs(struct ifaddrs *list,
return (result);
}
+#endif
-void printifnamemaybe()
+static void
+printifnamemaybe(void)
{
- if (printifname)
- printf("%s\n", name);
+ if (ifname_to_print[0] != '\0')
+ printf("%s\n", ifname_to_print);
}
-int
-main(int argc, char *argv[])
+static void
+list_interfaces(if_ctx *ctx)
{
- int c, all, namesonly, downonly, uponly;
- const struct afswtch *afp = NULL;
- int ifindex;
- struct ifaddrs *ifap, *sifap, *ifa;
- struct ifreq paifr;
- const struct sockaddr_dl *sdl;
- char options[1024], *cp, *envformat, *namecp = NULL;
- struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
- struct ifa_order_elt *cur, *tmp;
- const char *ifname, *matchgroup, *nogroup;
- struct option *p;
- size_t iflen;
- int flags;
+#ifdef WITHOUT_NETLINK
+ list_interfaces_ioctl(ctx);
+#else
+ list_interfaces_nl(ctx->args);
+#endif
+}
+
+static char *
+args_peek(struct ifconfig_args *args)
+{
+ if (args->argc > 0)
+ return (args->argv[0]);
+ return (NULL);
+}
- all = downonly = uponly = namesonly = noload = verbose = 0;
- f_inet = f_inet6 = f_ether = f_addr = NULL;
- matchgroup = nogroup = NULL;
+static char *
+args_pop(struct ifconfig_args *args)
+{
+ if (args->argc == 0)
+ return (NULL);
- lifh = ifconfig_open();
- if (lifh == NULL)
- err(EXIT_FAILURE, "ifconfig_open");
+ char *arg = args->argv[0];
- envformat = getenv("IFCONFIG_FORMAT");
- if (envformat != NULL)
- setformat(envformat);
+ args->argc--;
+ args->argv++;
- /*
- * Ensure we print interface name when expected to,
- * even if we terminate early due to error.
- */
- atexit(printifnamemaybe);
+ return (arg);
+}
+
+static void
+args_parse(struct ifconfig_args *args, int argc, char *argv[])
+{
+ char options[1024];
+ struct option *p;
+#ifdef JAIL
+ int jid;
+#endif
+ int c;
/* Parse leading line options */
- strlcpy(options, "G:adf:klmnuv", sizeof(options));
+ strlcpy(options, "G:adDf:j:klmnuv", sizeof(options));
for (p = opts; p != NULL; p = p->next)
strlcat(options, p->opt, sizeof(options));
while ((c = getopt(argc, argv, options)) != -1) {
switch (c) {
case 'a': /* scan all interfaces */
- all++;
+ args->all = true;
break;
case 'd': /* restrict scan to "down" interfaces */
- downonly++;
+ args->downonly = true;
+ break;
+ case 'D': /* Print driver name */
+ args->drivername = true;
break;
case 'f':
if (optarg == NULL)
@@ -456,33 +489,46 @@ main(int argc, char *argv[])
setformat(optarg);
break;
case 'G':
- if (optarg == NULL || all == 0)
+ if (optarg == NULL || args->all == 0)
+ usage();
+ args->nogroup = optarg;
+ break;
+ case 'j':
+#ifdef JAIL
+ if (optarg == NULL)
usage();
- nogroup = optarg;
+ jid = jail_getid(optarg);
+ if (jid == -1)
+ Perror("jail not found");
+ if (jail_attach(jid) != 0)
+ Perror("cannot attach to jail");
+#else
+ Perror("not built with jail support");
+#endif
break;
case 'k':
- printkeys++;
+ args->printkeys = true;
break;
case 'l': /* scan interface names only */
- namesonly++;
+ args->namesonly = true;
break;
case 'm': /* show media choices in status */
- supmedia = 1;
+ args->supmedia = true;
break;
case 'n': /* suppress module loading */
- noload++;
+ args->noload = true;
break;
case 'u': /* restrict scan to "up" interfaces */
- uponly++;
+ args->uponly = true;
break;
case 'v':
- verbose++;
+ args->verbose++;
break;
case 'g':
- if (all) {
+ if (args->all) {
if (optarg == NULL)
usage();
- matchgroup = optarg;
+ args->matchgroup = optarg;
break;
}
/* FALLTHROUGH */
@@ -501,26 +547,25 @@ main(int argc, char *argv[])
argv += optind;
/* -l cannot be used with -a or -m */
- if (namesonly && (all || supmedia))
+ if (args->namesonly && (args->all || args->supmedia))
usage();
/* nonsense.. */
- if (uponly && downonly)
+ if (args->uponly && args->downonly)
usage();
/* no arguments is equivalent to '-a' */
- if (!namesonly && argc < 1)
- all = 1;
+ if (!args->namesonly && argc < 1)
+ args->all = 1;
/* -a and -l allow an address family arg to limit the output */
- if (all || namesonly) {
+ if (args->all || args->namesonly) {
if (argc > 1)
usage();
- ifname = NULL;
- ifindex = 0;
if (argc == 1) {
- afp = af_getbyname(*argv);
+ const struct afswtch *afp = af_getbyname(*argv);
+
if (afp == NULL) {
warnx("Address family '%s' unknown.", *argv);
usage();
@@ -528,32 +573,95 @@ main(int argc, char *argv[])
if (afp->af_name != NULL)
argc--, argv++;
/* leave with afp non-zero */
+ args->afp = afp;
}
} else {
/* not listing, need an argument */
if (argc < 1)
usage();
+ }
- ifname = *argv;
- argc--, argv++;
+ args->argc = argc;
+ args->argv = argv;
+}
+
+static int
+ifconfig(if_ctx *ctx, int iscreate, const struct afswtch *uafp)
+{
+#ifdef WITHOUT_NETLINK
+ return (ifconfig_ioctl(ctx, iscreate, uafp));
+#else
+ return (ifconfig_nl(ctx, iscreate, uafp));
+#endif
+}
+
+static bool
+isargcreate(const char *arg)
+{
+ if (arg == NULL)
+ return (false);
+
+ if (strcmp(arg, "create") == 0 || strcmp(arg, "plumb") == 0)
+ return (true);
+
+ return (false);
+}
+
+static bool
+isnametoolong(const char *ifname)
+{
+ return (strlen(ifname) >= IFNAMSIZ);
+}
+
+int
+main(int ac, char *av[])
+{
+ char *envformat;
+ int flags;
+ struct ifconfig_args _args = {};
+ struct ifconfig_args *args = &_args;
+
+ struct ifconfig_context ctx = {
+ .args = args,
+ .io_s = -1,
+ };
+
+ lifh = ifconfig_open();
+ if (lifh == NULL)
+ err(EXIT_FAILURE, "ifconfig_open");
+
+ envformat = getenv("IFCONFIG_FORMAT");
+ if (envformat != NULL)
+ setformat(envformat);
+
+ /*
+ * Ensure we print interface name when expected to,
+ * even if we terminate early due to error.
+ */
+ atexit(printifnamemaybe);
+
+ args_parse(args, ac, av);
+
+ if (!args->all && !args->namesonly) {
+ /* not listing, need an argument */
+ args->ifname = args_pop(args);
+ ctx.ifname = args->ifname;
/* check and maybe load support for this interface */
- ifmaybeload(ifname);
+ ifmaybeload(args, args->ifname);
- ifindex = if_nametoindex(ifname);
- if (ifindex == 0) {
+ char *arg = args_peek(args);
+ if (if_nametoindex(args->ifname) == 0) {
/*
* NOTE: We must special-case the `create' command
* right here as we would otherwise fail when trying
* to find the interface.
*/
- if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
- strcmp(argv[0], "plumb") == 0)) {
- iflen = strlcpy(name, ifname, sizeof(name));
- if (iflen >= sizeof(name))
+ if (isargcreate(arg)) {
+ if (isnametoolong(args->ifname))
errx(1, "%s: cloning name too long",
- ifname);
- ifconfig(argc, argv, 1, NULL);
+ args->ifname);
+ ifconfig(&ctx, 1, NULL);
exit(exit_code);
}
#ifdef JAIL
@@ -562,36 +670,34 @@ main(int argc, char *argv[])
* right here as we would otherwise fail when trying
* to find the interface as it lives in another vnet.
*/
- if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) {
- iflen = strlcpy(name, ifname, sizeof(name));
- if (iflen >= sizeof(name))
+ if (arg != NULL && (strcmp(arg, "-vnet") == 0)) {
+ if (isnametoolong(args->ifname))
errx(1, "%s: interface name too long",
- ifname);
- ifconfig(argc, argv, 0, NULL);
+ args->ifname);
+ ifconfig(&ctx, 0, NULL);
exit(exit_code);
}
#endif
- errx(1, "interface %s does not exist", ifname);
+ errx(1, "interface %s does not exist", args->ifname);
} else {
/*
* Do not allow use `create` command as hostname if
* address family is not specified.
*/
- if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
- strcmp(argv[0], "plumb") == 0)) {
- if (argc == 1)
+ if (isargcreate(arg)) {
+ if (args->argc == 1)
errx(1, "interface %s already exists",
- ifname);
- argc--, argv++;
+ args->ifname);
+ args_pop(args);
}
}
}
/* Check for address family */
- if (argc > 0) {
- afp = af_getbyname(*argv);
- if (afp != NULL)
- argc--, argv++;
+ if (args->argc > 0) {
+ args->afp = af_getbyname(args_peek(args));
+ if (args->afp != NULL)
+ args_pop(args);
}
/*
@@ -599,24 +705,84 @@ main(int argc, char *argv[])
* which doesn't require building, sorting, and searching the entire
* system address list
*/
- if ((argc > 0) && (ifname != NULL)) {
- iflen = strlcpy(name, ifname, sizeof(name));
- if (iflen >= sizeof(name)) {
- warnx("%s: interface name too long, skipping", ifname);
- } else {
- flags = getifflags(name, -1, false);
+ if ((args->argc > 0) && (args->ifname != NULL)) {
+ if (isnametoolong(args->ifname))
+ warnx("%s: interface name too long, skipping", args->ifname);
+ else {
+ flags = getifflags(args->ifname, -1, false);
if (!(((flags & IFF_CANTCONFIG) != 0) ||
- (downonly && (flags & IFF_UP) != 0) ||
- (uponly && (flags & IFF_UP) == 0)))
- ifconfig(argc, argv, 0, afp);
+ (args->downonly && (flags & IFF_UP) != 0) ||
+ (args->uponly && (flags & IFF_UP) == 0)))
+ ifconfig(&ctx, 0, args->afp);
}
goto done;
}
+ args->allfamilies = args->afp == NULL;
+
+ list_interfaces(&ctx);
+
+done:
+ freeformat();
+ ifconfig_close(lifh);
+ exit(exit_code);
+}
+
+bool
+match_ether(const struct sockaddr_dl *sdl)
+{
+ switch (sdl->sdl_type) {
+ case IFT_ETHER:
+ case IFT_L2VLAN:
+ case IFT_BRIDGE:
+ if (sdl->sdl_alen == ETHER_ADDR_LEN)
+ return (true);
+ default:
+ return (false);
+ }
+}
+
+bool
+match_if_flags(struct ifconfig_args *args, int if_flags)
+{
+ if ((if_flags & IFF_CANTCONFIG) != 0)
+ return (false);
+ if (args->downonly && (if_flags & IFF_UP) != 0)
+ return (false);
+ if (args->uponly && (if_flags & IFF_UP) == 0)
+ return (false);
+ return (true);
+}
+
+#ifdef WITHOUT_NETLINK
+static bool
+match_afp(const struct afswtch *afp, int sa_family, const struct sockaddr_dl *sdl)
+{
+ if (afp == NULL)
+ return (true);
+ /* special case for "ether" address family */
+ if (!strcmp(afp->af_name, "ether")) {
+ if (sdl == NULL || !match_ether(sdl))
+ return (false);
+ return (true);
+ }
+ return (afp->af_af == sa_family);
+}
+
+static void
+list_interfaces_ioctl(if_ctx *ctx)
+{
+ struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
+ struct ifaddrs *ifap, *sifap, *ifa;
+ struct ifa_order_elt *cur, *tmp;
+ char *namecp = NULL;
+ int ifindex;
+ struct ifconfig_args *args = ctx->args;
+
if (getifaddrs(&ifap) != 0)
err(EXIT_FAILURE, "getifaddrs");
- cp = NULL;
+ char *cp = NULL;
if (calcorders(ifap, &q) != 0)
err(EXIT_FAILURE, "calcorders");
@@ -628,95 +794,76 @@ main(int argc, char *argv[])
ifindex = 0;
for (ifa = sifap; ifa; ifa = ifa->ifa_next) {
- memset(&paifr, 0, sizeof(paifr));
+ struct ifreq paifr = {};
+ const struct sockaddr_dl *sdl;
+
strlcpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
memcpy(&paifr.ifr_addr, ifa->ifa_addr,
ifa->ifa_addr->sa_len);
}
- if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
+ if (args->ifname != NULL && strcmp(args->ifname, ifa->ifa_name) != 0)
continue;
if (ifa->ifa_addr->sa_family == AF_LINK)
- sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
+ sdl = satosdl_c(ifa->ifa_addr);
else
sdl = NULL;
- if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !namesonly)
+ if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !args->namesonly)
continue;
- iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
- if (iflen >= sizeof(name)) {
+ if (isnametoolong(ifa->ifa_name)) {
warnx("%s: interface name too long, skipping",
ifa->ifa_name);
continue;
}
cp = ifa->ifa_name;
- if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0)
+ if (!match_if_flags(args, ifa->ifa_flags))
continue;
- if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
- continue;
- if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
- continue;
- if (!group_member(ifa->ifa_name, matchgroup, nogroup))
+ if (!group_member(ifa->ifa_name, args->matchgroup, args->nogroup))
continue;
+ ctx->ifname = cp;
/*
* Are we just listing the interfaces?
*/
- if (namesonly) {
+ if (args->namesonly) {
if (namecp == cp)
continue;
- if (afp != NULL) {
- /* special case for "ether" address family */
- if (!strcmp(afp->af_name, "ether")) {
- if (sdl == NULL ||
- (sdl->sdl_type != IFT_ETHER &&
- sdl->sdl_type != IFT_L2VLAN &&
- sdl->sdl_type != IFT_BRIDGE) ||
- sdl->sdl_alen != ETHER_ADDR_LEN)
- continue;
- } else {
- if (ifa->ifa_addr->sa_family
- != afp->af_af)
- continue;
- }
- }
+ if (!match_afp(args->afp, ifa->ifa_addr->sa_family, sdl))
+ continue;
namecp = cp;
ifindex++;
if (ifindex > 1)
printf(" ");
- fputs(name, stdout);
+ fputs(cp, stdout);
continue;
}
ifindex++;
- if (argc > 0)
- ifconfig(argc, argv, 0, afp);
+ if (args->argc > 0)
+ ifconfig(ctx, 0, args->afp);
else
- status(afp, sdl, ifa);
+ status(ctx, sdl, ifa);
}
- if (namesonly)
+ if (args->namesonly)
printf("\n");
freeifaddrs(ifap);
-
-done:
- freeformat();
- ifconfig_close(lifh);
- exit(exit_code);
}
+#endif
/*
* Returns true if an interface should be listed because any its groups
* matches shell pattern "match" and none of groups matches pattern "nomatch".
* If any pattern is NULL, corresponding condition is skipped.
*/
-static bool
+bool
group_member(const char *ifname, const char *match, const char *nomatch)
{
static int sock = -1;
struct ifgroupreq ifgr;
struct ifg_req *ifg;
- int len;
+ unsigned int len;
bool matched, nomatched;
/* Sanity checks. */
@@ -757,11 +904,11 @@ group_member(const char *ifname, const char *match, const char *nomatch)
matched = false;
nomatched = true;
for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) {
- len -= sizeof(struct ifg_req);
- if (match)
- matched |= !fnmatch(match, ifg->ifgrq_group, 0);
- if (nomatch)
- nomatched &= fnmatch(nomatch, ifg->ifgrq_group, 0);
+ len -= sizeof(*ifg);
+ if (match && !matched)
+ matched = !fnmatch(match, ifg->ifgrq_group, 0);
+ if (nomatch && nomatched)
+ nomatched = fnmatch(nomatch, ifg->ifgrq_group, 0);
}
free(ifgr.ifgr_groups);
@@ -792,7 +939,7 @@ af_getbyname(const char *name)
return NULL;
}
-static struct afswtch *
+struct afswtch *
af_getbyfamily(int af)
{
struct afswtch *afp;
@@ -803,8 +950,8 @@ af_getbyfamily(int af)
return NULL;
}
-static void
-af_other_status(int s)
+void
+af_other_status(if_ctx *ctx)
{
struct afswtch *afp;
uint8_t afmask[howmany(AF_MAX, NBBY)];
@@ -815,13 +962,13 @@ af_other_status(int s)
continue;
if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
continue;
- afp->af_other_status(s);
+ afp->af_other_status(ctx);
setbit(afmask, afp->af_af);
}
}
static void
-af_all_tunnel_status(int s)
+af_all_tunnel_status(if_ctx *ctx)
{
struct afswtch *afp;
uint8_t afmask[howmany(AF_MAX, NBBY)];
@@ -832,7 +979,7 @@ af_all_tunnel_status(int s)
continue;
if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
continue;
- afp->af_status_tunnel(s);
+ afp->af_status_tunnel(ctx);
setbit(afmask, afp->af_af);
}
}
@@ -886,22 +1033,80 @@ callback_register(callback_func *func, void *arg)
}
/* specially-handled commands */
-static void setifaddr(const char *, int, int, const struct afswtch *);
+static void setifaddr(if_ctx *ctx, const char *addr, int param);
static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr);
-static void setifdstaddr(const char *, int, int, const struct afswtch *);
+static void setifdstaddr(if_ctx *ctx, const char *addr, int param __unused);
static const struct cmd setifdstaddr_cmd =
DEF_CMD("ifdstaddr", 0, setifdstaddr);
-static int
-ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
+int
+af_exec_ioctl(if_ctx *ctx, unsigned long action, void *data)
+{
+ struct ifreq *req = (struct ifreq *)data;
+
+ strlcpy(req->ifr_name, ctx->ifname, sizeof(req->ifr_name));
+ if (ioctl_ctx(ctx, action, req) == 0)
+ return (0);
+ return (errno);
+}
+
+static void
+delifaddr(if_ctx *ctx, const struct afswtch *afp)
+{
+ int error;
+
+ if (afp->af_exec == NULL) {
+ warnx("interface %s cannot change %s addresses!",
+ ctx->ifname, afp->af_name);
+ clearaddr = 0;
+ return;
+ }
+
+ error = afp->af_exec(ctx, afp->af_difaddr, afp->af_ridreq);
+ if (error != 0) {
+ if (error == EADDRNOTAVAIL && (doalias >= 0)) {
+ /* means no previous address for interface */
+ } else
+ Perrorc("ioctl (SIOCDIFADDR)", error);
+ }
+}
+
+static void
+addifaddr(if_ctx *ctx, const struct afswtch *afp)
+{
+ if (afp->af_exec == NULL) {
+ warnx("interface %s cannot change %s addresses!",
+ ctx->ifname, afp->af_name);
+ newaddr = 0;
+ return;
+ }
+
+ if (setaddr || setmask) {
+ int error = afp->af_exec(ctx, afp->af_aifaddr, afp->af_addreq);
+ if (error != 0)
+ Perrorc("ioctl (SIOCAIFADDR)", error);
+ }
+}
+
+int
+ifconfig_ioctl(if_ctx *orig_ctx, int iscreate, const struct afswtch *uafp)
{
const struct afswtch *afp, *nafp;
const struct cmd *p;
struct callback *cb;
int s;
-
- strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
+ int argc = orig_ctx->args->argc;
+ char *const *argv = orig_ctx->args->argv;
+ struct ifconfig_context _ctx = {
+ .args = orig_ctx->args,
+ .io_ss = orig_ctx->io_ss,
+ .ifname = orig_ctx->ifname,
+ };
+ struct ifconfig_context *ctx = &_ctx;
+
+ struct ifreq ifr = {};
+ strlcpy(ifr.ifr_name, ctx->ifname, sizeof ifr.ifr_name);
afp = NULL;
if (uafp != NULL)
afp = uafp;
@@ -926,6 +1131,7 @@ ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
warnx("Please specify an address_family.");
usage();
}
+
top:
ifr.ifr_addr.sa_family =
afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
@@ -936,6 +1142,9 @@ top:
(s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0))
err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
+ ctx->io_s = s;
+ ctx->afp = afp;
+
while (argc > 0) {
p = cmd_lookup(*argv, iscreate);
if (iscreate && p == NULL) {
@@ -948,7 +1157,7 @@ top:
if (cb == NULL)
errx(1, "internal error, no callback");
callbacks = cb->cb_next;
- cb->cb_func(s, cb->cb_arg);
+ cb->cb_func(ctx, cb->cb_arg);
iscreate = 0;
/*
* Handle any address family spec that
@@ -980,22 +1189,29 @@ top:
if (argv[1] == NULL)
errx(1, "'%s' requires argument",
p->c_name);
- p->c_u.c_func(argv[1], 0, s, afp);
+ p->c_u.c_func(ctx, argv[1], 0);
argc--, argv++;
} else if (p->c_parameter == OPTARG && p->c_u.c_func) {
- p->c_u.c_func(argv[1], 0, s, afp);
+ p->c_u.c_func(ctx, argv[1], 0);
if (argv[1] != NULL)
argc--, argv++;
} else if (p->c_parameter == NEXTARG2 && p->c_u.c_func2) {
if (argc < 3)
errx(1, "'%s' requires 2 arguments",
p->c_name);
- p->c_u.c_func2(argv[1], argv[2], s, afp);
+ p->c_u.c_func2(ctx, argv[1], argv[2]);
argc -= 2, argv += 2;
} else if (p->c_parameter == SPARAM && p->c_u.c_func3) {
- p->c_u.c_func3(*argv, p->c_sparameter, s, afp);
+ p->c_u.c_func3(ctx, *argv, p->c_sparameter);
+ } else if (p->c_parameter == ARGVECTOR && p->c_u.c_funcv) {
+ int argsdone;
+
+ argsdone = p->c_u.c_funcv(ctx, argc - 1,
+ (const char *const *)argv + 1);
+ argc -= argsdone;
+ argv += argsdone;
} else if (p->c_u.c_func)
- p->c_u.c_func(*argv, p->c_parameter, s, afp);
+ p->c_u.c_func(ctx, *argv, p->c_parameter);
argc--, argv++;
}
@@ -1003,57 +1219,30 @@ top:
* Do any post argument processing required by the address family.
*/
if (afp->af_postproc != NULL)
- afp->af_postproc(s, afp, newaddr, getifflags(name, s, true));
+ afp->af_postproc(ctx, newaddr, getifflags(ctx->ifname, s, true));
/*
* Do deferred callbacks registered while processing
* command-line arguments.
*/
for (cb = callbacks; cb != NULL; cb = cb->cb_next)
- cb->cb_func(s, cb->cb_arg);
+ cb->cb_func(ctx, cb->cb_arg);
/*
* Do deferred operations.
*/
- if (clearaddr) {
- if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
- warnx("interface %s cannot change %s addresses!",
- name, afp->af_name);
- clearaddr = 0;
- }
- }
- if (clearaddr) {
- int ret;
- strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, name,
- sizeof ifr.ifr_name);
- ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
- if (ret < 0) {
- if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
- /* means no previous address for interface */
- } else
- Perror("ioctl (SIOCDIFADDR)");
- }
- }
- if (newaddr) {
- if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
- warnx("interface %s cannot change %s addresses!",
- name, afp->af_name);
- newaddr = 0;
- }
- }
- if (newaddr && (setaddr || setmask)) {
- strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name,
- sizeof ifr.ifr_name);
- if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
- Perror("ioctl (SIOCAIFADDR)");
- }
+ if (clearaddr)
+ delifaddr(ctx, afp);
+ if (newaddr)
+ addifaddr(ctx, afp);
close(s);
return(0);
}
-/*ARGSUSED*/
static void
-setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
+setifaddr(if_ctx *ctx, const char *addr, int param __unused)
{
+ const struct afswtch *afp = ctx->afp;
+
if (afp->af_getaddr == NULL)
return;
/*
@@ -1068,8 +1257,9 @@ setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
}
static void
-settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
+settunnel(if_ctx *ctx, const char *src, const char *dst)
{
+ const struct afswtch *afp = ctx->afp;
struct addrinfo *srcres, *dstres;
int ecode;
@@ -1091,55 +1281,52 @@ settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
errx(1,
"source and destination address families do not match");
- afp->af_settunnel(s, srcres, dstres);
+ afp->af_settunnel(ctx, srcres, dstres);
freeaddrinfo(srcres);
freeaddrinfo(dstres);
}
-/* ARGSUSED */
static void
-deletetunnel(const char *vname, int param, int s, const struct afswtch *afp)
+deletetunnel(if_ctx *ctx, const char *vname __unused, int param __unused)
{
+ struct ifreq ifr = {};
- if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCDIFPHYADDR, &ifr) < 0)
err(1, "SIOCDIFPHYADDR");
}
#ifdef JAIL
static void
-setifvnet(const char *jname, int dummy __unused, int s,
- const struct afswtch *afp)
+setifvnet(if_ctx *ctx, const char *jname, int dummy __unused)
{
- struct ifreq my_ifr;
+ struct ifreq ifr = {};
- memcpy(&my_ifr, &ifr, sizeof(my_ifr));
- my_ifr.ifr_jid = jail_getid(jname);
- if (my_ifr.ifr_jid < 0)
+ ifr.ifr_jid = jail_getid(jname);
+ if (ifr.ifr_jid < 0)
errx(1, "%s", jail_errmsg);
- if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCSIFVNET, &ifr) < 0)
err(1, "SIOCSIFVNET");
}
static void
-setifrvnet(const char *jname, int dummy __unused, int s,
- const struct afswtch *afp)
+setifrvnet(if_ctx *ctx, const char *jname, int dummy __unused)
{
- struct ifreq my_ifr;
+ struct ifreq ifr = {};
- memcpy(&my_ifr, &ifr, sizeof(my_ifr));
- my_ifr.ifr_jid = jail_getid(jname);
- if (my_ifr.ifr_jid < 0)
+ ifr.ifr_jid = jail_getid(jname);
+ if (ifr.ifr_jid < 0)
errx(1, "%s", jail_errmsg);
- if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0)
- err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name);
+ if (ioctl_ctx_ifr(ctx, SIOCSIFRVNET, &ifr) < 0)
+ err(1, "SIOCSIFRVNET(%d, %s)", ifr.ifr_jid, ifr.ifr_name);
}
#endif
static void
-setifnetmask(const char *addr, int dummy __unused, int s,
- const struct afswtch *afp)
+setifnetmask(if_ctx *ctx, const char *addr, int dummy __unused)
{
+ const struct afswtch *afp = ctx->afp;
+
if (afp->af_getaddr != NULL) {
setmask++;
afp->af_getaddr(addr, MASK);
@@ -1147,36 +1334,36 @@ setifnetmask(const char *addr, int dummy __unused, int s,
}
static void
-setifbroadaddr(const char *addr, int dummy __unused, int s,
- const struct afswtch *afp)
+setifbroadaddr(if_ctx *ctx, const char *addr, int dummy __unused)
{
+ const struct afswtch *afp = ctx->afp;
+
if (afp->af_getaddr != NULL)
- afp->af_getaddr(addr, DSTADDR);
+ afp->af_getaddr(addr, BRDADDR);
}
static void
-notealias(const char *addr, int param, int s, const struct afswtch *afp)
-{
-#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
- if (setaddr && doalias == 0 && param < 0)
- if (afp->af_addreq != NULL && afp->af_ridreq != NULL)
- bcopy((caddr_t)rqtosa(af_addreq),
- (caddr_t)rqtosa(af_ridreq),
- rqtosa(af_addreq)->sa_len);
+notealias(if_ctx *ctx, const char *addr __unused, int param)
+{
+ const struct afswtch *afp = ctx->afp;
+
+ if (setaddr && doalias == 0 && param < 0) {
+ if (afp->af_copyaddr != NULL)
+ afp->af_copyaddr(ctx, RIDADDR, ADDR);
+ }
doalias = param;
if (param < 0) {
clearaddr = 1;
newaddr = 0;
} else
clearaddr = 0;
-#undef rqtosa
}
-/*ARGSUSED*/
static void
-setifdstaddr(const char *addr, int param __unused, int s,
- const struct afswtch *afp)
+setifdstaddr(if_ctx *ctx, const char *addr, int param __unused)
{
+ const struct afswtch *afp = ctx->afp;
+
if (afp->af_getaddr != NULL)
afp->af_getaddr(addr, DSTADDR);
}
@@ -1211,59 +1398,90 @@ getifflags(const char *ifname, int us, bool err_ok)
* Make a private copy so we can avoid that.
*/
static void
-setifflags(const char *vname, int value, int s, const struct afswtch *afp)
+clearifflags(if_ctx *ctx, const char *vname, int value)
{
struct ifreq my_ifr;
int flags;
- flags = getifflags(name, s, false);
- if (value < 0) {
- value = -value;
- flags &= ~value;
- } else
- flags |= value;
+ flags = getifflags(ctx->ifname, ctx->io_s, false);
+ flags &= ~value;
memset(&my_ifr, 0, sizeof(my_ifr));
- (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name));
+ strlcpy(my_ifr.ifr_name, ctx->ifname, sizeof(my_ifr.ifr_name));
my_ifr.ifr_flags = flags & 0xffff;
my_ifr.ifr_flagshigh = flags >> 16;
- if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
+ if (ioctl(ctx->io_s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
+ Perror(vname);
+}
+
+static void
+setifflags(if_ctx *ctx, const char *vname, int value)
+{
+ struct ifreq my_ifr;
+ int flags;
+
+ flags = getifflags(ctx->ifname, ctx->io_s, false);
+ flags |= value;
+ memset(&my_ifr, 0, sizeof(my_ifr));
+ strlcpy(my_ifr.ifr_name, ctx->ifname, sizeof(my_ifr.ifr_name));
+ my_ifr.ifr_flags = flags & 0xffff;
+ my_ifr.ifr_flagshigh = flags >> 16;
+ if (ioctl(ctx->io_s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
Perror(vname);
}
void
-setifcap(const char *vname, int value, int s, const struct afswtch *afp)
+clearifcap(if_ctx *ctx, const char *vname, int value)
{
+ struct ifreq ifr = {};
int flags;
- if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
+ if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0) {
Perror("ioctl (SIOCGIFCAP)");
exit(1);
}
flags = ifr.ifr_curcap;
- if (value < 0) {
- value = -value;
- flags &= ~value;
- } else
- flags |= value;
+ flags &= ~value;
flags &= ifr.ifr_reqcap;
/* Check for no change in capabilities. */
if (ifr.ifr_curcap == flags)
return;
ifr.ifr_reqcap = flags;
- if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx(ctx, SIOCSIFCAP, &ifr) < 0)
Perror(vname);
}
void
-setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp)
+setifcap(if_ctx *ctx, const char *vname, int value)
+{
+ struct ifreq ifr = {};
+ int flags;
+
+ if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0) {
+ Perror("ioctl (SIOCGIFCAP)");
+ exit(1);
+ }
+ flags = ifr.ifr_curcap;
+ flags |= value;
+ flags &= ifr.ifr_reqcap;
+ /* Check for no change in capabilities. */
+ if (ifr.ifr_curcap == flags)
+ return;
+ ifr.ifr_reqcap = flags;
+ if (ioctl_ctx(ctx, SIOCSIFCAP, &ifr) < 0)
+ Perror(vname);
+}
+
+void
+setifcapnv(if_ctx *ctx, const char *vname, const char *arg)
{
nvlist_t *nvcap;
void *buf;
char *marg, *mopt;
size_t nvbuflen;
bool neg;
+ struct ifreq ifr = {};
- if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0)
Perror("ioctl (SIOCGIFCAP)");
if ((ifr.ifr_curcap & IFCAP_NV) == 0) {
warnx("IFCAP_NV not supported");
@@ -1294,7 +1512,7 @@ setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp)
}
ifr.ifr_cap_nv.buf_length = ifr.ifr_cap_nv.length = nvbuflen;
ifr.ifr_cap_nv.buffer = buf;
- if (ioctl(s, SIOCSIFCAPNV, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx(ctx, SIOCSIFCAPNV, (caddr_t)&ifr) < 0)
Perror(vname);
free(buf);
nvlist_destroy(nvcap);
@@ -1302,28 +1520,29 @@ setifcapnv(const char *vname, const char *arg, int s, const struct afswtch *afp)
}
static void
-setifmetric(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+setifmetric(if_ctx *ctx, const char *val, int dummy __unused)
{
- strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+ struct ifreq ifr = {};
+
ifr.ifr_metric = atoi(val);
- if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCSIFMETRIC, &ifr) < 0)
err(1, "ioctl SIOCSIFMETRIC (set metric)");
}
static void
-setifmtu(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+setifmtu(if_ctx *ctx, const char *val, int dummy __unused)
{
- strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+ struct ifreq ifr = {};
+
ifr.ifr_mtu = atoi(val);
- if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCSIFMTU, &ifr) < 0)
err(1, "ioctl SIOCSIFMTU (set mtu)");
}
static void
-setifpcp(const char *val, int arg __unused, int s, const struct afswtch *afp)
+setifpcp(if_ctx *ctx, const char *val, int arg __unused)
{
+ struct ifreq ifr = {};
u_long ul;
char *endp;
@@ -1333,50 +1552,45 @@ setifpcp(const char *val, int arg __unused, int s, const struct afswtch *afp)
if (ul > 7)
errx(1, "value for pcp out of range");
ifr.ifr_lan_pcp = ul;
- if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
+ if (ioctl_ctx_ifr(ctx, SIOCSLANPCP, &ifr) == -1)
err(1, "SIOCSLANPCP");
}
static void
-disableifpcp(const char *val, int arg __unused, int s,
- const struct afswtch *afp)
+disableifpcp(if_ctx *ctx, const char *val __unused, int arg __unused)
{
+ struct ifreq ifr = {};
ifr.ifr_lan_pcp = IFNET_PCP_NONE;
- if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
+ if (ioctl_ctx_ifr(ctx, SIOCSLANPCP, &ifr) == -1)
err(1, "SIOCSLANPCP");
}
static void
-setifname(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+setifname(if_ctx *ctx, const char *val, int dummy __unused)
{
+ struct ifreq ifr = {};
char *newname;
-
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr_set_name(&ifr, ctx->ifname);
newname = strdup(val);
if (newname == NULL)
err(1, "no memory to set ifname");
ifr.ifr_data = newname;
- if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
+ if (ioctl_ctx(ctx, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
free(newname);
err(1, "ioctl SIOCSIFNAME (set name)");
}
- printifname = 1;
- strlcpy(name, newname, sizeof(name));
+ ifname_update(ctx, newname);
free(newname);
}
-/* ARGSUSED */
static void
-setifdescr(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+setifdescr(if_ctx *ctx, const char *val, int dummy __unused)
{
+ struct ifreq ifr = {};
char *newdescr;
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
-
ifr.ifr_buffer.length = strlen(val) + 1;
if (ifr.ifr_buffer.length == 1) {
ifr.ifr_buffer.buffer = newdescr = NULL;
@@ -1390,75 +1604,198 @@ setifdescr(const char *val, int dummy __unused, int s,
}
}
- if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCSIFDESCR, &ifr) < 0)
err(1, "ioctl SIOCSIFDESCR (set descr)");
free(newdescr);
}
-/* ARGSUSED */
static void
-unsetifdescr(const char *val, int value, int s, const struct afswtch *afp)
+unsetifdescr(if_ctx *ctx, const char *val __unused, int value __unused)
{
-
- setifdescr("", 0, s, 0);
+ setifdescr(ctx, "", 0);
}
-#define IFFBITS \
-"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \
-"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
-"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP\25STICKYARP"
+#ifdef WITHOUT_NETLINK
+
+static const char *IFFBITS[] = {
+ [0] = "UP",
+ [1] = "BROADCAST",
+ [2] = "DEBUG",
+ [3] = "LOOPBACK",
+ [4] = "POINTOPOINT",
+ [6] = "RUNNING",
+ [7] = "NOARP",
+ [8] = "PROMISC",
+ [9] = "ALLMULTI",
+ [10] = "OACTIVE",
+ [11] = "SIMPLEX",
+ [12] = "LINK0",
+ [13] = "LINK1",
+ [14] = "LINK2",
+ [15] = "MULTICAST",
+ [17] = "PPROMISC",
+ [18] = "MONITOR",
+ [19] = "STATICARP",
+ [20] = "STICKYARP",
+};
-#define IFCAPBITS \
-"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
-"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \
-"\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \
-"\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6" \
-"\36VXLAN_HWCSUM\37VXLAN_HWTSO\40TXTLS_RTLMT"
+static const char *IFCAPBITS[] = {
+ [0] = "RXCSUM",
+ [1] = "TXCSUM",
+ [2] = "NETCONS",
+ [3] = "VLAN_MTU",
+ [4] = "VLAN_HWTAGGING",
+ [5] = "JUMBO_MTU",
+ [6] = "POLLING",
+ [7] = "VLAN_HWCSUM",
+ [8] = "TSO4",
+ [9] = "TSO6",
+ [10] = "LRO",
+ [11] = "WOL_UCAST",
+ [12] = "WOL_MCAST",
+ [13] = "WOL_MAGIC",
+ [14] = "TOE4",
+ [15] = "TOE6",
+ [16] = "VLAN_HWFILTER",
+ [18] = "VLAN_HWTSO",
+ [19] = "LINKSTATE",
+ [20] = "NETMAP",
+ [21] = "RXCSUM_IPV6",
+ [22] = "TXCSUM_IPV6",
+ [23] = "HWSTATS",
+ [24] = "TXRTLMT",
+ [25] = "HWRXTSTMP",
+ [26] = "MEXTPG",
+ [27] = "TXTLS4",
+ [28] = "TXTLS6",
+ [29] = "VXLAN_HWCSUM",
+ [30] = "VXLAN_HWTSO",
+ [31] = "TXTLS_RTLMT",
+};
-/*
- * Print the status of the interface. If an address family was
- * specified, show only it; otherwise, show them all.
- */
static void
-status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
- struct ifaddrs *ifa)
+print_ifcap_nv(if_ctx *ctx)
{
- struct ifaddrs *ift;
- struct ifstat ifs;
+ struct ifreq ifr = {};
nvlist_t *nvcap;
const char *nvname;
void *buf, *cookie;
- int allfamilies, s, type;
bool first, val;
+ int type;
- if (afp == NULL) {
- allfamilies = 1;
- ifr.ifr_addr.sa_family = AF_LOCAL;
- } else {
- allfamilies = 0;
- ifr.ifr_addr.sa_family =
- afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af;
+ buf = malloc(IFR_CAP_NV_MAXBUFSIZE);
+ if (buf == NULL)
+ Perror("malloc");
+ ifr.ifr_cap_nv.buffer = buf;
+ ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
+ if (ioctl_ctx_ifr(ctx, SIOCGIFCAPNV, &ifr) != 0)
+ Perror("ioctl (SIOCGIFCAPNV)");
+ nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer,
+ ifr.ifr_cap_nv.length, 0);
+ if (nvcap == NULL)
+ Perror("nvlist_unpack");
+ printf("\toptions");
+ cookie = NULL;
+ for (first = true;; first = false) {
+ nvname = nvlist_next(nvcap, &type, &cookie);
+ if (nvname == NULL) {
+ printf("\n");
+ break;
+ }
+ if (type == NV_TYPE_BOOL) {
+ val = nvlist_get_bool(nvcap, nvname);
+ if (val) {
+ printf("%c%s",
+ first ? ' ' : ',', nvname);
+ }
+ }
+ }
+ if (ctx->args->supmedia) {
+ printf("\tcapabilities");
+ cookie = NULL;
+ for (first = true;; first = false) {
+ nvname = nvlist_next(nvcap, &type,
+ &cookie);
+ if (nvname == NULL) {
+ printf("\n");
+ break;
+ }
+ if (type == NV_TYPE_BOOL)
+ printf("%c%s", first ? ' ' :
+ ',', nvname);
+ }
}
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ nvlist_destroy(nvcap);
+ free(buf);
- s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
- if (s < 0)
- err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
+ if (ioctl_ctx(ctx, SIOCGIFCAP, (caddr_t)&ifr) != 0)
+ Perror("ioctl (SIOCGIFCAP)");
+}
+
+static void
+print_ifcap(if_ctx *ctx)
+{
+ struct ifreq ifr = {};
+
+ if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) != 0)
+ return;
+
+ if ((ifr.ifr_curcap & IFCAP_NV) != 0)
+ print_ifcap_nv(ctx);
+ else {
+ printf("\toptions=%x", ifr.ifr_curcap);
+ print_bits("options", &ifr.ifr_curcap, 1, IFCAPBITS, nitems(IFCAPBITS));
+ putchar('\n');
+ if (ctx->args->supmedia && ifr.ifr_reqcap != 0) {
+ printf("\tcapabilities=%x", ifr.ifr_reqcap);
+ print_bits("capabilities", &ifr.ifr_reqcap, 1, IFCAPBITS, nitems(IFCAPBITS));
+ putchar('\n');
+ }
+ }
+}
+#endif
+
+void
+print_ifstatus(if_ctx *ctx)
+{
+ struct ifstat ifs;
- printf("%s: ", name);
- printb("flags", ifa->ifa_flags, IFFBITS);
- if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
+ strlcpy(ifs.ifs_name, ctx->ifname, sizeof ifs.ifs_name);
+ if (ioctl_ctx(ctx, SIOCGIFSTATUS, &ifs) == 0)
+ printf("%s", ifs.ascii);
+}
+
+void
+print_metric(if_ctx *ctx)
+{
+ struct ifreq ifr = {};
+
+ if (ioctl_ctx_ifr(ctx, SIOCGIFMETRIC, &ifr) != -1)
printf(" metric %d", ifr.ifr_metric);
- if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
+}
+
+#ifdef WITHOUT_NETLINK
+static void
+print_mtu(if_ctx *ctx)
+{
+ struct ifreq ifr = {};
+
+ if (ioctl_ctx_ifr(ctx, SIOCGIFMTU, &ifr) != -1)
printf(" mtu %d", ifr.ifr_mtu);
- putchar('\n');
+}
+
+static void
+print_description(if_ctx *ctx)
+{
+ struct ifreq ifr = {};
+ ifr_set_name(&ifr, ctx->ifname);
for (;;) {
if ((descr = reallocf(descr, descrlen)) != NULL) {
ifr.ifr_buffer.buffer = descr;
ifr.ifr_buffer.length = descrlen;
- if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
+ if (ioctl_ctx(ctx, SIOCGIFDESCR, &ifr) == 0) {
if (ifr.ifr_buffer.buffer == descr) {
if (strlen(descr) > 0)
printf("\tdescription: %s\n",
@@ -1473,68 +1810,44 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
"description");
break;
}
+}
- if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
- if ((ifr.ifr_curcap & IFCAP_NV) != 0) {
- buf = malloc(IFR_CAP_NV_MAXBUFSIZE);
- if (buf == NULL)
- Perror("malloc");
- ifr.ifr_cap_nv.buffer = buf;
- ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
- if (ioctl(s, SIOCGIFCAPNV, (caddr_t)&ifr) != 0)
- Perror("ioctl (SIOCGIFCAPNV)");
- nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer,
- ifr.ifr_cap_nv.length, 0);
- if (nvcap == NULL)
- Perror("nvlist_unpack");
- printf("\toptions");
- cookie = NULL;
- for (first = true;; first = false) {
- nvname = nvlist_next(nvcap, &type, &cookie);
- if (nvname == NULL) {
- printf("\n");
- break;
- }
- if (type == NV_TYPE_BOOL) {
- val = nvlist_get_bool(nvcap, nvname);
- if (val) {
- printf("%c%s",
- first ? ' ' : ',', nvname);
- }
- }
- }
- if (supmedia) {
- printf("\tcapabilities");
- cookie = NULL;
- for (first = true;; first = false) {
- nvname = nvlist_next(nvcap, &type,
- &cookie);
- if (nvname == NULL) {
- printf("\n");
- break;
- }
- if (type == NV_TYPE_BOOL)
- printf("%c%s", first ? ' ' :
- ',', nvname);
- }
- }
- nvlist_destroy(nvcap);
- free(buf);
+/*
+ * Print the status of the interface. If an address family was
+ * specified, show only it; otherwise, show them all.
+ */
+static void
+status(if_ctx *ctx, const struct sockaddr_dl *sdl __unused, struct ifaddrs *ifa)
+{
+ struct ifaddrs *ift;
+ int s, old_s;
+ struct ifconfig_args *args = ctx->args;
+ bool allfamilies = args->afp == NULL;
+ struct ifreq ifr = {};
- if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
- Perror("ioctl (SIOCGIFCAP)");
- } else if (ifr.ifr_curcap != 0) {
- printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
- putchar('\n');
- if (supmedia && ifr.ifr_reqcap != 0) {
- printb("\tcapabilities", ifr.ifr_reqcap,
- IFCAPBITS);
- putchar('\n');
- }
- }
- }
+ if (args->afp == NULL)
+ ifr.ifr_addr.sa_family = AF_LOCAL;
+ else
+ ifr.ifr_addr.sa_family =
+ args->afp->af_af == AF_LINK ? AF_LOCAL : args->afp->af_af;
- tunnel_status(s);
+ s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
+ if (s < 0)
+ err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
+ old_s = ctx->io_s;
+ ctx->io_s = s;
+
+ printf("%s: flags=%x", ctx->ifname, ifa->ifa_flags);
+ print_bits("flags", &ifa->ifa_flags, 1, IFFBITS, nitems(IFFBITS));
+ print_metric(ctx);
+ print_mtu(ctx);
+ putchar('\n');
+
+ print_description(ctx);
+
+ print_ifcap(ctx);
+
+ tunnel_status(ctx);
for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
if (ift->ifa_addr == NULL)
@@ -1545,9 +1858,9 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
const struct afswtch *p;
p = af_getbyfamily(ift->ifa_addr->sa_family);
if (p != NULL && p->af_status != NULL)
- p->af_status(s, ift);
- } else if (afp->af_af == ift->ifa_addr->sa_family)
- afp->af_status(s, ift);
+ p->af_status(ctx, ift);
+ } else if (args->afp->af_af == ift->ifa_addr->sa_family)
+ args->afp->af_status(ctx, ift);
}
#if 0
if (allfamilies || afp->af_af == AF_LINK) {
@@ -1567,29 +1880,28 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
}
#endif
if (allfamilies)
- af_other_status(s);
- else if (afp->af_other_status != NULL)
- afp->af_other_status(s);
+ af_other_status(ctx);
+ else if (args->afp->af_other_status != NULL)
+ args->afp->af_other_status(ctx);
- strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
- if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
- printf("%s", ifs.ascii);
-
- if (verbose > 0)
- sfp_status(s, &ifr, verbose);
+ print_ifstatus(ctx);
+ if (args->verbose > 0)
+ sfp_status(ctx);
close(s);
+ ctx->io_s = old_s;
return;
}
+#endif
-static void
-tunnel_status(int s)
+void
+tunnel_status(if_ctx *ctx)
{
- af_all_tunnel_status(s);
+ af_all_tunnel_status(ctx);
}
-void
-Perror(const char *cmd)
+static void
+Perrorc(const char *cmd, int error)
{
switch (errno) {
@@ -1602,8 +1914,37 @@ Perror(const char *cmd)
break;
default:
- err(1, "%s", cmd);
+ errc(1, error, "%s", cmd);
+ }
+}
+
+void
+Perror(const char *cmd)
+{
+ Perrorc(cmd, errno);
+}
+
+void
+print_bits(const char *btype, uint32_t *v, const int v_count,
+ const char **names, const int n_count)
+{
+ int num = 0;
+
+ for (int i = 0; i < v_count * 32; i++) {
+ bool is_set = v[i / 32] & (1U << (i % 32));
+ if (is_set) {
+ if (num++ == 0)
+ printf("<");
+ if (num != 1)
+ printf(",");
+ if (i < n_count)
+ printf("%s", names[i]);
+ else
+ printf("%s_%d", btype, i);
+ }
}
+ if (num > 0)
+ printf(">");
}
/*
@@ -1638,7 +1979,7 @@ printb(const char *s, unsigned v, const char *bits)
}
void
-print_vhid(const struct ifaddrs *ifa, const char *s)
+print_vhid(const struct ifaddrs *ifa)
{
struct if_data *ifd;
@@ -1653,32 +1994,34 @@ print_vhid(const struct ifaddrs *ifa, const char *s)
}
void
-ifmaybeload(const char *name)
+ifmaybeload(struct ifconfig_args *args, const char *name)
{
#define MOD_PREFIX_LEN 3 /* "if_" */
struct module_stat mstat;
- int i, fileid, modid;
+ int fileid, modid;
char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
const char *cp;
struct module_map_entry *mme;
bool found;
/* loading suppressed by the user */
- if (noload)
+ if (args->noload)
return;
/* trim the interface number off the end */
strlcpy(ifname, name, sizeof(ifname));
- for (dp = ifname; *dp != 0; dp++)
- if (isdigit(*dp)) {
- *dp = 0;
+ dp = ifname + strlen(ifname) - 1;
+ for (; dp > ifname; dp--) {
+ if (isdigit(*dp))
+ *dp = '\0';
+ else
break;
- }
+ }
/* Either derive it from the map or guess otherwise */
*ifkind = '\0';
found = false;
- for (i = 0; i < nitems(module_map); ++i) {
+ for (unsigned i = 0; i < nitems(module_map); ++i) {
mme = &module_map[i];
if (strcmp(mme->ifname, ifname) == 0) {
strlcpy(ifkind, mme->kldname, sizeof(ifkind));
@@ -1728,27 +2071,24 @@ ifmaybeload(const char *name)
static struct cmd basic_cmds[] = {
DEF_CMD("up", IFF_UP, setifflags),
- DEF_CMD("down", -IFF_UP, setifflags),
- DEF_CMD("arp", -IFF_NOARP, setifflags),
+ DEF_CMD("down", IFF_UP, clearifflags),
+ DEF_CMD("arp", IFF_NOARP, clearifflags),
DEF_CMD("-arp", IFF_NOARP, setifflags),
DEF_CMD("debug", IFF_DEBUG, setifflags),
- DEF_CMD("-debug", -IFF_DEBUG, setifflags),
+ DEF_CMD("-debug", IFF_DEBUG, clearifflags),
DEF_CMD_ARG("description", setifdescr),
DEF_CMD_ARG("descr", setifdescr),
DEF_CMD("-description", 0, unsetifdescr),
DEF_CMD("-descr", 0, unsetifdescr),
+ DEF_CMD("allmulti", IFF_PALLMULTI, setifflags),
+ DEF_CMD("-allmulti", IFF_PALLMULTI, clearifflags),
DEF_CMD("promisc", IFF_PPROMISC, setifflags),
- DEF_CMD("-promisc", -IFF_PPROMISC, setifflags),
+ DEF_CMD("-promisc", IFF_PPROMISC, clearifflags),
DEF_CMD("add", IFF_UP, notealias),
DEF_CMD("alias", IFF_UP, notealias),
DEF_CMD("-alias", -IFF_UP, notealias),
DEF_CMD("delete", -IFF_UP, notealias),
DEF_CMD("remove", -IFF_UP, notealias),
-#ifdef notdef
-#define EN_SWABIPS 0x1000
- DEF_CMD("swabips", EN_SWABIPS, setifflags),
- DEF_CMD("-swabips", -EN_SWABIPS, setifflags),
-#endif
DEF_CMD_ARG("netmask", setifnetmask),
DEF_CMD_ARG("metric", setifmetric),
DEF_CMD_ARG("broadcast", setifbroadaddr),
@@ -1760,64 +2100,66 @@ static struct cmd basic_cmds[] = {
DEF_CMD_ARG("-vnet", setifrvnet),
#endif
DEF_CMD("link0", IFF_LINK0, setifflags),
- DEF_CMD("-link0", -IFF_LINK0, setifflags),
+ DEF_CMD("-link0", IFF_LINK0, clearifflags),
DEF_CMD("link1", IFF_LINK1, setifflags),
- DEF_CMD("-link1", -IFF_LINK1, setifflags),
+ DEF_CMD("-link1", IFF_LINK1, clearifflags),
DEF_CMD("link2", IFF_LINK2, setifflags),
- DEF_CMD("-link2", -IFF_LINK2, setifflags),
+ DEF_CMD("-link2", IFF_LINK2, clearifflags),
DEF_CMD("monitor", IFF_MONITOR, setifflags),
- DEF_CMD("-monitor", -IFF_MONITOR, setifflags),
+ DEF_CMD("-monitor", IFF_MONITOR, clearifflags),
DEF_CMD("mextpg", IFCAP_MEXTPG, setifcap),
- DEF_CMD("-mextpg", -IFCAP_MEXTPG, setifcap),
+ DEF_CMD("-mextpg", IFCAP_MEXTPG, clearifcap),
DEF_CMD("staticarp", IFF_STATICARP, setifflags),
- DEF_CMD("-staticarp", -IFF_STATICARP, setifflags),
+ DEF_CMD("-staticarp", IFF_STATICARP, clearifflags),
DEF_CMD("stickyarp", IFF_STICKYARP, setifflags),
- DEF_CMD("-stickyarp", -IFF_STICKYARP, setifflags),
+ DEF_CMD("-stickyarp", IFF_STICKYARP, clearifflags),
DEF_CMD("rxcsum6", IFCAP_RXCSUM_IPV6, setifcap),
- DEF_CMD("-rxcsum6", -IFCAP_RXCSUM_IPV6, setifcap),
+ DEF_CMD("-rxcsum6", IFCAP_RXCSUM_IPV6, clearifcap),
DEF_CMD("txcsum6", IFCAP_TXCSUM_IPV6, setifcap),
- DEF_CMD("-txcsum6", -IFCAP_TXCSUM_IPV6, setifcap),
+ DEF_CMD("-txcsum6", IFCAP_TXCSUM_IPV6, clearifcap),
DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap),
- DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap),
+ DEF_CMD("-rxcsum", IFCAP_RXCSUM, clearifcap),
DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap),
- DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap),
+ DEF_CMD("-txcsum", IFCAP_TXCSUM, clearifcap),
DEF_CMD("netcons", IFCAP_NETCONS, setifcap),
- DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap),
+ DEF_CMD("-netcons", IFCAP_NETCONS, clearifcap),
DEF_CMD_ARG("pcp", setifpcp),
DEF_CMD("-pcp", 0, disableifpcp),
DEF_CMD("polling", IFCAP_POLLING, setifcap),
- DEF_CMD("-polling", -IFCAP_POLLING, setifcap),
+ DEF_CMD("-polling", IFCAP_POLLING, clearifcap),
DEF_CMD("tso6", IFCAP_TSO6, setifcap),
- DEF_CMD("-tso6", -IFCAP_TSO6, setifcap),
+ DEF_CMD("-tso6", IFCAP_TSO6, clearifcap),
DEF_CMD("tso4", IFCAP_TSO4, setifcap),
- DEF_CMD("-tso4", -IFCAP_TSO4, setifcap),
+ DEF_CMD("-tso4", IFCAP_TSO4, clearifcap),
DEF_CMD("tso", IFCAP_TSO, setifcap),
- DEF_CMD("-tso", -IFCAP_TSO, setifcap),
+ DEF_CMD("-tso", IFCAP_TSO, clearifcap),
DEF_CMD("toe", IFCAP_TOE, setifcap),
- DEF_CMD("-toe", -IFCAP_TOE, setifcap),
+ DEF_CMD("-toe", IFCAP_TOE, clearifcap),
DEF_CMD("lro", IFCAP_LRO, setifcap),
- DEF_CMD("-lro", -IFCAP_LRO, setifcap),
+ DEF_CMD("-lro", IFCAP_LRO, clearifcap),
DEF_CMD("txtls", IFCAP_TXTLS, setifcap),
- DEF_CMD("-txtls", -IFCAP_TXTLS, setifcap),
+ DEF_CMD("-txtls", IFCAP_TXTLS, clearifcap),
DEF_CMD_SARG("rxtls", IFCAP2_RXTLS4_NAME "," IFCAP2_RXTLS6_NAME,
setifcapnv),
DEF_CMD_SARG("-rxtls", "-"IFCAP2_RXTLS4_NAME ",-" IFCAP2_RXTLS6_NAME,
setifcapnv),
+ DEF_CMD_SARG("ipsec", IFCAP2_IPSEC_OFFLOAD_NAME, setifcapnv),
+ DEF_CMD_SARG("-ipsec", "-"IFCAP2_IPSEC_OFFLOAD_NAME, setifcapnv),
DEF_CMD("wol", IFCAP_WOL, setifcap),
- DEF_CMD("-wol", -IFCAP_WOL, setifcap),
+ DEF_CMD("-wol", IFCAP_WOL, clearifcap),
DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap),
- DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap),
+ DEF_CMD("-wol_ucast", IFCAP_WOL_UCAST, clearifcap),
DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap),
- DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap),
+ DEF_CMD("-wol_mcast", IFCAP_WOL_MCAST, clearifcap),
DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap),
- DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap),
+ DEF_CMD("-wol_magic", IFCAP_WOL_MAGIC, clearifcap),
DEF_CMD("txrtlmt", IFCAP_TXRTLMT, setifcap),
- DEF_CMD("-txrtlmt", -IFCAP_TXRTLMT, setifcap),
+ DEF_CMD("-txrtlmt", IFCAP_TXRTLMT, clearifcap),
DEF_CMD("txtlsrtlmt", IFCAP_TXTLS_RTLMT, setifcap),
- DEF_CMD("-txtlsrtlmt", -IFCAP_TXTLS_RTLMT, setifcap),
+ DEF_CMD("-txtlsrtlmt", IFCAP_TXTLS_RTLMT, clearifcap),
DEF_CMD("hwrxtstmp", IFCAP_HWRXTSTMP, setifcap),
- DEF_CMD("-hwrxtstmp", -IFCAP_HWRXTSTMP, setifcap),
- DEF_CMD("normal", -IFF_LINK0, setifflags),
+ DEF_CMD("-hwrxtstmp", IFCAP_HWRXTSTMP, clearifcap),
+ DEF_CMD("normal", IFF_LINK0, clearifflags),
DEF_CMD("compress", IFF_LINK0, setifflags),
DEF_CMD("noicmp", IFF_LINK1, setifflags),
DEF_CMD_ARG("mtu", setifmtu),
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
index 26f68d67cec2..672020443b8c 100644
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -32,24 +32,42 @@
* SUCH DAMAGE.
*
* so there!
- *
- * $FreeBSD$
*/
#pragma once
#include <libifconfig.h>
+#include <stdbool.h>
+#include <net/if_types.h>
#define __constructor __attribute__((constructor))
+#ifdef WITHOUT_NETLINK
+#define __netlink_used __unused
+#define __netlink_unused
+#else
+#define __netlink_used
+#define __netlink_unused __unused
+#endif
+
struct afswtch;
struct cmd;
+struct snl_state;
+struct ifconfig_args;
+struct ifconfig_context {
+ struct ifconfig_args *args;
+ const struct afswtch *afp;
+ int io_s; /* fd to use for ioctl() */
+ struct snl_state *io_ss; /* NETLINK_ROUTE socket */
+ const char *ifname; /* Current interface name */
+ char _ifname_storage_ioctl[IFNAMSIZ];
+};
+typedef struct ifconfig_context if_ctx;
-typedef void c_func(const char *cmd, int arg, int s, const struct afswtch *afp);
-typedef void c_func2(const char *arg1, const char *arg2, int s,
- const struct afswtch *afp);
-typedef void c_func3(const char *cmd, const char *arg, int s,
- const struct afswtch *afp);
+typedef void c_func(if_ctx *ctx, const char *cmd, int arg);
+typedef void c_func2(if_ctx *ctx, const char *arg1, const char *arg2);
+typedef void c_func3(if_ctx *ctx, const char *cmd, const char *arg);
+typedef int c_funcv(if_ctx *ctx, int argc, const char *const *argv);
struct cmd {
const char *c_name;
@@ -58,28 +76,25 @@ struct cmd {
#define NEXTARG2 0xfffffe /* has 2 following args */
#define OPTARG 0xfffffd /* has optional following arg */
#define SPARAM 0xfffffc /* parameter is string c_sparameter */
+#define ARGVECTOR 0xfffffb /* takes argument vector */
const char *c_sparameter;
union {
c_func *c_func;
c_func2 *c_func2;
c_func3 *c_func3;
+ c_funcv *c_funcv;
} c_u;
int c_iscloneop;
struct cmd *c_next;
};
void cmd_register(struct cmd *);
-typedef void callback_func(int s, void *);
+typedef void callback_func(if_ctx *, void *);
void callback_register(callback_func *, void *);
/*
- * Macros for declaring command functions and initializing entries.
+ * Macros for initializing command handlers.
*/
-#define DECL_CMD_FUNC(name, cmd, arg) \
- void name(const char *cmd, int arg, int s, const struct afswtch *afp)
-#define DECL_CMD_FUNC2(name, arg1, arg2) \
- void name(const char *arg1, const char *arg2, int s, \
- const struct afswtch *afp)
#define DEF_CMD(name, param, func) { \
.c_name = (name), \
@@ -109,6 +124,13 @@ void callback_register(callback_func *, void *);
.c_iscloneop = 0, \
.c_next = NULL, \
}
+#define DEF_CMD_VARG(name, func) { \
+ .c_name = (name), \
+ .c_parameter = ARGVECTOR, \
+ .c_u = { .c_funcv = (func) }, \
+ .c_iscloneop = 0, \
+ .c_next = NULL, \
+}
#define DEF_CMD_SARG(name, sparam, func) { \
.c_name = (name), \
.c_parameter = SPARAM, \
@@ -139,16 +161,39 @@ void callback_register(callback_func *, void *);
.c_next = NULL, \
}
+#define ioctl_ctx(ctx, _req, ...) ioctl((ctx)->io_s, _req, ## __VA_ARGS__)
+int ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr);
+
struct ifaddrs;
struct addrinfo;
enum {
- RIDADDR,
- ADDR,
- MASK,
- DSTADDR,
+ RIDADDR = 0,
+ ADDR = 1,
+ MASK = 2,
+ DSTADDR = 3,
+#ifdef WITHOUT_NETLINK
+ BRDADDR = 3,
+#else
+ BRDADDR = 4,
+#endif
};
+struct snl_parsed_addr;
+struct snl_parsed_link;
+typedef struct snl_parsed_link if_link_t;
+typedef struct snl_parsed_addr if_addr_t;
+
+typedef void af_setvhid_f(int vhid);
+typedef void af_status_nl_f(if_ctx *ctx, if_link_t *link, if_addr_t *ifa);
+typedef void af_status_f(if_ctx *ctx, const struct ifaddrs *);
+typedef void af_other_status_f(if_ctx *ctx);
+typedef void af_postproc_f(if_ctx *ctx, int newaddr, int ifflags);
+typedef int af_exec_f(if_ctx *ctx, unsigned long action, void *data);
+typedef void af_copyaddr_f(if_ctx *ctx, int to, int from);
+typedef void af_status_tunnel_f(if_ctx *ctx);
+typedef void af_settunnel_f(if_ctx *ctx, struct addrinfo *srcres, struct addrinfo *dstres);
+
struct afswtch {
const char *af_name; /* as given on cmd line, e.g. "inet" */
short af_af; /* AF_* */
@@ -161,14 +206,19 @@ struct afswtch {
* is defined then it is invoked after all address status
* is presented.
*/
- void (*af_status)(int, const struct ifaddrs *);
- void (*af_other_status)(int);
- /* parse address method */
+#ifndef WITHOUT_NETLINK
+ af_status_nl_f *af_status;
+#else
+ af_status_f *af_status;
+#endif
+ af_other_status_f *af_other_status;
void (*af_getaddr)(const char *, int);
+ af_copyaddr_f *af_copyaddr; /* Copy address between <RID|*>ADDR */
/* parse prefix method (IPv6) */
void (*af_getprefix)(const char *, int);
- void (*af_postproc)(int s, const struct afswtch *,
- int newaddr, int ifflags);
+ af_postproc_f *af_postproc;
+ af_setvhid_f *af_setvhid; /* Set CARP vhid for an address */
+ af_exec_f *af_exec; /* Handler to interact with kernel */
u_long af_difaddr; /* set dst if address ioctl */
u_long af_aifaddr; /* set if address ioctl */
void *af_ridreq; /* */
@@ -176,11 +226,30 @@ struct afswtch {
struct afswtch *af_next;
/* XXX doesn't fit model */
- void (*af_status_tunnel)(int);
- void (*af_settunnel)(int s, struct addrinfo *srcres,
- struct addrinfo *dstres);
+ af_status_tunnel_f *af_status_tunnel;
+ af_settunnel_f *af_settunnel;
};
void af_register(struct afswtch *);
+int af_exec_ioctl(if_ctx *ctx, unsigned long action, void *data);
+
+struct ifconfig_args {
+ bool all; /* Match everything */
+ bool downonly; /* Down-only items */
+ bool uponly; /* Up-only items */
+ bool namesonly; /* Output only names */
+ bool noload; /* Do not load relevant kernel modules */
+ bool supmedia; /* Supported media */
+ bool printkeys; /* Print security keys */
+ bool allfamilies; /* Print all families */
+ bool drivername; /* Print driver name */
+ int verbose; /* verbosity level */
+ int argc;
+ char **argv;
+ const char *ifname; /* Requested interface name */
+ const char *matchgroup; /* Group name to match */
+ const char *nogroup; /* Group name to exclude */
+ const struct afswtch *afp; /* AF we're operating on */
+};
struct option {
const char *opt;
@@ -191,38 +260,81 @@ struct option {
void opt_register(struct option *);
extern ifconfig_handle_t *lifh;
-extern struct ifreq ifr;
-extern char name[IFNAMSIZ]; /* name of interface */
extern int allmedia;
-extern int supmedia;
-extern int printkeys;
-extern int newaddr;
-extern int verbose;
-extern int printifname;
extern int exit_code;
+extern char *f_inet, *f_inet6, *f_ether, *f_addr;
-void setifcap(const char *, int value, int s, const struct afswtch *);
-void setifcapnv(const char *vname, const char *arg, int s,
- const struct afswtch *afp);
+void clearifcap(if_ctx *ctx, const char *, int value);
+void setifcap(if_ctx *ctx, const char *, int value);
+void setifcapnv(if_ctx *ctx, const char *vname, const char *arg);
void Perror(const char *cmd);
+void print_bits(const char *btype, uint32_t *v, const int v_count,
+ const char **names, const int n_count);
void printb(const char *s, unsigned value, const char *bits);
-void ifmaybeload(const char *name);
+void ifmaybeload(struct ifconfig_args *args, const char *name);
typedef int clone_match_func(const char *);
-typedef void clone_callback_func(int, struct ifreq *);
+typedef void clone_callback_func(if_ctx *, struct ifreq *);
void clone_setdefcallback_prefix(const char *, clone_callback_func *);
void clone_setdefcallback_filter(clone_match_func *, clone_callback_func *);
-void sfp_status(int s, struct ifreq *ifr, int verbose);
+void sfp_status(if_ctx *ctx);
+
+struct sockaddr_dl;
+bool match_ether(const struct sockaddr_dl *sdl);
+bool match_if_flags(struct ifconfig_args *args, int if_flags);
+int ifconfig_ioctl(if_ctx *ctx, int iscreate, const struct afswtch *uafp);
+bool group_member(const char *ifname, const char *match, const char *nomatch);
+void tunnel_status(if_ctx *ctx);
+struct afswtch *af_getbyfamily(int af);
+void af_other_status(if_ctx *ctx);
+void print_ifstatus(if_ctx *ctx);
+void print_metric(if_ctx *ctx);
+ifType convert_iftype(ifType iftype);
+
+/* Netlink-related functions */
+void list_interfaces_nl(struct ifconfig_args *args);
+int ifconfig_nl(if_ctx *ctx, int iscreate,
+ const struct afswtch *uafp);
+uint32_t if_nametoindex_nl(struct snl_state *ss, const char *ifname);
/*
- * XXX expose this so modules that neeed to know of any pending
+ * XXX expose this so modules that need to know of any pending
* operations on ifmedia can avoid cmd line ordering confusion.
*/
-struct ifmediareq *ifmedia_getstate(void);
+struct ifmediareq *ifmedia_getstate(if_ctx *ctx);
+
+void print_vhid(const struct ifaddrs *);
-void print_vhid(const struct ifaddrs *, const char *);
+void ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr);
+
+/* Helpers */
+struct sockaddr_in;
+struct sockaddr_in6;
+struct sockaddr;
+
+static inline struct sockaddr_in6 *
+satosin6(struct sockaddr *sa)
+{
+ return ((struct sockaddr_in6 *)(void *)sa);
+}
-void ioctl_ifcreate(int s, struct ifreq *);
+static inline struct sockaddr_in *
+satosin(struct sockaddr *sa)
+{
+ return ((struct sockaddr_in *)(void *)sa);
+}
+
+static inline struct sockaddr_dl *
+satosdl(struct sockaddr *sa)
+{
+ return ((struct sockaddr_dl *)(void *)sa);
+}
+
+static inline const struct sockaddr_dl *
+satosdl_c(const struct sockaddr *sa)
+{
+ return ((const struct sockaddr_dl *)(const void *)sa);
+}
diff --git a/sbin/ifconfig/ifconfig_netlink.c b/sbin/ifconfig/ifconfig_netlink.c
new file mode 100644
index 000000000000..b5badfd585b8
--- /dev/null
+++ b/sbin/ifconfig/ifconfig_netlink.c
@@ -0,0 +1,495 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2022 Alexander V. Chernikov <melifaro@FreeBSD.org>
+ *
+ * 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.
+ */
+
+#define _WANT_IFCAP_BIT_NAMES
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+
+#include <sys/bitcount.h>
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_strings.h>
+#include <net/if_types.h>
+#include "ifconfig.h"
+#include "ifconfig_netlink.h"
+
+static const char *IFFBITS[] = {
+ "UP", /* 00:0x1 IFF_UP*/
+ "BROADCAST", /* 01:0x2 IFF_BROADCAST*/
+ "DEBUG", /* 02:0x4 IFF_DEBUG*/
+ "LOOPBACK", /* 03:0x8 IFF_LOOPBACK*/
+ "POINTOPOINT", /* 04:0x10 IFF_POINTOPOINT*/
+ "NEEDSEPOCH", /* 05:0x20 IFF_NEEDSEPOCH*/
+ "RUNNING", /* 06:0x40 IFF_DRV_RUNNING*/
+ "NOARP", /* 07:0x80 IFF_NOARP*/
+ "PROMISC", /* 08:0x100 IFF_PROMISC*/
+ "ALLMULTI", /* 09:0x200 IFF_ALLMULTI*/
+ "DRV_OACTIVE", /* 10:0x400 IFF_DRV_OACTIVE*/
+ "SIMPLEX", /* 11:0x800 IFF_SIMPLEX*/
+ "LINK0", /* 12:0x1000 IFF_LINK0*/
+ "LINK1", /* 13:0x2000 IFF_LINK1*/
+ "LINK2", /* 14:0x4000 IFF_LINK2*/
+ "MULTICAST", /* 15:0x8000 IFF_MULTICAST*/
+ "CANTCONFIG", /* 16:0x10000 IFF_CANTCONFIG*/
+ "PPROMISC", /* 17:0x20000 IFF_PPROMISC*/
+ "MONITOR", /* 18:0x40000 IFF_MONITOR*/
+ "STATICARP", /* 19:0x80000 IFF_STATICARP*/
+ "STICKYARP", /* 20:0x100000 IFF_STICKYARP*/
+ "DYING", /* 21:0x200000 IFF_DYING*/
+ "RENAMING", /* 22:0x400000 IFF_RENAMING*/
+ "PALLMULTI", /* 23:0x800000 IFF_PALLMULTI*/
+ "LOWER_UP", /* 24:0x1000000 IFF_NETLINK_1*/
+};
+
+static void
+nl_init_socket(struct snl_state *ss)
+{
+ if (snl_init(ss, NETLINK_ROUTE))
+ return;
+
+ if (modfind("netlink") == -1 && errno == ENOENT) {
+ /* Try to load */
+ if (kldload("netlink") == -1)
+ err(1, "netlink is not loaded and load attempt failed");
+ if (snl_init(ss, NETLINK_ROUTE))
+ return;
+ }
+
+ err(1, "unable to open netlink socket");
+}
+
+int
+ifconfig_nl(if_ctx *ctx, int iscreate,
+ const struct afswtch *uafp)
+{
+ struct snl_state ss = {};
+
+ nl_init_socket(&ss);
+ ctx->io_ss = &ss;
+
+ int error = ifconfig_ioctl(ctx, iscreate, uafp);
+
+ snl_free(&ss);
+ ctx->io_ss = NULL;
+
+ return (error);
+}
+
+struct ifa {
+ struct ifa *next;
+ uint32_t idx;
+ struct snl_parsed_addr addr;
+};
+
+struct iface {
+ struct snl_parsed_link link;
+ struct ifa *ifa;
+ uint32_t ifa_count;
+ uint32_t idx;
+};
+
+struct ifmap {
+ uint32_t size;
+ uint32_t count;
+ struct iface **ifaces;
+};
+
+/*
+ * Returns ifmap ifindex->snl_parsed_link.
+ * Memory is allocated using snl temporary buffers
+ */
+static struct ifmap *
+prepare_ifmap(struct snl_state *ss, const char *ifname)
+{
+ struct snl_writer nw = {};
+
+ snl_init_writer(ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK);
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ snl_reserve_msg_object(&nw, struct ifinfomsg);
+ if (ifname != NULL)
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
+ return (NULL);
+
+ uint32_t nlmsg_seq = hdr->nlmsg_seq;
+ struct ifmap *ifmap = snl_allocz(ss, sizeof(*ifmap));
+ struct snl_errmsg_data e = {};
+
+ while ((hdr = snl_read_reply_multi(ss, nlmsg_seq, &e)) != NULL) {
+ struct iface *iface = snl_allocz(ss, sizeof(*iface));
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser, &iface->link))
+ continue;
+ if (iface->link.ifi_index >= ifmap->size) {
+ size_t new_size = MAX(ifmap->size, 32);
+
+ while (new_size <= iface->link.ifi_index + 1)
+ new_size *= 2;
+
+ struct iface **ifaces= snl_allocz(ss, new_size * sizeof(void *));
+ memcpy(ifaces, ifmap->ifaces, ifmap->size * sizeof(void *));
+ ifmap->ifaces = ifaces;
+ ifmap->size = new_size;
+ }
+ ifmap->ifaces[iface->link.ifi_index] = iface;
+ ifmap->count++;
+ iface->idx = ifmap->count;
+ }
+ return (ifmap);
+}
+
+uint32_t
+if_nametoindex_nl(struct snl_state *ss, const char *ifname)
+{
+ struct snl_writer nw = {};
+ struct snl_parsed_link_simple link = {};
+
+ snl_init_writer(ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETLINK);
+ snl_reserve_msg_object(&nw, struct ifinfomsg);
+ snl_add_msg_attr_string(&nw, IFLA_IFNAME, ifname);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
+ return (0);
+
+ hdr = snl_read_reply(ss, hdr->nlmsg_seq);
+ if (hdr->nlmsg_type != NL_RTM_NEWLINK)
+ return (0);
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser_simple, &link))
+ return (0);
+
+ return (link.ifi_index);
+}
+
+ifType
+convert_iftype(ifType iftype)
+{
+ switch (iftype) {
+ case IFT_IEEE8023ADLAG:
+ return (IFT_ETHER);
+ case IFT_INFINIBANDLAG:
+ return (IFT_INFINIBAND);
+ default:
+ return (iftype);
+ }
+}
+
+static void
+prepare_ifaddrs(struct snl_state *ss, struct ifmap *ifmap)
+{
+ struct snl_writer nw = {};
+
+ snl_init_writer(ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, RTM_GETADDR);
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ snl_reserve_msg_object(&nw, struct ifaddrmsg);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
+ return;
+
+ uint32_t nlmsg_seq = hdr->nlmsg_seq;
+ struct snl_errmsg_data e = {};
+ uint32_t count = 0;
+
+ while ((hdr = snl_read_reply_multi(ss, nlmsg_seq, &e)) != NULL) {
+ struct ifa *ifa = snl_allocz(ss, sizeof(*ifa));
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_addr_parser, &ifa->addr))
+ continue;
+
+ const uint32_t ifindex = ifa->addr.ifa_index;
+ if (ifindex >= ifmap->size || ifmap->ifaces[ifindex] == NULL)
+ continue;
+ struct iface *iface = ifmap->ifaces[ifindex];
+ ifa->next = iface->ifa;
+ ifa->idx = ++count;
+ iface->ifa = ifa;
+ iface->ifa_count++;
+ }
+}
+
+static bool
+match_iface(struct ifconfig_args *args, struct iface *iface)
+{
+ if_link_t *link = &iface->link;
+
+ if (args->ifname != NULL && strcmp(args->ifname, link->ifla_ifname))
+ return (false);
+
+ if (!match_if_flags(args, link->ifi_flags))
+ return (false);
+
+ if (!group_member(link->ifla_ifname, args->matchgroup, args->nogroup))
+ return (false);
+
+ if (args->afp == NULL)
+ return (true);
+
+ if (!strcmp(args->afp->af_name, "ether")) {
+ if (link->ifla_address == NULL)
+ return (false);
+
+ struct sockaddr_dl sdl = {
+ .sdl_len = sizeof(struct sockaddr_dl),
+ .sdl_family = AF_LINK,
+ .sdl_type = convert_iftype(link->ifi_type),
+ .sdl_alen = NLA_DATA_LEN(link->ifla_address),
+ };
+ return (match_ether(&sdl));
+ } else if (args->afp->af_af == AF_LINK)
+ /*
+ * The rtnetlink(4) RTM_GETADDR does not list link level
+ * addresses, so latter cycle won't match anything. Short
+ * circuit on RTM_GETLINK has provided us an address.
+ */
+ return (link->ifla_address != NULL);
+
+ for (struct ifa *ifa = iface->ifa; ifa != NULL; ifa = ifa->next) {
+ if (args->afp->af_af == ifa->addr.ifa_family)
+ return (true);
+ }
+
+ return (false);
+}
+
+/* Sort according to the kernel-provided order */
+static int
+cmp_iface(const void *_a, const void *_b)
+{
+ const struct iface *a = *((const void * const *)_a);
+ const struct iface *b = *((const void * const *)_b);
+
+ return ((a->idx > b->idx) * 2 - 1);
+}
+
+static int
+cmp_ifaddr(const void *_a, const void *_b)
+{
+ const struct ifa *a = *((const void * const *)_a);
+ const struct ifa *b = *((const void * const *)_b);
+
+ if (a->addr.ifa_family != b->addr.ifa_family)
+ return ((a->addr.ifa_family > b->addr.ifa_family) * 2 - 1);
+ return ((a->idx > b->idx) * 2 - 1);
+}
+
+static void
+sort_iface_ifaddrs(struct snl_state *ss, struct iface *iface)
+{
+ if (iface->ifa_count == 0)
+ return;
+
+ struct ifa **sorted_ifaddrs = snl_allocz(ss, iface->ifa_count * sizeof(void *));
+ struct ifa *ifa = iface->ifa;
+
+ for (uint32_t i = 0; i < iface->ifa_count; i++) {
+ struct ifa *ifa_next = ifa->next;
+
+ sorted_ifaddrs[i] = ifa;
+ ifa->next = NULL;
+ ifa = ifa_next;
+ }
+ qsort(sorted_ifaddrs, iface->ifa_count, sizeof(void *), cmp_ifaddr);
+ ifa = sorted_ifaddrs[0];
+ iface->ifa = ifa;
+ for (uint32_t i = 1; i < iface->ifa_count; i++) {
+ ifa->next = sorted_ifaddrs[i];
+ ifa = sorted_ifaddrs[i];
+ }
+}
+
+static void
+print_ifcaps(if_ctx *ctx, if_link_t *link)
+{
+ uint32_t sz_u32 = roundup2(link->iflaf_caps.nla_bitset_size, 32) / 32;
+
+ if (sz_u32 > 0) {
+ uint32_t *caps = link->iflaf_caps.nla_bitset_value;
+
+ printf("\toptions=%x", caps[0]);
+ print_bits("IFCAPS", caps, sz_u32, ifcap_bit_names, nitems(ifcap_bit_names));
+ putchar('\n');
+ }
+
+ if (ctx->args->supmedia && sz_u32 > 0) {
+ uint32_t *caps = link->iflaf_caps.nla_bitset_mask;
+
+ printf("\tcapabilities=%x", caps[0]);
+ print_bits("IFCAPS", caps, sz_u32, ifcap_bit_names, nitems(ifcap_bit_names));
+ putchar('\n');
+ }
+}
+
+static void
+status_nl(if_ctx *ctx, struct iface *iface)
+{
+ if_link_t *link = &iface->link;
+ struct ifconfig_args *args = ctx->args;
+ char *drivername = NULL;
+
+ printf("%s: ", link->ifla_ifname);
+
+ printf("flags=%x", link->ifi_flags);
+ print_bits("IFF", &link->ifi_flags, 1, IFFBITS, nitems(IFFBITS));
+
+ print_metric(ctx);
+ printf(" mtu %d\n", link->ifla_mtu);
+
+ if (link->ifla_ifalias != NULL)
+ printf("\tdescription: %s\n", link->ifla_ifalias);
+
+ print_ifcaps(ctx, link);
+ tunnel_status(ctx);
+
+ if (args->allfamilies | (args->afp != NULL && args->afp->af_af == AF_LINK)) {
+ /* Start with link-level */
+ const struct afswtch *p = af_getbyfamily(AF_LINK);
+ if (p != NULL && link->ifla_address != NULL)
+ p->af_status(ctx, link, NULL);
+ }
+
+ sort_iface_ifaddrs(ctx->io_ss, iface);
+
+ for (struct ifa *ifa = iface->ifa; ifa != NULL; ifa = ifa->next) {
+ if (args->allfamilies) {
+ const struct afswtch *p = af_getbyfamily(ifa->addr.ifa_family);
+
+ if (p != NULL)
+ p->af_status(ctx, link, &ifa->addr);
+ } else if (args->afp->af_af == ifa->addr.ifa_family) {
+ const struct afswtch *p = args->afp;
+
+ p->af_status(ctx, link, &ifa->addr);
+ }
+ }
+
+ /* TODO: convert to netlink */
+ if (args->allfamilies)
+ af_other_status(ctx);
+ else if (args->afp->af_other_status != NULL)
+ args->afp->af_other_status(ctx);
+
+ print_ifstatus(ctx);
+ if (args->drivername || args->verbose) {
+ if (ifconfig_get_orig_name(lifh, link->ifla_ifname,
+ &drivername) != 0) {
+ if (ifconfig_err_errtype(lifh) == OTHER)
+ fprintf(stderr, "get original name: %s\n",
+ strerror(ifconfig_err_errno(lifh)));
+ else
+ fprintf(stderr,
+ "get original name: error type %d\n",
+ ifconfig_err_errtype(lifh));
+ exit_code = 1;
+ }
+ if (drivername != NULL)
+ printf("\tdrivername: %s\n", drivername);
+ free(drivername);
+ }
+ if (args->verbose > 0)
+ sfp_status(ctx);
+}
+
+static int
+get_local_socket(void)
+{
+ int s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+
+ if (s < 0)
+ err(1, "socket(family %u,SOCK_DGRAM)", AF_LOCAL);
+ return (s);
+}
+
+void
+list_interfaces_nl(struct ifconfig_args *args)
+{
+ struct snl_state ss = {};
+ struct ifconfig_context _ctx = {
+ .args = args,
+ .io_s = get_local_socket(),
+ .io_ss = &ss,
+ };
+ struct ifconfig_context *ctx = &_ctx;
+
+ nl_init_socket(&ss);
+
+ struct ifmap *ifmap = prepare_ifmap(&ss, args->ifname);
+ struct iface **sorted_ifaces = snl_allocz(&ss, ifmap->count * sizeof(void *));
+ for (uint32_t i = 0, num = 0; i < ifmap->size; i++) {
+ if (ifmap->ifaces[i] != NULL) {
+ sorted_ifaces[num++] = ifmap->ifaces[i];
+ if (num == ifmap->count)
+ break;
+ }
+ }
+ qsort(sorted_ifaces, ifmap->count, sizeof(void *), cmp_iface);
+ prepare_ifaddrs(&ss, ifmap);
+
+ for (uint32_t i = 0, num = 0; i < ifmap->count; i++) {
+ struct iface *iface = sorted_ifaces[i];
+
+ if (!match_iface(args, iface))
+ continue;
+
+ ctx->ifname = iface->link.ifla_ifname;
+
+ if (args->namesonly) {
+ if (num++ != 0)
+ printf(" ");
+ fputs(iface->link.ifla_ifname, stdout);
+ } else if (args->argc == 0)
+ status_nl(ctx, iface);
+ else
+ ifconfig_ioctl(ctx, 0, args->afp);
+ }
+ if (args->namesonly)
+ printf("\n");
+
+ close(ctx->io_s);
+ snl_free(&ss);
+}
+
diff --git a/sbin/ifconfig/ifconfig_netlink.h b/sbin/ifconfig/ifconfig_netlink.h
new file mode 100644
index 000000000000..1c762619a483
--- /dev/null
+++ b/sbin/ifconfig/ifconfig_netlink.h
@@ -0,0 +1,37 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2023 Alexander V. Chernikov <melifaro@FreeBSD.org>
+ *
+ * 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.
+ */
+
+#pragma once
+
+#ifndef WITHOUT_NETLINK
+#include <netlink/netlink.h>
+#include <netlink/netlink_route.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_route.h>
+#include <netlink/netlink_snl_route_compat.h>
+#include <netlink/netlink_snl_route_parsers.h>
+#endif
diff --git a/sbin/ifconfig/iffib.c b/sbin/ifconfig/iffib.c
index 7cb21ce54b09..a99dd6885d08 100644
--- a/sbin/ifconfig/iffib.c
+++ b/sbin/ifconfig/iffib.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2011 Alexander V. Chernikov
* Copyright (c) 2011 Christian S.J. Peron
@@ -26,8 +26,6 @@
* 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>
@@ -46,27 +44,27 @@
#include "ifconfig.h"
static void
-fib_status(int s)
+fib_status(if_ctx *ctx)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIFFIB, (caddr_t)&ifr) == 0 &&
+ strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
+ if (ioctl_ctx(ctx, SIOCGIFFIB, (caddr_t)&ifr) == 0 &&
ifr.ifr_fib != RT_DEFAULT_FIB)
printf("\tfib: %u\n", ifr.ifr_fib);
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGTUNFIB, (caddr_t)&ifr) == 0 &&
+ strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
+ if (ioctl_ctx(ctx, SIOCGTUNFIB, (caddr_t)&ifr) == 0 &&
ifr.ifr_fib != RT_DEFAULT_FIB)
printf("\ttunnelfib: %u\n", ifr.ifr_fib);
}
static void
-setiffib(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+setiffib(if_ctx *ctx, const char *val, int dummy __unused)
{
+ struct ifreq ifr = {};
unsigned long fib;
char *ep;
@@ -76,16 +74,15 @@ setiffib(const char *val, int dummy __unused, int s,
return;
}
- strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
ifr.ifr_fib = fib;
- if (ioctl(s, SIOCSIFFIB, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCSIFFIB, &ifr) < 0)
warn("ioctl (SIOCSIFFIB)");
}
static void
-settunfib(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+settunfib(if_ctx *ctx, const char *val, int dummy __unused)
{
+ struct ifreq ifr = {};
unsigned long fib;
char *ep;
@@ -95,9 +92,8 @@ settunfib(const char *val, int dummy __unused, int s,
return;
}
- strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
ifr.ifr_fib = fib;
- if (ioctl(s, SIOCSTUNFIB, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCSTUNFIB, &ifr) < 0)
warn("ioctl (SIOCSTUNFIB)");
}
diff --git a/sbin/ifconfig/ifgif.c b/sbin/ifconfig/ifgif.c
index b75dd4e0a7dd..9b8be210a59e 100644
--- a/sbin/ifconfig/ifgif.c
+++ b/sbin/ifconfig/ifgif.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2009 Hiroki Sato. All rights reserved.
*
@@ -25,11 +25,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -53,31 +48,33 @@ static const char rcsid[] =
#include "ifconfig.h"
-#define GIFBITS "\020\2IGNORE_SOURCE"
-
-static void gif_status(int);
+static const char *GIFBITS[] = {
+ [0] = "NOCLAMP",
+ [1] = "IGNORE_SOURCE",
+};
static void
-gif_status(int s)
+gif_status(if_ctx *ctx)
{
int opts;
+ struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
- ifr.ifr_data = (caddr_t)&opts;
- if (ioctl(s, GIFGOPTS, &ifr) == -1)
+ if (ioctl_ctx_ifr(ctx, GIFGOPTS, &ifr) == -1)
return;
if (opts == 0)
return;
- printb("\toptions", opts, GIFBITS);
+ printf("\toptions=%x", opts);
+ print_bits("options", &opts, 1, GIFBITS, nitems(GIFBITS));
putchar('\n');
}
static void
-setgifopts(const char *val, int d, int s, const struct afswtch *afp)
+setgifopts(if_ctx *ctx, const char *val __unused, int d)
{
int opts;
+ struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
- ifr.ifr_data = (caddr_t)&opts;
- if (ioctl(s, GIFGOPTS, &ifr) == -1) {
+ if (ioctl_ctx_ifr(ctx, GIFGOPTS, &ifr) == -1) {
warn("ioctl(GIFGOPTS)");
return;
}
@@ -87,13 +84,15 @@ setgifopts(const char *val, int d, int s, const struct afswtch *afp)
else
opts |= d;
- if (ioctl(s, GIFSOPTS, &ifr) == -1) {
+ if (ioctl_ctx(ctx, GIFSOPTS, &ifr) == -1) {
warn("ioctl(GIFSOPTS)");
return;
}
}
static struct cmd gif_cmds[] = {
+ DEF_CMD("noclamp", GIF_NOCLAMP, setgifopts),
+ DEF_CMD("-noclamp", -GIF_NOCLAMP, setgifopts),
DEF_CMD("ignore_source", GIF_IGNORE_SOURCE, setgifopts),
DEF_CMD("-ignore_source", -GIF_IGNORE_SOURCE, setgifopts),
};
diff --git a/sbin/ifconfig/ifgre.c b/sbin/ifconfig/ifgre.c
index d6fc0d5b53a2..43c86a546167 100644
--- a/sbin/ifconfig/ifgre.c
+++ b/sbin/ifconfig/ifgre.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2008 Andrew Thompson. All rights reserved.
*
@@ -25,9 +25,6 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -44,63 +41,62 @@ __FBSDID("$FreeBSD$");
#include "ifconfig.h"
-#define GREBITS "\020\01ENABLE_CSUM\02ENABLE_SEQ\03UDPENCAP"
-
-static void gre_status(int s);
+static const char *GREBITS[] = {
+ [0] = "ENABLE_CSUM",
+ [1] = "ENABLE_SEQ",
+ [2] = "UDPENCAP",
+};
static void
-gre_status(int s)
+gre_status(if_ctx *ctx)
{
- uint32_t opts, port;
+ uint32_t opts = 0, port;
+ struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
- opts = 0;
- ifr.ifr_data = (caddr_t)&opts;
- if (ioctl(s, GREGKEY, &ifr) == 0)
+ if (ioctl_ctx(ctx, GREGKEY, &ifr) == 0)
if (opts != 0)
printf("\tgrekey: 0x%x (%u)\n", opts, opts);
opts = 0;
- if (ioctl(s, GREGOPTS, &ifr) != 0 || opts == 0)
+ if (ioctl_ctx(ctx, GREGOPTS, &ifr) != 0 || opts == 0)
return;
port = 0;
ifr.ifr_data = (caddr_t)&port;
- if (ioctl(s, GREGPORT, &ifr) == 0 && port != 0)
+ if (ioctl_ctx_ifr(ctx, GREGPORT, &ifr) == 0 && port != 0)
printf("\tudpport: %u\n", port);
- printb("\toptions", opts, GREBITS);
+ printf("\toptions=%x", opts);
+ print_bits("options", &opts, 1, GREBITS, nitems(GREBITS));
putchar('\n');
}
static void
-setifgrekey(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+setifgrekey(if_ctx *ctx, const char *val, int dummy __unused)
{
uint32_t grekey = strtol(val, NULL, 0);
+ struct ifreq ifr = { .ifr_data = (caddr_t)&grekey };
- strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
ifr.ifr_data = (caddr_t)&grekey;
- if (ioctl(s, GRESKEY, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, GRESKEY, &ifr) < 0)
warn("ioctl (set grekey)");
}
static void
-setifgreport(const char *val, int dummy __unused, int s,
- const struct afswtch *afp)
+setifgreport(if_ctx *ctx, const char *val, int dummy __unused)
{
uint32_t udpport = strtol(val, NULL, 0);
+ struct ifreq ifr = { .ifr_data = (caddr_t)&udpport };
- strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
- ifr.ifr_data = (caddr_t)&udpport;
- if (ioctl(s, GRESPORT, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, GRESPORT, &ifr) < 0)
warn("ioctl (set udpport)");
}
static void
-setifgreopts(const char *val, int d, int s, const struct afswtch *afp)
+setifgreopts(if_ctx *ctx, const char *val __unused, int d)
{
uint32_t opts;
+ struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
- ifr.ifr_data = (caddr_t)&opts;
- if (ioctl(s, GREGOPTS, &ifr) == -1) {
+ if (ioctl_ctx_ifr(ctx, GREGOPTS, &ifr) == -1) {
warn("ioctl(GREGOPTS)");
return;
}
@@ -110,7 +106,7 @@ setifgreopts(const char *val, int d, int s, const struct afswtch *afp)
else
opts |= d;
- if (ioctl(s, GRESOPTS, &ifr) == -1) {
+ if (ioctl_ctx(ctx, GRESOPTS, &ifr) == -1) {
warn("ioctl(GIFSOPTS)");
return;
}
diff --git a/sbin/ifconfig/ifgroup.c b/sbin/ifconfig/ifgroup.c
index 7f1173c316d7..49cce678bb5e 100644
--- a/sbin/ifconfig/ifgroup.c
+++ b/sbin/ifconfig/ifgroup.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2006 Max Laier. All rights reserved.
*
@@ -25,11 +25,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -47,49 +42,45 @@ static const char rcsid[] =
#include "ifconfig.h"
-/* ARGSUSED */
static void
-setifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
+setifgroup(if_ctx *ctx, const char *group_name, int dummy __unused)
{
- struct ifgroupreq ifgr;
+ struct ifgroupreq ifgr = {};
- memset(&ifgr, 0, sizeof(ifgr));
- strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+ strlcpy(ifgr.ifgr_name, ctx->ifname, IFNAMSIZ);
if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
errx(1, "setifgroup: group names may not end in a digit");
if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
errx(1, "setifgroup: group name too long");
- if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST)
+ if (ioctl_ctx(ctx, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST)
err(1," SIOCAIFGROUP");
}
-/* ARGSUSED */
static void
-unsetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
+unsetifgroup(if_ctx *ctx, const char *group_name, int dummy __unused)
{
- struct ifgroupreq ifgr;
+ struct ifgroupreq ifgr = {};
- memset(&ifgr, 0, sizeof(ifgr));
- strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+ strlcpy(ifgr.ifgr_name, ctx->ifname, IFNAMSIZ);
if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
errx(1, "unsetifgroup: group names may not end in a digit");
if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
errx(1, "unsetifgroup: group name too long");
- if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT)
+ if (ioctl_ctx(ctx, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT)
err(1, "SIOCDIFGROUP");
}
static void
-getifgroups(int s)
+getifgroups(if_ctx *ctx)
{
struct ifgroupreq ifgr;
size_t cnt;
- if (ifconfig_get_groups(lifh, name, &ifgr) == -1)
+ if (ifconfig_get_groups(lifh, ctx->ifname, &ifgr) == -1)
return;
cnt = 0;
@@ -114,7 +105,7 @@ printgroup(const char *groupname)
{
struct ifgroupreq ifgr;
struct ifg_req *ifg;
- int len, cnt = 0;
+ unsigned int len;
int s;
s = socket(AF_LOCAL, SOCK_DGRAM, 0);
@@ -140,7 +131,6 @@ printgroup(const char *groupname)
ifg++) {
len -= sizeof(struct ifg_req);
printf("%s\n", ifg->ifgrq_member);
- cnt++;
}
free(ifgr.ifgr_groups);
@@ -151,19 +141,23 @@ static struct cmd group_cmds[] = {
DEF_CMD_ARG("group", setifgroup),
DEF_CMD_ARG("-group", unsetifgroup),
};
+
static struct afswtch af_group = {
.af_name = "af_group",
.af_af = AF_UNSPEC,
.af_other_status = getifgroups,
};
-static struct option group_gopt = { "g:", "[-g groupname]", printgroup };
+
+static struct option group_gopt = {
+ .opt = "g:",
+ .opt_usage = "[-g groupname]",
+ .cb = printgroup,
+};
static __constructor void
group_ctor(void)
{
- int i;
-
- for (i = 0; i < nitems(group_cmds); i++)
+ for (size_t i = 0; i < nitems(group_cmds); i++)
cmd_register(&group_cmds[i]);
af_register(&af_group);
opt_register(&group_gopt);
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
index ee611a14b45e..e73dcc2c4f24 100644
--- a/sbin/ifconfig/ifieee80211.c
+++ b/sbin/ifconfig/ifieee80211.c
@@ -25,8 +25,6 @@
* 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$
*/
/*-
@@ -72,6 +70,7 @@
#include <net/if_media.h>
#include <net/route.h>
+#define WANT_NET80211 1
#include <net80211/ieee80211_ioctl.h>
#include <net80211/ieee80211_freebsd.h>
#include <net80211/ieee80211_superg.h>
@@ -134,8 +133,10 @@
#define IEEE80211_FVHT_VHT 0x000000001 /* CONF: VHT supported */
#define IEEE80211_FVHT_USEVHT40 0x000000002 /* CONF: Use VHT40 */
#define IEEE80211_FVHT_USEVHT80 0x000000004 /* CONF: Use VHT80 */
-#define IEEE80211_FVHT_USEVHT160 0x000000008 /* CONF: Use VHT160 */
-#define IEEE80211_FVHT_USEVHT80P80 0x000000010 /* CONF: Use VHT 80+80 */
+#define IEEE80211_FVHT_USEVHT80P80 0x000000008 /* CONF: Use VHT 80+80 */
+#define IEEE80211_FVHT_USEVHT160 0x000000010 /* CONF: Use VHT160 */
+#define IEEE80211_FVHT_STBC_TX 0x00000020 /* CONF: STBC tx enabled */
+#define IEEE80211_FVHT_STBC_RX 0x00000040 /* CONF: STBC rx enabled */
#endif
/* Helper macros unified. */
@@ -173,17 +174,17 @@ static const char *modename[IEEE80211_MODE_MAX] = {
[IEEE80211_MODE_VHT_5GHZ] = "11ac",
};
-static void set80211(int s, int type, int val, int len, void *data);
-static int get80211(int s, int type, void *data, int len);
-static int get80211len(int s, int type, void *data, int len, int *plen);
-static int get80211val(int s, int type, int *val);
+static void set80211(if_ctx *ctx, int type, int val, int len, void *data);
+static int get80211(if_ctx *ctx, int type, void *data, int len);
+static int get80211len(if_ctx *ctx, int type, void *data, int len, int *plen);
+static int get80211val(if_ctx *ctx, int type, int *val);
static const char *get_string(const char *val, const char *sep,
u_int8_t *buf, int *lenp);
static void print_string(const u_int8_t *buf, int len);
static void print_regdomain(const struct ieee80211_regdomain *, int);
-static void print_channels(int, const struct ieee80211req_chaninfo *,
+static void print_channels(if_ctx *, const struct ieee80211req_chaninfo *,
int allchans, int verbose);
-static void regdomain_makechannels(struct ieee80211_regdomain_req *,
+static void regdomain_makechannels(if_ctx *, struct ieee80211_regdomain_req *,
const struct ieee80211_devcaps_req *);
static const char *mesh_linkstate_string(uint8_t state);
@@ -196,30 +197,32 @@ static struct ieee80211_txparams_req txparams;
static int gottxparams = 0;
static struct ieee80211_channel curchan;
static int gotcurchan = 0;
-static struct ifmediareq *ifmr;
+static struct ifmediareq *global_ifmr;
+
+/* HT */
static int htconf = 0;
-static int gothtconf = 0;
+static int gothtconf = 0;
static void
-gethtconf(int s)
+gethtconf(if_ctx *ctx)
{
if (gothtconf)
return;
- if (get80211val(s, IEEE80211_IOC_HTCONF, &htconf) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_HTCONF, &htconf) < 0)
warn("unable to get HT configuration information");
gothtconf = 1;
}
/* VHT */
static int vhtconf = 0;
-static int gotvhtconf = 0;
+static int gotvhtconf = 0;
static void
-getvhtconf(int s)
+getvhtconf(if_ctx *ctx)
{
if (gotvhtconf)
return;
- if (get80211val(s, IEEE80211_IOC_VHTCONF, &vhtconf) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_VHTCONF, &vhtconf) < 0)
warn("unable to get VHT configuration information");
gotvhtconf = 1;
}
@@ -229,19 +232,19 @@ getvhtconf(int s)
* to handle mapping between frequency and IEEE channel number.
*/
static void
-getchaninfo(int s)
+getchaninfo(if_ctx *ctx)
{
if (chaninfo != NULL)
return;
chaninfo = malloc(IEEE80211_CHANINFO_SIZE(MAXCHAN));
if (chaninfo == NULL)
errx(1, "no space for channel list");
- if (get80211(s, IEEE80211_IOC_CHANINFO, chaninfo,
+ if (get80211(ctx, IEEE80211_IOC_CHANINFO, chaninfo,
IEEE80211_CHANINFO_SIZE(MAXCHAN)) < 0)
err(1, "unable to get channel information");
- ifmr = ifmedia_getstate();
- gethtconf(s);
- getvhtconf(s);
+ global_ifmr = ifmedia_getstate(ctx);
+ gethtconf(ctx);
+ getvhtconf(ctx);
}
static struct regdata *
@@ -264,7 +267,7 @@ getregdata(void)
* 11b > 11g.
*/
static int
-canpromote(int i, int from, int to)
+canpromote(unsigned int i, uint32_t from, uint32_t to)
{
const struct ieee80211_channel *fc = &chaninfo->ic_chans[i];
u_int j;
@@ -301,7 +304,7 @@ canpromote(int i, int from, int to)
* XXX VHT
*/
static int
-promote(int i)
+promote(unsigned int i)
{
/*
* Query the current mode of the interface in case it's
@@ -317,7 +320,7 @@ promote(int i)
* the socket descriptor down to here so we can make
* the ifmedia_getstate call ourselves.
*/
- int chanmode = ifmr != NULL ? IFM_MODE(ifmr->ifm_current) : IFM_AUTO;
+ int chanmode = global_ifmr != NULL ? IFM_MODE(global_ifmr->ifm_current) : IFM_AUTO;
/* when ambiguous promote to ``best'' */
/* NB: we abitrarily pick HT40+ over HT40- */
@@ -347,7 +350,7 @@ promote(int i)
}
static void
-mapfreq(struct ieee80211_channel *chan, int freq, int flags)
+mapfreq(struct ieee80211_channel *chan, uint16_t freq, unsigned int flags)
{
u_int i;
@@ -367,7 +370,7 @@ mapfreq(struct ieee80211_channel *chan, int freq, int flags)
}
static void
-mapchan(struct ieee80211_channel *chan, int ieee, int flags)
+mapchan(struct ieee80211_channel *chan, uint8_t ieee, unsigned int flags)
{
u_int i;
@@ -387,16 +390,16 @@ mapchan(struct ieee80211_channel *chan, int ieee, int flags)
}
static const struct ieee80211_channel *
-getcurchan(int s)
+getcurchan(if_ctx *ctx)
{
if (gotcurchan)
return &curchan;
- if (get80211(s, IEEE80211_IOC_CURCHAN, &curchan, sizeof(curchan)) < 0) {
+ if (get80211(ctx, IEEE80211_IOC_CURCHAN, &curchan, sizeof(curchan)) < 0) {
int val;
/* fall back to legacy ioctl */
- if (get80211val(s, IEEE80211_IOC_CHANNEL, &val) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_CHANNEL, &val) < 0)
err(-1, "cannot figure out current channel");
- getchaninfo(s);
+ getchaninfo(ctx);
mapchan(&curchan, val, 0);
}
gotcurchan = 1;
@@ -436,62 +439,62 @@ chan2mode(const struct ieee80211_channel *c)
}
static void
-getroam(int s)
+getroam(if_ctx *ctx)
{
if (gotroam)
return;
- if (get80211(s, IEEE80211_IOC_ROAM,
+ if (get80211(ctx, IEEE80211_IOC_ROAM,
&roamparams, sizeof(roamparams)) < 0)
err(1, "unable to get roaming parameters");
gotroam = 1;
}
static void
-setroam_cb(int s, void *arg)
+setroam_cb(if_ctx *ctx, void *arg)
{
struct ieee80211_roamparams_req *roam = arg;
- set80211(s, IEEE80211_IOC_ROAM, 0, sizeof(*roam), roam);
+ set80211(ctx, IEEE80211_IOC_ROAM, 0, sizeof(*roam), roam);
}
static void
-gettxparams(int s)
+gettxparams(if_ctx *ctx)
{
if (gottxparams)
return;
- if (get80211(s, IEEE80211_IOC_TXPARAMS,
+ if (get80211(ctx, IEEE80211_IOC_TXPARAMS,
&txparams, sizeof(txparams)) < 0)
err(1, "unable to get transmit parameters");
gottxparams = 1;
}
static void
-settxparams_cb(int s, void *arg)
+settxparams_cb(if_ctx *ctx, void *arg)
{
struct ieee80211_txparams_req *txp = arg;
- set80211(s, IEEE80211_IOC_TXPARAMS, 0, sizeof(*txp), txp);
+ set80211(ctx, IEEE80211_IOC_TXPARAMS, 0, sizeof(*txp), txp);
}
static void
-getregdomain(int s)
+getregdomain(if_ctx *ctx)
{
if (gotregdomain)
return;
- if (get80211(s, IEEE80211_IOC_REGDOMAIN,
+ if (get80211(ctx, IEEE80211_IOC_REGDOMAIN,
&regdomain, sizeof(regdomain)) < 0)
err(1, "unable to get regulatory domain info");
gotregdomain = 1;
}
static void
-getdevcaps(int s, struct ieee80211_devcaps_req *dc)
+getdevcaps(if_ctx *ctx, struct ieee80211_devcaps_req *dc)
{
- if (get80211(s, IEEE80211_IOC_DEVCAPS, dc,
+ if (get80211(ctx, IEEE80211_IOC_DEVCAPS, dc,
IEEE80211_DEVCAPS_SPACE(dc)) < 0)
err(1, "unable to get device capabilities");
}
static void
-setregdomain_cb(int s, void *arg)
+setregdomain_cb(if_ctx *ctx, void *arg)
{
struct ieee80211_regdomain_req *req;
struct ieee80211_regdomain *rd = arg;
@@ -545,7 +548,7 @@ setregdomain_cb(int s, void *arg)
if (dc == NULL)
errx(1, "no space for device capabilities");
dc->dc_chaninfo.ic_nchans = MAXCHAN;
- getdevcaps(s, dc);
+ getdevcaps(ctx, dc);
#if 0
if (verbose) {
printf("drivercaps: 0x%x\n", dc->dc_drivercaps);
@@ -563,8 +566,8 @@ setregdomain_cb(int s, void *arg)
if (req == NULL)
errx(1, "no space for regdomain request");
req->rd = *rd;
- regdomain_makechannels(req, dc);
- if (verbose) {
+ regdomain_makechannels(ctx, req, dc);
+ if (ctx->args->verbose) {
LINE_INIT(':');
print_regdomain(rd, 1/*verbose*/);
LINE_BREAK();
@@ -576,11 +579,11 @@ setregdomain_cb(int s, void *arg)
errx(1, "no space for channel list");
memcpy(chaninfo, &req->chaninfo,
IEEE80211_CHANINFO_SPACE(&req->chaninfo));
- print_channels(s, &req->chaninfo, 1/*allchans*/, 1/*verbose*/);
+ print_channels(ctx, &req->chaninfo, 1/*allchans*/, 1/*verbose*/);
}
if (req->chaninfo.ic_nchans == 0)
errx(1, "no channels calculated");
- set80211(s, IEEE80211_IOC_REGDOMAIN, 0,
+ set80211(ctx, IEEE80211_IOC_REGDOMAIN, 0,
IEEE80211_REGDOMAIN_SPACE(req), req);
free(req);
free(dc);
@@ -602,7 +605,7 @@ isanyarg(const char *arg)
}
static void
-set80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
+set80211ssid(if_ctx *ctx, const char *val, int dummy __unused)
{
int ssid;
int len;
@@ -620,11 +623,11 @@ set80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
if (get_string(val, NULL, data, &len) == NULL)
exit(1);
- set80211(s, IEEE80211_IOC_SSID, ssid, len, data);
+ set80211(ctx, IEEE80211_IOC_SSID, ssid, len, data);
}
static void
-set80211meshid(const char *val, int d, int s, const struct afswtch *rafp)
+set80211meshid(if_ctx *ctx, const char *val, int dummy __unused)
{
int len;
u_int8_t data[IEEE80211_NWID_LEN];
@@ -634,11 +637,11 @@ set80211meshid(const char *val, int d, int s, const struct afswtch *rafp)
if (get_string(val, NULL, data, &len) == NULL)
exit(1);
- set80211(s, IEEE80211_IOC_MESH_ID, 0, len, data);
+ set80211(ctx, IEEE80211_IOC_MESH_ID, 0, len, data);
}
static void
-set80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
+set80211stationname(if_ctx *ctx, const char *val, int dummy __unused)
{
int len;
u_int8_t data[33];
@@ -647,7 +650,7 @@ set80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
len = sizeof(data);
get_string(val, NULL, data, &len);
- set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data);
+ set80211(ctx, IEEE80211_IOC_STATIONNAME, 0, len, data);
}
/*
@@ -662,7 +665,7 @@ set80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
* The result is not validated here; it's assumed to be
* checked against the channel table fetched from the kernel.
*/
-static int
+static unsigned int
getchannelflags(const char *val, int freq)
{
#define _CHAN_HT 0x80000000
@@ -806,9 +809,9 @@ getchannelflags(const char *val, int freq)
}
static void
-getchannel(int s, struct ieee80211_channel *chan, const char *val)
+getchannel(if_ctx *ctx, struct ieee80211_channel *chan, const char *val)
{
- int v, flags;
+ unsigned int v, flags;
char *eptr;
memset(chan, 0, sizeof(*chan));
@@ -816,7 +819,7 @@ getchannel(int s, struct ieee80211_channel *chan, const char *val)
chan->ic_freq = IEEE80211_CHAN_ANY;
return;
}
- getchaninfo(s);
+ getchaninfo(ctx);
errno = 0;
v = strtol(val, &eptr, 10);
if (val[0] == '\0' || val == eptr || errno == ERANGE ||
@@ -833,27 +836,27 @@ getchannel(int s, struct ieee80211_channel *chan, const char *val)
}
static void
-set80211channel(const char *val, int d, int s, const struct afswtch *rafp)
+set80211channel(if_ctx *ctx, const char *val, int dummy __unused)
{
struct ieee80211_channel chan;
- getchannel(s, &chan, val);
- set80211(s, IEEE80211_IOC_CURCHAN, 0, sizeof(chan), &chan);
+ getchannel(ctx, &chan, val);
+ set80211(ctx, IEEE80211_IOC_CURCHAN, 0, sizeof(chan), &chan);
}
static void
-set80211chanswitch(const char *val, int d, int s, const struct afswtch *rafp)
+set80211chanswitch(if_ctx *ctx, const char *val, int dummy __unused)
{
struct ieee80211_chanswitch_req csr;
- getchannel(s, &csr.csa_chan, val);
+ getchannel(ctx, &csr.csa_chan, val);
csr.csa_mode = 1;
csr.csa_count = 5;
- set80211(s, IEEE80211_IOC_CHANSWITCH, 0, sizeof(csr), &csr);
+ set80211(ctx, IEEE80211_IOC_CHANSWITCH, 0, sizeof(csr), &csr);
}
static void
-set80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
+set80211authmode(if_ctx *ctx, const char *val, int dummy __unused)
{
int mode;
@@ -871,11 +874,11 @@ set80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
errx(1, "unknown authmode");
}
- set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
}
static void
-set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp)
+set80211powersavemode(if_ctx *ctx, const char *val, int dummy __unused)
{
int mode;
@@ -893,28 +896,28 @@ set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp)
errx(1, "unknown powersavemode");
}
- set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
}
static void
-set80211powersave(const char *val, int d, int s, const struct afswtch *rafp)
+set80211powersave(if_ctx *ctx, const char *val __unused, int d)
{
if (d == 0)
- set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
+ set80211(ctx, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
0, NULL);
else
- set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
+ set80211(ctx, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
0, NULL);
}
static void
-set80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp)
+set80211powersavesleep(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
}
static void
-set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp)
+set80211wepmode(if_ctx *ctx, const char *val, int dummy __unused)
{
int mode;
@@ -928,13 +931,13 @@ set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp)
errx(1, "unknown wep mode");
}
- set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_WEP, mode, 0, NULL);
}
static void
-set80211wep(const char *val, int d, int s, const struct afswtch *rafp)
+set80211wep(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_WEP, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_WEP, d, 0, NULL);
}
static int
@@ -944,16 +947,16 @@ isundefarg(const char *arg)
}
static void
-set80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp)
+set80211weptxkey(if_ctx *ctx, const char *val, int dummy __unused)
{
if (isundefarg(val))
- set80211(s, IEEE80211_IOC_WEPTXKEY, IEEE80211_KEYIX_NONE, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_WEPTXKEY, IEEE80211_KEYIX_NONE, 0, NULL);
else
- set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
}
static void
-set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
+set80211wepkey(if_ctx *ctx, const char *val, int dummy __unused)
{
int key = 0;
int len;
@@ -968,7 +971,7 @@ set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
len = sizeof(data);
get_string(val, NULL, data, &len);
- set80211(s, IEEE80211_IOC_WEPKEY, key, len, data);
+ set80211(ctx, IEEE80211_IOC_WEPKEY, key, len, data);
}
/*
@@ -977,13 +980,13 @@ set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
* it's not all that hard.
*/
static void
-set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
+set80211nwkey(if_ctx *ctx, const char *val, int dummy __unused)
{
int txkey;
int i, len;
u_int8_t data[IEEE80211_KEYBUF_SIZE];
- set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
if (isdigit((int)val[0]) && val[1] == ':') {
txkey = val[0]-'0'-1;
@@ -996,7 +999,7 @@ set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
if (val == NULL)
exit(1);
- set80211(s, IEEE80211_IOC_WEPKEY, i, len, data);
+ set80211(ctx, IEEE80211_IOC_WEPKEY, i, len, data);
}
} else {
bzero(data, sizeof(data));
@@ -1004,25 +1007,25 @@ set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
get_string(val, NULL, data, &len);
txkey = 0;
- set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data);
+ set80211(ctx, IEEE80211_IOC_WEPKEY, 0, len, data);
bzero(data, sizeof(data));
for (i = 1; i < 4; i++)
- set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data);
+ set80211(ctx, IEEE80211_IOC_WEPKEY, i, 0, data);
}
- set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
}
static void
-set80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp)
+set80211rtsthreshold(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_RTSTHRESHOLD,
+ set80211(ctx, IEEE80211_IOC_RTSTHRESHOLD,
isundefarg(val) ? IEEE80211_RTS_MAX : atoi(val), 0, NULL);
}
static void
-set80211protmode(const char *val, int d, int s, const struct afswtch *rafp)
+set80211protmode(if_ctx *ctx, const char *val, int dummy __unused)
{
int mode;
@@ -1036,11 +1039,11 @@ set80211protmode(const char *val, int d, int s, const struct afswtch *rafp)
errx(1, "unknown protection mode");
}
- set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_PROTMODE, mode, 0, NULL);
}
static void
-set80211htprotmode(const char *val, int d, int s, const struct afswtch *rafp)
+set80211htprotmode(if_ctx *ctx, const char *val, int dummy __unused)
{
int mode;
@@ -1052,11 +1055,11 @@ set80211htprotmode(const char *val, int d, int s, const struct afswtch *rafp)
errx(1, "unknown protection mode");
}
- set80211(s, IEEE80211_IOC_HTPROTMODE, mode, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_HTPROTMODE, mode, 0, NULL);
}
static void
-set80211txpower(const char *val, int d, int s, const struct afswtch *rafp)
+set80211txpower(if_ctx *ctx, const char *val, int dummy __unused)
{
double v = atof(val);
int txpow;
@@ -1064,7 +1067,7 @@ set80211txpower(const char *val, int d, int s, const struct afswtch *rafp)
txpow = (int) (2*v);
if (txpow != 2*v)
errx(-1, "invalid tx power (must be .5 dBm units)");
- set80211(s, IEEE80211_IOC_TXPOWER, txpow, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_TXPOWER, txpow, 0, NULL);
}
#define IEEE80211_ROAMING_DEVICE 0
@@ -1072,7 +1075,7 @@ set80211txpower(const char *val, int d, int s, const struct afswtch *rafp)
#define IEEE80211_ROAMING_MANUAL 2
static void
-set80211roaming(const char *val, int d, int s, const struct afswtch *rafp)
+set80211roaming(if_ctx *ctx, const char *val, int dummy __unused)
{
int mode;
@@ -1085,41 +1088,41 @@ set80211roaming(const char *val, int d, int s, const struct afswtch *rafp)
} else {
errx(1, "unknown roaming mode");
}
- set80211(s, IEEE80211_IOC_ROAMING, mode, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_ROAMING, mode, 0, NULL);
}
static void
-set80211wme(const char *val, int d, int s, const struct afswtch *rafp)
+set80211wme(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_WME, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_WME, d, 0, NULL);
}
static void
-set80211hidessid(const char *val, int d, int s, const struct afswtch *rafp)
+set80211hidessid(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_HIDESSID, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_HIDESSID, d, 0, NULL);
}
static void
-set80211apbridge(const char *val, int d, int s, const struct afswtch *rafp)
+set80211apbridge(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_APBRIDGE, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_APBRIDGE, d, 0, NULL);
}
static void
-set80211fastframes(const char *val, int d, int s, const struct afswtch *rafp)
+set80211fastframes(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_FF, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_FF, d, 0, NULL);
}
static void
-set80211dturbo(const char *val, int d, int s, const struct afswtch *rafp)
+set80211dturbo(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_TURBOP, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_TURBOP, d, 0, NULL);
}
static void
-set80211chanlist(const char *val, int d, int s, const struct afswtch *rafp)
+set80211chanlist(if_ctx *ctx, const char *val, int dummy __unused)
{
struct ieee80211req_chanlist chanlist;
char *temp, *cp, *tp;
@@ -1166,14 +1169,13 @@ set80211chanlist(const char *val, int d, int s, const struct afswtch *rafp)
break;
cp = tp;
}
- set80211(s, IEEE80211_IOC_CHANLIST, 0, sizeof(chanlist), &chanlist);
+ set80211(ctx, IEEE80211_IOC_CHANLIST, 0, sizeof(chanlist), &chanlist);
free(temp);
}
static void
-set80211bssid(const char *val, int d, int s, const struct afswtch *rafp)
+set80211bssid(if_ctx *ctx, const char *val, int dummy __unused)
{
-
if (!isanyarg(val)) {
char *temp;
struct sockaddr_dl sdl;
@@ -1188,12 +1190,12 @@ set80211bssid(const char *val, int d, int s, const struct afswtch *rafp)
free(temp);
if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
errx(1, "malformed link-level address");
- set80211(s, IEEE80211_IOC_BSSID, 0,
+ set80211(ctx, IEEE80211_IOC_BSSID, 0,
IEEE80211_ADDR_LEN, LLADDR(&sdl));
} else {
uint8_t zerobssid[IEEE80211_ADDR_LEN];
memset(zerobssid, 0, sizeof(zerobssid));
- set80211(s, IEEE80211_IOC_BSSID, 0,
+ set80211(ctx, IEEE80211_IOC_BSSID, 0,
IEEE80211_ADDR_LEN, zerobssid);
}
}
@@ -1212,94 +1214,95 @@ getac(const char *ac)
errx(1, "unknown wme access class %s", ac);
}
-static
-DECL_CMD_FUNC2(set80211cwmin, ac, val)
+static void
+set80211cwmin(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL);
}
-static
-DECL_CMD_FUNC2(set80211cwmax, ac, val)
+static void
+set80211cwmax(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL);
}
-static
-DECL_CMD_FUNC2(set80211aifs, ac, val)
+static void
+set80211aifs(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL);
}
-static
-DECL_CMD_FUNC2(set80211txoplimit, ac, val)
+static void
+set80211txoplimit(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL);
}
-static
-DECL_CMD_FUNC(set80211acm, ac, d)
+static void
+set80211acm(if_ctx *ctx, const char *ac, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_WME_ACM, 1, getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_ACM, 1, getac(ac), NULL);
}
-static
-DECL_CMD_FUNC(set80211noacm, ac, d)
+
+static void
+set80211noacm(if_ctx *ctx, const char *ac, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_WME_ACM, 0, getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_ACM, 0, getac(ac), NULL);
}
-static
-DECL_CMD_FUNC(set80211ackpolicy, ac, d)
+static void
+set80211ackpolicy(if_ctx *ctx, const char *ac, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 1, getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_ACKPOLICY, 1, getac(ac), NULL);
}
-static
-DECL_CMD_FUNC(set80211noackpolicy, ac, d)
+static void
+set80211noackpolicy(if_ctx *ctx, const char *ac, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 0, getac(ac), NULL);
+ set80211(ctx, IEEE80211_IOC_WME_ACKPOLICY, 0, getac(ac), NULL);
}
-static
-DECL_CMD_FUNC2(set80211bsscwmin, ac, val)
+static void
+set80211bsscwmin(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val),
+ set80211(ctx, IEEE80211_IOC_WME_CWMIN, atoi(val),
getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
}
-static
-DECL_CMD_FUNC2(set80211bsscwmax, ac, val)
+static void
+set80211bsscwmax(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val),
+ set80211(ctx, IEEE80211_IOC_WME_CWMAX, atoi(val),
getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
}
-static
-DECL_CMD_FUNC2(set80211bssaifs, ac, val)
+static void
+set80211bssaifs(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val),
+ set80211(ctx, IEEE80211_IOC_WME_AIFS, atoi(val),
getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
}
-static
-DECL_CMD_FUNC2(set80211bsstxoplimit, ac, val)
+static void
+set80211bsstxoplimit(if_ctx *ctx, const char *ac, const char *val)
{
- set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val),
+ set80211(ctx, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val),
getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
}
-static
-DECL_CMD_FUNC(set80211dtimperiod, val, d)
+static void
+set80211dtimperiod(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211bintval, val, d)
+static void
+set80211bintval(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL);
}
static void
-set80211macmac(int s, int op, const char *val)
+set80211macmac(if_ctx *ctx, int op, const char *val)
{
char *temp;
struct sockaddr_dl sdl;
@@ -1314,23 +1317,23 @@ set80211macmac(int s, int op, const char *val)
free(temp);
if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
errx(1, "malformed link-level address");
- set80211(s, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl));
+ set80211(ctx, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl));
}
-static
-DECL_CMD_FUNC(set80211addmac, val, d)
+static void
+set80211addmac(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211macmac(s, IEEE80211_IOC_ADDMAC, val);
+ set80211macmac(ctx, IEEE80211_IOC_ADDMAC, val);
}
-static
-DECL_CMD_FUNC(set80211delmac, val, d)
+static void
+set80211delmac(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211macmac(s, IEEE80211_IOC_DELMAC, val);
+ set80211macmac(ctx, IEEE80211_IOC_DELMAC, val);
}
-static
-DECL_CMD_FUNC(set80211kickmac, val, d)
+static void
+set80211kickmac(if_ctx *ctx, const char *val, int dummy __unused)
{
char *temp;
struct sockaddr_dl sdl;
@@ -1350,17 +1353,17 @@ DECL_CMD_FUNC(set80211kickmac, val, d)
mlme.im_op = IEEE80211_MLME_DEAUTH;
mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;
memcpy(mlme.im_macaddr, LLADDR(&sdl), IEEE80211_ADDR_LEN);
- set80211(s, IEEE80211_IOC_MLME, 0, sizeof(mlme), &mlme);
+ set80211(ctx, IEEE80211_IOC_MLME, 0, sizeof(mlme), &mlme);
}
-static
-DECL_CMD_FUNC(set80211maccmd, val, d)
+static void
+set80211maccmd(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_MACCMD, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_MACCMD, d, 0, NULL);
}
static void
-set80211meshrtmac(int s, int req, const char *val)
+set80211meshrtmac(if_ctx *ctx, int req, const char *val)
{
char *temp;
struct sockaddr_dl sdl;
@@ -1375,30 +1378,30 @@ set80211meshrtmac(int s, int req, const char *val)
free(temp);
if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
errx(1, "malformed link-level address");
- set80211(s, IEEE80211_IOC_MESH_RTCMD, req,
+ set80211(ctx, IEEE80211_IOC_MESH_RTCMD, req,
IEEE80211_ADDR_LEN, LLADDR(&sdl));
}
-static
-DECL_CMD_FUNC(set80211addmeshrt, val, d)
+static void
+set80211addmeshrt(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211meshrtmac(s, IEEE80211_MESH_RTCMD_ADD, val);
+ set80211meshrtmac(ctx, IEEE80211_MESH_RTCMD_ADD, val);
}
-static
-DECL_CMD_FUNC(set80211delmeshrt, val, d)
+static void
+set80211delmeshrt(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211meshrtmac(s, IEEE80211_MESH_RTCMD_DELETE, val);
+ set80211meshrtmac(ctx, IEEE80211_MESH_RTCMD_DELETE, val);
}
-static
-DECL_CMD_FUNC(set80211meshrtcmd, val, d)
+static void
+set80211meshrtcmd(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_MESH_RTCMD, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_MESH_RTCMD, d, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211hwmprootmode, val, d)
+static void
+set80211hwmprootmode(if_ctx *ctx, const char *val, int dummy __unused)
{
int mode;
@@ -1410,73 +1413,73 @@ DECL_CMD_FUNC(set80211hwmprootmode, val, d)
mode = IEEE80211_HWMP_ROOTMODE_RANN;
else
mode = IEEE80211_HWMP_ROOTMODE_DISABLED;
- set80211(s, IEEE80211_IOC_HWMP_ROOTMODE, mode, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_HWMP_ROOTMODE, mode, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211hwmpmaxhops, val, d)
+static void
+set80211hwmpmaxhops(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_HWMP_MAXHOPS, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_HWMP_MAXHOPS, atoi(val), 0, NULL);
}
static void
-set80211pureg(const char *val, int d, int s, const struct afswtch *rafp)
+set80211pureg(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_PUREG, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_PUREG, d, 0, NULL);
}
static void
-set80211quiet(const char *val, int d, int s, const struct afswtch *rafp)
+set80211quiet(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_QUIET, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_QUIET, d, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211quietperiod, val, d)
+static void
+set80211quietperiod(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_QUIET_PERIOD, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_QUIET_PERIOD, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211quietcount, val, d)
+static void
+set80211quietcount(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_QUIET_COUNT, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_QUIET_COUNT, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211quietduration, val, d)
+static void
+set80211quietduration(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_QUIET_DUR, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_QUIET_DUR, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211quietoffset, val, d)
+static void
+set80211quietoffset(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_QUIET_OFFSET, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_QUIET_OFFSET, atoi(val), 0, NULL);
}
static void
-set80211bgscan(const char *val, int d, int s, const struct afswtch *rafp)
+set80211bgscan(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_BGSCAN, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_BGSCAN, d, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211bgscanidle, val, d)
+static void
+set80211bgscanidle(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_BGSCAN_IDLE, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_BGSCAN_IDLE, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211bgscanintvl, val, d)
+static void
+set80211bgscanintvl(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_BGSCAN_INTERVAL, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_BGSCAN_INTERVAL, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211scanvalid, val, d)
+static void
+set80211scanvalid(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_SCANVALID, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_SCANVALID, atoi(val), 0, NULL);
}
/*
@@ -1615,8 +1618,8 @@ getmodeflags(const char *val)
_APPLY1(_flags, _base, _param, _v); \
} while (0)
-static
-DECL_CMD_FUNC(set80211roamrssi, val, d)
+static void
+set80211roamrssi(if_ctx *ctx, const char *val, int dummy __unused)
{
double v = atof(val);
int rssi, flags;
@@ -1625,9 +1628,9 @@ DECL_CMD_FUNC(set80211roamrssi, val, d)
if (rssi != 2*v)
errx(-1, "invalid rssi (must be .5 dBm units)");
flags = getmodeflags(val);
- getroam(s);
+ getroam(ctx);
if (flags == 0) { /* NB: no flags => current channel */
- flags = getcurchan(s)->ic_flags;
+ flags = getcurchan(ctx)->ic_flags;
_APPLY1(flags, roamparams, rssi, rssi);
} else
_APPLY(flags, roamparams, rssi, rssi);
@@ -1646,64 +1649,64 @@ getrate(const char *val, const char *tag)
return rate; /* NB: returns 2x the specified value */
}
-static
-DECL_CMD_FUNC(set80211roamrate, val, d)
+static void
+set80211roamrate(if_ctx *ctx, const char *val, int dummy __unused)
{
int rate, flags;
rate = getrate(val, "roam");
flags = getmodeflags(val);
- getroam(s);
+ getroam(ctx);
if (flags == 0) { /* NB: no flags => current channel */
- flags = getcurchan(s)->ic_flags;
+ flags = getcurchan(ctx)->ic_flags;
_APPLY_RATE1(flags, roamparams, rate, rate);
} else
_APPLY_RATE(flags, roamparams, rate, rate);
callback_register(setroam_cb, &roamparams);
}
-static
-DECL_CMD_FUNC(set80211mcastrate, val, d)
+static void
+set80211mcastrate(if_ctx *ctx, const char *val, int dummy __unused)
{
int rate, flags;
rate = getrate(val, "mcast");
flags = getmodeflags(val);
- gettxparams(s);
+ gettxparams(ctx);
if (flags == 0) { /* NB: no flags => current channel */
- flags = getcurchan(s)->ic_flags;
+ flags = getcurchan(ctx)->ic_flags;
_APPLY_RATE1(flags, txparams, mcastrate, rate);
} else
_APPLY_RATE(flags, txparams, mcastrate, rate);
callback_register(settxparams_cb, &txparams);
}
-static
-DECL_CMD_FUNC(set80211mgtrate, val, d)
+static void
+set80211mgtrate(if_ctx *ctx, const char *val, int dummy __unused)
{
int rate, flags;
rate = getrate(val, "mgmt");
flags = getmodeflags(val);
- gettxparams(s);
+ gettxparams(ctx);
if (flags == 0) { /* NB: no flags => current channel */
- flags = getcurchan(s)->ic_flags;
+ flags = getcurchan(ctx)->ic_flags;
_APPLY_RATE1(flags, txparams, mgmtrate, rate);
} else
_APPLY_RATE(flags, txparams, mgmtrate, rate);
callback_register(settxparams_cb, &txparams);
}
-static
-DECL_CMD_FUNC(set80211ucastrate, val, d)
+static void
+set80211ucastrate(if_ctx *ctx, const char *val, int dummy __unused)
{
int flags;
- gettxparams(s);
+ gettxparams(ctx);
flags = getmodeflags(val);
if (isanyarg(val)) {
if (flags == 0) { /* NB: no flags => current channel */
- flags = getcurchan(s)->ic_flags;
+ flags = getcurchan(ctx)->ic_flags;
_APPLY1(flags, txparams, ucastrate,
IEEE80211_FIXED_RATE_NONE);
} else
@@ -1712,7 +1715,7 @@ DECL_CMD_FUNC(set80211ucastrate, val, d)
} else {
int rate = getrate(val, "ucast");
if (flags == 0) { /* NB: no flags => current channel */
- flags = getcurchan(s)->ic_flags;
+ flags = getcurchan(ctx)->ic_flags;
_APPLY_RATE1(flags, txparams, ucastrate, rate);
} else
_APPLY_RATE(flags, txparams, ucastrate, rate);
@@ -1720,15 +1723,15 @@ DECL_CMD_FUNC(set80211ucastrate, val, d)
callback_register(settxparams_cb, &txparams);
}
-static
-DECL_CMD_FUNC(set80211maxretry, val, d)
+static void
+set80211maxretry(if_ctx *ctx, const char *val, int dummy __unused)
{
int v = atoi(val), flags;
flags = getmodeflags(val);
- gettxparams(s);
+ gettxparams(ctx);
if (flags == 0) { /* NB: no flags => current channel */
- flags = getcurchan(s)->ic_flags;
+ flags = getcurchan(ctx)->ic_flags;
_APPLY1(flags, txparams, maxretry, v);
} else
_APPLY(flags, txparams, maxretry, v);
@@ -1737,100 +1740,100 @@ DECL_CMD_FUNC(set80211maxretry, val, d)
#undef _APPLY_RATE
#undef _APPLY
-static
-DECL_CMD_FUNC(set80211fragthreshold, val, d)
+static void
+set80211fragthreshold(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_FRAGTHRESHOLD,
+ set80211(ctx, IEEE80211_IOC_FRAGTHRESHOLD,
isundefarg(val) ? IEEE80211_FRAG_MAX : atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211bmissthreshold, val, d)
+static void
+set80211bmissthreshold(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_BMISSTHRESHOLD,
+ set80211(ctx, IEEE80211_IOC_BMISSTHRESHOLD,
isundefarg(val) ? IEEE80211_HWBMISS_MAX : atoi(val), 0, NULL);
}
static void
-set80211burst(const char *val, int d, int s, const struct afswtch *rafp)
+set80211burst(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_BURST, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_BURST, d, 0, NULL);
}
static void
-set80211doth(const char *val, int d, int s, const struct afswtch *rafp)
+set80211doth(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_DOTH, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_DOTH, d, 0, NULL);
}
static void
-set80211dfs(const char *val, int d, int s, const struct afswtch *rafp)
+set80211dfs(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_DFS, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_DFS, d, 0, NULL);
}
static void
-set80211shortgi(const char *val, int d, int s, const struct afswtch *rafp)
+set80211shortgi(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_SHORTGI,
+ set80211(ctx, IEEE80211_IOC_SHORTGI,
d ? (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40) : 0,
0, NULL);
}
/* XXX 11ac density/size is different */
static void
-set80211ampdu(const char *val, int d, int s, const struct afswtch *rafp)
+set80211ampdu(if_ctx *ctx, const char *val __unused, int d)
{
int ampdu;
- if (get80211val(s, IEEE80211_IOC_AMPDU, &ampdu) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_AMPDU, &ampdu) < 0)
errx(-1, "cannot set AMPDU setting");
if (d < 0) {
d = -d;
ampdu &= ~d;
} else
ampdu |= d;
- set80211(s, IEEE80211_IOC_AMPDU, ampdu, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_AMPDU, ampdu, 0, NULL);
}
static void
-set80211stbc(const char *val, int d, int s, const struct afswtch *rafp)
+set80211stbc(if_ctx *ctx, const char *val __unused, int d)
{
int stbc;
- if (get80211val(s, IEEE80211_IOC_STBC, &stbc) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_STBC, &stbc) < 0)
errx(-1, "cannot set STBC setting");
if (d < 0) {
d = -d;
stbc &= ~d;
} else
stbc |= d;
- set80211(s, IEEE80211_IOC_STBC, stbc, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_STBC, stbc, 0, NULL);
}
static void
-set80211ldpc(const char *val, int d, int s, const struct afswtch *rafp)
+set80211ldpc(if_ctx *ctx, const char *val __unused, int d)
{
int ldpc;
- if (get80211val(s, IEEE80211_IOC_LDPC, &ldpc) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_LDPC, &ldpc) < 0)
errx(-1, "cannot set LDPC setting");
if (d < 0) {
d = -d;
ldpc &= ~d;
} else
ldpc |= d;
- set80211(s, IEEE80211_IOC_LDPC, ldpc, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_LDPC, ldpc, 0, NULL);
}
static void
-set80211uapsd(const char *val, int d, int s, const struct afswtch *rafp)
+set80211uapsd(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_UAPSD, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_UAPSD, d, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211ampdulimit, val, d)
+static void
+set80211ampdulimit(if_ctx *ctx, const char *val, int dummy __unused)
{
int v;
@@ -1854,12 +1857,12 @@ DECL_CMD_FUNC(set80211ampdulimit, val, d)
default:
errx(-1, "invalid A-MPDU limit %s", val);
}
- set80211(s, IEEE80211_IOC_AMPDU_LIMIT, v, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_AMPDU_LIMIT, v, 0, NULL);
}
/* XXX 11ac density/size is different */
-static
-DECL_CMD_FUNC(set80211ampdudensity, val, d)
+static void
+set80211ampdudensity(if_ctx *ctx, const char *val, int dummy __unused)
{
int v;
@@ -1893,164 +1896,162 @@ DECL_CMD_FUNC(set80211ampdudensity, val, d)
default:
errx(-1, "invalid A-MPDU density %s", val);
}
- set80211(s, IEEE80211_IOC_AMPDU_DENSITY, v, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_AMPDU_DENSITY, v, 0, NULL);
}
static void
-set80211amsdu(const char *val, int d, int s, const struct afswtch *rafp)
+set80211amsdu(if_ctx *ctx, const char *val __unused, int d)
{
int amsdu;
- if (get80211val(s, IEEE80211_IOC_AMSDU, &amsdu) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_AMSDU, &amsdu) < 0)
err(-1, "cannot get AMSDU setting");
if (d < 0) {
d = -d;
amsdu &= ~d;
} else
amsdu |= d;
- set80211(s, IEEE80211_IOC_AMSDU, amsdu, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_AMSDU, amsdu, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211amsdulimit, val, d)
+static void
+set80211amsdulimit(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_AMSDU_LIMIT, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_AMSDU_LIMIT, atoi(val), 0, NULL);
}
static void
-set80211puren(const char *val, int d, int s, const struct afswtch *rafp)
+set80211puren(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_PUREN, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_PUREN, d, 0, NULL);
}
static void
-set80211htcompat(const char *val, int d, int s, const struct afswtch *rafp)
+set80211htcompat(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_HTCOMPAT, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_HTCOMPAT, d, 0, NULL);
}
static void
-set80211htconf(const char *val, int d, int s, const struct afswtch *rafp)
+set80211htconf(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_HTCONF, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_HTCONF, d, 0, NULL);
htconf = d;
}
static void
-set80211dwds(const char *val, int d, int s, const struct afswtch *rafp)
+set80211dwds(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_DWDS, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_DWDS, d, 0, NULL);
}
static void
-set80211inact(const char *val, int d, int s, const struct afswtch *rafp)
+set80211inact(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_INACTIVITY, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_INACTIVITY, d, 0, NULL);
}
static void
-set80211tsn(const char *val, int d, int s, const struct afswtch *rafp)
+set80211tsn(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_TSN, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_TSN, d, 0, NULL);
}
static void
-set80211dotd(const char *val, int d, int s, const struct afswtch *rafp)
+set80211dotd(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_DOTD, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_DOTD, d, 0, NULL);
}
static void
-set80211smps(const char *val, int d, int s, const struct afswtch *rafp)
+set80211smps(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_SMPS, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_SMPS, d, 0, NULL);
}
static void
-set80211rifs(const char *val, int d, int s, const struct afswtch *rafp)
+set80211rifs(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_RIFS, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_RIFS, d, 0, NULL);
}
static void
-set80211vhtconf(const char *val, int d, int s, const struct afswtch *rafp)
+set80211vhtconf(if_ctx *ctx, const char *val __unused, int d)
{
- if (get80211val(s, IEEE80211_IOC_VHTCONF, &vhtconf) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_VHTCONF, &vhtconf) < 0)
errx(-1, "cannot set VHT setting");
- printf("%s: vhtconf=0x%08x, d=%d\n", __func__, vhtconf, d);
if (d < 0) {
d = -d;
vhtconf &= ~d;
} else
vhtconf |= d;
- printf("%s: vhtconf is now 0x%08x\n", __func__, vhtconf);
- set80211(s, IEEE80211_IOC_VHTCONF, vhtconf, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_VHTCONF, vhtconf, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211tdmaslot, val, d)
+static void
+set80211tdmaslot(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_TDMA_SLOT, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_TDMA_SLOT, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211tdmaslotcnt, val, d)
+static void
+set80211tdmaslotcnt(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_TDMA_SLOTCNT, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_TDMA_SLOTCNT, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211tdmaslotlen, val, d)
+static void
+set80211tdmaslotlen(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_TDMA_SLOTLEN, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_TDMA_SLOTLEN, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211tdmabintval, val, d)
+static void
+set80211tdmabintval(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_TDMA_BINTERVAL, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_TDMA_BINTERVAL, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211meshttl, val, d)
+static void
+set80211meshttl(if_ctx *ctx, const char *val, int dummy __unused)
{
- set80211(s, IEEE80211_IOC_MESH_TTL, atoi(val), 0, NULL);
+ set80211(ctx, IEEE80211_IOC_MESH_TTL, atoi(val), 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211meshforward, val, d)
+static void
+set80211meshforward(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_MESH_FWRD, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_MESH_FWRD, d, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211meshgate, val, d)
+static void
+set80211meshgate(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_MESH_GATE, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_MESH_GATE, d, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211meshpeering, val, d)
+static void
+set80211meshpeering(if_ctx *ctx, const char *val __unused, int d)
{
- set80211(s, IEEE80211_IOC_MESH_AP, d, 0, NULL);
+ set80211(ctx, IEEE80211_IOC_MESH_AP, d, 0, NULL);
}
-static
-DECL_CMD_FUNC(set80211meshmetric, val, d)
+static void
+set80211meshmetric(if_ctx *ctx, const char *val, int dummy __unused)
{
char v[12];
memcpy(v, val, sizeof(v));
- set80211(s, IEEE80211_IOC_MESH_PR_METRIC, 0, 0, v);
+ set80211(ctx, IEEE80211_IOC_MESH_PR_METRIC, 0, 0, v);
}
-static
-DECL_CMD_FUNC(set80211meshpath, val, d)
+static void
+set80211meshpath(if_ctx *ctx, const char *val, int dummy __unused)
{
char v[12];
memcpy(v, val, sizeof(v));
- set80211(s, IEEE80211_IOC_MESH_PR_PATH, 0, 0, v);
+ set80211(ctx, IEEE80211_IOC_MESH_PR_PATH, 0, 0, v);
}
static int
@@ -2062,14 +2063,14 @@ regdomain_sort(const void *a, const void *b)
const struct ieee80211_channel *cb = b;
return ca->ic_freq == cb->ic_freq ?
- (ca->ic_flags & CHAN_ALL) - (cb->ic_flags & CHAN_ALL) :
+ (int)(ca->ic_flags & CHAN_ALL) - (int)(cb->ic_flags & CHAN_ALL) :
ca->ic_freq - cb->ic_freq;
#undef CHAN_ALL
}
static const struct ieee80211_channel *
chanlookup(const struct ieee80211_channel chans[], int nchans,
- int freq, int flags)
+ int freq, uint32_t flags)
{
int i;
@@ -2084,11 +2085,9 @@ chanlookup(const struct ieee80211_channel chans[], int nchans,
}
static int
-chanfind(const struct ieee80211_channel chans[], int nchans, int flags)
+chanfind(const struct ieee80211_channel chans[], int nchans, uint32_t flags)
{
- int i;
-
- for (i = 0; i < nchans; i++) {
+ for (int i = 0; i < nchans; i++) {
const struct ieee80211_channel *c = &chans[i];
if ((c->ic_flags & flags) == flags)
return 1;
@@ -2100,7 +2099,7 @@ chanfind(const struct ieee80211_channel chans[], int nchans, int flags)
* Check channel compatibility.
*/
static int
-checkchan(const struct ieee80211req_chaninfo *avail, int freq, int flags)
+checkchan(const struct ieee80211req_chaninfo *avail, int freq, uint32_t flags)
{
flags &= ~REQ_FLAGS;
/*
@@ -2144,7 +2143,7 @@ checkchan(const struct ieee80211req_chaninfo *avail, int freq, int flags)
}
static void
-regdomain_addchans(struct ieee80211req_chaninfo *ci,
+regdomain_addchans(if_ctx *ctx, struct ieee80211req_chaninfo *ci,
const netband_head *bands,
const struct ieee80211_regdomain *reg,
uint32_t chanFlags,
@@ -2155,6 +2154,7 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci,
struct ieee80211_channel *c, *prev;
int freq, hi_adj, lo_adj, channelSep;
uint32_t flags;
+ const int verbose = ctx->args->verbose;
hi_adj = (chanFlags & IEEE80211_CHAN_HT40U) ? -20 : 0;
lo_adj = (chanFlags & IEEE80211_CHAN_HT40D) ? 20 : 0;
@@ -2298,7 +2298,7 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci,
memset(c, 0, sizeof(*c));
c->ic_freq = freq;
c->ic_flags = flags;
- if (c->ic_flags & IEEE80211_CHAN_DFS)
+ if (c->ic_flags & IEEE80211_CHAN_DFS)
c->ic_maxregpower = nb->maxPowerDFS;
else
c->ic_maxregpower = nb->maxPower;
@@ -2316,6 +2316,7 @@ regdomain_addchans(struct ieee80211req_chaninfo *ci,
static void
regdomain_makechannels(
+ if_ctx *ctx,
struct ieee80211_regdomain_req *req,
const struct ieee80211_devcaps_req *dc)
{
@@ -2354,40 +2355,40 @@ regdomain_makechannels(
*/
ci->ic_nchans = 0;
if (!LIST_EMPTY(&rd->bands_11b))
- regdomain_addchans(ci, &rd->bands_11b, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11b, reg,
IEEE80211_CHAN_B, &dc->dc_chaninfo);
if (!LIST_EMPTY(&rd->bands_11g))
- regdomain_addchans(ci, &rd->bands_11g, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11g, reg,
IEEE80211_CHAN_G, &dc->dc_chaninfo);
if (!LIST_EMPTY(&rd->bands_11a))
- regdomain_addchans(ci, &rd->bands_11a, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11a, reg,
IEEE80211_CHAN_A, &dc->dc_chaninfo);
if (!LIST_EMPTY(&rd->bands_11na) && dc->dc_htcaps != 0) {
- regdomain_addchans(ci, &rd->bands_11na, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11na, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT20,
&dc->dc_chaninfo);
if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
- regdomain_addchans(ci, &rd->bands_11na, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11na, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U,
&dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11na, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11na, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D,
&dc->dc_chaninfo);
}
}
if (!LIST_EMPTY(&rd->bands_11ac) && dc->dc_vhtcaps != 0) {
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT20 |
IEEE80211_CHAN_VHT20,
&dc->dc_chaninfo);
/* VHT40 is a function of HT40.. */
if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U |
IEEE80211_CHAN_VHT40U,
&dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D |
IEEE80211_CHAN_VHT40D,
&dc->dc_chaninfo);
@@ -2395,11 +2396,11 @@ regdomain_makechannels(
/* VHT80 is mandatory (and so should be VHT40 above). */
if (1) {
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U |
IEEE80211_CHAN_VHT80,
&dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D |
IEEE80211_CHAN_VHT80,
&dc->dc_chaninfo);
@@ -2408,11 +2409,11 @@ regdomain_makechannels(
/* VHT160 */
if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160MHZ(
dc->dc_vhtcaps)) {
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U |
IEEE80211_CHAN_VHT160,
&dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D |
IEEE80211_CHAN_VHT160,
&dc->dc_chaninfo);
@@ -2421,11 +2422,11 @@ regdomain_makechannels(
/* VHT80P80 */
if (IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_IS_160_80P80MHZ(
dc->dc_vhtcaps)) {
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U |
IEEE80211_CHAN_VHT80P80,
&dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11ac, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ac, reg,
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D |
IEEE80211_CHAN_VHT80P80,
&dc->dc_chaninfo);
@@ -2433,14 +2434,14 @@ regdomain_makechannels(
}
if (!LIST_EMPTY(&rd->bands_11ng) && dc->dc_htcaps != 0) {
- regdomain_addchans(ci, &rd->bands_11ng, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ng, reg,
IEEE80211_CHAN_G | IEEE80211_CHAN_HT20,
&dc->dc_chaninfo);
if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
- regdomain_addchans(ci, &rd->bands_11ng, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ng, reg,
IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U,
&dc->dc_chaninfo);
- regdomain_addchans(ci, &rd->bands_11ng, reg,
+ regdomain_addchans(ctx, ci, &rd->bands_11ng, reg,
IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D,
&dc->dc_chaninfo);
}
@@ -2491,8 +2492,8 @@ defaultcountry(const struct regdomain *rd)
regdomain.isocc[1] = cc->isoname[1];
}
-static
-DECL_CMD_FUNC(set80211regdomain, val, d)
+static void
+set80211regdomain(if_ctx *ctx, const char *val, int dummy __unused)
{
struct regdata *rdp = getregdata();
const struct regdomain *rd;
@@ -2507,7 +2508,7 @@ DECL_CMD_FUNC(set80211regdomain, val, d)
if (eptr == val || rd == NULL)
errx(1, "unknown regdomain %s", val);
}
- getregdomain(s);
+ getregdomain(ctx);
regdomain.regdomain = rd->sku;
if (regdomain.country == 0 && rd->cc != NULL) {
/*
@@ -2519,8 +2520,8 @@ DECL_CMD_FUNC(set80211regdomain, val, d)
callback_register(setregdomain_cb, &regdomain);
}
-static
-DECL_CMD_FUNC(set80211country, val, d)
+static void
+set80211country(if_ctx *ctx, const char *val, int dummy __unused)
{
struct regdata *rdp = getregdata();
const struct country *cc;
@@ -2535,7 +2536,7 @@ DECL_CMD_FUNC(set80211country, val, d)
if (eptr == val || cc == NULL)
errx(1, "unknown ISO country code %s", val);
}
- getregdomain(s);
+ getregdomain(ctx);
regdomain.regdomain = cc->rd->sku;
regdomain.country = cc->code;
regdomain.isocc[0] = cc->isoname[0];
@@ -2544,17 +2545,17 @@ DECL_CMD_FUNC(set80211country, val, d)
}
static void
-set80211location(const char *val, int d, int s, const struct afswtch *rafp)
+set80211location(if_ctx *ctx, const char *val __unused, int d)
{
- getregdomain(s);
+ getregdomain(ctx);
regdomain.location = d;
callback_register(setregdomain_cb, &regdomain);
}
static void
-set80211ecm(const char *val, int d, int s, const struct afswtch *rafp)
+set80211ecm(if_ctx *ctx, const char *val __unused, int d)
{
- getregdomain(s);
+ getregdomain(ctx);
regdomain.ecm = d;
callback_register(setregdomain_cb, &regdomain);
}
@@ -2699,10 +2700,10 @@ getflags(int flags)
}
static void
-printie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen)
+printie(if_ctx *ctx, const char* tag, const uint8_t *ie, size_t ielen, unsigned int maxlen)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
maxlen -= strlen(tag)+2;
if (2*ielen > maxlen)
maxlen--;
@@ -2736,7 +2737,7 @@ printie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen)
*/
static void
-printwmeparam(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printwmeparam(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
static const char *acnames[] = { "BE", "BK", "VO", "VI" };
const struct ieee80211_wme_param *wme =
@@ -2744,7 +2745,7 @@ printwmeparam(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
int i;
printf("%s", tag);
- if (!verbose)
+ if (!ctx->args->verbose)
return;
printf("<qosinfo 0x%x", wme->param_qosInfo);
ie += offsetof(struct ieee80211_wme_param, params_acParams);
@@ -2766,10 +2767,10 @@ printwmeparam(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printwmeinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printwmeinfo(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_wme_info *wme =
(const struct ieee80211_wme_info *) ie;
printf("<version 0x%x info 0x%x>",
@@ -2778,14 +2779,193 @@ printwmeinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printvhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printhecap(if_ctx *ctx, const char *tag, const uint8_t *ie)
{
+ const struct ieee80211_he_cap_elem *hecap;
+ const struct ieee80211_he_mcs_nss_supp *mcsnss;
+ unsigned int i;
+ uint8_t chw;
+
printf("%s", tag);
- if (verbose) {
- const struct ieee80211_ie_vhtcap *vhtcap =
- (const struct ieee80211_ie_vhtcap *) ie;
- uint32_t vhtcap_info = LE_READ_4(&vhtcap->vht_cap_info);
+ if (!ctx->args->verbose)
+ return;
+
+ /* Check that the right size. */
+ if (ie[1] < 1 + sizeof(*hecap) + 4) {
+ printf("<err: he_cap inval. length %#0x>", ie[1]);
+ return;
+ }
+ /* Skip Element ID, Length, EID Extension. */
+ hecap = (const struct ieee80211_he_cap_elem *)(ie + 3);
+
+ /* XXX-BZ we need to somehow decode each field? */
+ printf("<mac_cap");
+ for (i = 0; i < nitems(hecap->mac_cap_info); i++)
+ printf(" %#04x", hecap->mac_cap_info[i]);
+ printf(" phy_cap");
+ for (i = 0; i < nitems(hecap->phy_cap_info); i++)
+ printf(" %#04x", hecap->phy_cap_info[i]);
+
+ chw = hecap->phy_cap_info[0];
+ ie = (const uint8_t *)(const void *)(hecap + 1);
+ mcsnss = (const struct ieee80211_he_mcs_nss_supp *)ie;
+ /* Cannot use <= as < is a delimiter. */
+ printf(" rx/tx_he_mcs map: loweq80 %#06x/%#06x",
+ mcsnss->rx_mcs_80, mcsnss->tx_mcs_80);
+ ie += 2;
+ if ((chw & (1<<2)) != 0) {
+ printf(" 160 %#06x/%#06x",
+ mcsnss->rx_mcs_160, mcsnss->tx_mcs_160);
+ ie += 2;
+ }
+ if ((chw & (1<<3)) != 0) {
+ printf(" 80+80 %#06x/%#06x",
+ mcsnss->rx_mcs_80p80, mcsnss->tx_mcs_80p80);
+ ie += 2;
+ }
+ /* TODO: ppet = (struct ... *)ie; */
+
+ printf(">");
+}
+
+static void
+printheoper(if_ctx *ctx, const char *tag, const uint8_t *ie)
+{
+ printf("%s", tag);
+ if (ctx->args->verbose) {
+ const struct ieee80211_he_operation *heoper;
+ uint32_t params;
+
+ /* Check that the right size. */
+ if (ie[1] < 1 + sizeof(*heoper)) {
+ printf("<err: he_oper inval. length %#0x>", ie[1]);
+ return;
+ }
+ /* Skip Element ID, Length, EID Extension. */
+ heoper = (const struct ieee80211_he_operation *)(ie + 3);
+
+ /* XXX-BZ we need to somehow decode each field? */
+ params = heoper->he_oper_params & 0x00ffffff;
+ printf("<params %#08x", params);
+ printf(" bss_col %#04x", (heoper->he_oper_params & 0xff000000) >> 24);
+ printf(" mcs_nss %#06x", heoper->he_mcs_nss_set);
+ if ((params & (1 << 14)) != 0) {
+ printf(" vht_op 0-3");
+ }
+ if ((params & (1 << 15)) != 0) {
+ printf(" max_coh_bssid 0-1");
+ }
+ if ((params & (1 << 17)) != 0) {
+ printf(" 6ghz_op 0-5");
+ }
+ printf(">");
+ }
+}
+
+static void
+printmuedcaparamset(if_ctx *ctx, const char *tag, const uint8_t *ie)
+{
+ static const char *acnames[] = { "BE", "BK", "VO", "VI" };
+ const struct ieee80211_mu_edca_param_set *mu_edca;
+ int i;
+
+ printf("%s", tag);
+ if (!ctx->args->verbose)
+ return;
+
+ /* Check that the right size. */
+ if (ie[1] != 1 + sizeof(*mu_edca)) {
+ printf("<err: mu_edca inval. length %#04x>", ie[1]);
+ return;
+ }
+ /* Skip Element ID, Length, EID Extension. */
+ mu_edca = (const struct ieee80211_mu_edca_param_set *)(ie + 3);
+
+ printf("<qosinfo 0x%x", mu_edca->mu_qos_info);
+ ie++;
+ for (i = 0; i < WME_NUM_AC; i++) {
+ const struct ieee80211_he_mu_edca_param_ac_rec *ac =
+ &mu_edca->param_ac_recs[i];
+
+ printf(" %s[aifsn %u ecwmin %u ecwmax %u timer %u]", acnames[i],
+ ac->aifsn,
+ _IEEE80211_MASKSHIFT(ac->ecw_min_max, WME_PARAM_LOGCWMIN),
+ _IEEE80211_MASKSHIFT(ac->ecw_min_max, WME_PARAM_LOGCWMAX),
+ ac->mu_edca_timer);
+ }
+ printf(">");
+}
+
+static void
+printsupopclass(if_ctx *ctx, const char *tag, const u_int8_t *ie)
+{
+ uint8_t len, i;
+
+ printf("%s", tag);
+ if (!ctx->args->verbose)
+ return;
+
+ /* Check that the right size. */
+ len = ie[1];
+ if (len < 2) {
+ printf("<err: sup_op_class inval. length %#04x>", ie[1]);
+ return;
+ }
+
+ ie += 2;
+ i = 0;
+ printf("<cur op class %u", *ie);
+ i++;
+ if (i < len && *(ie + i) != 130)
+ printf(" op classes");
+ while (i < len && *(ie + i) != 130) {
+ printf(" %u", *(ie + i));
+ i++;
+ }
+ if (i > 1 && i < len && *(ie + i) != 130) {
+ printf(" parsing error at %#0x>", i);
+ return;
+ }
+ /* Skip OneHundredAndThirty Delimiter. */
+ i++;
+ if (i < len && *(ie + i) != 0)
+ printf(" ext seq");
+ while (i < len && *(ie + i) != 0) {
+ printf(" %u", *(ie + i));
+ i++;
+ }
+ if (i > 1 && i < len && *(ie + i) != 0) {
+ printf(" parsing error at %#0x>", i);
+ return;
+ }
+ /* Skip Zero Delimiter. */
+ i++;
+ if ((i + 1) < len)
+ printf(" duple seq");
+ while ((i + 1) < len) {
+ printf(" %u/%u", *(ie + i), *(ie + i + 1));
+ i += 2;
+ }
+ printf(">");
+}
+
+static void
+printvhtcap(if_ctx *ctx, const char *tag, const u_int8_t *ie)
+{
+ printf("%s", tag);
+ if (ctx->args->verbose) {
+ const struct ieee80211_vht_cap *vhtcap;
+ uint32_t vhtcap_info;
+ /* Check that the right size. */
+ if (ie[1] != sizeof(*vhtcap)) {
+ printf("<err: vht_cap inval. length>");
+ return;
+ }
+ /* Skip Element ID and Length. */
+ vhtcap = (const struct ieee80211_vht_cap *)(ie + 2);
+
+ vhtcap_info = LE_READ_4(&vhtcap->vht_cap_info);
printf("<cap 0x%08x", vhtcap_info);
printf(" rx_mcs_map 0x%x",
LE_READ_2(&vhtcap->supp_mcs.rx_mcs_map));
@@ -2801,23 +2981,30 @@ printvhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printvhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printvhtinfo(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
printf("%s", tag);
- if (verbose) {
- const struct ieee80211_ie_vht_operation *vhtinfo =
- (const struct ieee80211_ie_vht_operation *) ie;
+ if (ctx->args->verbose) {
+ const struct ieee80211_vht_operation *vhtinfo;
- printf("<chw %d freq1_idx %d freq2_idx %d basic_mcs_set 0x%04x>",
+ /* Check that the right size. */
+ if (ie[1] != sizeof(*vhtinfo)) {
+ printf("<err: vht_operation inval. length>");
+ return;
+ }
+ /* Skip Element ID and Length. */
+ vhtinfo = (const struct ieee80211_vht_operation *)(ie + 2);
+
+ printf("<chw %d freq0_idx %d freq1_idx %d basic_mcs_set 0x%04x>",
vhtinfo->chan_width,
- vhtinfo->center_freq_seg1_idx,
- vhtinfo->center_freq_seg2_idx,
+ vhtinfo->center_freq_seq0_idx,
+ vhtinfo->center_freq_seq1_idx,
LE_READ_2(&vhtinfo->basic_mcs_set));
}
}
static void
-printvhtpwrenv(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printvhtpwrenv(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen)
{
printf("%s", tag);
static const char *txpwrmap[] = {
@@ -2826,17 +3013,17 @@ printvhtpwrenv(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
"80",
"160",
};
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_ie_vht_txpwrenv *vhtpwr =
(const struct ieee80211_ie_vht_txpwrenv *) ie;
- int i, n;
+ size_t i, n;
const char *sep = "";
/* Get count; trim at ielen */
n = (vhtpwr->tx_info &
IEEE80211_VHT_TXPWRENV_INFO_COUNT_MASK) + 1;
/* Trim at ielen */
- if (n > ielen - 3)
+ if (n + 3 > ielen)
n = ielen - 3;
printf("<tx_info 0x%02x pwr:[", vhtpwr->tx_info);
for (i = 0; i < n; i++) {
@@ -2850,10 +3037,10 @@ printvhtpwrenv(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printhtcap(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_ie_htcap *htcap =
(const struct ieee80211_ie_htcap *) ie;
const char *sep;
@@ -2884,10 +3071,10 @@ printhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printhtinfo(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_ie_htinfo *htinfo =
(const struct ieee80211_ie_htinfo *) ie;
const char *sep;
@@ -2916,11 +3103,11 @@ printhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printathie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printathie(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_ath_ie *ath =
(const struct ieee80211_ath_ie *)ie;
@@ -2947,11 +3134,11 @@ printathie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
static void
-printmeshconf(const char *tag, const uint8_t *ie, size_t ielen, int maxlen)
+printmeshconf(if_ctx *ctx, const char *tag, const uint8_t *ie)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_meshconf_ie *mconf =
(const struct ieee80211_meshconf_ie *)ie;
printf("<PATH:");
@@ -2985,10 +3172,10 @@ printmeshconf(const char *tag, const uint8_t *ie, size_t ielen, int maxlen)
}
static void
-printbssload(const char *tag, const uint8_t *ie, size_t ielen, int maxlen)
+printbssload(if_ctx *ctx, const char *tag, const uint8_t *ie)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_bss_load_ie *bssload =
(const struct ieee80211_bss_load_ie *) ie;
printf("<sta count %d, chan load %d, aac %d>",
@@ -2999,18 +3186,17 @@ printbssload(const char *tag, const uint8_t *ie, size_t ielen, int maxlen)
}
static void
-printapchanrep(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printapchanrep(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const struct ieee80211_ap_chan_report_ie *ap =
(const struct ieee80211_ap_chan_report_ie *) ie;
const char *sep = "";
- int i;
printf("<class %u, chan:[", ap->i_class);
- for (i = 3; i < ielen; i++) {
+ for (size_t i = 3; i < ielen; i++) {
printf("%s%u", sep, ie[i]);
sep = ",";
}
@@ -3059,12 +3245,12 @@ wpa_keymgmt(const u_int8_t *sel)
}
static void
-printwpaie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printwpaie(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
u_int8_t len = ie[1];
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const char *sep;
int n;
@@ -3121,6 +3307,12 @@ rsn_cipher(const u_int8_t *sel)
return "AES-CCMP";
case RSN_SEL(RSN_CSE_WRAP):
return "AES-OCB";
+ case RSN_SEL(RSN_CSE_GCMP_128):
+ return "AES-GCMP";
+ case RSN_SEL(RSN_CSE_CCMP_256):
+ return "AES-CCMP-256";
+ case RSN_SEL(RSN_CSE_GCMP_256):
+ return "AES-GCMP-256";
}
return "?";
#undef WPA_SEL
@@ -3137,6 +3329,10 @@ rsn_keymgmt(const u_int8_t *sel)
return "8021X-UNSPEC";
case RSN_SEL(RSN_ASE_8021X_PSK):
return "8021X-PSK";
+ case RSN_SEL(RSN_ASE_8021X_UNSPEC_SHA256):
+ return "8021X-UNSPEC-SHA256";
+ case RSN_SEL(RSN_ASE_8021X_PSK_SHA256):
+ return "8021X-PSK-256";
case RSN_SEL(RSN_ASE_NONE):
return "NONE";
}
@@ -3145,10 +3341,10 @@ rsn_keymgmt(const u_int8_t *sel)
}
static void
-printrsnie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printrsnie(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen)
{
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
const char *sep;
int n;
@@ -3187,18 +3383,45 @@ printrsnie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
}
+static void
+printrsnxe(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen)
+{
+ size_t n;
+
+ printf("%s", tag);
+ if (!ctx->args->verbose)
+ return;
+
+ ie += 2, ielen -= 2;
+
+ n = (*ie & 0x0f);
+ printf("<%zu", n + 1);
+
+ /* We do not yet know about more than n=1 (0). */
+ if (n != 0)
+ goto end;
+
+ if (*ie & 0x10)
+ printf(" PTWTOPS");
+ if (*ie & 0x20)
+ printf(" SAE h-t-e");
+
+end:
+ printf(">");
+}
+
#define BE_READ_2(p) \
((u_int16_t) \
((((const u_int8_t *)(p))[1] ) | \
(((const u_int8_t *)(p))[0] << 8)))
static void
-printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printwpsie(if_ctx *ctx, const char *tag, const u_int8_t *ie)
{
u_int8_t len = ie[1];
printf("%s", tag);
- if (verbose) {
+ if (ctx->args->verbose) {
static const char *dev_pass_id[] = {
"D", /* Default (PIN) */
"U", /* User-specified */
@@ -3331,7 +3554,7 @@ printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
break;
case IEEE80211_WPS_ATTR_DEV_PASSWORD_ID:
n = LE_READ_2(ie);
- if (n < nitems(dev_pass_id))
+ if (n < (int)nitems(dev_pass_id))
printf(" dpi:%s", dev_pass_id[n]);
break;
case IEEE80211_WPS_ATTR_MANUFACTURER:
@@ -3423,10 +3646,10 @@ printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printtdmaie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printtdmaie(if_ctx *ctx, const char *tag, const u_int8_t *ie, size_t ielen)
{
printf("%s", tag);
- if (verbose && ielen >= sizeof(struct ieee80211_tdma_param)) {
+ if (ctx->args->verbose && ielen >= sizeof(struct ieee80211_tdma_param)) {
const struct ieee80211_tdma_param *tdma =
(const struct ieee80211_tdma_param *) ie;
@@ -3481,7 +3704,7 @@ copy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len)
}
static void
-printssid(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printssid(const char *tag, const u_int8_t *ie, int maxlen)
{
char ssid[2*IEEE80211_NWID_LEN+1];
@@ -3489,14 +3712,13 @@ printssid(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printrates(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printrates(const char *tag, const u_int8_t *ie, size_t ielen)
{
const char *sep;
- int i;
printf("%s", tag);
sep = "<";
- for (i = 2; i < ielen; i++) {
+ for (size_t i = 2; i < ielen; i++) {
printf("%s%s%d", sep,
ie[i] & IEEE80211_RATE_BASIC ? "B" : "",
ie[i] & IEEE80211_RATE_VAL);
@@ -3506,7 +3728,7 @@ printrates(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
-printcountry(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+printcountry(const char *tag, const u_int8_t *ie)
{
const struct ieee80211_country_ie *cie =
(const struct ieee80211_country_ie *) ie;
@@ -3565,7 +3787,22 @@ iswpsoui(const uint8_t *frm)
}
static const char *
-iename(int elemid)
+ie_ext_name(uint8_t ext_elemid)
+{
+ static char iename_buf[32];
+
+ switch (ext_elemid) {
+ case IEEE80211_ELEMID_EXT_HE_CAPA: return " HECAP";
+ case IEEE80211_ELEMID_EXT_HE_OPER: return " HEOPER";
+ case IEEE80211_ELEMID_EXT_MU_EDCA_PARAM_SET: return " MU_EDCA_PARAM_SET";
+ }
+ snprintf(iename_buf, sizeof(iename_buf), " ELEMID_EXT_%d",
+ ext_elemid & 0xff);
+ return (const char *) iename_buf;
+}
+
+static const char *
+iename(uint8_t elemid, const u_int8_t *vp)
{
static char iename_buf[64];
switch (elemid) {
@@ -3587,6 +3824,8 @@ iename(int elemid)
case IEEE80211_ELEMID_IBSSDFS: return " IBSSDFS";
case IEEE80211_ELEMID_RESERVED_47:
return " RESERVED_47";
+ case IEEE80211_ELEMID_SUP_OP_CLASS:
+ return " SUP_OP_CLASS";
case IEEE80211_ELEMID_MOBILITY_DOMAIN:
return " MOBILITY_DOMAIN";
case IEEE80211_ELEMID_RRM_ENACAPS:
@@ -3596,26 +3835,58 @@ iename(int elemid)
case IEEE80211_ELEMID_TPC: return " TPC";
case IEEE80211_ELEMID_CCKM: return " CCKM";
case IEEE80211_ELEMID_EXTCAP: return " EXTCAP";
+ case IEEE80211_ELEMID_RSN_EXT: return " RSNXE";
+ case IEEE80211_ELEMID_EXTFIELD:
+ if (vp[1] >= 1)
+ return ie_ext_name(vp[2]);
+ break;
}
- snprintf(iename_buf, sizeof(iename_buf), " UNKNOWN_ELEMID_%d",
+ snprintf(iename_buf, sizeof(iename_buf), " ELEMID_%d",
elemid);
return (const char *) iename_buf;
}
static void
-printies(const u_int8_t *vp, int ielen, int maxcols)
+printexties(if_ctx *ctx, const u_int8_t *vp, unsigned int maxcols)
+{
+ const int verbose = ctx->args->verbose;
+
+ if (vp[1] < 1)
+ return;
+
+ switch (vp[2]) {
+ case IEEE80211_ELEMID_EXT_HE_CAPA:
+ printhecap(ctx, " HECAP", vp);
+ break;
+ case IEEE80211_ELEMID_EXT_HE_OPER:
+ printheoper(ctx, " HEOPER", vp);
+ break;
+ case IEEE80211_ELEMID_EXT_MU_EDCA_PARAM_SET:
+ printmuedcaparamset(ctx, " MU_EDCA_PARAM_SET", vp);
+ break;
+ default:
+ if (verbose)
+ printie(ctx, iename(vp[0], vp), vp, 2+vp[1], maxcols);
+ break;
+ }
+}
+
+static void
+printies(if_ctx *ctx, const u_int8_t *vp, int ielen, unsigned int maxcols)
{
+ const int verbose = ctx->args->verbose;
+
while (ielen > 0) {
switch (vp[0]) {
case IEEE80211_ELEMID_SSID:
if (verbose)
- printssid(" SSID", vp, 2+vp[1], maxcols);
+ printssid(" SSID", vp, maxcols);
break;
case IEEE80211_ELEMID_RATES:
case IEEE80211_ELEMID_XRATES:
if (verbose)
printrates(vp[0] == IEEE80211_ELEMID_RATES ?
- " RATES" : " XRATES", vp, 2+vp[1], maxcols);
+ " RATES" : " XRATES", vp, 2+vp[1]);
break;
case IEEE80211_ELEMID_DSPARMS:
if (verbose)
@@ -3623,7 +3894,7 @@ printies(const u_int8_t *vp, int ielen, int maxcols)
break;
case IEEE80211_ELEMID_COUNTRY:
if (verbose)
- printcountry(" COUNTRY", vp, 2+vp[1], maxcols);
+ printcountry(" COUNTRY", vp);
break;
case IEEE80211_ELEMID_ERP:
if (verbose)
@@ -3631,55 +3902,64 @@ printies(const u_int8_t *vp, int ielen, int maxcols)
break;
case IEEE80211_ELEMID_VENDOR:
if (iswpaoui(vp))
- printwpaie(" WPA", vp, 2+vp[1], maxcols);
+ printwpaie(ctx, " WPA", vp);
else if (iswmeinfo(vp))
- printwmeinfo(" WME", vp, 2+vp[1], maxcols);
+ printwmeinfo(ctx, " WME", vp);
else if (iswmeparam(vp))
- printwmeparam(" WME", vp, 2+vp[1], maxcols);
+ printwmeparam(ctx, " WME", vp);
else if (isatherosoui(vp))
- printathie(" ATH", vp, 2+vp[1], maxcols);
+ printathie(ctx, " ATH", vp);
else if (iswpsoui(vp))
- printwpsie(" WPS", vp, 2+vp[1], maxcols);
+ printwpsie(ctx, " WPS", vp);
else if (istdmaoui(vp))
- printtdmaie(" TDMA", vp, 2+vp[1], maxcols);
+ printtdmaie(ctx, " TDMA", vp, 2+vp[1]);
else if (verbose)
- printie(" VEN", vp, 2+vp[1], maxcols);
- break;
+ printie(ctx, " VEN", vp, 2+vp[1], maxcols);
+ break;
case IEEE80211_ELEMID_RSN:
- printrsnie(" RSN", vp, 2+vp[1], maxcols);
+ printrsnie(ctx, " RSN", vp, 2+vp[1]);
break;
case IEEE80211_ELEMID_HTCAP:
- printhtcap(" HTCAP", vp, 2+vp[1], maxcols);
+ printhtcap(ctx, " HTCAP", vp);
+ break;
+ case IEEE80211_ELEMID_SUP_OP_CLASS:
+ printsupopclass(ctx, " SUP_OP_CLASS", vp);
break;
case IEEE80211_ELEMID_HTINFO:
if (verbose)
- printhtinfo(" HTINFO", vp, 2+vp[1], maxcols);
+ printhtinfo(ctx, " HTINFO", vp);
break;
case IEEE80211_ELEMID_MESHID:
if (verbose)
- printssid(" MESHID", vp, 2+vp[1], maxcols);
+ printssid(" MESHID", vp, maxcols);
break;
case IEEE80211_ELEMID_MESHCONF:
- printmeshconf(" MESHCONF", vp, 2+vp[1], maxcols);
+ printmeshconf(ctx, " MESHCONF", vp);
break;
case IEEE80211_ELEMID_VHT_CAP:
- printvhtcap(" VHTCAP", vp, 2+vp[1], maxcols);
+ printvhtcap(ctx, " VHTCAP", vp);
break;
case IEEE80211_ELEMID_VHT_OPMODE:
- printvhtinfo(" VHTOPMODE", vp, 2+vp[1], maxcols);
+ printvhtinfo(ctx, " VHTOPMODE", vp);
break;
case IEEE80211_ELEMID_VHT_PWR_ENV:
- printvhtpwrenv(" VHTPWRENV", vp, 2+vp[1], maxcols);
+ printvhtpwrenv(ctx, " VHTPWRENV", vp, 2+vp[1]);
break;
case IEEE80211_ELEMID_BSSLOAD:
- printbssload(" BSSLOAD", vp, 2+vp[1], maxcols);
+ printbssload(ctx, " BSSLOAD", vp);
break;
case IEEE80211_ELEMID_APCHANREP:
- printapchanrep(" APCHANREP", vp, 2+vp[1], maxcols);
+ printapchanrep(ctx, " APCHANREP", vp, 2+vp[1]);
+ break;
+ case IEEE80211_ELEMID_RSN_EXT:
+ printrsnxe(ctx, " RSNXE", vp, 2+vp[1]);
+ break;
+ case IEEE80211_ELEMID_EXTFIELD:
+ printexties(ctx, vp, maxcols);
break;
default:
if (verbose)
- printie(iename(vp[0]), vp, 2+vp[1], maxcols);
+ printie(ctx, iename(vp[0], vp), vp, 2+vp[1], maxcols);
break;
}
ielen -= 2+vp[1];
@@ -3694,7 +3974,7 @@ printmimo(const struct ieee80211_mimo_info *mi)
int r = 0;
for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {
- if (mi->ch[i].rssi != 0) {
+ if (mi->ch[i].rssi[0] != 0) {
r = 1;
break;
}
@@ -3717,19 +3997,30 @@ printmimo(const struct ieee80211_mimo_info *mi)
}
static void
-list_scan(int s)
+printbssidname(const struct ether_addr *n)
+{
+ char name[MAXHOSTNAMELEN + 1];
+
+ if (ether_ntohost(name, n) != 0)
+ return;
+
+ printf(" (%s)", name);
+}
+
+static void
+list_scan(if_ctx *ctx)
{
uint8_t buf[24*1024];
char ssid[IEEE80211_NWID_LEN+1];
const uint8_t *cp;
int len, idlen;
- if (get80211len(s, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf), &len) < 0)
+ if (get80211len(ctx, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf), &len) < 0)
errx(1, "unable to get scan results");
- if (len < sizeof(struct ieee80211req_scan_result))
+ if (len < (int)sizeof(struct ieee80211req_scan_result))
return;
- getchaninfo(s);
+ getchaninfo(ctx);
printf("%-*.*s %-17.17s %4s %4s %-7s %3s %4s\n"
, IEEE80211_NWID_LEN, IEEE80211_NWID_LEN, "SSID/MESH ID"
@@ -3745,7 +4036,7 @@ list_scan(int s)
const struct ieee80211req_scan_result *sr;
const uint8_t *vp, *idp;
- sr = (const struct ieee80211req_scan_result *) cp;
+ sr = (const struct ieee80211req_scan_result *)(const void *) cp;
vp = cp + sr->isr_ie_off;
if (sr->isr_meshid_len) {
idp = vp + sr->isr_ssid_len;
@@ -3765,15 +4056,16 @@ list_scan(int s)
, sr->isr_intval
, getcaps(sr->isr_capinfo)
);
- printies(vp + sr->isr_ssid_len + sr->isr_meshid_len,
+ printies(ctx, vp + sr->isr_ssid_len + sr->isr_meshid_len,
sr->isr_ie_len, 24);
+ printbssidname((const struct ether_addr *)sr->isr_bssid);
printf("\n");
cp += sr->isr_len, len -= sr->isr_len;
- } while (len >= sizeof(struct ieee80211req_scan_result));
+ } while (len >= (int)sizeof(struct ieee80211req_scan_result));
}
static void
-scan_and_wait(int s)
+scan_and_wait(if_ctx *ctx)
{
struct ieee80211_scan_req sr;
struct ieee80211req ireq;
@@ -3784,8 +4076,8 @@ scan_and_wait(int s)
perror("socket(PF_ROUTE,SOCK_RAW)");
return;
}
- (void) memset(&ireq, 0, sizeof(ireq));
- (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name));
+ memset(&ireq, 0, sizeof(ireq));
+ strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name));
ireq.i_type = IEEE80211_IOC_SCAN_REQ;
memset(&sr, 0, sizeof(sr));
@@ -3803,7 +4095,7 @@ scan_and_wait(int s)
* possible errors from net80211, even if no new scan could be
* started there might still be a valid scan cache.
*/
- if (ioctl(s, SIOCS80211, &ireq) == 0) {
+ if (ioctl_ctx(ctx, SIOCS80211, &ireq) == 0) {
char buf[2048];
struct if_announcemsghdr *ifan;
struct rt_msghdr *rtm;
@@ -3813,7 +4105,7 @@ scan_and_wait(int s)
perror("read(PF_ROUTE)");
break;
}
- rtm = (struct rt_msghdr *) buf;
+ rtm = (struct rt_msghdr *)(void *)buf;
if (rtm->rtm_version != RTM_VERSION)
break;
ifan = (struct if_announcemsghdr *) rtm;
@@ -3823,14 +4115,14 @@ scan_and_wait(int s)
close(sroute);
}
-static
-DECL_CMD_FUNC(set80211scan, val, d)
+static void
+set80211scan(if_ctx *ctx, const char *val __unused, int dummy __unused)
{
- scan_and_wait(s);
- list_scan(s);
+ scan_and_wait(ctx);
+ list_scan(ctx);
}
-static enum ieee80211_opmode get80211opmode(int s);
+static enum ieee80211_opmode get80211opmode(if_ctx *ctx);
static int
gettxseq(const struct ieee80211req_sta_info *si)
@@ -3850,26 +4142,26 @@ gettxseq(const struct ieee80211req_sta_info *si)
static int
getrxseq(const struct ieee80211req_sta_info *si)
{
- int i, rxseq;
+ int rxseq;
if ((si->isi_state & IEEE80211_NODE_QOS) == 0)
return si->isi_rxseqs[0];
/* XXX not right but usually what folks want */
rxseq = 0;
- for (i = 0; i < IEEE80211_TID_SIZE; i++)
+ for (unsigned int i = 0; i < IEEE80211_TID_SIZE; i++)
if (si->isi_rxseqs[i] > rxseq)
rxseq = si->isi_rxseqs[i];
return rxseq;
}
static void
-list_stations(int s)
+list_stations(if_ctx *ctx)
{
union {
struct ieee80211req_sta_req req;
uint8_t buf[24*1024];
} u;
- enum ieee80211_opmode opmode = get80211opmode(s);
+ enum ieee80211_opmode opmode = get80211opmode(ctx);
const uint8_t *cp;
int len;
@@ -3879,15 +4171,15 @@ list_stations(int s)
/*
* Get information about the associated AP.
*/
- (void) get80211(s, IEEE80211_IOC_BSSID,
+ (void) get80211(ctx, IEEE80211_IOC_BSSID,
u.req.is_u.macaddr, IEEE80211_ADDR_LEN);
}
- if (get80211len(s, IEEE80211_IOC_STA_INFO, &u, sizeof(u), &len) < 0)
+ if (get80211len(ctx, IEEE80211_IOC_STA_INFO, &u, sizeof(u), &len) < 0)
errx(1, "unable to get station information");
- if (len < sizeof(struct ieee80211req_sta_info))
+ if (len < (int)sizeof(struct ieee80211req_sta_info))
return;
- getchaninfo(s);
+ getchaninfo(ctx);
if (opmode == IEEE80211_M_MBSS)
printf("%-17.17s %4s %5s %5s %7s %4s %4s %4s %6s %6s\n"
@@ -3919,7 +4211,7 @@ list_stations(int s)
do {
const struct ieee80211req_sta_info *si;
- si = (const struct ieee80211req_sta_info *) cp;
+ si = (const struct ieee80211req_sta_info *)(const void *)cp;
if (si->isi_len < sizeof(*si))
break;
if (opmode == IEEE80211_M_MBSS)
@@ -3952,11 +4244,11 @@ list_stations(int s)
, getcaps(si->isi_capinfo)
, getflags(si->isi_state)
);
- printies(cp + si->isi_ie_off, si->isi_ie_len, 24);
+ printies(ctx, cp + si->isi_ie_off, si->isi_ie_len, 24);
printmimo(&si->isi_mimo);
printf("\n");
cp += si->isi_len, len -= si->isi_len;
- } while (len >= sizeof(struct ieee80211req_sta_info));
+ } while (len >= (int)sizeof(struct ieee80211req_sta_info));
}
static const char *
@@ -4090,13 +4382,13 @@ chanpref(const struct ieee80211_channel *c)
}
static void
-print_channels(int s, const struct ieee80211req_chaninfo *chans,
+print_channels(if_ctx *ctx, const struct ieee80211req_chaninfo *chans,
int allchans, int verb)
{
struct ieee80211req_chaninfo *achans;
uint8_t reported[IEEE80211_CHAN_BYTES];
const struct ieee80211_channel *c;
- int i, half;
+ unsigned int i, half;
achans = malloc(IEEE80211_CHANINFO_SPACE(chans));
if (achans == NULL)
@@ -4106,7 +4398,7 @@ print_channels(int s, const struct ieee80211req_chaninfo *chans,
if (!allchans) {
struct ieee80211req_chanlist active;
- if (get80211(s, IEEE80211_IOC_CHANLIST, &active, sizeof(active)) < 0)
+ if (get80211(ctx, IEEE80211_IOC_CHANLIST, &active, sizeof(active)) < 0)
errx(1, "unable to get active channel list");
for (i = 0; i < chans->ic_nchans; i++) {
c = &chans->ic_chans[i];
@@ -4159,10 +4451,10 @@ print_channels(int s, const struct ieee80211req_chaninfo *chans,
}
static void
-list_channels(int s, int allchans)
+list_channels(if_ctx *ctx, int allchans)
{
- getchaninfo(s);
- print_channels(s, chaninfo, allchans, verbose);
+ getchaninfo(ctx);
+ print_channels(ctx, chaninfo, allchans, ctx->args->verbose);
}
static void
@@ -4185,14 +4477,14 @@ print_txpow_verbose(const struct ieee80211_channel *c)
}
static void
-list_txpow(int s)
+list_txpow(if_ctx *ctx)
{
struct ieee80211req_chaninfo *achans;
uint8_t reported[IEEE80211_CHAN_BYTES];
struct ieee80211_channel *c, *prev;
- int i, half;
+ unsigned int i, half;
- getchaninfo(s);
+ getchaninfo(ctx);
achans = malloc(IEEE80211_CHANINFO_SPACE(chaninfo));
if (achans == NULL)
errx(1, "no space for active channel list");
@@ -4201,7 +4493,7 @@ list_txpow(int s)
for (i = 0; i < chaninfo->ic_nchans; i++) {
c = &chaninfo->ic_chans[i];
/* suppress duplicates as above */
- if (isset(reported, c->ic_ieee) && !verbose) {
+ if (isset(reported, c->ic_ieee) && !ctx->args->verbose) {
/* XXX we assume duplicates are adjacent */
assert(achans->ic_nchans > 0);
prev = &achans->ic_chans[achans->ic_nchans-1];
@@ -4213,7 +4505,7 @@ list_txpow(int s)
setbit(reported, c->ic_ieee);
}
}
- if (!verbose) {
+ if (!ctx->args->verbose) {
half = achans->ic_nchans / 2;
if (achans->ic_nchans % 2)
half++;
@@ -4237,14 +4529,15 @@ list_txpow(int s)
}
static void
-list_keys(int s)
+list_keys(int s __unused)
{
}
static void
-list_capabilities(int s)
+list_capabilities(if_ctx *ctx)
{
struct ieee80211_devcaps_req *dc;
+ const int verbose = ctx->args->verbose;
if (verbose)
dc = malloc(IEEE80211_DEVCAPS_SIZE(MAXCHAN));
@@ -4253,7 +4546,7 @@ list_capabilities(int s)
if (dc == NULL)
errx(1, "no space for device capabilities");
dc->dc_chaninfo.ic_nchans = verbose ? MAXCHAN : 1;
- getdevcaps(s, dc);
+ getdevcaps(ctx, dc);
printb("drivercaps", dc->dc_drivercaps, IEEE80211_C_BITS);
if (dc->dc_cryptocaps != 0 || verbose) {
putchar('\n');
@@ -4271,21 +4564,20 @@ list_capabilities(int s)
putchar('\n');
if (verbose) {
chaninfo = &dc->dc_chaninfo; /* XXX */
- print_channels(s, &dc->dc_chaninfo, 1/*allchans*/, verbose);
+ print_channels(ctx, &dc->dc_chaninfo, 1/*allchans*/, verbose);
}
free(dc);
}
static int
-get80211wme(int s, int param, int ac, int *val)
+get80211wme(if_ctx *ctx, int param, int ac, int *val)
{
- struct ieee80211req ireq;
+ struct ieee80211req ireq = {};
- (void) memset(&ireq, 0, sizeof(ireq));
- (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name));
+ strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name));
ireq.i_type = param;
ireq.i_len = ac;
- if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) {
warn("cannot get WME parameter %d, ac %d%s",
param, ac & IEEE80211_WMEPARAM_VAL,
ac & IEEE80211_WMEPARAM_BSS ? " (BSS)" : "");
@@ -4296,33 +4588,33 @@ get80211wme(int s, int param, int ac, int *val)
}
static void
-list_wme_aci(int s, const char *tag, int ac)
+list_wme_aci(if_ctx *ctx, const char *tag, int ac)
{
int val;
printf("\t%s", tag);
/* show WME BSS parameters */
- if (get80211wme(s, IEEE80211_IOC_WME_CWMIN, ac, &val) != -1)
+ if (get80211wme(ctx, IEEE80211_IOC_WME_CWMIN, ac, &val) != -1)
printf(" cwmin %2u", val);
- if (get80211wme(s, IEEE80211_IOC_WME_CWMAX, ac, &val) != -1)
+ if (get80211wme(ctx, IEEE80211_IOC_WME_CWMAX, ac, &val) != -1)
printf(" cwmax %2u", val);
- if (get80211wme(s, IEEE80211_IOC_WME_AIFS, ac, &val) != -1)
+ if (get80211wme(ctx, IEEE80211_IOC_WME_AIFS, ac, &val) != -1)
printf(" aifs %2u", val);
- if (get80211wme(s, IEEE80211_IOC_WME_TXOPLIMIT, ac, &val) != -1)
+ if (get80211wme(ctx, IEEE80211_IOC_WME_TXOPLIMIT, ac, &val) != -1)
printf(" txopLimit %3u", val);
- if (get80211wme(s, IEEE80211_IOC_WME_ACM, ac, &val) != -1) {
+ if (get80211wme(ctx, IEEE80211_IOC_WME_ACM, ac, &val) != -1) {
if (val)
printf(" acm");
- else if (verbose)
+ else if (ctx->args->verbose)
printf(" -acm");
}
/* !BSS only */
if ((ac & IEEE80211_WMEPARAM_BSS) == 0) {
- if (get80211wme(s, IEEE80211_IOC_WME_ACKPOLICY, ac, &val) != -1) {
+ if (get80211wme(ctx, IEEE80211_IOC_WME_ACKPOLICY, ac, &val) != -1) {
if (!val)
printf(" -ack");
- else if (verbose)
+ else if (ctx->args->verbose)
printf(" ack");
}
}
@@ -4330,19 +4622,19 @@ list_wme_aci(int s, const char *tag, int ac)
}
static void
-list_wme(int s)
+list_wme(if_ctx *ctx)
{
static const char *acnames[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" };
int ac;
- if (verbose) {
+ if (ctx->args->verbose) {
/* display both BSS and local settings */
for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++) {
again:
if (ac & IEEE80211_WMEPARAM_BSS)
- list_wme_aci(s, " ", ac);
+ list_wme_aci(ctx, " ", ac);
else
- list_wme_aci(s, acnames[ac], ac);
+ list_wme_aci(ctx, acnames[ac], ac);
if ((ac & IEEE80211_WMEPARAM_BSS) == 0) {
ac |= IEEE80211_WMEPARAM_BSS;
goto again;
@@ -4352,17 +4644,17 @@ list_wme(int s)
} else {
/* display only channel settings */
for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++)
- list_wme_aci(s, acnames[ac], ac);
+ list_wme_aci(ctx, acnames[ac], ac);
}
}
static void
-list_roam(int s)
+list_roam(if_ctx *ctx)
{
const struct ieee80211_roamparam *rp;
int mode;
- getroam(s);
+ getroam(ctx);
for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) {
rp = &roamparams.params[mode];
if (rp->rssi == 0 && rp->rate == 0)
@@ -4406,12 +4698,12 @@ get_rate_value(uint8_t rate)
}
static void
-list_txparams(int s)
+list_txparams(if_ctx *ctx)
{
const struct ieee80211_txparam *tp;
int mode;
- gettxparams(s);
+ gettxparams(ctx);
for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) {
tp = &txparams.params[mode];
if (tp->mgmtrate == 0 && tp->mcastrate == 0)
@@ -4479,19 +4771,18 @@ printpolicy(int policy)
}
static void
-list_mac(int s)
+list_mac(if_ctx *ctx)
{
- struct ieee80211req ireq;
+ struct ieee80211req ireq = {};
struct ieee80211req_maclist *acllist;
int i, nacls, policy, len;
uint8_t *data;
char c;
- (void) memset(&ireq, 0, sizeof(ireq));
- (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name)); /* XXX ?? */
+ strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name)); /* XXX ?? */
ireq.i_type = IEEE80211_IOC_MACCMD;
ireq.i_val = IEEE80211_MACCMD_POLICY;
- if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0) {
if (errno == EINVAL) {
printf("No acl policy loaded\n");
return;
@@ -4511,15 +4802,15 @@ list_mac(int s)
printf("policy: unknown (%u)\n", policy);
c = '?';
}
- if (verbose || c == '?')
+ if (ctx->args->verbose || c == '?')
printpolicy(policy);
ireq.i_val = IEEE80211_MACCMD_LIST;
ireq.i_len = 0;
- if (ioctl(s, SIOCG80211, &ireq) < 0)
+ if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0)
err(1, "unable to get mac acl list size");
if (ireq.i_len == 0) { /* NB: no acls */
- if (!(verbose || c == '?'))
+ if (!(ctx->args->verbose || c == '?'))
printpolicy(policy);
return;
}
@@ -4530,7 +4821,7 @@ list_mac(int s)
err(1, "out of memory for acl list");
ireq.i_data = data;
- if (ioctl(s, SIOCG80211, &ireq) < 0)
+ if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0)
err(1, "unable to get mac acl list");
nacls = len / sizeof(*acllist);
acllist = (struct ieee80211req_maclist *) data;
@@ -4573,33 +4864,32 @@ print_regdomain(const struct ieee80211_regdomain *reg, int verb)
}
static void
-list_regdomain(int s, int channelsalso)
+list_regdomain(if_ctx *ctx, int channelsalso)
{
- getregdomain(s);
+ getregdomain(ctx);
if (channelsalso) {
- getchaninfo(s);
+ getchaninfo(ctx);
spacer = ':';
print_regdomain(&regdomain, 1);
LINE_BREAK();
- print_channels(s, chaninfo, 1/*allchans*/, 1/*verbose*/);
+ print_channels(ctx, chaninfo, 1/*allchans*/, 1/*verbose*/);
} else
- print_regdomain(&regdomain, verbose);
+ print_regdomain(&regdomain, ctx->args->verbose);
}
static void
-list_mesh(int s)
+list_mesh(if_ctx *ctx)
{
- struct ieee80211req ireq;
+ struct ieee80211req ireq = {};
struct ieee80211req_mesh_route routes[128];
struct ieee80211req_mesh_route *rt;
- (void) memset(&ireq, 0, sizeof(ireq));
- (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name));
+ strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name));
ireq.i_type = IEEE80211_IOC_MESH_RTCMD;
ireq.i_val = IEEE80211_MESH_RTCMD_LIST;
ireq.i_data = &routes;
ireq.i_len = sizeof(routes);
- if (ioctl(s, SIOCG80211, &ireq) < 0)
+ if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0)
err(1, "unable to get the Mesh routing table");
printf("%-17.17s %-17.17s %4s %4s %4s %6s %s\n"
@@ -4611,7 +4901,8 @@ list_mesh(int s)
, "MSEQ"
, "FLAGS");
- for (rt = &routes[0]; rt - &routes[0] < ireq.i_len / sizeof(*rt); rt++){
+ for (unsigned int i = 0; i < ireq.i_len / sizeof(*rt); i++) {
+ rt = &routes[i];
printf("%s ",
ether_ntoa((const struct ether_addr *)rt->imr_dest));
printf("%s %4u %4u %6u %6u %c%c\n",
@@ -4629,56 +4920,56 @@ list_mesh(int s)
}
}
-static
-DECL_CMD_FUNC(set80211list, arg, d)
+static void
+set80211list(if_ctx *ctx, const char *arg, int dummy __unused)
{
+ int s = ctx->io_s;
#define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0)
LINE_INIT('\t');
if (iseq(arg, "sta"))
- list_stations(s);
+ list_stations(ctx);
else if (iseq(arg, "scan") || iseq(arg, "ap"))
- list_scan(s);
+ list_scan(ctx);
else if (iseq(arg, "chan") || iseq(arg, "freq"))
- list_channels(s, 1);
+ list_channels(ctx, 1);
else if (iseq(arg, "active"))
- list_channels(s, 0);
+ list_channels(ctx, 0);
else if (iseq(arg, "keys"))
list_keys(s);
else if (iseq(arg, "caps"))
- list_capabilities(s);
+ list_capabilities(ctx);
else if (iseq(arg, "wme") || iseq(arg, "wmm"))
- list_wme(s);
+ list_wme(ctx);
else if (iseq(arg, "mac"))
- list_mac(s);
+ list_mac(ctx);
else if (iseq(arg, "txpow"))
- list_txpow(s);
+ list_txpow(ctx);
else if (iseq(arg, "roam"))
- list_roam(s);
+ list_roam(ctx);
else if (iseq(arg, "txparam") || iseq(arg, "txparm"))
- list_txparams(s);
+ list_txparams(ctx);
else if (iseq(arg, "regdomain"))
- list_regdomain(s, 1);
+ list_regdomain(ctx, 1);
else if (iseq(arg, "countries"))
list_countries();
else if (iseq(arg, "mesh"))
- list_mesh(s);
+ list_mesh(ctx);
else
- errx(1, "Don't know how to list %s for %s", arg, name);
+ errx(1, "Don't know how to list %s for %s", arg, ctx->ifname);
LINE_BREAK();
#undef iseq
}
static enum ieee80211_opmode
-get80211opmode(int s)
+get80211opmode(if_ctx *ctx)
{
- struct ifmediareq ifmr;
+ struct ifmediareq ifmr = {};
- (void) memset(&ifmr, 0, sizeof(ifmr));
- (void) strlcpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
+ strlcpy(ifmr.ifm_name, ctx->ifname, sizeof(ifmr.ifm_name));
- if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
+ if (ioctl_ctx(ctx, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
if (ifmr.ifm_current & IFM_FLAG0)
return IEEE80211_M_AHDEMO;
@@ -4720,6 +5011,9 @@ printcipher(int s, struct ieee80211req *ireq, int keylenop)
case IEEE80211_CIPHER_AES_CCM:
printf("AES-CCM");
break;
+ case IEEE80211_CIPHER_AES_GCM_128:
+ printf("AES-GCM");
+ break;
case IEEE80211_CIPHER_CKIP:
printf("CKIP");
break;
@@ -4734,43 +5028,61 @@ printcipher(int s, struct ieee80211req *ireq, int keylenop)
#endif
static void
-printkey(const struct ieee80211req_key *ik)
+printkey_index(uint16_t keyix, char *buf, size_t buflen)
+{
+ buf[0] = '\0';
+ if (keyix == IEEE80211_KEYIX_NONE) {
+ snprintf(buf, buflen, "ucast");
+ } else {
+ snprintf(buf, buflen, "%u", keyix+1);
+ }
+}
+
+static void
+printkey(if_ctx *ctx, const struct ieee80211req_key *ik)
{
static const uint8_t zerodata[IEEE80211_KEYBUF_SIZE];
u_int keylen = ik->ik_keylen;
int printcontents;
+ const int verbose = ctx->args->verbose;
+ const bool printkeys = ctx->args->printkeys;
+ char keyix[16];
printcontents = printkeys &&
(memcmp(ik->ik_keydata, zerodata, keylen) != 0 || verbose);
if (printcontents)
LINE_BREAK();
+ printkey_index(ik->ik_keyix, keyix, sizeof(keyix));
switch (ik->ik_type) {
case IEEE80211_CIPHER_WEP:
/* compatibility */
- LINE_CHECK("wepkey %u:%s", ik->ik_keyix+1,
+ LINE_CHECK("wepkey %s:%s", keyix,
keylen <= 5 ? "40-bit" :
keylen <= 13 ? "104-bit" : "128-bit");
break;
case IEEE80211_CIPHER_TKIP:
if (keylen > 128/8)
keylen -= 128/8; /* ignore MIC for now */
- LINE_CHECK("TKIP %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ LINE_CHECK("TKIP %s:%u-bit", keyix, 8*keylen);
break;
case IEEE80211_CIPHER_AES_OCB:
- LINE_CHECK("AES-OCB %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ LINE_CHECK("AES-OCB %s:%u-bit", keyix, 8*keylen);
break;
case IEEE80211_CIPHER_AES_CCM:
- LINE_CHECK("AES-CCM %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ LINE_CHECK("AES-CCM %s:%u-bit", keyix, 8*keylen);
+ break;
+ case IEEE80211_CIPHER_AES_GCM_128:
+ LINE_CHECK("AES-GCM %s:%u-bit", keyix, 8*keylen);
break;
case IEEE80211_CIPHER_CKIP:
- LINE_CHECK("CKIP %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ LINE_CHECK("CKIP %s:%u-bit", keyix, 8*keylen);
break;
case IEEE80211_CIPHER_NONE:
- LINE_CHECK("NULL %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ LINE_CHECK("NULL %s:%u-bit", keyix, 8*keylen);
break;
default:
- LINE_CHECK("UNKNOWN (0x%x) %u:%u-bit",
- ik->ik_type, ik->ik_keyix+1, 8*keylen);
+ LINE_CHECK("UNKNOWN (0x%x) %s:%u-bit",
+ ik->ik_type, keyix, 8*keylen);
break;
}
if (printcontents) {
@@ -4817,51 +5129,52 @@ printrate(const char *tag, int v, int defrate, int defmcs)
}
static int
-getid(int s, int ix, void *data, size_t len, int *plen, int mesh)
+getid(if_ctx *ctx, int ix, void *data, size_t len, int *plen, int mesh)
{
- struct ieee80211req ireq;
+ struct ieee80211req ireq = {};
- (void) memset(&ireq, 0, sizeof(ireq));
- (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name));
+ strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name));
ireq.i_type = (!mesh) ? IEEE80211_IOC_SSID : IEEE80211_IOC_MESH_ID;
ireq.i_val = ix;
ireq.i_data = data;
ireq.i_len = len;
- if (ioctl(s, SIOCG80211, &ireq) < 0)
+ if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0)
return -1;
*plen = ireq.i_len;
return 0;
}
static int
-getdevicename(int s, void *data, size_t len, int *plen)
+getdevicename(if_ctx *ctx, void *data, size_t len, int *plen)
{
- struct ieee80211req ireq;
+ struct ieee80211req ireq = {};
- (void) memset(&ireq, 0, sizeof(ireq));
- (void) strlcpy(ireq.i_name, name, sizeof(ireq.i_name));
+ strlcpy(ireq.i_name, ctx->ifname, sizeof(ireq.i_name));
ireq.i_type = IEEE80211_IOC_IC_NAME;
ireq.i_val = -1;
ireq.i_data = data;
ireq.i_len = len;
- if (ioctl(s, SIOCG80211, &ireq) < 0)
+ if (ioctl_ctx(ctx, SIOCG80211, &ireq) < 0)
return (-1);
*plen = ireq.i_len;
return (0);
}
static void
-ieee80211_status(int s)
+ieee80211_status(if_ctx *ctx)
{
+ int s = ctx->io_s;
static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
- enum ieee80211_opmode opmode = get80211opmode(s);
+ uint8_t bssid[IEEE80211_ADDR_LEN];
+ enum ieee80211_opmode opmode = get80211opmode(ctx);
int i, num, wpa, wme, bgscan, bgscaninterval, val, len, wepmode;
uint8_t data[32];
const struct ieee80211_channel *c;
const struct ieee80211_roamparam *rp;
const struct ieee80211_txparam *tp;
+ const int verbose = ctx->args->verbose;
- if (getid(s, -1, data, sizeof(data), &len, 0) < 0) {
+ if (getid(ctx, -1, data, sizeof(data), &len, 0) < 0) {
/* If we can't get the SSID, this isn't an 802.11 device. */
return;
}
@@ -4879,15 +5192,15 @@ ieee80211_status(int s)
printf("\t");
if (opmode == IEEE80211_M_MBSS) {
printf("meshid ");
- getid(s, 0, data, sizeof(data), &len, 1);
+ getid(ctx, 0, data, sizeof(data), &len, 1);
print_string(data, len);
} else {
- if (get80211val(s, IEEE80211_IOC_NUMSSIDS, &num) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_NUMSSIDS, &num) < 0)
num = 0;
printf("ssid ");
if (num > 1) {
for (i = 0; i < num; i++) {
- if (getid(s, i, data, sizeof(data), &len, 0) >= 0 && len > 0) {
+ if (getid(ctx, i, data, sizeof(data), &len, 0) >= 0 && len > 0) {
printf(" %d:", i + 1);
print_string(data, len);
}
@@ -4895,7 +5208,7 @@ ieee80211_status(int s)
} else
print_string(data, len);
}
- c = getcurchan(s);
+ c = getcurchan(ctx);
if (c->ic_freq != IEEE80211_CHAN_ANY) {
char buf[14];
printf(" channel %d (%u MHz%s)", c->ic_ieee, c->ic_freq,
@@ -4903,11 +5216,13 @@ ieee80211_status(int s)
} else if (verbose)
printf(" channel UNDEF");
- if (get80211(s, IEEE80211_IOC_BSSID, data, IEEE80211_ADDR_LEN) >= 0 &&
- (memcmp(data, zerobssid, sizeof(zerobssid)) != 0 || verbose))
- printf(" bssid %s", ether_ntoa((struct ether_addr *)data));
+ if (get80211(ctx, IEEE80211_IOC_BSSID, bssid, IEEE80211_ADDR_LEN) >= 0 &&
+ (memcmp(bssid, zerobssid, sizeof(zerobssid)) != 0 || verbose)) {
+ printf(" bssid %s", ether_ntoa((struct ether_addr *)bssid));
+ printbssidname((struct ether_addr *)bssid);
+ }
- if (get80211len(s, IEEE80211_IOC_STATIONNAME, data, sizeof(data), &len) != -1) {
+ if (get80211len(ctx, IEEE80211_IOC_STATIONNAME, data, sizeof(data), &len) != -1) {
printf("\n\tstationname ");
print_string(data, len);
}
@@ -4915,10 +5230,10 @@ ieee80211_status(int s)
spacer = ' '; /* force first break */
LINE_BREAK();
- list_regdomain(s, 0);
+ list_regdomain(ctx, 0);
wpa = 0;
- if (get80211val(s, IEEE80211_IOC_AUTHMODE, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_AUTHMODE, &val) != -1) {
switch (val) {
case IEEE80211_AUTH_NONE:
LINE_CHECK("authmode NONE");
@@ -4933,7 +5248,7 @@ ieee80211_status(int s)
LINE_CHECK("authmode 802.1x");
break;
case IEEE80211_AUTH_WPA:
- if (get80211val(s, IEEE80211_IOC_WPA, &wpa) < 0)
+ if (get80211val(ctx, IEEE80211_IOC_WPA, &wpa) < 0)
wpa = 1; /* default to WPA1 */
switch (wpa) {
case 2:
@@ -4957,13 +5272,13 @@ ieee80211_status(int s)
}
if (wpa || verbose) {
- if (get80211val(s, IEEE80211_IOC_WPS, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_WPS, &val) != -1) {
if (val)
LINE_CHECK("wps");
else if (verbose)
LINE_CHECK("-wps");
}
- if (get80211val(s, IEEE80211_IOC_TSN, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_TSN, &val) != -1) {
if (val)
LINE_CHECK("tsn");
else if (verbose)
@@ -5008,7 +5323,7 @@ ieee80211_status(int s)
#endif
}
- if (get80211val(s, IEEE80211_IOC_WEP, &wepmode) != -1 &&
+ if (get80211val(ctx, IEEE80211_IOC_WEP, &wepmode) != -1 &&
wepmode != IEEE80211_WEP_NOSUP) {
switch (wepmode) {
@@ -5031,7 +5346,7 @@ ieee80211_status(int s)
* to print WEP status.
*/
- if (get80211val(s, IEEE80211_IOC_WEPTXKEY, &val) < 0) {
+ if (get80211val(ctx, IEEE80211_IOC_WEPTXKEY, &val) < 0) {
warn("WEP support, but no tx key!");
goto end;
}
@@ -5040,7 +5355,7 @@ ieee80211_status(int s)
else if (wepmode != IEEE80211_WEP_OFF || verbose)
LINE_CHECK("deftxkey UNDEF");
- if (get80211val(s, IEEE80211_IOC_NUMWEPKEYS, &num) < 0) {
+ if (get80211val(ctx, IEEE80211_IOC_NUMWEPKEYS, &num) < 0) {
warn("WEP support, but no NUMWEPKEYS support!");
goto end;
}
@@ -5050,14 +5365,29 @@ ieee80211_status(int s)
memset(&ik, 0, sizeof(ik));
ik.ik_keyix = i;
- if (get80211(s, IEEE80211_IOC_WPAKEY, &ik, sizeof(ik)) < 0) {
- warn("WEP support, but can get keys!");
+ if (get80211(ctx, IEEE80211_IOC_WPAKEY, &ik, sizeof(ik)) < 0) {
+ warn("WEP support, but cannot get keys!");
goto end;
}
if (ik.ik_keylen != 0) {
if (verbose)
LINE_BREAK();
- printkey(&ik);
+ printkey(ctx, &ik);
+ }
+ }
+ if (opmode == IEEE80211_M_STA && wpa >= 2) {
+ struct ieee80211req_key ik;
+ int error;
+
+ memset(&ik, 0, sizeof(ik));
+ ik.ik_keyix = IEEE80211_KEYIX_NONE;
+ memcpy(ik.ik_macaddr, bssid, sizeof(ik.ik_macaddr));
+ error = get80211(ctx, IEEE80211_IOC_WPAKEY, &ik, sizeof(ik));
+ if (error == 0 && ik.ik_keylen != 0) {
+ if (verbose)
+ LINE_BREAK();
+ printkey(ctx, &ik);
+ i++;
}
}
if (i > 0 && verbose)
@@ -5066,7 +5396,7 @@ end:
;
}
- if (get80211val(s, IEEE80211_IOC_POWERSAVE, &val) != -1 &&
+ if (get80211val(ctx, IEEE80211_IOC_POWERSAVE, &val) != -1 &&
val != IEEE80211_POWERSAVE_NOSUP ) {
if (val != IEEE80211_POWERSAVE_OFF || verbose) {
switch (val) {
@@ -5083,47 +5413,47 @@ end:
LINE_CHECK("powersavemode PSP-CAM");
break;
}
- if (get80211val(s, IEEE80211_IOC_POWERSAVESLEEP, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_POWERSAVESLEEP, &val) != -1)
LINE_CHECK("powersavesleep %d", val);
}
}
- if (get80211val(s, IEEE80211_IOC_TXPOWER, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_TXPOWER, &val) != -1) {
if (val & 1)
LINE_CHECK("txpower %d.5", val/2);
else
LINE_CHECK("txpower %d", val/2);
}
if (verbose) {
- if (get80211val(s, IEEE80211_IOC_TXPOWMAX, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_TXPOWMAX, &val) != -1)
LINE_CHECK("txpowmax %.1f", val/2.);
}
- if (get80211val(s, IEEE80211_IOC_DOTD, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_DOTD, &val) != -1) {
if (val)
LINE_CHECK("dotd");
else if (verbose)
LINE_CHECK("-dotd");
}
- if (get80211val(s, IEEE80211_IOC_RTSTHRESHOLD, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_RTSTHRESHOLD, &val) != -1) {
if (val != IEEE80211_RTS_MAX || verbose)
LINE_CHECK("rtsthreshold %d", val);
}
- if (get80211val(s, IEEE80211_IOC_FRAGTHRESHOLD, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_FRAGTHRESHOLD, &val) != -1) {
if (val != IEEE80211_FRAG_MAX || verbose)
LINE_CHECK("fragthreshold %d", val);
}
if (opmode == IEEE80211_M_STA || verbose) {
- if (get80211val(s, IEEE80211_IOC_BMISSTHRESHOLD, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_BMISSTHRESHOLD, &val) != -1) {
if (val != IEEE80211_HWBMISS_MAX || verbose)
LINE_CHECK("bmiss %d", val);
}
}
if (!verbose) {
- gettxparams(s);
+ gettxparams(ctx);
tp = &txparams.params[chan2mode(c)];
printrate("ucastrate", tp->ucastrate,
IEEE80211_FIXED_RATE_NONE, IEEE80211_FIXED_RATE_NONE);
@@ -5135,19 +5465,19 @@ end:
LINE_CHECK("maxretry %d", tp->maxretry);
} else {
LINE_BREAK();
- list_txparams(s);
+ list_txparams(ctx);
}
bgscaninterval = -1;
- (void) get80211val(s, IEEE80211_IOC_BGSCAN_INTERVAL, &bgscaninterval);
+ (void) get80211val(ctx, IEEE80211_IOC_BGSCAN_INTERVAL, &bgscaninterval);
- if (get80211val(s, IEEE80211_IOC_SCANVALID, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_SCANVALID, &val) != -1) {
if (val != bgscaninterval || verbose)
LINE_CHECK("scanvalid %u", val);
}
bgscan = 0;
- if (get80211val(s, IEEE80211_IOC_BGSCAN, &bgscan) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_BGSCAN, &bgscan) != -1) {
if (bgscan)
LINE_CHECK("bgscan");
else if (verbose)
@@ -5156,10 +5486,10 @@ end:
if (bgscan || verbose) {
if (bgscaninterval != -1)
LINE_CHECK("bgscanintvl %u", bgscaninterval);
- if (get80211val(s, IEEE80211_IOC_BGSCAN_IDLE, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_BGSCAN_IDLE, &val) != -1)
LINE_CHECK("bgscanidle %u", val);
if (!verbose) {
- getroam(s);
+ getroam(ctx);
rp = &roamparams.params[chan2mode(c)];
if (rp->rssi & 1)
LINE_CHECK("roam:rssi %u.5", rp->rssi/2);
@@ -5170,19 +5500,19 @@ end:
get_rate_value(rp->rate));
} else {
LINE_BREAK();
- list_roam(s);
+ list_roam(ctx);
LINE_BREAK();
}
}
if (IEEE80211_IS_CHAN_ANYG(c) || verbose) {
- if (get80211val(s, IEEE80211_IOC_PUREG, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_PUREG, &val) != -1) {
if (val)
LINE_CHECK("pureg");
else if (verbose)
LINE_CHECK("-pureg");
}
- if (get80211val(s, IEEE80211_IOC_PROTMODE, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_PROTMODE, &val) != -1) {
switch (val) {
case IEEE80211_PROTMODE_OFF:
LINE_CHECK("protmode OFF");
@@ -5201,7 +5531,7 @@ end:
}
if (IEEE80211_IS_CHAN_HT(c) || verbose) {
- gethtconf(s);
+ gethtconf(ctx);
switch (htconf & 3) {
case 0:
case 2:
@@ -5215,13 +5545,13 @@ end:
LINE_CHECK("ht");
break;
}
- if (get80211val(s, IEEE80211_IOC_HTCOMPAT, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_HTCOMPAT, &val) != -1) {
if (!val)
LINE_CHECK("-htcompat");
else if (verbose)
LINE_CHECK("htcompat");
}
- if (get80211val(s, IEEE80211_IOC_AMPDU, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_AMPDU, &val) != -1) {
switch (val) {
case 0:
LINE_CHECK("-ampdu");
@@ -5239,7 +5569,7 @@ end:
}
}
/* XXX 11ac density/size is different */
- if (get80211val(s, IEEE80211_IOC_AMPDU_LIMIT, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_AMPDU_LIMIT, &val) != -1) {
switch (val) {
case IEEE80211_HTCAP_MAXRXAMPDU_8K:
LINE_CHECK("ampdulimit 8k");
@@ -5256,7 +5586,7 @@ end:
}
}
/* XXX 11ac density/size is different */
- if (get80211val(s, IEEE80211_IOC_AMPDU_DENSITY, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_AMPDU_DENSITY, &val) != -1) {
switch (val) {
case IEEE80211_HTCAP_MPDUDENSITY_NA:
if (verbose)
@@ -5285,7 +5615,7 @@ end:
break;
}
}
- if (get80211val(s, IEEE80211_IOC_AMSDU, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_AMSDU, &val) != -1) {
switch (val) {
case 0:
LINE_CHECK("-amsdu");
@@ -5303,13 +5633,13 @@ end:
}
}
/* XXX amsdu limit */
- if (get80211val(s, IEEE80211_IOC_SHORTGI, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_SHORTGI, &val) != -1) {
if (val)
LINE_CHECK("shortgi");
else if (verbose)
LINE_CHECK("-shortgi");
}
- if (get80211val(s, IEEE80211_IOC_HTPROTMODE, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_HTPROTMODE, &val) != -1) {
if (val == IEEE80211_PROTMODE_OFF)
LINE_CHECK("htprotmode OFF");
else if (val != IEEE80211_PROTMODE_RTSCTS)
@@ -5317,13 +5647,13 @@ end:
else if (verbose)
LINE_CHECK("htprotmode RTSCTS");
}
- if (get80211val(s, IEEE80211_IOC_PUREN, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_PUREN, &val) != -1) {
if (val)
LINE_CHECK("puren");
else if (verbose)
LINE_CHECK("-puren");
}
- if (get80211val(s, IEEE80211_IOC_SMPS, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_SMPS, &val) != -1) {
if (val == IEEE80211_HTCAP_SMPS_DYNAMIC)
LINE_CHECK("smpsdyn");
else if (val == IEEE80211_HTCAP_SMPS_ENA)
@@ -5331,7 +5661,7 @@ end:
else if (verbose)
LINE_CHECK("-smps");
}
- if (get80211val(s, IEEE80211_IOC_RIFS, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_RIFS, &val) != -1) {
if (val)
LINE_CHECK("rifs");
else if (verbose)
@@ -5339,7 +5669,7 @@ end:
}
/* XXX VHT STBC? */
- if (get80211val(s, IEEE80211_IOC_STBC, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_STBC, &val) != -1) {
switch (val) {
case 0:
LINE_CHECK("-stbc");
@@ -5356,7 +5686,7 @@ end:
break;
}
}
- if (get80211val(s, IEEE80211_IOC_LDPC, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_LDPC, &val) != -1) {
switch (val) {
case 0:
LINE_CHECK("-ldpc");
@@ -5373,7 +5703,7 @@ end:
break;
}
}
- if (get80211val(s, IEEE80211_IOC_UAPSD, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_UAPSD, &val) != -1) {
switch (val) {
case 0:
LINE_CHECK("-uapsd");
@@ -5386,30 +5716,31 @@ end:
}
if (IEEE80211_IS_CHAN_VHT(c) || verbose) {
- getvhtconf(s);
- if (vhtconf & IEEE80211_FVHT_VHT)
+ getvhtconf(ctx);
+ if (vhtconf & IEEE80211_FVHT_VHT) {
LINE_CHECK("vht");
- else
+
+ if (vhtconf & IEEE80211_FVHT_USEVHT40)
+ LINE_CHECK("vht40");
+ else
+ LINE_CHECK("-vht40");
+ if (vhtconf & IEEE80211_FVHT_USEVHT80)
+ LINE_CHECK("vht80");
+ else
+ LINE_CHECK("-vht80");
+ if (vhtconf & IEEE80211_FVHT_USEVHT160)
+ LINE_CHECK("vht160");
+ else
+ LINE_CHECK("-vht160");
+ if (vhtconf & IEEE80211_FVHT_USEVHT80P80)
+ LINE_CHECK("vht80p80");
+ else
+ LINE_CHECK("-vht80p80");
+ } else if (verbose)
LINE_CHECK("-vht");
- if (vhtconf & IEEE80211_FVHT_USEVHT40)
- LINE_CHECK("vht40");
- else
- LINE_CHECK("-vht40");
- if (vhtconf & IEEE80211_FVHT_USEVHT80)
- LINE_CHECK("vht80");
- else
- LINE_CHECK("-vht80");
- if (vhtconf & IEEE80211_FVHT_USEVHT160)
- LINE_CHECK("vht160");
- else
- LINE_CHECK("-vht160");
- if (vhtconf & IEEE80211_FVHT_USEVHT80P80)
- LINE_CHECK("vht80p80");
- else
- LINE_CHECK("-vht80p80");
}
- if (get80211val(s, IEEE80211_IOC_WME, &wme) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_WME, &wme) != -1) {
if (wme)
LINE_CHECK("wme");
else if (verbose)
@@ -5417,26 +5748,26 @@ end:
} else
wme = 0;
- if (get80211val(s, IEEE80211_IOC_BURST, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_BURST, &val) != -1) {
if (val)
LINE_CHECK("burst");
else if (verbose)
LINE_CHECK("-burst");
}
- if (get80211val(s, IEEE80211_IOC_FF, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_FF, &val) != -1) {
if (val)
LINE_CHECK("ff");
else if (verbose)
LINE_CHECK("-ff");
}
- if (get80211val(s, IEEE80211_IOC_TURBOP, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_TURBOP, &val) != -1) {
if (val)
LINE_CHECK("dturbo");
else if (verbose)
LINE_CHECK("-dturbo");
}
- if (get80211val(s, IEEE80211_IOC_DWDS, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_DWDS, &val) != -1) {
if (val)
LINE_CHECK("dwds");
else if (verbose)
@@ -5444,41 +5775,41 @@ end:
}
if (opmode == IEEE80211_M_HOSTAP) {
- if (get80211val(s, IEEE80211_IOC_HIDESSID, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_HIDESSID, &val) != -1) {
if (val)
LINE_CHECK("hidessid");
else if (verbose)
LINE_CHECK("-hidessid");
}
- if (get80211val(s, IEEE80211_IOC_APBRIDGE, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_APBRIDGE, &val) != -1) {
if (!val)
LINE_CHECK("-apbridge");
else if (verbose)
LINE_CHECK("apbridge");
}
- if (get80211val(s, IEEE80211_IOC_DTIM_PERIOD, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_DTIM_PERIOD, &val) != -1)
LINE_CHECK("dtimperiod %u", val);
- if (get80211val(s, IEEE80211_IOC_DOTH, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_DOTH, &val) != -1) {
if (!val)
LINE_CHECK("-doth");
else if (verbose)
LINE_CHECK("doth");
}
- if (get80211val(s, IEEE80211_IOC_DFS, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_DFS, &val) != -1) {
if (!val)
LINE_CHECK("-dfs");
else if (verbose)
LINE_CHECK("dfs");
}
- if (get80211val(s, IEEE80211_IOC_INACTIVITY, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_INACTIVITY, &val) != -1) {
if (!val)
LINE_CHECK("-inact");
else if (verbose)
LINE_CHECK("inact");
}
} else {
- if (get80211val(s, IEEE80211_IOC_ROAMING, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_ROAMING, &val) != -1) {
if (val != IEEE80211_ROAMING_AUTO || verbose) {
switch (val) {
case IEEE80211_ROAMING_DEVICE:
@@ -5500,15 +5831,15 @@ end:
}
if (opmode == IEEE80211_M_AHDEMO) {
- if (get80211val(s, IEEE80211_IOC_TDMA_SLOT, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_TDMA_SLOT, &val) != -1)
LINE_CHECK("tdmaslot %u", val);
- if (get80211val(s, IEEE80211_IOC_TDMA_SLOTCNT, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_TDMA_SLOTCNT, &val) != -1)
LINE_CHECK("tdmaslotcnt %u", val);
- if (get80211val(s, IEEE80211_IOC_TDMA_SLOTLEN, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_TDMA_SLOTLEN, &val) != -1)
LINE_CHECK("tdmaslotlen %u", val);
- if (get80211val(s, IEEE80211_IOC_TDMA_BINTERVAL, &val) != -1)
+ if (get80211val(ctx, IEEE80211_IOC_TDMA_BINTERVAL, &val) != -1)
LINE_CHECK("tdmabintval %u", val);
- } else if (get80211val(s, IEEE80211_IOC_BEACON_INTERVAL, &val) != -1) {
+ } else if (get80211val(ctx, IEEE80211_IOC_BEACON_INTERVAL, &val) != -1) {
/* XXX default define not visible */
if (val != 100 || verbose)
LINE_CHECK("bintval %u", val);
@@ -5516,42 +5847,42 @@ end:
if (wme && verbose) {
LINE_BREAK();
- list_wme(s);
+ list_wme(ctx);
}
if (opmode == IEEE80211_M_MBSS) {
- if (get80211val(s, IEEE80211_IOC_MESH_TTL, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_MESH_TTL, &val) != -1) {
LINE_CHECK("meshttl %u", val);
}
- if (get80211val(s, IEEE80211_IOC_MESH_AP, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_MESH_AP, &val) != -1) {
if (val)
LINE_CHECK("meshpeering");
else
LINE_CHECK("-meshpeering");
}
- if (get80211val(s, IEEE80211_IOC_MESH_FWRD, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_MESH_FWRD, &val) != -1) {
if (val)
LINE_CHECK("meshforward");
else
LINE_CHECK("-meshforward");
}
- if (get80211val(s, IEEE80211_IOC_MESH_GATE, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_MESH_GATE, &val) != -1) {
if (val)
LINE_CHECK("meshgate");
else
LINE_CHECK("-meshgate");
}
- if (get80211len(s, IEEE80211_IOC_MESH_PR_METRIC, data, 12,
+ if (get80211len(ctx, IEEE80211_IOC_MESH_PR_METRIC, data, 12,
&len) != -1) {
data[len] = '\0';
LINE_CHECK("meshmetric %s", data);
}
- if (get80211len(s, IEEE80211_IOC_MESH_PR_PATH, data, 12,
+ if (get80211len(ctx, IEEE80211_IOC_MESH_PR_PATH, data, 12,
&len) != -1) {
data[len] = '\0';
LINE_CHECK("meshpath %s", data);
}
- if (get80211val(s, IEEE80211_IOC_HWMP_ROOTMODE, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_HWMP_ROOTMODE, &val) != -1) {
switch (val) {
case IEEE80211_HWMP_ROOTMODE_DISABLED:
LINE_CHECK("hwmprootmode DISABLED");
@@ -5570,14 +5901,14 @@ end:
break;
}
}
- if (get80211val(s, IEEE80211_IOC_HWMP_MAXHOPS, &val) != -1) {
+ if (get80211val(ctx, IEEE80211_IOC_HWMP_MAXHOPS, &val) != -1) {
LINE_CHECK("hwmpmaxhops %u", val);
}
}
LINE_BREAK();
- if (getdevicename(s, data, sizeof(data), &len) < 0)
+ if (getdevicename(ctx, data, sizeof(data), &len) < 0)
return;
LINE_CHECK("parent interface: %s", data);
@@ -5585,32 +5916,32 @@ end:
}
static int
-get80211(int s, int type, void *data, int len)
+get80211(if_ctx *ctx, int type, void *data, int len)
{
- return (lib80211_get80211(s, name, type, data, len));
+ return (lib80211_get80211(ctx->io_s, ctx->ifname, type, data, len));
}
static int
-get80211len(int s, int type, void *data, int len, int *plen)
+get80211len(if_ctx *ctx, int type, void *data, int len, int *plen)
{
- return (lib80211_get80211len(s, name, type, data, len, plen));
+ return (lib80211_get80211len(ctx->io_s, ctx->ifname, type, data, len, plen));
}
static int
-get80211val(int s, int type, int *val)
+get80211val(if_ctx *ctx, int type, int *val)
{
- return (lib80211_get80211val(s, name, type, val));
+ return (lib80211_get80211val(ctx->io_s, ctx->ifname, type, val));
}
static void
-set80211(int s, int type, int val, int len, void *data)
+set80211(if_ctx *ctx, int type, int val, int len, void *data)
{
int ret;
- ret = lib80211_set80211(s, name, type, val, len, data);
+ ret = lib80211_set80211(ctx->io_s, ctx->ifname, type, val, len, data);
if (ret < 0)
err(1, "SIOCS80211");
}
@@ -5703,7 +6034,7 @@ print_string(const u_int8_t *buf, int len)
}
static void
-setdefregdomain(int s)
+setdefregdomain(if_ctx *ctx)
{
struct regdata *rdp = getregdata();
const struct regdomain *rd;
@@ -5714,7 +6045,7 @@ setdefregdomain(int s)
regdomain.country != CTRY_DEFAULT)
return;
- getregdomain(s);
+ getregdomain(ctx);
/* Check if it was already set by the driver. */
if (regdomain.regdomain != 0 ||
@@ -5731,9 +6062,9 @@ setdefregdomain(int s)
defaultcountry(rd);
/* Send changes to net80211. */
- setregdomain_cb(s, &regdomain);
+ setregdomain_cb(ctx, &regdomain);
- /* Cleanup (so it can be overriden by subsequent parameters). */
+ /* Cleanup (so it can be overridden by subsequent parameters). */
regdomain.regdomain = 0;
regdomain.country = CTRY_DEFAULT;
regdomain.isocc[0] = 0;
@@ -5748,10 +6079,9 @@ static struct ieee80211_clone_params params = {
};
static void
-wlan_create(int s, struct ifreq *ifr)
+wlan_create(if_ctx *ctx, struct ifreq *ifr)
{
static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
- char orig_name[IFNAMSIZ];
if (params.icp_parent[0] == '\0')
errx(1, "must specify a parent device (wlandev) when creating "
@@ -5760,25 +6090,19 @@ wlan_create(int s, struct ifreq *ifr)
memcmp(params.icp_bssid, zerobssid, sizeof(zerobssid)) == 0)
errx(1, "no bssid specified for WDS (use wlanbssid)");
ifr->ifr_data = (caddr_t) &params;
- ioctl_ifcreate(s, ifr);
-
- /* XXX preserve original name for ifclonecreate(). */
- strlcpy(orig_name, name, sizeof(orig_name));
- strlcpy(name, ifr->ifr_name, sizeof(name));
+ ifcreate_ioctl(ctx, ifr);
- setdefregdomain(s);
-
- strlcpy(name, orig_name, sizeof(name));
+ setdefregdomain(ctx);
}
-static
-DECL_CMD_FUNC(set80211clone_wlandev, arg, d)
+static void
+set80211clone_wlandev(if_ctx *ctx __unused, const char *arg, int dummy __unused)
{
strlcpy(params.icp_parent, arg, IFNAMSIZ);
}
-static
-DECL_CMD_FUNC(set80211clone_wlanbssid, arg, d)
+static void
+set80211clone_wlanbssid(if_ctx *ctx __unused, const char *arg, int dummy __unused)
{
const struct ether_addr *ea;
@@ -5788,8 +6112,8 @@ DECL_CMD_FUNC(set80211clone_wlanbssid, arg, d)
memcpy(params.icp_bssid, ea->octet, IEEE80211_ADDR_LEN);
}
-static
-DECL_CMD_FUNC(set80211clone_wlanaddr, arg, d)
+static void
+set80211clone_wlanaddr(if_ctx *ctx __unused, const char *arg, int dummy __unused)
{
const struct ether_addr *ea;
@@ -5800,8 +6124,8 @@ DECL_CMD_FUNC(set80211clone_wlanaddr, arg, d)
params.icp_flags |= IEEE80211_CLONE_MACADDR;
}
-static
-DECL_CMD_FUNC(set80211clone_wlanmode, arg, d)
+static void
+set80211clone_wlanmode(if_ctx *ctx, const char *arg, int dummy __unused)
{
#define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0)
if (iseq(arg, "sta"))
@@ -5822,12 +6146,12 @@ DECL_CMD_FUNC(set80211clone_wlanmode, arg, d)
} else if (iseq(arg, "mesh") || iseq(arg, "mp")) /* mesh point */
params.icp_opmode = IEEE80211_M_MBSS;
else
- errx(1, "Don't know to create %s for %s", arg, name);
+ errx(1, "Don't know to create %s for %s", arg, ctx->ifname);
#undef iseq
}
static void
-set80211clone_beacons(const char *val, int d, int s, const struct afswtch *rafp)
+set80211clone_beacons(if_ctx *ctx __unused, const char *val __unused, int d)
{
/* NB: inverted sense */
if (d)
@@ -5837,7 +6161,7 @@ set80211clone_beacons(const char *val, int d, int s, const struct afswtch *rafp)
}
static void
-set80211clone_bssid(const char *val, int d, int s, const struct afswtch *rafp)
+set80211clone_bssid(if_ctx *ctx __unused, const char *val __unused, int d)
{
if (d)
params.icp_flags |= IEEE80211_CLONE_BSSID;
@@ -5846,7 +6170,7 @@ set80211clone_bssid(const char *val, int d, int s, const struct afswtch *rafp)
}
static void
-set80211clone_wdslegacy(const char *val, int d, int s, const struct afswtch *rafp)
+set80211clone_wdslegacy(if_ctx *ctx __unused, const char *val __unused, int d)
{
if (d)
params.icp_flags |= IEEE80211_CLONE_WDSLEGACY;
@@ -6007,7 +6331,7 @@ static struct cmd ieee80211_cmds[] = {
DEF_CMD("ht", 3, set80211htconf), /* NB: 20+40 */
DEF_CMD("-ht", 0, set80211htconf),
DEF_CMD("vht", IEEE80211_FVHT_VHT, set80211vhtconf),
- DEF_CMD("-vht", 0, set80211vhtconf),
+ DEF_CMD("-vht", -IEEE80211_FVHT_VHT, set80211vhtconf),
DEF_CMD("vht40", IEEE80211_FVHT_USEVHT40, set80211vhtconf),
DEF_CMD("-vht40", -IEEE80211_FVHT_USEVHT40, set80211vhtconf),
DEF_CMD("vht80", IEEE80211_FVHT_USEVHT80, set80211vhtconf),
@@ -6016,6 +6340,12 @@ static struct cmd ieee80211_cmds[] = {
DEF_CMD("-vht160", -IEEE80211_FVHT_USEVHT160, set80211vhtconf),
DEF_CMD("vht80p80", IEEE80211_FVHT_USEVHT80P80, set80211vhtconf),
DEF_CMD("-vht80p80", -IEEE80211_FVHT_USEVHT80P80, set80211vhtconf),
+ DEF_CMD("vhtstbctx", IEEE80211_FVHT_STBC_TX, set80211vhtconf),
+ DEF_CMD("-vhtstbctx", -IEEE80211_FVHT_STBC_TX, set80211vhtconf),
+ DEF_CMD("vhtstbcrx", IEEE80211_FVHT_STBC_RX, set80211vhtconf),
+ DEF_CMD("-vhtstbcrx", -IEEE80211_FVHT_STBC_RX, set80211vhtconf),
+ DEF_CMD("vhtstbc", (IEEE80211_FVHT_STBC_TX|IEEE80211_FVHT_STBC_RX), set80211vhtconf),
+ DEF_CMD("-vhtstbc", -(IEEE80211_FVHT_STBC_TX|IEEE80211_FVHT_STBC_RX), set80211vhtconf),
DEF_CMD("rifs", 1, set80211rifs),
DEF_CMD("-rifs", 0, set80211rifs),
DEF_CMD("smps", IEEE80211_HTCAP_SMPS_ENA, set80211smps),
@@ -6065,9 +6395,7 @@ static struct afswtch af_ieee80211 = {
static __constructor void
ieee80211_ctor(void)
{
- int i;
-
- for (i = 0; i < nitems(ieee80211_cmds); i++)
+ for (size_t i = 0; i < nitems(ieee80211_cmds); i++)
cmd_register(&ieee80211_cmds[i]);
af_register(&af_ieee80211);
clone_setdefcallback_prefix("wlan", wlan_create);
diff --git a/sbin/ifconfig/ifipsec.c b/sbin/ifconfig/ifipsec.c
index 0e615a27e205..b8ab38d6165a 100644
--- a/sbin/ifconfig/ifipsec.c
+++ b/sbin/ifconfig/ifipsec.c
@@ -25,9 +25,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -51,30 +48,29 @@ __FBSDID("$FreeBSD$");
#include "ifconfig.h"
static void
-ipsec_status(int s)
+ipsec_status(if_ctx *ctx)
{
uint32_t reqid;
+ struct ifreq ifr = { .ifr_data = (caddr_t)&reqid };
- ifr.ifr_data = (caddr_t)&reqid;
- if (ioctl(s, IPSECGREQID, &ifr) == -1)
+ if (ioctl_ctx_ifr(ctx, IPSECGREQID, &ifr) == -1)
return;
printf("\treqid: %u\n", reqid);
}
-static
-DECL_CMD_FUNC(setreqid, val, arg)
+static void
+setreqid(if_ctx *ctx, const char *val, int dummy __unused)
{
char *ep;
uint32_t v;
+ struct ifreq ifr = { .ifr_data = (caddr_t)&v };
v = strtoul(val, &ep, 0);
if (*ep != '\0') {
warn("Invalid reqid value %s", val);
return;
}
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- ifr.ifr_data = (char *)&v;
- if (ioctl(s, IPSECSREQID, &ifr) == -1) {
+ if (ioctl_ctx_ifr(ctx, IPSECSREQID, &ifr) == -1) {
warn("ioctl(IPSECSREQID)");
return;
}
diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c
index 48d7450076a9..4de437d25bd9 100644
--- a/sbin/ifconfig/iflagg.c
+++ b/sbin/ifconfig/iflagg.c
@@ -1,11 +1,6 @@
/*-
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -39,12 +34,11 @@ static struct iflaggparam params = {
static char lacpbuf[120]; /* LACP peer '[(a,a,a),(p,p,p)]' */
static void
-setlaggport(const char *val, int d, int s, const struct afswtch *afp)
+setlaggport(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct lagg_reqport rp;
+ struct lagg_reqport rp = {};
- bzero(&rp, sizeof(rp));
- strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
+ strlcpy(rp.rp_ifname, ctx->ifname, sizeof(rp.rp_ifname));
strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
/*
@@ -53,37 +47,35 @@ setlaggport(const char *val, int d, int s, const struct afswtch *afp)
*
* Don't error at all if the port is already in the lagg.
*/
- if (ioctl(s, SIOCSLAGGPORT, &rp) && errno != EEXIST) {
+ if (ioctl_ctx(ctx, SIOCSLAGGPORT, &rp) && errno != EEXIST) {
warnx("%s %s: SIOCSLAGGPORT: %s",
- name, val, strerror(errno));
+ ctx->ifname, val, strerror(errno));
exit_code = 1;
}
}
static void
-unsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
+unsetlaggport(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct lagg_reqport rp;
+ struct lagg_reqport rp = {};
- bzero(&rp, sizeof(rp));
- strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
+ strlcpy(rp.rp_ifname, ctx->ifname, sizeof(rp.rp_ifname));
strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
- if (ioctl(s, SIOCSLAGGDELPORT, &rp))
+ if (ioctl_ctx(ctx, SIOCSLAGGDELPORT, &rp))
err(1, "SIOCSLAGGDELPORT");
}
static void
-setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
+setlaggproto(if_ctx *ctx, const char *val, int dummy __unused)
{
struct lagg_protos lpr[] = LAGG_PROTOS;
struct lagg_reqall ra;
- int i;
bzero(&ra, sizeof(ra));
ra.ra_proto = LAGG_PROTO_MAX;
- for (i = 0; i < nitems(lpr); i++) {
+ for (size_t i = 0; i < nitems(lpr); i++) {
if (strcmp(val, lpr[i].lpr_name) == 0) {
ra.ra_proto = lpr[i].lpr_proto;
break;
@@ -92,49 +84,46 @@ setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
if (ra.ra_proto == LAGG_PROTO_MAX)
errx(1, "Invalid aggregation protocol: %s", val);
- strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
- if (ioctl(s, SIOCSLAGG, &ra) != 0)
+ strlcpy(ra.ra_ifname, ctx->ifname, sizeof(ra.ra_ifname));
+ if (ioctl_ctx(ctx, SIOCSLAGG, &ra) != 0)
err(1, "SIOCSLAGG");
}
static void
-setlaggflowidshift(const char *val, int d, int s, const struct afswtch *afp)
+setlaggflowidshift(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct lagg_reqopts ro;
+ struct lagg_reqopts ro = {};
- bzero(&ro, sizeof(ro));
ro.ro_opts = LAGG_OPT_FLOWIDSHIFT;
- strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
+ strlcpy(ro.ro_ifname, ctx->ifname, sizeof(ro.ro_ifname));
ro.ro_flowid_shift = (int)strtol(val, NULL, 10);
if (ro.ro_flowid_shift & ~LAGG_OPT_FLOWIDSHIFT_MASK)
errx(1, "Invalid flowid_shift option: %s", val);
- if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
+ if (ioctl_ctx(ctx, SIOCSLAGGOPTS, &ro) != 0)
err(1, "SIOCSLAGGOPTS");
}
static void
-setlaggrr_limit(const char *val, int d, int s, const struct afswtch *afp)
+setlaggrr_limit(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct lagg_reqopts ro;
+ struct lagg_reqopts ro = {};
- bzero(&ro, sizeof(ro));
- strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
+ strlcpy(ro.ro_ifname, ctx->ifname, sizeof(ro.ro_ifname));
ro.ro_opts = LAGG_OPT_RR_LIMIT;
ro.ro_bkt = (uint32_t)strtoul(val, NULL, 10);
if (ro.ro_bkt == 0)
errx(1, "Invalid round-robin stride: %s", val);
- if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
+ if (ioctl_ctx(ctx, SIOCSLAGGOPTS, &ro) != 0)
err(1, "SIOCSLAGGOPTS");
}
static void
-setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp)
+setlaggsetopt(if_ctx *ctx, const char *val __unused, int d)
{
- struct lagg_reqopts ro;
+ struct lagg_reqopts ro = {};
- bzero(&ro, sizeof(ro));
ro.ro_opts = d;
switch (ro.ro_opts) {
case LAGG_OPT_USE_FLOWID:
@@ -153,14 +142,14 @@ setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp)
default:
err(1, "Invalid lagg option");
}
- strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
+ strlcpy(ro.ro_ifname, ctx->ifname, sizeof(ro.ro_ifname));
- if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
+ if (ioctl_ctx(ctx, SIOCSLAGGOPTS, &ro) != 0)
err(1, "SIOCSLAGGOPTS");
}
static void
-setlagghash(const char *val, int d, int s, const struct afswtch *afp)
+setlagghash(if_ctx *ctx, const char *val, int dummy __unused)
{
struct lagg_reqflags rf;
char *str, *tmp, *tok;
@@ -182,8 +171,8 @@ setlagghash(const char *val, int d, int s, const struct afswtch *afp)
if (rf.rf_flags == 0)
errx(1, "No lagghash options supplied");
- strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname));
- if (ioctl(s, SIOCSLAGGHASH, &rf))
+ strlcpy(rf.rf_ifname, ctx->ifname, sizeof(rf.rf_ifname));
+ if (ioctl_ctx(ctx, SIOCSLAGGHASH, &rf))
err(1, "SIOCSLAGGHASH");
}
@@ -216,7 +205,7 @@ lacp_format_peer(struct lacp_opreq *req, const char *sep)
}
static void
-lagg_status(int s)
+lagg_status(if_ctx *ctx)
{
struct lagg_protos protos[] = LAGG_PROTOS;
struct ifconfig_lagg_status *lagg;
@@ -226,8 +215,9 @@ lagg_status(int s)
struct lagg_reqport *ports;
struct lacp_opreq *lp;
const char *proto;
+ const int verbose = ctx->args->verbose;
- if (ifconfig_lagg_get_lagg_status(lifh, name, &lagg) == -1)
+ if (ifconfig_lagg_get_lagg_status(lifh, ctx->ifname, &lagg) == -1)
return;
ra = lagg->ra;
@@ -279,7 +269,7 @@ lagg_status(int s)
}
}
- for (size_t i = 0; i < ra->ra_ports; ++i) {
+ for (size_t i = 0; i < (size_t)ra->ra_ports; ++i) {
lp = &ports[i].rp_lacpreq;
printf("\tlaggport: %s ", ports[i].rp_portname);
printb("flags", ports[i].rp_flags, LAGG_PORT_BITS);
@@ -294,13 +284,12 @@ lagg_status(int s)
ifconfig_lagg_free_lagg_status(lagg);
}
-static
-DECL_CMD_FUNC(setlaggtype, arg, d)
+static void
+setlaggtype(if_ctx *ctx __unused, const char *arg, int dummy __unused)
{
static const struct lagg_types lt[] = LAGG_TYPES;
- int i;
- for (i = 0; i < nitems(lt); i++) {
+ for (size_t i = 0; i < nitems(lt); i++) {
if (strcmp(arg, lt[i].lt_name) == 0) {
params.lagg_type = lt[i].lt_value;
return;
@@ -310,10 +299,10 @@ DECL_CMD_FUNC(setlaggtype, arg, d)
}
static void
-lagg_create(int s, struct ifreq *ifr)
+lagg_create(if_ctx *ctx, struct ifreq *ifr)
{
ifr->ifr_data = (caddr_t) &params;
- ioctl_ifcreate(s, ifr);
+ ifcreate_ioctl(ctx, ifr);
}
static struct cmd lagg_cmds[] = {
@@ -346,9 +335,7 @@ static struct afswtch af_lagg = {
static __constructor void
lagg_ctor(void)
{
- int i;
-
- for (i = 0; i < nitems(lagg_cmds); i++)
+ for (size_t i = 0; i < nitems(lagg_cmds); i++)
cmd_register(&lagg_cmds[i]);
af_register(&af_lagg);
clone_setdefcallback_prefix("lagg", lagg_create);
diff --git a/sbin/ifconfig/ifmac.c b/sbin/ifconfig/ifmac.c
index 31f4e970951c..278d2e79592f 100644
--- a/sbin/ifconfig/ifmac.c
+++ b/sbin/ifconfig/ifmac.c
@@ -32,8 +32,6 @@
* 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>
@@ -52,19 +50,19 @@
#include "ifconfig.h"
static void
-maclabel_status(int s)
+maclabel_status(if_ctx *ctx)
{
struct ifreq ifr;
mac_t label;
char *label_text;
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
if (mac_prepare_ifnet_label(&label) == -1)
return;
ifr.ifr_ifru.ifru_data = (void *)label;
- if (ioctl(s, SIOCGIFMAC, &ifr) == -1)
+ if (ioctl_ctx(ctx, SIOCGIFMAC, &ifr) == -1)
goto mac_free;
@@ -80,7 +78,7 @@ mac_free:
}
static void
-setifmaclabel(const char *val, int d, int s, const struct afswtch *rafp)
+setifmaclabel(if_ctx *ctx, const char *val, int d __unused)
{
struct ifreq ifr;
mac_t label;
@@ -92,10 +90,10 @@ setifmaclabel(const char *val, int d, int s, const struct afswtch *rafp)
}
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
ifr.ifr_ifru.ifru_data = (void *)label;
- error = ioctl(s, SIOCSIFMAC, &ifr);
+ error = ioctl(ctx->io_s, SIOCSIFMAC, &ifr);
mac_free(label);
if (error == -1)
perror("setifmac");
diff --git a/sbin/ifconfig/ifmedia.c b/sbin/ifconfig/ifmedia.c
index aacf34a13248..8f355bc5187f 100644
--- a/sbin/ifconfig/ifmedia.c
+++ b/sbin/ifconfig/ifmedia.c
@@ -1,5 +1,4 @@
/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
-/* $FreeBSD$ */
/*-
* SPDX-License-Identifier: BSD-4-Clause
@@ -90,7 +89,7 @@
#include "ifconfig.h"
-static void domediaopt(const char *, bool, int);
+static void domediaopt(if_ctx *, const char *, bool);
static ifmedia_t get_media_subtype(ifmedia_t, const char *);
static ifmedia_t get_media_mode(ifmedia_t, const char *);
static ifmedia_t get_media_options(ifmedia_t, const char *);
@@ -98,15 +97,15 @@ static void print_media(ifmedia_t, bool);
static void print_media_ifconfig(ifmedia_t);
static void
-media_status(int s)
+media_status(if_ctx *ctx)
{
struct ifmediareq *ifmr;
- if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1)
+ if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1)
return;
if (ifmr->ifm_count == 0) {
- warnx("%s: no media types?", name);
+ warnx("%s: no media types?", ctx->ifname);
goto free;
}
@@ -128,7 +127,7 @@ media_status(int s)
status = ifconfig_media_get_status(ifmr);
printf("\tstatus: %s", status);
if (strcmp(status, "no carrier") == 0 &&
- ifconfig_media_get_downreason(lifh, name, &ifdr) == 0) {
+ ifconfig_media_get_downreason(lifh, ctx->ifname, &ifdr) == 0) {
switch (ifdr.ifdr_reason) {
case IFDR_REASON_MSG:
printf(" (%s)", ifdr.ifdr_msg);
@@ -144,9 +143,9 @@ media_status(int s)
putchar('\n');
}
- if (supmedia) {
+ if (ctx->args->supmedia) {
printf("\tsupported media:\n");
- for (size_t i = 0; i < ifmr->ifm_count; ++i) {
+ for (int i = 0; i < ifmr->ifm_count; ++i) {
printf("\t\t");
print_media_ifconfig(ifmr->ifm_ulist[i]);
putchar('\n');
@@ -157,32 +156,33 @@ free:
}
struct ifmediareq *
-ifmedia_getstate(void)
+ifmedia_getstate(if_ctx *ctx)
{
static struct ifmediareq *ifmr = NULL;
if (ifmr != NULL)
return (ifmr);
- if (ifconfig_media_get_mediareq(lifh, name, &ifmr) == -1)
+ if (ifconfig_media_get_mediareq(lifh, ctx->ifname, &ifmr) == -1)
errc(1, ifconfig_err_errno(lifh),
- "%s: ifconfig_media_get_mediareq", name);
+ "%s: ifconfig_media_get_mediareq", ctx->ifname);
if (ifmr->ifm_count == 0)
- errx(1, "%s: no media types?", name);
+ errx(1, "%s: no media types?", ctx->ifname);
return (ifmr);
}
static void
-setifmediacallback(int s, void *arg)
+setifmediacallback(if_ctx *ctx, void *arg)
{
struct ifmediareq *ifmr = (struct ifmediareq *)arg;
static bool did_it = false;
+ struct ifreq ifr = {};
if (!did_it) {
ifr.ifr_media = ifmr->ifm_current;
- if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
+ if (ioctl_ctx_ifr(ctx, SIOCSIFMEDIA, &ifr) < 0)
err(1, "SIOCSIFMEDIA (media)");
free(ifmr);
did_it = true;
@@ -190,12 +190,12 @@ setifmediacallback(int s, void *arg)
}
static void
-setmedia(const char *val, int d, int s, const struct afswtch *afp)
+setmedia(if_ctx *ctx, const char *val, int d __unused)
{
struct ifmediareq *ifmr;
int subtype;
- ifmr = ifmedia_getstate();
+ ifmr = ifmedia_getstate(ctx);
/*
* We are primarily concerned with the top-level type.
@@ -208,86 +208,77 @@ setmedia(const char *val, int d, int s, const struct afswtch *afp)
*/
subtype = get_media_subtype(ifmr->ifm_ulist[0], val);
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- ifr.ifr_media = (ifmr->ifm_current & IFM_IMASK) |
+ ifmr->ifm_current = (ifmr->ifm_current & IFM_IMASK) |
IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
- ifmr->ifm_current = ifr.ifr_media;
callback_register(setifmediacallback, (void *)ifmr);
}
static void
-setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
+setmediaopt(if_ctx *ctx, const char *val, int d __unused)
{
- domediaopt(val, false, s);
+ domediaopt(ctx, val, false);
}
static void
-unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
+unsetmediaopt(if_ctx *ctx, const char *val, int d __unused)
{
- domediaopt(val, true, s);
+ domediaopt(ctx, val, true);
}
static void
-domediaopt(const char *val, bool clear, int s)
+domediaopt(if_ctx *ctx, const char *val, bool clear)
{
struct ifmediareq *ifmr;
ifmedia_t options;
- ifmr = ifmedia_getstate();
+ ifmr = ifmedia_getstate(ctx);
options = get_media_options(ifmr->ifm_ulist[0], val);
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- ifr.ifr_media = ifmr->ifm_current;
if (clear)
- ifr.ifr_media &= ~options;
+ ifmr->ifm_current &= ~options;
else {
if (options & IFM_HDX) {
- ifr.ifr_media &= ~IFM_FDX;
+ ifmr->ifm_current &= ~IFM_FDX;
options &= ~IFM_HDX;
}
- ifr.ifr_media |= options;
+ ifmr->ifm_current |= options;
}
- ifmr->ifm_current = ifr.ifr_media;
callback_register(setifmediacallback, (void *)ifmr);
}
static void
-setmediainst(const char *val, int d, int s, const struct afswtch *afp)
+setmediainst(if_ctx *ctx, const char *val, int d __unused)
{
struct ifmediareq *ifmr;
int inst;
- ifmr = ifmedia_getstate();
+ ifmr = ifmedia_getstate(ctx);
inst = atoi(val);
if (inst < 0 || inst > (int)IFM_INST_MAX)
errx(1, "invalid media instance: %s", val);
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
+ ifmr->ifm_current = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
- ifmr->ifm_current = ifr.ifr_media;
callback_register(setifmediacallback, (void *)ifmr);
}
static void
-setmediamode(const char *val, int d, int s, const struct afswtch *afp)
+setmediamode(if_ctx *ctx, const char *val, int d __unused)
{
struct ifmediareq *ifmr;
int mode;
- ifmr = ifmedia_getstate();
+ ifmr = ifmedia_getstate(ctx);
mode = get_media_mode(ifmr->ifm_ulist[0], val);
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
+ ifmr->ifm_current = (ifmr->ifm_current & ~IFM_MMASK) | mode;
- ifmr->ifm_current = ifr.ifr_media;
callback_register(setifmediacallback, (void *)ifmr);
}
@@ -486,9 +477,7 @@ static struct afswtch af_media = {
static __constructor void
ifmedia_ctor(void)
{
- size_t i;
-
- for (i = 0; i < nitems(media_cmds); i++)
+ for (size_t i = 0; i < nitems(media_cmds); i++)
cmd_register(&media_cmds[i]);
af_register(&af_media);
}
diff --git a/sbin/ifconfig/ifpfsync.c b/sbin/ifconfig/ifpfsync.c
index e3b5e6a30bbc..264b1ecd5b56 100644
--- a/sbin/ifconfig/ifpfsync.c
+++ b/sbin/ifconfig/ifpfsync.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2003 Ryan McBride. All rights reserved.
* Copyright (c) 2004 Max Laier. All rights reserved.
@@ -24,12 +24,12 @@
* 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/errno.h>
#include <sys/ioctl.h>
+#include <sys/nv.h>
#include <sys/socket.h>
#include <net/if.h>
@@ -48,169 +48,354 @@
#include "ifconfig.h"
-void setpfsync_syncdev(const char *, int, int, const struct afswtch *);
-void unsetpfsync_syncdev(const char *, int, int, const struct afswtch *);
-void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
-void unsetpfsync_syncpeer(const char *, int, int, const struct afswtch *);
-void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
-void setpfsync_maxupd(const char *, int, int, const struct afswtch *);
-void setpfsync_defer(const char *, int, int, const struct afswtch *);
-void pfsync_status(int);
-
-void
-setpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
+static int
+pfsync_do_ioctl(if_ctx *ctx, uint cmd, nvlist_t **nvl)
+{
+ void *data;
+ size_t nvlen;
+ struct ifreq ifr = {};
+
+ data = nvlist_pack(*nvl, &nvlen);
+
+ ifr.ifr_cap_nv.buffer = malloc(IFR_CAP_NV_MAXBUFSIZE);
+ memcpy(ifr.ifr_cap_nv.buffer, data, nvlen);
+ ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
+ ifr.ifr_cap_nv.length = nvlen;
+ free(data);
+
+ if (ioctl_ctx_ifr(ctx, cmd, &ifr) == -1) {
+ free(ifr.ifr_cap_nv.buffer);
+ return -1;
+ }
+
+ nvlist_destroy(*nvl);
+ *nvl = NULL;
+
+ *nvl = nvlist_unpack(ifr.ifr_cap_nv.buffer, ifr.ifr_cap_nv.length, 0);
+ if (*nvl == NULL) {
+ free(ifr.ifr_cap_nv.buffer);
+ return (EIO);
+ }
+
+ free(ifr.ifr_cap_nv.buffer);
+ return (errno);
+}
+
+static nvlist_t *
+pfsync_sockaddr_to_syncpeer_nvlist(struct sockaddr_storage *sa)
{
- struct pfsyncreq preq;
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL) {
+ return (nvl);
+ }
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ switch (sa->ss_family) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *in = (struct sockaddr_in *)sa;
+ nvlist_add_number(nvl, "af", in->sin_family);
+ nvlist_add_binary(nvl, "address", in, sizeof(*in));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+ nvlist_add_number(nvl, "af", in6->sin6_family);
+ nvlist_add_binary(nvl, "address", in6, sizeof(*in6));
+ break;
+ }
+#endif
+ default:
+ nvlist_add_number(nvl, "af", AF_UNSPEC);
+ nvlist_add_binary(nvl, "address", sa, sizeof(*sa));
+ break;
+ }
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ return (nvl);
+}
- strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev));
+static int
+pfsync_syncpeer_nvlist_to_sockaddr(const nvlist_t *nvl,
+ struct sockaddr_storage *sa)
+{
+ int af;
+
+#if (!defined INET && !defined INET6)
+ (void)sa;
+#endif
+
+ if (!nvlist_exists_number(nvl, "af"))
+ return (EINVAL);
+ if (!nvlist_exists_binary(nvl, "address"))
+ return (EINVAL);
+
+ af = nvlist_get_number(nvl, "af");
+
+ switch (af) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *in = (struct sockaddr_in *)sa;
+ size_t len;
+ const void *addr = nvlist_get_binary(nvl, "address", &len);
+ in->sin_family = af;
+ if (len != sizeof(*in))
+ return (EINVAL);
+
+ memcpy(in, addr, sizeof(*in));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+ size_t len;
+ const void *addr = nvlist_get_binary(nvl, "address", &len);
+ if (len != sizeof(*in6))
+ return (EINVAL);
+
+ memcpy(in6, addr, sizeof(*in6));
+ break;
+ }
+#endif
+ default:
+ return (EINVAL);
+ }
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ return (0);
}
-/* ARGSUSED */
-void
-unsetpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
+static void
+setpfsync_syncdev(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct pfsyncreq preq;
+ nvlist_t *nvl = nvlist_create(0);
+
+ if (strlen(val) > IFNAMSIZ)
+ errx(1, "interface name %s is too long", val);
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ if (nvlist_exists_string(nvl, "syncdev"))
+ nvlist_free_string(nvl, "syncdev");
- bzero((char *)&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev));
+ nvlist_add_string(nvl, "syncdev", val);
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
}
-/* ARGSUSED */
-void
-setpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
+static void
+unsetpfsync_syncdev(if_ctx *ctx, const char *val __unused, int dummy __unused)
{
- struct pfsyncreq preq;
- struct addrinfo hints, *peerres;
- int ecode;
+ nvlist_t *nvl = nvlist_create(0);
+
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
+
+ if (nvlist_exists_string(nvl, "syncdev"))
+ nvlist_free_string(nvl, "syncdev");
+
+ nvlist_add_string(nvl, "syncdev", "");
+
+ if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
+}
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+static void
+setpfsync_syncpeer(if_ctx *ctx, const char *val, int dummy __unused)
+{
+ struct addrinfo *peerres;
+ struct sockaddr_storage addr;
+ int ecode;
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ nvlist_t *nvl = nvlist_create(0);
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET;
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0)
+ if ((ecode = getaddrinfo(val, NULL, NULL, &peerres)) != 0)
errx(1, "error in parsing address string: %s",
gai_strerror(ecode));
- if (peerres->ai_addr->sa_family != AF_INET)
- errx(1, "only IPv4 addresses supported for the syncpeer");
+ switch (peerres->ai_family) {
+#ifdef INET
+ case AF_INET: {
+ struct sockaddr_in *sin = satosin(peerres->ai_addr);
+
+ memcpy(&addr, sin, sizeof(*sin));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = satosin6(peerres->ai_addr);
+
+ memcpy(&addr, sin6, sizeof(*sin6));
+ break;
+ }
+#endif
+ default:
+ errx(1, "syncpeer address %s not supported", val);
+ }
+
+ if (nvlist_exists_nvlist(nvl, "syncpeer"))
+ nvlist_free_nvlist(nvl, "syncpeer");
- preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *)
- peerres->ai_addr)->sin_addr.s_addr;
+ nvlist_add_nvlist(nvl, "syncpeer",
+ pfsync_sockaddr_to_syncpeer_nvlist(&addr));
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
+
+ nvlist_destroy(nvl);
freeaddrinfo(peerres);
}
-/* ARGSUSED */
-void
-unsetpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
+static void
+unsetpfsync_syncpeer(if_ctx *ctx, const char *val __unused, int dummy __unused)
{
- struct pfsyncreq preq;
+ struct sockaddr_storage addr;
+ memset(&addr, 0, sizeof(addr));
+
+ nvlist_t *nvl = nvlist_create(0);
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ if (nvlist_exists_nvlist(nvl, "syncpeer"))
+ nvlist_free_nvlist(nvl, "syncpeer");
- preq.pfsyncr_syncpeer.s_addr = 0;
+ nvlist_add_nvlist(nvl, "syncpeer",
+ pfsync_sockaddr_to_syncpeer_nvlist(&addr));
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
+
+ nvlist_destroy(nvl);
}
-/* ARGSUSED */
-void
-setpfsync_maxupd(const char *val, int d, int s, const struct afswtch *rafp)
+static void
+setpfsync_maxupd(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct pfsyncreq preq;
int maxupdates;
+ nvlist_t *nvl = nvlist_create(0);
maxupdates = atoi(val);
if ((maxupdates < 0) || (maxupdates > 255))
errx(1, "maxupd %s: out of range", val);
- memset((char *)&preq, 0, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ nvlist_free_number(nvl, "maxupdates");
+ nvlist_add_number(nvl, "maxupdates", maxupdates);
- preq.pfsyncr_maxupdates = maxupdates;
+ if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ nvlist_destroy(nvl);
}
-/* ARGSUSED */
-void
-setpfsync_defer(const char *val, int d, int s, const struct afswtch *rafp)
+static void
+setpfsync_defer(if_ctx *ctx, const char *val __unused, int d)
{
- struct pfsyncreq preq;
+ nvlist_t *nvl = nvlist_create(0);
+
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- memset((char *)&preq, 0, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ nvlist_free_number(nvl, "flags");
+ nvlist_add_number(nvl, "flags", d ? PFSYNCF_DEFER : 0);
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCGETPFSYNC");
+ if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
- preq.pfsyncr_defer = d ? PFSYNCF_DEFER : 0;
- if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
- err(1, "SIOCSETPFSYNC");
+ nvlist_destroy(nvl);
}
-void
-pfsync_status(int s)
+static void
+setpfsync_version(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct pfsyncreq preq;
+ int version;
+ nvlist_t *nvl = nvlist_create(0);
+
+ /* Don't verify, kernel knows which versions are supported.*/
+ version = atoi(val);
- bzero((char *)&preq, sizeof(struct pfsyncreq));
- ifr.ifr_data = (caddr_t)&preq;
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCGETPFSYNCNV");
- if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ nvlist_free_number(nvl, "version");
+ nvlist_add_number(nvl, "version", version);
+
+ if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
+ err(1, "SIOCSETPFSYNCNV");
+
+ nvlist_destroy(nvl);
+}
+
+static void
+pfsync_status(if_ctx *ctx)
+{
+ nvlist_t *nvl;
+ char syncdev[IFNAMSIZ];
+ char syncpeer_str[NI_MAXHOST];
+ struct sockaddr_storage syncpeer;
+ int maxupdates = 0;
+ int flags = 0;
+ int version;
+ int error;
+
+ nvl = nvlist_create(0);
+
+ if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) {
+ nvlist_destroy(nvl);
return;
+ }
+
+ memset((char *)&syncdev, 0, IFNAMSIZ);
+ if (nvlist_exists_string(nvl, "syncdev"))
+ strlcpy(syncdev, nvlist_get_string(nvl, "syncdev"),
+ IFNAMSIZ);
+ if (nvlist_exists_number(nvl, "maxupdates"))
+ maxupdates = nvlist_get_number(nvl, "maxupdates");
+ if (nvlist_exists_number(nvl, "version"))
+ version = nvlist_get_number(nvl, "version");
+ if (nvlist_exists_number(nvl, "flags"))
+ flags = nvlist_get_number(nvl, "flags");
+ if (nvlist_exists_nvlist(nvl, "syncpeer")) {
+ pfsync_syncpeer_nvlist_to_sockaddr(nvlist_get_nvlist(nvl,
+ "syncpeer"),
+ &syncpeer);
+ }
+
+ nvlist_destroy(nvl);
+
+ printf("\t");
+
+ if (syncdev[0] != '\0')
+ printf("syncdev: %s ", syncdev);
- if (preq.pfsyncr_syncdev[0] != '\0' ||
- preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP))
- printf("\t");
-
- if (preq.pfsyncr_syncdev[0] != '\0')
- printf("pfsync: syncdev: %s ", preq.pfsyncr_syncdev);
- if (preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP))
- printf("syncpeer: %s ", inet_ntoa(preq.pfsyncr_syncpeer));
-
- if (preq.pfsyncr_syncdev[0] != '\0' ||
- preq.pfsyncr_syncpeer.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
- printf("maxupd: %d ", preq.pfsyncr_maxupdates);
- printf("defer: %s\n",
- (preq.pfsyncr_defer & PFSYNCF_DEFER) ? "on" : "off");
- printf("\tsyncok: %d\n",
- (preq.pfsyncr_defer & PFSYNCF_OK) ? 1 : 0);
+ if ((syncpeer.ss_family == AF_INET &&
+ ((struct sockaddr_in *)&syncpeer)->sin_addr.s_addr !=
+ htonl(INADDR_PFSYNC_GROUP)) || syncpeer.ss_family == AF_INET6) {
+
+ struct sockaddr *syncpeer_sa =
+ (struct sockaddr *)&syncpeer;
+ if ((error = getnameinfo(syncpeer_sa, syncpeer_sa->sa_len,
+ syncpeer_str, sizeof(syncpeer_str), NULL, 0,
+ NI_NUMERICHOST)) != 0)
+ errx(1, "getnameinfo: %s", gai_strerror(error));
+ printf("syncpeer: %s ", syncpeer_str);
}
+
+ printf("maxupd: %d ", maxupdates);
+ printf("defer: %s ", (flags & PFSYNCF_DEFER) ? "on" : "off");
+ printf("version: %d\n", version);
+ printf("\tsyncok: %d\n", (flags & PFSYNCF_OK) ? 1 : 0);
}
static struct cmd pfsync_cmds[] = {
@@ -223,6 +408,7 @@ static struct cmd pfsync_cmds[] = {
DEF_CMD_ARG("maxupd", setpfsync_maxupd),
DEF_CMD("defer", 1, setpfsync_defer),
DEF_CMD("-defer", 0, setpfsync_defer),
+ DEF_CMD_ARG("version", setpfsync_version),
};
static struct afswtch af_pfsync = {
.af_name = "af_pfsync",
@@ -233,9 +419,7 @@ static struct afswtch af_pfsync = {
static __constructor void
pfsync_ctor(void)
{
- int i;
-
- for (i = 0; i < nitems(pfsync_cmds); i++)
+ for (size_t i = 0; i < nitems(pfsync_cmds); i++)
cmd_register(&pfsync_cmds[i]);
af_register(&af_pfsync);
}
diff --git a/sbin/ifconfig/ifstf.c b/sbin/ifconfig/ifstf.c
index f6c3cb5d5447..a99592b4801f 100644
--- a/sbin/ifconfig/ifstf.c
+++ b/sbin/ifconfig/ifstf.c
@@ -52,26 +52,24 @@
#include "ifconfig.h"
static int
-do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
+do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set)
{
- struct ifdrv ifd;
+ struct ifdrv ifd = {};
- memset(&ifd, 0, sizeof(ifd));
-
- strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
+ strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name));
ifd.ifd_cmd = op;
ifd.ifd_len = argsize;
ifd.ifd_data = arg;
- return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
+ return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
}
static void
-stf_status(int s)
+stf_status(if_ctx *ctx)
{
struct stfv4args param;
- if (do_cmd(s, STF6RD_GV4NET, &param, sizeof(param), 0) < 0)
+ if (do_cmd(ctx, STF6RD_GV4NET, &param, sizeof(param), 0) < 0)
return;
printf("\tv4net %s/%d -> ", inet_ntoa(param.srcv4_addr),
@@ -80,7 +78,7 @@ stf_status(int s)
}
static void
-setstf_br(const char *val, int d, int s, const struct afswtch *afp)
+setstf_br(if_ctx *ctx, const char *val, int d __unused)
{
struct stfv4args req;
struct sockaddr_in sin;
@@ -94,12 +92,12 @@ setstf_br(const char *val, int d, int s, const struct afswtch *afp)
errx(1, "%s: bad value", val);
req.braddr = sin.sin_addr;
- if (do_cmd(s, STF6RD_SBR, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, STF6RD_SBR, &req, sizeof(req), 1) < 0)
err(1, "STF6RD_SBR%s", val);
}
static void
-setstf_set(const char *val, int d, int s, const struct afswtch *afp)
+setstf_set(if_ctx *ctx, const char *val, int d __unused)
{
struct stfv4args req;
struct sockaddr_in sin;
@@ -126,7 +124,7 @@ setstf_set(const char *val, int d, int s, const struct afswtch *afp)
errx(1, "%s: bad value", val);
memcpy(&req.srcv4_addr, &sin.sin_addr, sizeof(req.srcv4_addr));
- if (do_cmd(s, STF6RD_SV4NET, &req, sizeof(req), 1) < 0)
+ if (do_cmd(ctx, STF6RD_SV4NET, &req, sizeof(req), 1) < 0)
err(1, "STF6RD_SV4NET %s", val);
}
@@ -144,9 +142,7 @@ static struct afswtch af_stf = {
static __constructor void
stf_ctor(void)
{
- int i;
-
- for (i = 0; i < nitems(stf_cmds); i++)
+ for (size_t i = 0; i < nitems(stf_cmds); i++)
cmd_register(&stf_cmds[i]);
af_register(&af_stf);
}
diff --git a/sbin/ifconfig/ifvlan.c b/sbin/ifconfig/ifvlan.c
index 8b7b6e9daf9a..0a2603f1736f 100644
--- a/sbin/ifconfig/ifvlan.c
+++ b/sbin/ifconfig/ifvlan.c
@@ -4,7 +4,7 @@
* Copyright (c) 1999 Bill Paul <wpaul@ctr.columbia.edu>
* Copyright (c) 2012 ADARA Networks, Inc.
* All rights reserved.
- *
+ *
* Portions of this software were developed by Robert N. M. Watson under
* contract to ADARA Networks, Inc.
*
@@ -59,12 +59,8 @@
#include "ifconfig.h"
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-
#define NOTAG ((u_short) -1)
+#define NOPROTO ((u_short) -1)
static const char proto_8021Q[] = "802.1q";
static const char proto_8021ad[] = "802.1ad";
@@ -72,24 +68,16 @@ static const char proto_qinq[] = "qinq";
static struct vlanreq params = {
.vlr_tag = NOTAG,
- .vlr_proto = ETHERTYPE_VLAN,
+ .vlr_proto = NOPROTO,
};
-static int
-getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq)
-{
- bzero((char *)vreq, sizeof(*vreq));
- ifr->ifr_data = (caddr_t)vreq;
-
- return ioctl(s, SIOCGETVLAN, (caddr_t)ifr);
-}
-
static void
-vlan_status(int s)
+vlan_status(if_ctx *ctx)
{
- struct vlanreq vreq;
+ struct vlanreq vreq = {};
+ struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
- if (getvlan(s, &ifr, &vreq) == -1)
+ if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) == -1)
return;
printf("\tvlan: %d", vreq.vlr_tag);
printf(" vlanproto: ");
@@ -103,7 +91,7 @@ vlan_status(int s)
default:
printf("0x%04x", vreq.vlr_proto);
}
- if (ioctl(s, SIOCGVLANPCP, (caddr_t)&ifr) != -1)
+ if (ioctl_ctx_ifr(ctx, SIOCGVLANPCP, &ifr) != -1)
printf(" vlanpcp: %u", ifr.ifr_vlan_pcp);
printf(" parent interface: %s", vreq.vlr_parent[0] == '\0' ?
"<none>" : vreq.vlr_parent);
@@ -121,7 +109,7 @@ vlan_parse_ethervid(const char *name)
{
char ifname[IFNAMSIZ];
char *cp;
- int vid;
+ unsigned int vid;
strlcpy(ifname, name, IFNAMSIZ);
if ((cp = strrchr(ifname, '.')) == NULL)
@@ -134,9 +122,12 @@ vlan_parse_ethervid(const char *name)
errx(1, "invalid vlan tag");
vid = *cp++ - '0';
- while ((*cp >= '0') && (*cp <= '9'))
+ while ((*cp >= '0') && (*cp <= '9')) {
vid = (vid * 10) + (*cp++ - '0');
- if ((*cp != '\0') || (vid & ~0xFFF))
+ if (vid >= 0xFFF)
+ errx(1, "invalid vlan tag");
+ }
+ if (*cp != '\0')
errx(1, "invalid vlan tag");
/*
@@ -155,7 +146,7 @@ vlan_parse_ethervid(const char *name)
}
static void
-vlan_create(int s, struct ifreq *ifr)
+vlan_create(if_ctx *ctx, struct ifreq *ifr)
{
vlan_parse_ethervid(ifr->ifr_name);
@@ -167,13 +158,15 @@ vlan_create(int s, struct ifreq *ifr)
errx(1, "must specify a tag for vlan create");
if (params.vlr_parent[0] == '\0')
errx(1, "must specify a parent device for vlan create");
+ if (params.vlr_proto == NOPROTO)
+ params.vlr_proto = ETHERTYPE_VLAN;
ifr->ifr_data = (caddr_t) &params;
}
- ioctl_ifcreate(s, ifr);
+ ifcreate_ioctl(ctx, ifr);
}
static void
-vlan_cb(int s, void *arg)
+vlan_cb(if_ctx *ctx __unused, void *arg __unused)
{
if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0'))
errx(1, "both vlan and vlandev must be specified");
@@ -183,16 +176,19 @@ static void
vlan_set(int s, struct ifreq *ifr)
{
if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') {
+ if (params.vlr_proto == NOPROTO)
+ params.vlr_proto = ETHERTYPE_VLAN;
ifr->ifr_data = (caddr_t) &params;
if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1)
err(1, "SIOCSETVLAN");
}
}
-static
-DECL_CMD_FUNC(setvlantag, val, d)
+static void
+setvlantag(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct vlanreq vreq;
+ struct vlanreq vreq = {};
+ struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
u_long ul;
char *endp;
@@ -204,25 +200,38 @@ DECL_CMD_FUNC(setvlantag, val, d)
if (params.vlr_tag != ul)
errx(1, "value for vlan out of range");
- if (getvlan(s, &ifr, &vreq) != -1)
- vlan_set(s, &ifr);
+ if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1) {
+ /*
+ * Retrieve the current settings if the interface has already
+ * been configured.
+ */
+ if (vreq.vlr_parent[0] != '\0') {
+ if (params.vlr_parent[0] == '\0')
+ strlcpy(params.vlr_parent, vreq.vlr_parent, IFNAMSIZ);
+ if (params.vlr_proto == NOPROTO)
+ params.vlr_proto = vreq.vlr_proto;
+ }
+ vlan_set(ctx->io_s, &ifr);
+ }
}
-static
-DECL_CMD_FUNC(setvlandev, val, d)
+static void
+setvlandev(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct vlanreq vreq;
+ struct vlanreq vreq = {};
+ struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent));
- if (getvlan(s, &ifr, &vreq) != -1)
- vlan_set(s, &ifr);
+ if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1)
+ vlan_set(ctx->io_s, &ifr);
}
-static
-DECL_CMD_FUNC(setvlanproto, val, d)
+static void
+setvlanproto(if_ctx *ctx, const char *val, int dummy __unused)
{
- struct vlanreq vreq;
+ struct vlanreq vreq = {};
+ struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
if (strncasecmp(proto_8021Q, val,
strlen(proto_8021Q)) == 0) {
@@ -233,15 +242,27 @@ DECL_CMD_FUNC(setvlanproto, val, d)
} else
errx(1, "invalid value for vlanproto");
- if (getvlan(s, &ifr, &vreq) != -1)
- vlan_set(s, &ifr);
+ if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) != -1) {
+ /*
+ * Retrieve the current settings if the interface has already
+ * been configured.
+ */
+ if (vreq.vlr_parent[0] != '\0') {
+ if (params.vlr_parent[0] == '\0')
+ strlcpy(params.vlr_parent, vreq.vlr_parent, IFNAMSIZ);
+ if (params.vlr_tag == NOTAG)
+ params.vlr_tag = vreq.vlr_tag;
+ }
+ vlan_set(ctx->io_s, &ifr);
+ }
}
-static
-DECL_CMD_FUNC(setvlanpcp, val, d)
+static void
+setvlanpcp(if_ctx *ctx, const char *val, int dummy __unused)
{
u_long ul;
char *endp;
+ struct ifreq ifr = {};
ul = strtoul(val, &endp, 0);
if (*endp != '\0')
@@ -249,25 +270,23 @@ DECL_CMD_FUNC(setvlanpcp, val, d)
if (ul > 7)
errx(1, "value for vlanpcp out of range");
ifr.ifr_vlan_pcp = ul;
- if (ioctl(s, SIOCSVLANPCP, (caddr_t)&ifr) == -1)
+ if (ioctl_ctx_ifr(ctx, SIOCSVLANPCP, &ifr) == -1)
err(1, "SIOCSVLANPCP");
}
-static
-DECL_CMD_FUNC(unsetvlandev, val, d)
+static void
+unsetvlandev(if_ctx *ctx, const char *val __unused, int dummy __unused)
{
- struct vlanreq vreq;
-
- bzero((char *)&vreq, sizeof(struct vlanreq));
- ifr.ifr_data = (caddr_t)&vreq;
+ struct vlanreq vreq = {};
+ struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
- if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
+ if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) == -1)
err(1, "SIOCGETVLAN");
bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
vreq.vlr_tag = 0;
- if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+ if (ioctl_ctx(ctx, SIOCSETVLAN, (caddr_t)&ifr) == -1)
err(1, "SIOCSETVLAN");
}
@@ -283,15 +302,15 @@ static struct cmd vlan_cmds[] = {
/* XXX For compatibility. Should become DEF_CMD() some day. */
DEF_CMD_OPTARG("-vlandev", unsetvlandev),
DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap),
- DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap),
+ DEF_CMD("-vlanmtu", IFCAP_VLAN_MTU, clearifcap),
DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap),
- DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap),
+ DEF_CMD("-vlanhwtag", IFCAP_VLAN_HWTAGGING, clearifcap),
DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap),
- DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap),
- DEF_CMD("-vlanhwtso", -IFCAP_VLAN_HWTSO, setifcap),
+ DEF_CMD("-vlanhwfilter", IFCAP_VLAN_HWFILTER, clearifcap),
DEF_CMD("vlanhwtso", IFCAP_VLAN_HWTSO, setifcap),
+ DEF_CMD("-vlanhwtso", IFCAP_VLAN_HWTSO, clearifcap),
DEF_CMD("vlanhwcsum", IFCAP_VLAN_HWCSUM, setifcap),
- DEF_CMD("-vlanhwcsum", -IFCAP_VLAN_HWCSUM, setifcap),
+ DEF_CMD("-vlanhwcsum", IFCAP_VLAN_HWCSUM, clearifcap),
};
static struct afswtch af_vlan = {
.af_name = "af_vlan",
diff --git a/sbin/ifconfig/ifvxlan.c b/sbin/ifconfig/ifvxlan.c
index fda435343a16..cbea685b6ba0 100644
--- a/sbin/ifconfig/ifvxlan.c
+++ b/sbin/ifconfig/ifvxlan.c
@@ -24,9 +24,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -73,32 +70,30 @@ get_val(const char *cp, u_long *valp)
}
static int
-do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
+do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set)
{
- struct ifdrv ifd;
-
- bzero(&ifd, sizeof(ifd));
+ struct ifdrv ifd = {};
- strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
+ strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name));
ifd.ifd_cmd = op;
ifd.ifd_len = argsize;
ifd.ifd_data = arg;
- return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
+ return (ioctl_ctx(ctx, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
}
static int
-vxlan_exists(int sock)
+vxlan_exists(if_ctx *ctx)
{
struct ifvxlancfg cfg;
bzero(&cfg, sizeof(cfg));
- return (do_cmd(sock, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
+ return (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) != -1);
}
static void
-vxlan_status(int s)
+vxlan_status(if_ctx *ctx)
{
struct ifvxlancfg cfg;
char src[NI_MAXHOST], dst[NI_MAXHOST];
@@ -108,7 +103,7 @@ vxlan_status(int s)
bzero(&cfg, sizeof(cfg));
- if (do_cmd(s, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_GET_CONFIG, &cfg, sizeof(cfg), 0) < 0)
return;
vni = cfg.vxlc_vni;
@@ -128,10 +123,10 @@ vxlan_status(int s)
dst[0] = dstport[0] = '\0';
if (!ipv6) {
- struct sockaddr_in *sin = (struct sockaddr_in *)rsa;
+ struct sockaddr_in *sin = satosin(rsa);
mc = IN_MULTICAST(ntohl(sin->sin_addr.s_addr));
} else {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)rsa;
+ struct sockaddr_in6 *sin6 = satosin6(rsa);
mc = IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr);
}
@@ -141,7 +136,7 @@ vxlan_status(int s)
printf(" %s %s%s%s:%s", mc ? "group" : "remote", ipv6 ? "[" : "",
dst, ipv6 ? "]" : "", dstport);
- if (verbose) {
+ if (ctx->args->verbose) {
printf("\n\t\tconfig: ");
printf("%slearning portrange %d-%d ttl %d",
cfg.vxlc_learn ? "" : "no", cfg.vxlc_port_min,
@@ -179,23 +174,17 @@ vxlan_check_params(void)
#undef _REMOTE_ADDR46
static void
-vxlan_cb(int s, void *arg)
-{
-
-}
-
-static void
-vxlan_create(int s, struct ifreq *ifr)
+vxlan_create(if_ctx *ctx, struct ifreq *ifr)
{
vxlan_check_params();
ifr->ifr_data = (caddr_t) &params;
- ioctl_ifcreate(s, ifr);
+ ifcreate_ioctl(ctx, ifr);
}
-static
-DECL_CMD_FUNC(setvxlan_vni, arg, d)
+static void
+setvxlan_vni(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifvxlancmd cmd;
u_long val;
@@ -203,7 +192,7 @@ DECL_CMD_FUNC(setvxlan_vni, arg, d)
if (get_val(arg, &val) < 0 || val >= VXLAN_VNI_MAX)
errx(1, "invalid network identifier: %s", arg);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_VNI;
params.vxlp_vni = val;
return;
@@ -212,16 +201,18 @@ DECL_CMD_FUNC(setvxlan_vni, arg, d)
bzero(&cmd, sizeof(cmd));
cmd.vxlcmd_vni = val;
- if (do_cmd(s, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_VNI, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_VNI");
}
-static
-DECL_CMD_FUNC(setvxlan_local, addr, d)
+static void
+setvxlan_local(if_ctx *ctx, const char *addr, int dummy __unused)
{
struct ifvxlancmd cmd;
struct addrinfo *ai;
+#if (defined INET || defined INET6)
struct sockaddr *sa;
+#endif
int error;
bzero(&cmd, sizeof(cmd));
@@ -230,12 +221,14 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
errx(1, "error in parsing local address string: %s",
gai_strerror(error));
+#if (defined INET || defined INET6)
sa = ai->ai_addr;
+#endif
switch (ai->ai_family) {
#ifdef INET
case AF_INET: {
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ struct sockaddr_in *sin = satosin(sa);
if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
errx(1, "local address cannot be multicast");
@@ -246,7 +239,7 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
#endif
#ifdef INET6
case AF_INET6: {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ struct sockaddr_in6 *sin6 = satosin6(sa);
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
errx(1, "local address cannot be multicast");
@@ -261,7 +254,7 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
freeaddrinfo(ai);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_ADDR4;
params.vxlp_local_sa.in4 = cmd.vxlcmd_sa.in4;
@@ -272,16 +265,18 @@ DECL_CMD_FUNC(setvxlan_local, addr, d)
return;
}
- if (do_cmd(s, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_ADDR, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_LOCAL_ADDR");
}
-static
-DECL_CMD_FUNC(setvxlan_remote, addr, d)
+static void
+setvxlan_remote(if_ctx *ctx, const char *addr, int dummy __unused)
{
struct ifvxlancmd cmd;
struct addrinfo *ai;
+#if (defined INET || defined INET6)
struct sockaddr *sa;
+#endif
int error;
bzero(&cmd, sizeof(cmd));
@@ -290,12 +285,14 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
errx(1, "error in parsing remote address string: %s",
gai_strerror(error));
+#if (defined INET || defined INET6)
sa = ai->ai_addr;
+#endif
switch (ai->ai_family) {
#ifdef INET
case AF_INET: {
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ struct sockaddr_in *sin = satosin(sa);
if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
errx(1, "remote address cannot be multicast");
@@ -306,7 +303,7 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
#endif
#ifdef INET6
case AF_INET6: {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ struct sockaddr_in6 *sin6 = satosin6(sa);
if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
errx(1, "remote address cannot be multicast");
@@ -321,7 +318,7 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
freeaddrinfo(ai);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
@@ -332,16 +329,18 @@ DECL_CMD_FUNC(setvxlan_remote, addr, d)
return;
}
- if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
}
-static
-DECL_CMD_FUNC(setvxlan_group, addr, d)
+static void
+setvxlan_group(if_ctx *ctx, const char *addr, int dummy __unused)
{
struct ifvxlancmd cmd;
struct addrinfo *ai;
+#if (defined INET || defined INET6)
struct sockaddr *sa;
+#endif
int error;
bzero(&cmd, sizeof(cmd));
@@ -350,12 +349,14 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
errx(1, "error in parsing group address string: %s",
gai_strerror(error));
+#if (defined INET || defined INET6)
sa = ai->ai_addr;
+#endif
switch (ai->ai_family) {
#ifdef INET
case AF_INET: {
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ struct sockaddr_in *sin = satosin(sa);
if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
errx(1, "group address must be multicast");
@@ -366,7 +367,7 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
#endif
#ifdef INET6
case AF_INET6: {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ struct sockaddr_in6 *sin6 = satosin6(sa);
if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
errx(1, "group address must be multicast");
@@ -381,7 +382,7 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
freeaddrinfo(ai);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
if (cmd.vxlcmd_sa.sa.sa_family == AF_INET) {
params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_ADDR4;
params.vxlp_remote_sa.in4 = cmd.vxlcmd_sa.in4;
@@ -392,12 +393,12 @@ DECL_CMD_FUNC(setvxlan_group, addr, d)
return;
}
- if (do_cmd(s, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_ADDR, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_REMOTE_ADDR");
}
-static
-DECL_CMD_FUNC(setvxlan_local_port, arg, d)
+static void
+setvxlan_local_port(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifvxlancmd cmd;
u_long val;
@@ -405,7 +406,7 @@ DECL_CMD_FUNC(setvxlan_local_port, arg, d)
if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
errx(1, "invalid local port: %s", arg);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_LOCAL_PORT;
params.vxlp_local_port = val;
return;
@@ -414,12 +415,12 @@ DECL_CMD_FUNC(setvxlan_local_port, arg, d)
bzero(&cmd, sizeof(cmd));
cmd.vxlcmd_port = val;
- if (do_cmd(s, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_LOCAL_PORT, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_LOCAL_PORT");
}
-static
-DECL_CMD_FUNC(setvxlan_remote_port, arg, d)
+static void
+setvxlan_remote_port(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifvxlancmd cmd;
u_long val;
@@ -427,7 +428,7 @@ DECL_CMD_FUNC(setvxlan_remote_port, arg, d)
if (get_val(arg, &val) < 0 || val >= UINT16_MAX)
errx(1, "invalid remote port: %s", arg);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_REMOTE_PORT;
params.vxlp_remote_port = val;
return;
@@ -436,12 +437,12 @@ DECL_CMD_FUNC(setvxlan_remote_port, arg, d)
bzero(&cmd, sizeof(cmd));
cmd.vxlcmd_port = val;
- if (do_cmd(s, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_REMOTE_PORT, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_REMOTE_PORT");
}
-static
-DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2)
+static void
+setvxlan_port_range(if_ctx *ctx, const char *arg1, const char *arg2)
{
struct ifvxlancmd cmd;
u_long min, max;
@@ -453,7 +454,7 @@ DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2)
if (max < min)
errx(1, "invalid port range");
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_PORT_RANGE;
params.vxlp_min_port = min;
params.vxlp_max_port = max;
@@ -464,12 +465,12 @@ DECL_CMD_FUNC2(setvxlan_port_range, arg1, arg2)
cmd.vxlcmd_port_min = min;
cmd.vxlcmd_port_max = max;
- if (do_cmd(s, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_PORT_RANGE, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_PORT_RANGE");
}
-static
-DECL_CMD_FUNC(setvxlan_timeout, arg, d)
+static void
+setvxlan_timeout(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifvxlancmd cmd;
u_long val;
@@ -477,7 +478,7 @@ DECL_CMD_FUNC(setvxlan_timeout, arg, d)
if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
errx(1, "invalid timeout value: %s", arg);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_TIMEOUT;
params.vxlp_ftable_timeout = val & 0xFFFFFFFF;
return;
@@ -486,12 +487,12 @@ DECL_CMD_FUNC(setvxlan_timeout, arg, d)
bzero(&cmd, sizeof(cmd));
cmd.vxlcmd_ftable_timeout = val & 0xFFFFFFFF;
- if (do_cmd(s, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_TIMEOUT, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_FTABLE_TIMEOUT");
}
-static
-DECL_CMD_FUNC(setvxlan_maxaddr, arg, d)
+static void
+setvxlan_maxaddr(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifvxlancmd cmd;
u_long val;
@@ -499,7 +500,7 @@ DECL_CMD_FUNC(setvxlan_maxaddr, arg, d)
if (get_val(arg, &val) < 0 || (val & ~0xFFFFFFFF) != 0)
errx(1, "invalid maxaddr value: %s", arg);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_FTABLE_MAX;
params.vxlp_ftable_max = val & 0xFFFFFFFF;
return;
@@ -508,16 +509,16 @@ DECL_CMD_FUNC(setvxlan_maxaddr, arg, d)
bzero(&cmd, sizeof(cmd));
cmd.vxlcmd_ftable_max = val & 0xFFFFFFFF;
- if (do_cmd(s, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_FTABLE_MAX, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_FTABLE_MAX");
}
-static
-DECL_CMD_FUNC(setvxlan_dev, arg, d)
+static void
+setvxlan_dev(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifvxlancmd cmd;
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_MULTICAST_IF;
strlcpy(params.vxlp_mc_ifname, arg,
sizeof(params.vxlp_mc_ifname));
@@ -527,12 +528,12 @@ DECL_CMD_FUNC(setvxlan_dev, arg, d)
bzero(&cmd, sizeof(cmd));
strlcpy(cmd.vxlcmd_ifname, arg, sizeof(cmd.vxlcmd_ifname));
- if (do_cmd(s, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_MULTICAST_IF, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_MULTICAST_IF");
}
-static
-DECL_CMD_FUNC(setvxlan_ttl, arg, d)
+static void
+setvxlan_ttl(if_ctx *ctx, const char *arg, int dummy __unused)
{
struct ifvxlancmd cmd;
u_long val;
@@ -540,7 +541,7 @@ DECL_CMD_FUNC(setvxlan_ttl, arg, d)
if (get_val(arg, &val) < 0 || val > 256)
errx(1, "invalid TTL value: %s", arg);
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_TTL;
params.vxlp_ttl = val;
return;
@@ -549,16 +550,16 @@ DECL_CMD_FUNC(setvxlan_ttl, arg, d)
bzero(&cmd, sizeof(cmd));
cmd.vxlcmd_ttl = val;
- if (do_cmd(s, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_TTL, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_TTL");
}
-static
-DECL_CMD_FUNC(setvxlan_learn, arg, d)
+static void
+setvxlan_learn(if_ctx *ctx, const char *arg __unused, int d)
{
struct ifvxlancmd cmd;
- if (!vxlan_exists(s)) {
+ if (!vxlan_exists(ctx)) {
params.vxlp_with |= VXLAN_PARAM_WITH_LEARN;
params.vxlp_learn = d;
return;
@@ -568,12 +569,12 @@ DECL_CMD_FUNC(setvxlan_learn, arg, d)
if (d != 0)
cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_LEARN;
- if (do_cmd(s, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_SET_LEARN, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_SET_LEARN");
}
static void
-setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp)
+setvxlan_flush(if_ctx *ctx, const char *val __unused, int d)
{
struct ifvxlancmd cmd;
@@ -581,7 +582,7 @@ setvxlan_flush(const char *val, int d, int s, const struct afswtch *afp)
if (d != 0)
cmd.vxlcmd_flags |= VXLAN_CMD_FLAG_FLUSH_ALL;
- if (do_cmd(s, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0)
+ if (do_cmd(ctx, VXLAN_CMD_FLUSH, &cmd, sizeof(cmd), 1) < 0)
err(1, "VXLAN_CMD_FLUSH");
}
@@ -621,9 +622,9 @@ static struct cmd vxlan_cmds[] = {
DEF_CMD("vxlanflushall", 1, setvxlan_flush),
DEF_CMD("vxlanhwcsum", IFCAP_VXLAN_HWCSUM, setifcap),
- DEF_CMD("-vxlanhwcsum", -IFCAP_VXLAN_HWCSUM, setifcap),
+ DEF_CMD("-vxlanhwcsum", IFCAP_VXLAN_HWCSUM, clearifcap),
DEF_CMD("vxlanhwtso", IFCAP_VXLAN_HWTSO, setifcap),
- DEF_CMD("-vxlanhwtso", -IFCAP_VXLAN_HWTSO, setifcap),
+ DEF_CMD("-vxlanhwtso", IFCAP_VXLAN_HWTSO, clearifcap),
};
static struct afswtch af_vxlan = {
@@ -640,6 +641,5 @@ vxlan_ctor(void)
for (i = 0; i < nitems(vxlan_cmds); i++)
cmd_register(&vxlan_cmds[i]);
af_register(&af_vxlan);
- callback_register(vxlan_cb, NULL);
clone_setdefcallback_prefix("vxlan", vxlan_create);
}
diff --git a/sbin/ifconfig/sfp.c b/sbin/ifconfig/sfp.c
index 4900b18ff2c8..0dc1def751b1 100644
--- a/sbin/ifconfig/sfp.c
+++ b/sbin/ifconfig/sfp.c
@@ -23,11 +23,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -55,15 +50,16 @@ static const char rcsid[] =
#include "ifconfig.h"
void
-sfp_status(int s, struct ifreq *ifr, int verbose)
+sfp_status(if_ctx *ctx)
{
struct ifconfig_sfp_info info;
struct ifconfig_sfp_info_strings strings;
struct ifconfig_sfp_vendor_info vendor_info;
struct ifconfig_sfp_status status;
size_t channel_count;
+ int verbose = ctx->args->verbose;
- if (ifconfig_sfp_get_sfp_info(lifh, name, &info) == -1)
+ if (ifconfig_sfp_get_sfp_info(lifh, ctx->ifname, &info) == -1)
return;
ifconfig_sfp_get_sfp_info_strings(&info, &strings);
@@ -73,7 +69,7 @@ sfp_status(int s, struct ifreq *ifr, int verbose)
ifconfig_sfp_physical_spec(&info, &strings),
strings.sfp_conn);
- if (ifconfig_sfp_get_sfp_vendor_info(lifh, name, &vendor_info) == -1)
+ if (ifconfig_sfp_get_sfp_vendor_info(lifh, ctx->ifname, &vendor_info) == -1)
return;
printf("\tvendor: %s PN: %s SN: %s DATE: %s\n",
@@ -93,7 +89,7 @@ sfp_status(int s, struct ifreq *ifr, int verbose)
}
}
- if (ifconfig_sfp_get_sfp_status(lifh, name, &status) == 0) {
+ if (ifconfig_sfp_get_sfp_status(lifh, ctx->ifname, &status) == 0) {
if (ifconfig_sfp_id_is_qsfp(info.sfp_id) && verbose > 1)
printf("\tnominal bitrate: %u Mbps\n", status.bitrate);
printf("\tmodule temperature: %.2f C voltage: %.2f Volts\n",
@@ -112,7 +108,7 @@ sfp_status(int s, struct ifreq *ifr, int verbose)
if (verbose > 2) {
struct ifconfig_sfp_dump dump;
- if (ifconfig_sfp_get_sfp_dump(lifh, name, &dump) == -1)
+ if (ifconfig_sfp_get_sfp_dump(lifh, ctx->ifname, &dump) == -1)
return;
if (ifconfig_sfp_id_is_qsfp(info.sfp_id)) {
diff --git a/sbin/ifconfig/tests/Makefile b/sbin/ifconfig/tests/Makefile
index 93967c705175..e902f262552a 100644
--- a/sbin/ifconfig/tests/Makefile
+++ b/sbin/ifconfig/tests/Makefile
@@ -1,7 +1,8 @@
-# $FreeBSD$
+NETBSD_ATF_TESTS_SH= nonexistent_test
+ATF_TESTS_SH+= inet6
-NETBSD_ATF_TESTS_SH= nonexistent_test
+TEST_METADATA+= execenv="jail"
+TEST_METADATA+= execenv_jail_params="vnet allow.raw_sockets"
.include <netbsd-tests.test.mk>
-
.include <bsd.test.mk>
diff --git a/sbin/ifconfig/tests/Makefile.depend b/sbin/ifconfig/tests/Makefile.depend
index f80275d86ab1..11aba52f82cf 100644
--- a/sbin/ifconfig/tests/Makefile.depend
+++ b/sbin/ifconfig/tests/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/ifconfig/tests/inet6.sh b/sbin/ifconfig/tests/inet6.sh
new file mode 100644
index 000000000000..22399915a64d
--- /dev/null
+++ b/sbin/ifconfig/tests/inet6.sh
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2025 Lexi Winter
+
+. $(atf_get_srcdir)/../../sys/common/vnet.subr
+
+# Bug 286910: adding 'netmask' or 'broadcast' to an IPv6 address crashed
+# ifconfig.
+
+atf_test_case "netmask" "cleanup"
+netmask_head()
+{
+ atf_set descr "Test invalid 'netmask' option"
+ atf_set require.user root
+}
+
+netmask_body()
+{
+ vnet_init
+
+ ep=$(vnet_mkepair)
+ vnet_mkjail ifcjail ${ep}a
+
+ # Add the address the wrong way
+ atf_check -s exit:1 \
+ -e match:"ifconfig: netmask: invalid option for inet6" \
+ jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1 netmask 64
+
+ # Add the address the correct way
+ atf_check -s exit:0 \
+ jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1/64
+ atf_check -s exit:0 -o match:"2001:db8:1::1 prefixlen 64" \
+ jexec ifcjail ifconfig ${ep}a
+
+ # Remove the address the wrong way
+ atf_check -s exit:1 \
+ -e match:"ifconfig: netmask: invalid option for inet6" \
+ jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1 netmask 64 -alias
+}
+
+netmask_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "broadcast" "cleanup"
+broadcast_head()
+{
+ atf_set descr "Test invalid 'broadcast' option"
+ atf_set require.user root
+}
+
+broadcast_body()
+{
+ vnet_init
+
+ ep=$(vnet_mkepair)
+ vnet_mkjail ifcjail ${ep}a
+
+ atf_check -s exit:1 \
+ -e match:"ifconfig: broadcast: invalid option for inet6" \
+ jexec ifcjail ifconfig ${ep}a \
+ inet6 2001:db8:1::1 broadcast 2001:db8:1::ffff
+
+ atf_check -s exit:0 \
+ jexec ifcjail ifconfig ${ep}a inet6 2001:db8:1::1/64
+
+ atf_check -s exit:1 \
+ -e match:"ifconfig: broadcast: invalid option for inet6" \
+ jexec ifcjail ifconfig ${ep}a \
+ inet6 2001:db8:1::1 broadcast 2001:db:1::ffff -alias
+}
+
+broadcast_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "delete6" "cleanup"
+delete6_head()
+{
+ atf_set descr 'Test removing IPv6 addresses'
+ atf_set require.user root
+}
+
+delete6_body()
+{
+ vnet_init
+
+ ep=$(vnet_mkepair)
+
+ atf_check -s exit:0 \
+ ifconfig ${ep}a inet6 fe80::42/64
+ atf_check -s exit:0 -o match:"fe80::42%${ep}" \
+ ifconfig ${ep}a inet6
+
+ atf_check -s exit:0 \
+ ifconfig ${ep}a inet6 -alias fe80::42
+ atf_check -s exit:0 -o not-match:"fe80::42%${ep}" \
+ ifconfig ${ep}a inet6
+}
+
+delete6_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case netmask
+ atf_add_test_case broadcast
+ atf_add_test_case delete6
+}
diff --git a/sbin/init/Makefile b/sbin/init/Makefile
index 3a914dc7acef..1fc9b633f664 100644
--- a/sbin/init/Makefile
+++ b/sbin/init/Makefile
@@ -1,10 +1,6 @@
-# @(#)Makefile 8.1 (Berkeley) 7/19/93
-# $FreeBSD$
-
CONFGROUPS= CONFTTYS
PACKAGE=runtime
PROG= init
-SRCS= init.c getmntopts.c
MAN= init.8
PRECIOUSPROG=
INSTALLFLAGS=-b -B.bak
@@ -14,11 +10,6 @@ LIBADD= util crypt
CONFTTYSNAME= ttys
CONFTTYS+= ttys
-# Needed for getmntopts.c
-MOUNT= ${SRCTOP}/sbin/mount
-CFLAGS+=-I${MOUNT}
-.PATH: ${MOUNT}
-
NO_SHARED?= YES
.include <bsd.prog.mk>
diff --git a/sbin/init/Makefile.depend b/sbin/init/Makefile.depend
index 10a95e7fdc38..1a673c53cbc6 100644
--- a/sbin/init/Makefile.depend
+++ b/sbin/init/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/init/init.8 b/sbin/init/init.8
index 9475b1cce48f..8f6e78b79d7b 100644
--- a/sbin/init/init.8
+++ b/sbin/init/init.8
@@ -28,9 +28,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)init.8 8.3 (Berkeley) 4/18/94
-.\" $FreeBSD$
-.\"
.Dd July 22, 2021
.Dt INIT 8
.Os
@@ -399,6 +396,7 @@ back to the default, so that the
.Pa /etc/rc
script is executed with the standard shell
.Pa /bin/sh .
+.El
.Sh FILES
.Bl -tag -width /var/log/init.log -compact
.It Pa /dev/console
diff --git a/sbin/init/init.c b/sbin/init/init.c
index 813387f63c81..d28501053c7f 100644
--- a/sbin/init/init.c
+++ b/sbin/init/init.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1991, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 7/15/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/boottrace.h>
#include <sys/ioctl.h>
@@ -63,6 +49,7 @@ static const char rcsid[] =
#include <fcntl.h>
#include <kenv.h>
#include <libutil.h>
+#include <mntopts.h>
#include <paths.h>
#include <signal.h>
#include <stdarg.h>
@@ -83,7 +70,6 @@ static const char rcsid[] =
#include <login_cap.h>
#endif
-#include "mntopts.h"
#include "pathnames.h"
/*
@@ -99,6 +85,7 @@ static const char rcsid[] =
#define RESOURCE_RC "daemon"
#define RESOURCE_WINDOW "default"
#define RESOURCE_GETTY "default"
+#define SCRIPT_ARGV_SIZE 3 /* size of argv passed to execute_script, can be increased if needed */
static void handle(sig_t, ...);
static void delset(sigset_t *, ...);
@@ -864,9 +851,9 @@ single_user(void)
const char *shell;
char *argv[2];
struct timeval tv, tn;
+ struct passwd *pp;
#ifdef SECURE
struct ttyent *typ;
- struct passwd *pp;
static const char banner[] =
"Enter root password, or ^D to go multi-user\n";
char *clear, *password;
@@ -898,6 +885,7 @@ single_user(void)
*/
open_console();
+ pp = getpwnam("root");
#ifdef SECURE
/*
* Check the root password.
@@ -905,7 +893,6 @@ single_user(void)
* it's the only tty that can be 'off' and 'secure'.
*/
typ = getttynam("console");
- pp = getpwnam("root");
if (typ && (typ->ty_status & TTY_SECURE) == 0 &&
pp && *pp->pw_passwd) {
write_stderr(banner);
@@ -922,7 +909,6 @@ single_user(void)
}
}
endttyent();
- endpwent();
#endif /* SECURE */
#ifdef DEBUGSHELL
@@ -943,6 +929,15 @@ single_user(void)
}
#endif /* DEBUGSHELL */
+ if (pp != NULL && pp->pw_dir != NULL && *pp->pw_dir != '\0' &&
+ chdir(pp->pw_dir) == 0) {
+ setenv("HOME", pp->pw_dir, 1);
+ } else {
+ chdir("/");
+ setenv("HOME", "/", 1);
+ }
+ endpwent();
+
/*
* Unblock signals.
* We catch all the interesting ones,
@@ -1044,8 +1039,9 @@ static void
execute_script(char *argv[])
{
struct sigaction sa;
+ char* sh_argv[3 + SCRIPT_ARGV_SIZE];
const char *shell, *script;
- int error;
+ int error, sh_argv_len, i;
bzero(&sa, sizeof(sa));
sigemptyset(&sa.sa_mask);
@@ -1066,17 +1062,28 @@ execute_script(char *argv[])
* to sh(1). Don't complain if it fails because of
* the missing execute bit.
*/
- script = argv[1];
+ script = argv[0];
error = access(script, X_OK);
if (error == 0) {
- execv(script, argv + 1);
+ execv(script, argv);
warning("can't directly exec %s: %m", script);
} else if (errno != EACCES) {
warning("can't access %s: %m", script);
}
shell = get_shell();
- execv(shell, argv);
+ sh_argv[0] = __DECONST(char*, shell);
+ sh_argv_len = 1;
+#ifdef SECURE
+ if (strcmp(shell, _PATH_BSHELL) == 0) {
+ sh_argv[1] = __DECONST(char*, "-o");
+ sh_argv[2] = __DECONST(char*, "verify");
+ sh_argv_len = 3;
+ }
+#endif
+ for (i = 0; i != SCRIPT_ARGV_SIZE; ++i)
+ sh_argv[i + sh_argv_len] = argv[i];
+ execv(shell, sh_argv);
stall("can't exec %s for %s: %m", shell, script);
}
@@ -1086,12 +1093,10 @@ execute_script(char *argv[])
static void
replace_init(char *path)
{
- char *argv[3];
- char sh[] = "sh";
+ char *argv[SCRIPT_ARGV_SIZE];
- argv[0] = sh;
- argv[1] = path;
- argv[2] = NULL;
+ argv[0] = path;
+ argv[1] = NULL;
execute_script(argv);
}
@@ -1108,20 +1113,18 @@ run_script(const char *script)
{
pid_t pid, wpid;
int status;
- char *argv[4];
+ char *argv[SCRIPT_ARGV_SIZE];
const char *shell;
shell = get_shell();
if ((pid = fork()) == 0) {
- char _sh[] = "sh";
- char _autoboot[] = "autoboot";
+ char _autoboot[] = "autoboot";
- argv[0] = _sh;
- argv[1] = __DECONST(char *, script);
- argv[2] = runcom_mode == AUTOBOOT ? _autoboot : 0;
- argv[3] = NULL;
+ argv[0] = __DECONST(char *, script);
+ argv[1] = runcom_mode == AUTOBOOT ? _autoboot : NULL;
+ argv[2] = NULL;
execute_script(argv);
sleep(STALL_TIMEOUT);
@@ -1143,10 +1146,10 @@ run_script(const char *script)
do {
if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
collect_child(wpid);
+ if (requested_transition == death_single ||
+ requested_transition == reroot)
+ return (state_func_t) requested_transition;
if (wpid == -1) {
- if (requested_transition == death_single ||
- requested_transition == reroot)
- return (state_func_t) requested_transition;
if (errno == EINTR)
continue;
warning("wait for %s on %s failed: %m; going to "
@@ -1957,7 +1960,7 @@ runshutdown(void)
int status;
int shutdowntimeout;
size_t len;
- char *argv[4];
+ char *argv[SCRIPT_ARGV_SIZE];
struct stat sb;
BOOTTRACE("init(8): start rc.shutdown");
@@ -1972,16 +1975,14 @@ runshutdown(void)
return 0;
if ((pid = fork()) == 0) {
- char _sh[] = "sh";
char _reboot[] = "reboot";
char _single[] = "single";
char _path_rundown[] = _PATH_RUNDOWN;
- argv[0] = _sh;
- argv[1] = _path_rundown;
- argv[2] = Reboot ? _reboot : _single;
- argv[3] = NULL;
-
+ argv[0] = _path_rundown;
+ argv[1] = Reboot ? _reboot : _single;
+ argv[2] = NULL;
+
execute_script(argv);
_exit(1); /* force single user mode */
}
diff --git a/sbin/init/pathnames.h b/sbin/init/pathnames.h
index 7dc75ba52491..c04155a901ae 100644
--- a/sbin/init/pathnames.h
+++ b/sbin/init/pathnames.h
@@ -30,9 +30,6 @@
* 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.
- *
- * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
- * $FreeBSD$
*/
#include <paths.h>
diff --git a/sbin/init/ttys b/sbin/init/ttys
index a2f5b8975ecd..d3ac4546d9be 100644
--- a/sbin/init/ttys
+++ b/sbin/init/ttys
@@ -1,7 +1,3 @@
-#
-# $FreeBSD$
-# @(#)ttys 5.1 (Berkeley) 4/17/89
-#
# This file specifies various information about terminals on the system.
# It is used by several different programs. Common entries for the
# various columns include:
@@ -46,8 +42,8 @@ ttyu1 "/usr/libexec/getty 3wire" vt100 onifconsole secure
ttyu2 "/usr/libexec/getty 3wire" vt100 onifconsole secure
ttyu3 "/usr/libexec/getty 3wire" vt100 onifconsole secure
# Dumb console
-dcons "/usr/libexec/getty std.9600" vt100 off secure
+dcons "/usr/libexec/getty std.115200" vt100 off secure
# Xen Virtual console
xc0 "/usr/libexec/getty Pc" xterm onifconsole secure
# RISC-V HTIF console
-rcons "/usr/libexec/getty std.9600" vt100 onifconsole secure
+rcons "/usr/libexec/getty std.115200" vt100 onifconsole secure
diff --git a/sbin/ipf/Makefile b/sbin/ipf/Makefile
index 075119abd542..1b0a18d3d9c3 100644
--- a/sbin/ipf/Makefile
+++ b/sbin/ipf/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
SUBDIR= libipf .WAIT
SUBDIR+= ipf ipfs ipfstat ipmon ipnat ippool
# XXX Temporarily disconnected.
diff --git a/sbin/ipf/Makefile.inc b/sbin/ipf/Makefile.inc
index 1f256a343b9a..cb3a3df50e0c 100644
--- a/sbin/ipf/Makefile.inc
+++ b/sbin/ipf/Makefile.inc
@@ -1,10 +1,7 @@
-# $FreeBSD$
-
.include <src.opts.mk>
WARNS?= 2
NO_WFORMAT=
-NO_WARRAY_BOUNDS=
CFLAGS+= -I${SRCTOP}/sys
CFLAGS+= -I${SRCTOP}/sys/netpfil/ipfilter
diff --git a/sbin/ipf/common/genmask.c b/sbin/ipf/common/genmask.c
index 5b715cf4c901..a3b912b67ef3 100644
--- a/sbin/ipf/common/genmask.c
+++ b/sbin/ipf/common/genmask.c
@@ -9,10 +9,8 @@
#include "ipf.h"
-int genmask(family, msk, mskp)
- int family;
- char *msk;
- i6addr_t *mskp;
+int
+genmask(int family, char *msk, i6addr_t *mskp)
{
char *endptr = 0L;
u_32_t addr;
diff --git a/sbin/ipf/common/ipf.h b/sbin/ipf/common/ipf.h
index b278d8ec5d6c..3e6ee594b8b6 100644
--- a/sbin/ipf/common/ipf.h
+++ b/sbin/ipf/common/ipf.h
@@ -1,11 +1,8 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
- *
- * @(#)ipf.h 1.12 6/5/96
* $Id$
*/
@@ -47,6 +44,7 @@
#include <errno.h>
#include <limits.h>
#include <netdb.h>
+#include <stdarg.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
@@ -173,20 +171,14 @@ typedef struct proxyrule {
} proxyrule_t;
-#if defined(__NetBSD__) || defined(__FreeBSD__) || \
- SOLARIS
-# include <stdarg.h>
typedef int (* ioctlfunc_t)(int, ioctlcmd_t, ...);
-#else
-typedef int (* ioctlfunc_t)(dev_t, ioctlcmd_t, void *);
-#endif
typedef int (* addfunc_t)(int, ioctlfunc_t, void *);
typedef int (* copyfunc_t)(void *, void *, size_t);
extern char thishost[MAXHOSTNAMELEN];
extern char flagset[];
-extern u_char flags[];
+extern uint16_t flags[];
extern struct ipopt_names ionames[];
extern struct ipopt_names secclass[];
extern char *icmpcodes[MAX_ICMPCODE + 1];
@@ -318,7 +310,7 @@ extern ipf_dstnode_t *printdstlistnode(ipf_dstnode_t *, copyfunc_t,
extern void printdstlistpolicy(ippool_policy_t);
extern struct ip_pool_s *printpool(struct ip_pool_s *, copyfunc_t,
char *, int, wordtab_t *);
-extern struct ip_pool_s *printpool_live(struct ip_pool_s *, int,
+extern void printpool_live(struct ip_pool_s *, int,
char *, int, wordtab_t *);
extern void printpooldata(ip_pool_t *, int);
extern void printpoolfield(void *, int, int);
@@ -338,7 +330,7 @@ extern int remove_hash(struct iphtable_s *, ioctlfunc_t);
extern int remove_hashnode(int, char *, struct iphtent_s *, ioctlfunc_t);
extern int remove_pool(ip_pool_t *, ioctlfunc_t);
extern int remove_poolnode(int, char *, ip_pool_node_t *, ioctlfunc_t);
-extern u_char tcpflags(char *);
+extern uint16_t tcpflags(char *);
extern void printc(struct frentry *);
extern void printC(int);
extern void emit(int, int, void *, struct frentry *);
diff --git a/sbin/ipf/common/ipf_y.y b/sbin/ipf/common/ipf_y.y
index ad4200023781..b3f7221672f3 100644
--- a/sbin/ipf/common/ipf_y.y
+++ b/sbin/ipf/common/ipf_y.y
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/common/ipmon.h b/sbin/ipf/common/ipmon.h
index 4807299c49d2..4d377027eb3d 100644
--- a/sbin/ipf/common/ipmon.h
+++ b/sbin/ipf/common/ipmon.h
@@ -1,11 +1,8 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
- *
- * @(#)ip_fil.h 1.35 6/5/96
* $Id$
*/
diff --git a/sbin/ipf/common/ipt.h b/sbin/ipf/common/ipt.h
index 9a4d75a85ccb..3ecdabdb61c5 100644
--- a/sbin/ipf/common/ipt.h
+++ b/sbin/ipf/common/ipt.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/common/kmem.h b/sbin/ipf/common/kmem.h
index c4b65ed63ce9..2adff4363b0b 100644
--- a/sbin/ipf/common/kmem.h
+++ b/sbin/ipf/common/kmem.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/common/lexer.c b/sbin/ipf/common/lexer.c
index 16fbb2272034..56ac3586af6e 100644
--- a/sbin/ipf/common/lexer.c
+++ b/sbin/ipf/common/lexer.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -11,6 +10,7 @@
# include "netinet/ip_scan.h"
#endif
#include <sys/ioctl.h>
+#include <sys/param.h>
#include <syslog.h>
#ifdef TEST_LEXER
# define NO_YACC
@@ -449,7 +449,7 @@ buildipv6:
oc = c;
if (prior == YY_NUMBER && c == ':') {
- snprintf(s, sizeof(s), "%d", priornum);
+ snprintf(s, sizeof(ipv6buf), "%d", priornum);
s += strlen(s);
}
@@ -603,8 +603,7 @@ done:
}
-static wordtab_t *yyfindkey(key)
- char *key;
+static wordtab_t *yyfindkey(char *key)
{
wordtab_t *w;
@@ -677,7 +676,7 @@ yysetfixeddict(wordtab_t *newdict)
if (yydebug)
printf("yysetfixeddict(%lx)\n", (u_long)newdict);
- if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
+ if (yysavedepth == nitems(yysavewords)) {
fprintf(stderr, "%d: at maximum dictionary depth\n",
yylineNum);
return;
@@ -696,7 +695,7 @@ yysetdict(wordtab_t *newdict)
if (yydebug)
printf("yysetdict(%lx)\n", (u_long)newdict);
- if (yysavedepth == sizeof(yysavewords)/sizeof(yysavewords[0])) {
+ if (yysavedepth == nitems(yysavewords)) {
fprintf(stderr, "%d: at maximum dictionary depth\n",
yylineNum);
return;
diff --git a/sbin/ipf/common/lexer.h b/sbin/ipf/common/lexer.h
index cc200f1cad41..c5f9a0c4183e 100644
--- a/sbin/ipf/common/lexer.h
+++ b/sbin/ipf/common/lexer.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/common/opts.h b/sbin/ipf/common/opts.h
index 17844e89ecfc..1281458c145a 100644
--- a/sbin/ipf/common/opts.h
+++ b/sbin/ipf/common/opts.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/common/pcap-ipf.h b/sbin/ipf/common/pcap-ipf.h
index b856760eaa53..ba596e795efa 100644
--- a/sbin/ipf/common/pcap-ipf.h
+++ b/sbin/ipf/common/pcap-ipf.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/ipf/Makefile b/sbin/ipf/ipf/Makefile
index f1b87ac20fae..00cabf50cd89 100644
--- a/sbin/ipf/ipf/Makefile
+++ b/sbin/ipf/ipf/Makefile
@@ -1,11 +1,10 @@
-# $FreeBSD$
-
PACKAGE= ipf
PROG= ipf
SRCS= ${GENHDRS} ipf.c ipfcomp.c ipf_y.c ipf_l.c bpf_filter.c
MAN= ipfilter.4 ipfilter.5 ipf.8 ipf.4 ipf.5 ipl.4
MLINKS= ipf.5 ipf.conf.5 ipf.5 ipf6.conf.5
CFLAGS+= -I. -DIPFILTER_BPF -DHAS_SYS_MD5_H
+CFLAGS+= -Wno-error=unused-but-set-variable
GENHDRS= ipf_l.h ipf_y.h
CLEANFILES+= ${GENHDRS} ipf_y.c ipf_l.c
diff --git a/sbin/ipf/ipf/Makefile.depend b/sbin/ipf/ipf/Makefile.depend
index 84ddd8bb35de..d66414571fe3 100644
--- a/sbin/ipf/ipf/Makefile.depend
+++ b/sbin/ipf/ipf/Makefile.depend
@@ -1,15 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
lib/libpcap \
sbin/ipf/libipf \
diff --git a/sbin/ipf/ipf/bpf-ipf.h b/sbin/ipf/ipf/bpf-ipf.h
index 2350e6cf0692..e41e9d71bbb9 100644
--- a/sbin/ipf/ipf/bpf-ipf.h
+++ b/sbin/ipf/ipf/bpf-ipf.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -36,10 +35,6 @@
* 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.
- *
- * @(#)bpf.h 7.1 (Berkeley) 5/7/91
- *
- * @(#) $Header: /devel/CVS/IP-Filter/bpf-ipf.h,v 2.1 2002/10/26 12:14:26 darrenr Exp $ (LBL)
*/
#ifndef BPF_MAJOR_VERSION
@@ -91,7 +86,7 @@ struct bpf_stat {
* bpf understands a program iff kernel_major == filter_major &&
* kernel_minor >= filter_minor, that is, if the value returned by the
* running kernel has the same major number and a minor number equal
- * equal to or less than the filter being downloaded. Otherwise, the
+ * to or less than the filter being downloaded. Otherwise, the
* results are undefined, meaning an error may be returned or packets
* may be accepted haphazardly.
* It has nothing to do with the source code version.
diff --git a/sbin/ipf/ipf/bpf_filter.c b/sbin/ipf/ipf/bpf_filter.c
index fbb0138f51d8..bd7012d2f1ab 100644
--- a/sbin/ipf/ipf/bpf_filter.c
+++ b/sbin/ipf/ipf/bpf_filter.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -36,15 +35,8 @@
* 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.
- *
- * @(#)bpf.c 7.5 (Berkeley) 7/15/91
*/
-#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
-static const char rcsid[] =
- "@(#) $Header: /devel/CVS/IP-Filter/bpf_filter.c,v 2.2.2.3 2006/10/03 11:25:56 darrenr Exp $ (LBL)";
-#endif
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -117,9 +109,7 @@ static int m_xhalf(mb_t *, int, int *);
}
static int
-m_xword(m, k, err)
- register mb_t *m;
- register int k, *err;
+m_xword(mb_t *m, int k, int *err)
{
register int len;
register u_char *cp, *np;
@@ -153,9 +143,7 @@ m_xword(m, k, err)
}
static int
-m_xhalf(m, k, err)
- register mb_t *m;
- register int k, *err;
+m_xhalf(mb_t *m, int k, int *err)
{
register int len;
register u_char *cp;
@@ -185,11 +173,7 @@ m_xhalf(m, k, err)
* in all other cases, p is a pointer to a buffer and buflen is its size.
*/
u_int
-bpf_filter(pc, p, wirelen, buflen)
- register struct bpf_insn *pc;
- register u_char *p;
- u_int wirelen;
- register u_int buflen;
+bpf_filter(struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
{
register u_int32 A, X;
register int k;
@@ -478,9 +462,7 @@ bpf_filter(pc, p, wirelen, buflen)
* Otherwise, a bogus program could easily crash the system.
*/
int
-bpf_validate(f, len)
- struct bpf_insn *f;
- int len;
+bpf_validate(struct bpf_insn *f, int len)
{
u_int i, from;
const struct bpf_insn *p;
diff --git a/sbin/ipf/ipf/ipf.4 b/sbin/ipf/ipf/ipf.4
index 73a17a0cc8d3..c5b3bac34947 100644
--- a/sbin/ipf/ipf/ipf.4
+++ b/sbin/ipf/ipf/ipf.4
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.TH IPF 4
.SH NAME
ipf \- packet filtering kernel interface
@@ -7,7 +6,6 @@ ipf \- packet filtering kernel interface
.br
#include <netinet/ip_fil.h>
.SH IOCTLS
-.PP
To add and delete rules to the filter list, three 'basic' ioctls are provided
for use. The ioctl's are called as:
.LP
@@ -121,7 +119,7 @@ Flags which are recognised in fr_flags:
FR_RETRST 0x000080 /* return a TCP RST packet if blocked */
FR_RETICMP 0x000100 /* return an ICMP packet if blocked */
FR_FAKEICMP 0x00180 /* Return ICMP unreachable with fake source */
- FR_NOMATCH 0x000200 /* no match occured */
+ FR_NOMATCH 0x000200 /* no match occurred */
FR_ACCOUNT 0x000400 /* count packet bytes */
FR_KEEPFRAG 0x000800 /* keep fragment information */
FR_KEEPSTATE 0x001000 /* keep `connection' state information */
diff --git a/sbin/ipf/ipf/ipf.5 b/sbin/ipf/ipf/ipf.5
index 7f72a817617b..4ff33290814a 100644
--- a/sbin/ipf/ipf/ipf.5
+++ b/sbin/ipf/ipf/ipf.5
@@ -1,9 +1,7 @@
-.\" $FreeBSD$
.TH IPF 5
.SH NAME
ipf, ipf.conf \- IPFilter firewall rules file format
.SH DESCRIPTION
-.PP
The ipf.conf file is used to specify rules for the firewall, packet
authentication and packet accounting components of IPFilter. To load rules
specified in the ipf.conf file, the ipf(8) program is used.
@@ -30,9 +28,8 @@ the direction of the packet (in or out)
address patterns or "all" to match any address information
.RE
.SS Long lines
-.PP
For rules lines that are particularly long, it is possible to split
-them over multiple lines implicity like this:
+them over multiple lines implicitly like this:
.PP
.nf
pass in on bgeo proto tcp from 1.1.1.1 port > 1000
@@ -46,7 +43,6 @@ pass in on bgeo proto tcp from 1.1.1.1 port > 1000 \\
to 2.2.2.2 port < 5000 flags S keep state
.fi
.SS Comments
-.PP
Comments in the ipf.conf file are indicated by the use of the '#' character.
This can either be at the start of the line, like this:
.PP
@@ -61,7 +57,6 @@ Or at the end of a like, like this:
pass in proto icmp from any to any # Allow all ICMP packets in
.fi
.SH Firewall rules
-.PP
This section goes into detail on how to construct firewall rules that
are placed in the ipf.conf file.
.PP
@@ -70,7 +65,6 @@ firewall rule set or which packets should be blocked or allowed in.
Some suggestions will be provided but further reading is expected to
fully understand what is safe and unsafe to allow in/out.
.SS Filter rule keywords
-.PP
The first word found in any filter rule describes what the eventual outcome
of a packet that matches it will be. Descriptions of the many and various
sections that can be used to match on the contents of packet headers will
@@ -132,7 +126,6 @@ rule to match a packet is a pass, if there is a later matching rule
that is a block and no further rules match the packet, then it will
be blocked.
.SS Matching Network Interfaces
-.PP
On systems with more than one network interface, it is necessary
to be able to specify different filter rules for each of them.
In the first instance, this is because different networks will send us
@@ -159,7 +152,6 @@ block in on bge0 all
pass out on bge0 all
.fi
.SS Address matching (basic)
-.PP
The first and most basic part of matching for filtering rules is to
specify IP addresses and TCP/UDP port numbers. The source address
information is matched by the "from" information in a filter rule
@@ -198,7 +190,6 @@ is processing that part of the configuration file, leading to long
delays, if not errors, in loading the filter rules.
.RE
.SS Protocol Matching
-.PP
To match packets based on TCP/UDP port information, it is first necessary
to indicate which protocol the packet must be. This is done using the
"proto" keyword, followed by either the protocol number or a name which
@@ -210,7 +201,6 @@ block out proto udp from any to 10.1.1.1
pass in proto icmp from any to 192.168.0.0/16
.fi
.SS Sending back error packets
-.PP
When a packet is just discarded using a block rule, there is no feedback given
to the host that sent the packet. This is both good and bad. If this is the
desired behaviour and it is not desirable to send any feedback about packets
@@ -224,7 +214,7 @@ To address this problem, a block rule can be qualified in two ways.
The first of these is specific to TCP and instructs IPFilter to send back
a reset (RST) packet. This packet indicates to the remote system that the
packet it sent has been rejected and that it shouldn't make any further
-attempts( to send packets to that port. Telling IPFilter to return a TCP);
+attempts to send packets to that port. Telling IPFilter to return a TCP
RST packet in response to something that has been received is achieved
with the return-rst keyword like this:
.PP
@@ -240,18 +230,18 @@ For all of the other protocols handled by the IP protocol suite, to send
back an error indicating that the received packet was dropped requires
sending back an ICMP error packet. Whilst these can also be used for TCP,
the sending host may not treat the received ICMP error as a hard error
-in( the same way as it does the TCP RST packet. To return an ICMP error);
+in the same way as it does the TCP RST packet. To return an ICMP error
it is necessary to place return-icmp after the block keyword like this:
.PP
.nf
block return-icmp in proto udp from any to 192.168.0.1/24
.fi
.PP
-When( electing to return an ICMP error packet, it is also possible to);
+When electing to return an ICMP error packet, it is also possible to
select what type of ICMP error is returned. Whilst the full compliment
of ICMP unreachable codes can be used by specifying a number instead of
the string below, only the following should be used in conjunction with
-return-icmp.( Which return code to use is a choice to be made when);
+return-icmp. Which return code to use is a choice to be made when
weighing up the pro's and con's. Using some of the codes may make it
more obvious that a firewall is being used rather than just the host
not responding.
@@ -296,7 +286,7 @@ proto-unr
(protocol unreachable)
the IP protocol specified in the packet is not available to receive
packets.
-.DE
+.RE
.PP
An example that shows how to send back a port unreachable packet for
UDP packets to 192.168.1.0/24 is as follows:
@@ -318,7 +308,6 @@ block return-icmp-as-dest(port-unr) in proto udp \\
from any to 192.168.1.0/24
.fi
.SS TCP/UDP Port Matching
-.PP
Having specified which protocol is being matched, it is then possible to
indicate which port numbers a packet must have in order to match the rule.
Due to port numbers being used differently to addresses, it is therefore
@@ -362,7 +351,6 @@ If there is no desire to mention any specific source or destintion
information in a filter rule then the word "all" can be used to
indicate that all addresses are considered to match the rule.
.SS IPv4 or IPv6
-.PP
If a filter rule is constructed without any addresses then IPFilter
will attempt to match both IPv4 and IPv6 packets with it. In the
next list of rules, each one can be applied to either network protocol
@@ -400,13 +388,11 @@ protocol family qualifier:
pass in family inet6 proto udp from any to any port = 53
.fi
.SS First match vs last match
-.PP
To change the default behaviour from being the last matched rule decides
the outcome to being the first matched rule, the word "quick" is inserted
to the rule.
.SH Extended Packet Matching
.SS Beyond using plain addresses
-.PP
On firewalls that are working with large numbers of hosts and networks
or simply trying to filter discretely against various hosts, it can
be an easier administration task to define a pool of addresses and have
@@ -476,7 +462,6 @@ with.
pass in proto icmp from any to (bge0)/32
.fi
.SS Using address pools
-.PP
Rather than list out multiple rules that either allow or deny specific
addresses, it is possible to create a single object, call an address
pool, that contains all of those addresses and reference that in the
@@ -506,7 +491,6 @@ There are different operational characteristics with each, so there
may be some situations where a pool works better than hash and vice
versa.
.SS Matching TCP flags
-.PP
The TCP header contains a field of flags that is used to decide if the
packet is a connection request, connection termination, data, etc.
By matching on the flags in conjunction with port numbers, it is
@@ -537,7 +521,7 @@ URG - this bit is set to indicate that the packet contains urgent data
.HP
R
RST - this bit is set only in packets that are a reply to another
-that has been received but is not targetted at any open port
+that has been received but is not targeted at any open port
.HP
C
CWN
@@ -549,10 +533,10 @@ When matching TCP flags, it is normal to just list the flag that you
wish to be set. By default the set of flags it is compared against
is "FSRPAU". Rules that say "flags S" will be displayed by ipfstat(8)
as having "flags S/FSRPAU". This is normal.
-The last two flags, "C" and "E", are optional - they
+The last three flags, "E", "W" and "e", are optional - they
may or may not be used by an end host and have no bearing on either
the acceptance of data nor control of the connection. Masking them
-out with "flags S/FSRPAUCE" may cause problems for remote hosts
+out with "flags S/FSRPAUEWe" may cause problems for remote hosts
making a successful connection.
.PP
.nf
@@ -563,7 +547,6 @@ pass out quick proto tcp from any port = 22 to any flags SA
By itself, filtering based on the TCP flags becomes more work but when
combined with stateful filtering (see below), the situation changes.
.SS Matching on ICMP header information
-.PP
The TCP and UDP are not the only protocols for which filtering beyond
just the IP header is possible, extended matching on ICMP packets is
also available. The list of valid ICMP types is different for IPv4
@@ -628,7 +611,6 @@ unreach (unreachable,
whoreq (WRU request),
whorep (WRU reply).
.SH Stateful Packet Filtering
-.PP
Stateful packet filtering is where IPFilter remembers some information from
one or more packets that it has seen and is able to apply it to future
packets that it receives from the network.
@@ -687,7 +669,7 @@ Once a TCP connection has reached the established state, the default
timeout allows for it to be idle for 5 days before it is removed from
the state table. The timeouts for the other TCP connection states
vary from 240 seconds to 30 seconds.
-Both UDP and ICMP state entries have asymetric timeouts where the timeout
+Both UDP and ICMP state entries have asymmetric timeouts where the timeout
set upon seeing packets in the forward direction is much larger than
for the reverse direction. For UDP the default timeouts are 120 and
12 seconds, for ICMP 60 and 6 seconds. This is a reflection of the
@@ -695,7 +677,6 @@ use of these protocols being more for query-response than for ongoing
connections. For all other protocols the
timeout is 60 seconds in both directions.
.SS Stateful filtering options
-.PP
The following options can be used with stateful filtering:
.HP
limit
@@ -813,7 +794,6 @@ If there is no IP protocol implied by addresses or other features of
the rule, IPFilter will assume that no netmask is an all ones netmask
for both IPv4 and IPv6.
.SS Tieing down a connection
-.PP
For any connection that transits a firewall, each packet will be seen
twice: once going in and once going out. Thus a connection has 4 flows
of packets:
@@ -852,7 +832,6 @@ pass in on bge0,bge1 out-via bge1,bge0 proto tcp \\
from any to any port = 22 flags S keep state
.fi
.SS Working with packet fragments
-.PP
Fragmented packets result in 1 packet containing all of the layer 3 and 4
header information whilst the data is split across a number of other packets.
.PP
@@ -884,15 +863,14 @@ An example of how this is done is as follows:
pass in proto udp from any port = 2049 to any with frags keep frags
.fi
.SH Building a tree of rules
-.PP
Writing your filter rules as one long list of rules can be both inefficient
in terms of processing the rules and difficult to understand. To make the
construction of filter rules easier, it is possible to place them in groups.
A rule can be both a member of a group and the head of a new group.
.PP
Using filter groups requires at least two rules: one to be in the group
-one one to send matchign packets to the group. If a packet matches a
-filtre rule that is a group head but does not match any of the rules
+one one to send matching packets to the group. If a packet matches a
+filter rule that is a group head but does not match any of the rules
in that group, then the packet is considered to have matched the head
rule.
.PP
@@ -948,7 +926,6 @@ to deliver spam, I could load the following rule to complement the above:
block in quick from 10.1.1.1 to any group spammers
.fi
.SS Decapsulation
-.PP
Rule groups also form a different but vital role for decapsulation rules.
With the following simple rule, if IPFilter receives an IP packet that has
an AH header as its layer 4 payload, IPFilter would adjust its view of the
@@ -983,7 +960,6 @@ It is possible to construct a decapsulate rule without the group
head at the end that ipf(8) will accept but such rules will not
result in anything happening.
.SS Policy Based Routing
-.PP
With firewalls being in the position they often are, at the boundary
of different networks connecting together and multiple connections that
have different properties, it is often desirable to have packets flow
@@ -1035,10 +1011,9 @@ pass in on bge0 to bge1:1.1.1.1 reply-to hme1:2.1.1.2 \\
to any port = 80 flags S keep state
.fi
.SS Matching IPv4 options
-.PP
The design for IPv4 allows for the header to be upto 64 bytes long,
however most traffic only uses the basic header which is 20 bytes long.
-The other 44 bytes can be uesd to store IP options. These options are
+The other 44 bytes can be used to store IP options. These options are
generally not necessary for proper interaction and function on the
Internet today. For most people it is sufficient to block and drop
all packets that have any options set. This can be achieved with this
@@ -1091,7 +1066,7 @@ some of the nodes the packet must go through, with the ssrr option,
every next hop router must be specified.
.PP
The complete list of IPv4 options that can be matched on is:
-addext (Address Extention),
+addext (Address Extension),
cipso (Classical IP Security Option),
dps (Dynamic Packet State),
e-sec (Extended Security),
@@ -1116,7 +1091,6 @@ ump (Upstream Multicast Packet),
visa (Experimental Access Control)
and zsu (Experimental Measurement).
.SS Security with CIPSO and IPSO
-.PP
IPFilter supports filtering on IPv4 packets using security attributes embedded
in the IP options part of the packet. These options are usually only used on
networks and systems that are using lablled security. Unless you know that
@@ -1140,7 +1114,6 @@ block in quick all with opt sec-class unclass
pass in all with opt sec-class secret
.fi
.SS Matching IPv6 extension headers
-.PP
Just as it is possible to filter on the various IPv4 header options,
so too it is possible to filter on the IPv6 extension headers that are
placed between the IPv6 header and the transport protocol header.
@@ -1154,7 +1127,6 @@ mobility (IP mobility),
none,
routing.
.SS Logging
-.PP
There are two ways in which packets can be logged with IPFilter. The
first is with a rule that specifically says log these types of packets
and the second is a qualifier to one of the other keywords. Thus it is
@@ -1212,7 +1184,6 @@ pass in log level local1.info proto tcp \\
ipfstat(8) reports how many packets have been successfully logged and how
many failed attempts to log a packet there were.
.SS Filter rule comments
-.PP
If there is a desire to associate a text string, be it an administrative
comment or otherwise, with an IPFilter rule, this can be achieved by giving
the filter rule a comment. The comment is loaded with the rule into the
@@ -1225,7 +1196,6 @@ pass out quick proto tcp from any port = 80 \\
to any comment "all web server traffic is ok"
.fi
.SS Tags
-.PP
To enable filtering and NAT to correctly match up packets with rules,
tags can be added at with NAT (for inbound packets) and filtering (for
outbound packets.) This allows a filter to be correctly mated with its
@@ -1250,7 +1220,6 @@ such as grep, extracting log records of interest is simplified.
block in quick log ... set-tag(log=33)
.fi
.SH Filter Rule Expiration
-.PP
IPFilter allows rules to be added into the kernel that it will remove after
a specific period of time by specifying rule-ttl at the end of a rule.
When listing rules in the kernel using ipfstat(8), rules that are going
@@ -1265,7 +1234,6 @@ pass in on fxp0 proto tcp from any \\
to port = 22 flags S keep state rule-ttl 30
.fi
.SH Internal packet attributes
-.PP
In addition to being able to filter on very specific network and transport
header fields, it is possible to filter on other attributes that IPFilter
attaches to a packet. These attributes are placed in a rule after the
@@ -1333,7 +1301,6 @@ block in all
pass in all with not bad
.fi
.SH Tuning IPFilter
-.PP
The ipf.conf file can also be used to tune the behaviour of IPFilter,
allowing, for example, timeouts for the NAT/state table(s) to be set
along with their sizes. The presence and names of tunables may change
@@ -1358,7 +1325,7 @@ A list of the currently available variables inside IPFilter that may
be tuned from ipf.conf are as follows:
.HP
active
-set through -s command line switch of ipf(8). See ipf(8) for detals.
+set through -s command line switch of ipf(8). See ipf(8) for details.
.HP
chksrc
when set, enables reverse path verification on source addresses and
@@ -1431,7 +1398,7 @@ sets the size of the in-kernel log buffer in bytes.
log_suppress
when set, IPFilter will check to see if the packet it is logging is
similar to the one it previously logged and if so, increases
-the occurance count for that packet. The previously logged packet
+the occurrence count for that packet. The previously logged packet
must not have yet been read by ipmon(8).
.HP
min_ttl
@@ -1468,8 +1435,8 @@ when the fill percentage of the NAT table exceeds this mark, more
aggressive flushing is enabled.
.HP
nat_table_wm_low
-this sets the percentage at which the NAT table's agressive flushing
-will turn itself off at.
+this sets the percentage at which the NAT table's aggressive flushing
+will turn itself off.
.HP
rdr_rules_size
size of the hash table to store rdr rules.
@@ -1493,7 +1460,7 @@ state_size
size of the hash table used for stateful filtering
.HP
state_wm_freq
-this controls how often the agressive flushing should be run once the
+this controls how often the aggressive flushing should be run once the
state table exceeds state_wm_high in percentage full.
.HP
state_wm_high
@@ -1501,7 +1468,7 @@ when the fill percentage of the state table exceeds this mark, more
aggressive flushing is enabled.
.HP
state_wm_low
-this sets the percentage at which the state table's agressive flushing
+this sets the percentage at which the state table's aggressive flushing
will turn itself off at.
.HP
tcp_close_wait
@@ -1544,7 +1511,6 @@ update_ipid
when set, turns on changing the IP id field in NAT'd packets to a random
number.
.SS Table of visible variables
-.PP
A list of all of the tunables, their minimum, maximum and current
values is as follows.
.PP
@@ -1603,7 +1569,6 @@ udp_timeout 1 MAXINT 240
update_ipid 0 1 0
.fi
.SH Calling out to internal functions
-.PP
IPFilter provides a pair of functions that can be called from a rule
that allow for a single rule to jump out to a group rather than walk
through a list of rules to find the group. If you've got multiple
@@ -1638,7 +1603,6 @@ group-map in role=ipf number=1010
{ 1.1.1.1 group = 1020, 3.3.0.0/16 group = 1030; };
.fi
.SS IPFilter matching expressions
-.PP
An experimental feature that has been added to filter rules is to use
the same expression matching that is available with various commands
to flush and list state/NAT table entries. The use of such an expression
@@ -1648,7 +1612,6 @@ precludes the filter rule from using the normal IP header matching.
pass in exp { "tcp.sport 23 or tcp.sport 50" } keep state
.fi
.SS Filter rules with BPF
-.PP
On platforms that have the BPF built into the kernel, IPFilter can be
built to allow BPF expressions in filter rules. This allows for packet
matching to be on arbitrary data in the packt. The use of a BPF expression
@@ -1666,7 +1629,6 @@ accurately reconstruct the original text filter. The end result is that
while ipf.conf() can be easy to read, understanding the output from
ipfstat might not be.
.SH VARIABLES
-.PP
This configuration file, like all others used with IPFilter, supports the
use of variable substitution throughout the text.
.PP
diff --git a/sbin/ipf/ipf/ipf.8 b/sbin/ipf/ipf/ipf.8
index 3a84e7776b47..fba145b0c785 100644
--- a/sbin/ipf/ipf/ipf.8
+++ b/sbin/ipf/ipf/ipf.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.TH IPF 8
.SH NAME
ipf \- alters packet filtering lists for IP packet input and output
@@ -23,7 +22,6 @@ ipf \- alters packet filtering lists for IP packet input and output
<\fIfilename\fP>
[...]]
.SH DESCRIPTION
-.PP
\fBipf\fP opens the filenames listed (treating "\-" as stdin) and parses the
file for a set of rules which are to be added or removed from the packet
filter rule set.
@@ -49,7 +47,7 @@ supports \fBlanguage\fI. At present, the only target language supported is
\fBC\fB (-cc) for which two files - \fBip_rules.c\fP
and \fBip_rules.h\fP are generated in the \fBCURRENT DIRECTORY\fP when
\fBipf\fP is being run. These files can be used with the
-\fBIPFILTER_COMPILED\fP kernel option to build filter rules staticlly into
+\fBIPFILTER_COMPILED\fP kernel option to build filter rules statically into
the kernel.
.TP
.B \-d
@@ -159,7 +157,8 @@ Zero global statistics held in the kernel for filtering only (this doesn't
affect fragment or state statistics).
.DT
.SH ENVIRONMENT
-.NM utilizes the following environment variable.
+.B ipf
+utilizes the following environment variable.
.TP
.B IPF_PREDEFINED
ipfilter variables, see VARIABLES in ipf(5), can be specified in this
@@ -176,9 +175,7 @@ IPF_PREDEFINED='my_server="10.1.1.1"; my_client="10.1.1.2";'
.SH SEE ALSO
ipftest(1), mkfilters(1), ipf(4), ipl(4), ipf(5), ipfstat(8), ipmon(8), ipnat(8)
.SH DIAGNOSTICS
-.PP
Needs to be run as root for the packet filtering lists to actually
be affected inside the kernel.
.SH BUGS
-.PP
If you find any, please send email to me at darrenr@pobox.com
diff --git a/sbin/ipf/ipf/ipf.c b/sbin/ipf/ipf/ipf.c
index de5121d94767..cf14c06ee829 100644
--- a/sbin/ipf/ipf/ipf.c
+++ b/sbin/ipf/ipf/ipf.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -11,10 +10,6 @@
#include <sys/ioctl.h>
#include "netinet/ipl.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipf.c 1.23 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#if !defined(__SVR4) && defined(__GNUC__)
extern char *index(const char *, int);
@@ -367,7 +362,7 @@ flushfilter(char *arg, int *filter)
if (!(opts & OPT_DONOTHING)) {
if (use_inet6) {
fprintf(stderr,
- "IPv6 rules are no longer seperate\n");
+ "IPv6 rules are no longer separate\n");
} else if (filter != NULL) {
ipfobj_t obj;
diff --git a/sbin/ipf/ipf/ipfcomp.c b/sbin/ipf/ipf/ipfcomp.c
index cf01838d7966..9d0b3642e732 100644
--- a/sbin/ipf/ipf/ipfcomp.c
+++ b/sbin/ipf/ipf/ipfcomp.c
@@ -1,14 +1,9 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include "ipf.h"
@@ -690,7 +685,7 @@ emitGroup(int num, int dir, void *v, frentry_t *fr, char *group,
if (n) {
/*
* Calculate the indentation interval upto the last common
- * common comparison being made.
+ * comparison being made.
*/
for (i = 0, in = 1; i < FRC_MAX; i++) {
if (n[i].c != m[i].c)
diff --git a/sbin/ipf/ipf/ipfilter.4 b/sbin/ipf/ipf/ipfilter.4
index 10fd18e0606f..39676e3c1dae 100644
--- a/sbin/ipf/ipf/ipfilter.4
+++ b/sbin/ipf/ipf/ipfilter.4
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IP\ FILTER 4
.SH NAME
@@ -124,7 +123,7 @@ file
syslog
.PP
ipsend(1)
-generates arbitary IP packets for ethernet connected machines.
+generates arbitrary IP packets for ethernet connected machines.
.PP
ipresend(1)
reads in a data file of saved IP packets (ie
@@ -232,8 +231,7 @@ various stages introduced by IP Filter.
.fi
.SH MORE INFORMATION
-More information (including pointers to the FAQ and the mailing list) can be
-obtained from the sofware's official homepage: www.ipfilter.org
+The IP Filter FAQ can be found at https://www.phildev.net/ipf/
.SH SEE ALSO
ipf(4), ipf(5), ipf(8), ipfilter(5), ipfs(8), ipfstat(8), ipftest(1),
diff --git a/sbin/ipf/ipf/ipfilter.5 b/sbin/ipf/ipf/ipfilter.5
index 97e504df15fa..0a1da67d70cd 100644
--- a/sbin/ipf/ipf/ipfilter.5
+++ b/sbin/ipf/ipf/ipfilter.5
@@ -1,9 +1,7 @@
-.\" $FreeBSD$
.TH IPFILTER 1
.SH NAME
IP Filter
.SH DESCRIPTION
-.PP
IP Filter is a package providing packet filtering capabilities for a variety
of operating systems. On a properly setup system, it can be used to build a
firewall.
diff --git a/sbin/ipf/ipf/ipl.4 b/sbin/ipf/ipf/ipl.4
index da1d9e61ce0f..a59d1b2bf7b1 100644
--- a/sbin/ipf/ipf/ipl.4
+++ b/sbin/ipf/ipf/ipl.4
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPL 4
.SH NAME
diff --git a/sbin/ipf/ipfs/Makefile b/sbin/ipf/ipfs/Makefile
index 6f76f9db5d76..09bf881deca3 100644
--- a/sbin/ipf/ipfs/Makefile
+++ b/sbin/ipf/ipfs/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=ipf
PROG= ipfs
MAN= ipfs.8
diff --git a/sbin/ipf/ipfs/Makefile.depend b/sbin/ipf/ipfs/Makefile.depend
index 2b60f342cc06..177321b7cb0b 100644
--- a/sbin/ipf/ipfs/Makefile.depend
+++ b/sbin/ipf/ipfs/Makefile.depend
@@ -1,15 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
sbin/ipf/libipf \
diff --git a/sbin/ipf/ipfs/ipfs.8 b/sbin/ipf/ipfs/ipfs.8
index 01d0c707d60c..cf668cc09400 100644
--- a/sbin/ipf/ipfs/ipfs.8
+++ b/sbin/ipf/ipfs/ipfs.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPFS 8
.SH NAME
@@ -41,7 +40,6 @@ ipfs \- saves and restores information for NAT and state tables.
.B \-i
<if1>,<if2>
.SH DESCRIPTION
-.PP
\fBipfs\fP allows state information created for NAT entries and rules using
\fIkeep state\fP to be locked (modification prevented) and then saved to disk,
allowing for the system to experience a reboot, followed by the restoration
@@ -118,10 +116,8 @@ operation and unlocked once complete.
.SH SEE ALSO
ipf(8), ipl(4), ipmon(8), ipnat(8)
.SH DIAGNOSTICS
-.PP
Perhaps the -W and -R operations should set the locking but rather than
undo it, restore it to what it was previously. Fragment table information
is currently not saved.
.SH BUGS
-.PP
If you find any, please send email to me at darrenr@pobox.com
diff --git a/sbin/ipf/ipfs/ipfs.c b/sbin/ipf/ipfs/ipfs.c
index 3f1202894fad..6225c6e1154d 100644
--- a/sbin/ipf/ipfs/ipfs.c
+++ b/sbin/ipf/ipfs/ipfs.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -31,9 +30,6 @@
#include "ipf.h"
#include "netinet/ipl.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
#ifndef IPF_SAVEDIR
# define IPF_SAVEDIR "/var/db/ipf"
diff --git a/sbin/ipf/ipfstat/Makefile b/sbin/ipf/ipfstat/Makefile
index 80c2e89a2c88..795e89e0a14f 100644
--- a/sbin/ipf/ipfstat/Makefile
+++ b/sbin/ipf/ipfstat/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
NOGCCERROR= # defined
PACKAGE= ipf
diff --git a/sbin/ipf/ipfstat/Makefile.depend b/sbin/ipf/ipfstat/Makefile.depend
index 8e480ba0d4ec..2d8f0cbb9bab 100644
--- a/sbin/ipf/ipfstat/Makefile.depend
+++ b/sbin/ipf/ipfstat/Makefile.depend
@@ -1,17 +1,15 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
- lib/ncurses/ncursesw \
+ lib/ncurses/ncurses \
+ lib/ncurses/tinfo \
sbin/ipf/libipf \
diff --git a/sbin/ipf/ipfstat/ipfstat.8 b/sbin/ipf/ipfstat/ipfstat.8
index 3762bccbdccf..0d9bbb72e81c 100644
--- a/sbin/ipf/ipfstat/ipfstat.8
+++ b/sbin/ipf/ipfstat/ipfstat.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.TH ipfstat 8
.SH NAME
ipfstat \- reports on packet filter statistics and filter list
diff --git a/sbin/ipf/ipfstat/ipfstat.c b/sbin/ipf/ipfstat/ipfstat.c
index 11b3043f919c..fd0ac83097a0 100644
--- a/sbin/ipf/ipfstat/ipfstat.c
+++ b/sbin/ipf/ipfstat/ipfstat.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -38,10 +37,6 @@
# include <paths.h>
#endif
-#if !defined(lint)
-static const char sccsid[] = "@(#)fils.c 1.21 4/20/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
extern char *optarg;
@@ -162,8 +157,7 @@ static int sort_dstpt(const void *, const void *);
#endif
-static void usage(name)
- char *name;
+static void usage(char *name)
{
#ifdef USE_INET6
fprintf(stderr, "Usage: %s [-46aAdfghIilnoRsv]\n", name);
@@ -329,7 +323,7 @@ int main(int argc, char *argv[])
case 'm' :
filter = parseipfexpr(optarg, NULL);
if (filter == NULL) {
- fprintf(stderr, "Error parseing '%s'\n",
+ fprintf(stderr, "Error parsing '%s'\n",
optarg);
exit(1);
}
@@ -1574,7 +1568,7 @@ static void topipstates(i6addr_t saddr, i6addr_t daddr, int sport, int dport,
/*
* For an IPv4 IP address we need at most 15 characters,
* 4 tuples of 3 digits, separated by 3 dots. Enforce this
- * length, so the colums do not change positions based
+ * length, so the columns do not change positions based
* on the size of the IP address. This length makes the
* output fit in a 80 column terminal.
* We are lacking a good solution for IPv6 addresses (that
diff --git a/sbin/ipf/ipfsync/ipfsyncd.c b/sbin/ipf/ipfsync/ipfsyncd.c
index ead92b70371c..e22aa7c1423c 100644
--- a/sbin/ipf/ipfsync/ipfsyncd.c
+++ b/sbin/ipf/ipfsync/ipfsyncd.c
@@ -3,10 +3,6 @@
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ipfsyncd.c,v 1.1.2.2 2012/07/22 08:04:24 darren_r Exp $";
-#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
diff --git a/sbin/ipf/ipfsync/ipsyncm.c b/sbin/ipf/ipfsync/ipsyncm.c
index d57196379210..74dada9f56c5 100644
--- a/sbin/ipf/ipfsync/ipsyncm.c
+++ b/sbin/ipf/ipfsync/ipsyncm.c
@@ -1,14 +1,9 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
diff --git a/sbin/ipf/ipfsync/ipsyncs.c b/sbin/ipf/ipfsync/ipsyncs.c
index a53cfb8c9508..4aec6925f079 100644
--- a/sbin/ipf/ipfsync/ipsyncs.c
+++ b/sbin/ipf/ipfsync/ipsyncs.c
@@ -1,14 +1,9 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
diff --git a/sbin/ipf/ipftest/Makefile b/sbin/ipf/ipftest/Makefile
index 671d9eeb8046..d446ab9d22be 100644
--- a/sbin/ipf/ipftest/Makefile
+++ b/sbin/ipf/ipftest/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= ipf
PROG= ipftest
SRCS= ${GENHDRS} ipftest.c fil.c ip_frag.c ip_state.c ip_nat.c \
diff --git a/sbin/ipf/ipftest/Makefile.depend b/sbin/ipf/ipftest/Makefile.depend
index cfe5ad5352e5..59af14fecc53 100644
--- a/sbin/ipf/ipftest/Makefile.depend
+++ b/sbin/ipf/ipftest/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/ipf/ipftest/ip_fil.c b/sbin/ipf/ipftest/ip_fil.c
index f5955ddffdfe..6df3bed8224e 100644
--- a/sbin/ipf/ipftest/ip_fil.c
+++ b/sbin/ipf/ipftest/ip_fil.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -7,10 +6,6 @@
*
* $Id$
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include "ipf.h"
#include "md5.h"
@@ -558,7 +553,7 @@ ipf_newisn(fin)
/* ------------------------------------------------------------------------ */
/* Function: ipf_nextipid */
-/* Returns: int - 0 == success, -1 == error (packet should be droppped) */
+/* Returns: int - 0 == success, -1 == error (packet should be dropped) */
/* Parameters: fin(I) - pointer to packet information */
/* */
/* Returns the next IPv4 ID to use for this packet. */
diff --git a/sbin/ipf/ipftest/ipftest.1 b/sbin/ipf/ipftest/ipftest.1
index 10232d338d9f..456304c9d0b2 100644
--- a/sbin/ipf/ipftest/ipftest.1
+++ b/sbin/ipf/ipftest/ipftest.1
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.TH ipftest 1
.SH NAME
ipftest \- test packet filter rules with arbitrary input.
@@ -35,7 +34,6 @@ interface
<optionlist>
]
.SH DESCRIPTION
-.PP
\fBipftest\fP is provided for the purpose of being able to test a set of
filter rules without having to put them in place, in operation and proceed
to test their effectiveness. The hope is that this minimises disruptions
@@ -127,7 +125,7 @@ This is the default if no \fB\-F\fP argument is specified.
The format used is as follows:
.nf
"in"|"out" "on" if ["tcp"|"udp"|"icmp"]
- srchost[,srcport] dsthost[,destport] [FSRPAU]
+ srchost[,srcport] dsthost[,destport] [FSRPAUEWe]
.fi
.PP
This allows for a packet going "in" or "out" of an interface (if) to be
diff --git a/sbin/ipf/ipftest/ipftest.c b/sbin/ipf/ipftest/ipftest.c
index e7a0d71fffca..2dfbe20592b3 100644
--- a/sbin/ipf/ipftest/ipftest.c
+++ b/sbin/ipf/ipftest/ipftest.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -10,10 +9,6 @@
#include <sys/ioctl.h>
#include <sys/file.h>
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipt.c 1.19 6/3/96 (C) 1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
extern char *optarg;
extern struct ipread pcap, iptext, iphex;
diff --git a/sbin/ipf/ipftest/md5.c b/sbin/ipf/ipftest/md5.c
index d27430b1f212..54c0ac1ed5b0 100644
--- a/sbin/ipf/ipftest/md5.c
+++ b/sbin/ipf/ipftest/md5.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
diff --git a/sbin/ipf/ipftest/md5.h b/sbin/ipf/ipftest/md5.h
index 6f59500daf19..ab94cd21eac7 100644
--- a/sbin/ipf/ipftest/md5.h
+++ b/sbin/ipf/ipftest/md5.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
***********************************************************************
diff --git a/sbin/ipf/iplang/iplang.h b/sbin/ipf/iplang/iplang.h
index f38ef9671701..acf8369afb15 100644
--- a/sbin/ipf/iplang/iplang.h
+++ b/sbin/ipf/iplang/iplang.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/iplang/iplang_l.l b/sbin/ipf/iplang/iplang_l.l
index 58538d8e4d1c..ce1ae2031454 100644
--- a/sbin/ipf/iplang/iplang_l.l
+++ b/sbin/ipf/iplang/iplang_l.l
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
%{
/*
diff --git a/sbin/ipf/iplang/iplang_y.y b/sbin/ipf/iplang/iplang_y.y
index e6c88ddcd9bc..9e8ebf4e4312 100644
--- a/sbin/ipf/iplang/iplang_y.y
+++ b/sbin/ipf/iplang/iplang_y.y
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
%{
/*
@@ -7,7 +6,6 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
* Id: iplang_y.y,v 2.9.2.4 2006/03/17 12:11:29 darrenr Exp $
- * $FreeBSD$
*/
#include <stdio.h>
@@ -1047,9 +1045,9 @@ void set_tcpsum(char **arg)
void set_tcpflags(char **arg)
{
- static char flags[] = "ASURPF";
+ static char flags[] = "ASURPFEWe";
static int flagv[] = { TH_ACK, TH_SYN, TH_URG, TH_RST, TH_PUSH,
- TH_FIN } ;
+ TH_FIN, TH_ECE, TH_CWR, TH_AE } ;
char *s, *t;
for (s = *arg; *s; s++)
@@ -1058,10 +1056,11 @@ void set_tcpflags(char **arg)
fprintf(stderr, "unknown TCP flag %c\n", *s);
break;
}
- tcp->th_flags = strtol(*arg, NULL, 0);
+ __tcp_set_flags(tcp, strtol(*arg, NULL, 0));
break;
} else
- tcp->th_flags |= flagv[t - flags];
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) |
+ flagv[t - flags]);
free(*arg);
*arg = NULL;
}
diff --git a/sbin/ipf/ipmon/Makefile b/sbin/ipf/ipmon/Makefile
index 7225f8c8bcb1..257e3b999777 100644
--- a/sbin/ipf/ipmon/Makefile
+++ b/sbin/ipf/ipmon/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= ipf
PROG= ipmon
SRCS= ${GENHDRS} ipmon.c ipmon_y.c ipmon_l.c
@@ -7,6 +5,7 @@ MAN= ipmon.5 ipmon.8
MLINKS= ipmon.5 ipmon.conf.5
CFLAGS+= -DLOGFAC=LOG_LOCAL0 -I.
+CFLAGS+= -Wno-error=unused-but-set-variable
GENHDRS+= ipmon_l.h ipmon_y.h
CLEANFILES+= ${GENHDRS} ipmon_y.c ipmon_l.c
diff --git a/sbin/ipf/ipmon/Makefile.depend b/sbin/ipf/ipmon/Makefile.depend
index cfe5ad5352e5..4d9091bff680 100644
--- a/sbin/ipf/ipmon/Makefile.depend
+++ b/sbin/ipf/ipmon/Makefile.depend
@@ -1,15 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
sbin/ipf/libipf \
usr.bin/yacc.host \
diff --git a/sbin/ipf/ipmon/ipmon.5 b/sbin/ipf/ipmon/ipmon.5
index 95126f0c83c3..c6a4b6c12a42 100644
--- a/sbin/ipf/ipmon/ipmon.5
+++ b/sbin/ipf/ipmon/ipmon.5
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPMON 5
.SH NAME
@@ -53,7 +52,6 @@ The lines above would save all ipf log entries to /var/log/ipf-log, send
all of the entries for NAT (ipnat related) to syslog and generate an email
to root for each log entry from the state tables.
.SH SYNTAX - MATCHING
-.PP
In the above example, the matching segment was confined to matching on
the type of log entry generated. The full list of fields that can be
used here is:
@@ -190,7 +188,6 @@ it can then be used in any
.I do
statement.
.SH EXAMPLES
-.PP
Some further examples are:
.nf
@@ -209,7 +206,6 @@ match { dstip 127.0.0.1; } do { local("local options"); };
#
.fi
.SH MATCHING
-.PP
All entries of the rules present in the file are
compared for matches - there is no first or last rule match.
.SH FILES
diff --git a/sbin/ipf/ipmon/ipmon.8 b/sbin/ipf/ipmon/ipmon.8
index 3f4036d96e21..901d1a2a804e 100644
--- a/sbin/ipf/ipmon/ipmon.8
+++ b/sbin/ipf/ipmon/ipmon.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.TH ipmon 8
.SH NAME
ipmon \- monitors /dev/ipl for logged packets
@@ -28,7 +27,6 @@ ipmon \- monitors /dev/ipl for logged packets
.B <filename>
]
.SH DESCRIPTION
-.LP
\fBipmon\fP opens \fB/dev/ipl\fP for reading and awaits data to be saved from
the packet filter. The binary data read from the device is reprinted in
human readable form, however, IP#'s are not mapped back to hostnames, nor are
@@ -192,5 +190,4 @@ recorded data.
.SH SEE ALSO
ipl(4), ipmon(5), ipf(8), ipfstat(8), ipnat(8)
.SH BUGS
-.PP
If you find any, please send email to me at darrenr@pobox.com
diff --git a/sbin/ipf/ipmon/ipmon.c b/sbin/ipf/ipmon/ipmon.c
index f71a33b1034e..a07401ff5e88 100644
--- a/sbin/ipf/ipmon/ipmon.c
+++ b/sbin/ipf/ipmon/ipmon.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -14,10 +13,6 @@
#include <fcntl.h>
#include <signal.h>
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#define STRERROR(x) strerror(x)
@@ -82,7 +77,8 @@ struct flags tcpfl[] = {
{ TH_URG, 'U' },
{ TH_PUSH,'P' },
{ TH_ECN, 'E' },
- { TH_CWR, 'C' },
+ { TH_CWR, 'W' },
+ { TH_AE, 'e' },
{ 0, '\0' }
};
@@ -304,7 +300,6 @@ static icmp_subtype_t *
find_icmpsubtype(int type, icmp_subtype_t *table, size_t tablesz)
{
icmp_subtype_t *ist;
- int i;
if (tablesz < 2)
return (NULL);
@@ -312,11 +307,10 @@ find_icmpsubtype(int type, icmp_subtype_t *table, size_t tablesz)
if ((type < 0) || (type > table[tablesz - 2].ist_val))
return (NULL);
- i = type;
if (table[type].ist_val == type)
return (table + type);
- for (i = 0, ist = table; ist->ist_val != -2; i++, ist++)
+ for (ist = table; ist->ist_val != -2; ist++)
if (ist->ist_val == type)
return (ist);
return (NULL);
@@ -327,7 +321,6 @@ static icmp_type_t *
find_icmptype(int type, icmp_type_t *table, size_t tablesz)
{
icmp_type_t *it;
- int i;
if (tablesz < 2)
return (NULL);
@@ -335,11 +328,10 @@ find_icmptype(int type, icmp_type_t *table, size_t tablesz)
if ((type < 0) || (type > table[tablesz - 2].it_val))
return (NULL);
- i = type;
if (table[type].it_val == type)
return (table + type);
- for (i = 0, it = table; it->it_val != -2; i++, it++)
+ for (it = table; it->it_val != -2; it++)
if (it->it_val == type)
return (it);
return (NULL);
@@ -470,10 +462,7 @@ read_log(int fd, int *lenp, char *buf, int bufsize)
char *
-portlocalname(res, proto, port)
- int res;
- char *proto;
- u_int port;
+portlocalname(int res, char *proto, u_int port)
{
static char pname[8];
char *s;
@@ -590,7 +579,7 @@ dumphex(FILE *log, int dopts, char *buf, int len)
}
if ((j + 1) & 0xf)
- *t++ = ' ';;
+ *t++ = ' ';
}
if (j & 0xf) {
@@ -1208,7 +1197,7 @@ print_ipflog(config_t *conf, char *buf, int blen)
*t++ = ' ';
*t++ = '-';
for (i = 0; tcpfl[i].value; i++)
- if (tp->th_flags & tcpfl[i].value)
+ if (__tcp_get_flags(tp) & tcpfl[i].value)
*t++ = tcpfl[i].flag;
if (ipmonopts & IPMON_VERBOSE) {
sprintf(t, " %lu %lu %hu",
diff --git a/sbin/ipf/ipmon/ipmon_y.y b/sbin/ipf/ipmon/ipmon_y.y
index c70e17adcec0..9d3a7ff30c93 100644
--- a/sbin/ipf/ipmon/ipmon_y.y
+++ b/sbin/ipf/ipmon/ipmon_y.y
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/ipnat/Makefile b/sbin/ipf/ipnat/Makefile
index 1bdbe61235fb..869a399bd44f 100644
--- a/sbin/ipf/ipnat/Makefile
+++ b/sbin/ipf/ipnat/Makefile
@@ -1,11 +1,10 @@
-# $FreeBSD$
-
PACKAGE= ipf
PROG= ipnat
SRCS= ${GENHDRS} ipnat.c ipnat_y.c ipnat_l.c
MAN= ipnat.8 ipnat.4 ipnat.5
MLINKS= ipnat.5 ipnat.conf.5
CFLAGS+= -I.
+CFLAGS+= -Wno-error=unused-but-set-variable
GENHDRS= ipnat_l.h ipnat_y.h
CLEANFILES+= ${GENHDRS} ipnat_y.c ipnat_l.c
diff --git a/sbin/ipf/ipnat/Makefile.depend b/sbin/ipf/ipnat/Makefile.depend
index cfe5ad5352e5..4d9091bff680 100644
--- a/sbin/ipf/ipnat/Makefile.depend
+++ b/sbin/ipf/ipnat/Makefile.depend
@@ -1,15 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
sbin/ipf/libipf \
usr.bin/yacc.host \
diff --git a/sbin/ipf/ipnat/ipnat.1 b/sbin/ipf/ipnat/ipnat.1
index f24141546171..0e41ccc42b2a 100644
--- a/sbin/ipf/ipnat/ipnat.1
+++ b/sbin/ipf/ipnat/ipnat.1
@@ -8,7 +8,6 @@ ipnat \- user interface to the NAT
]
.B \-f <\fIfilename\fP>
.SH DESCRIPTION
-.PP
\fBipnat\fP opens the filename given (treating "\-" as stdin) and parses the
file for a set of rules which are to be added or removed from the IP NAT.
.PP
diff --git a/sbin/ipf/ipnat/ipnat.4 b/sbin/ipf/ipnat/ipnat.4
index 80c5ba444708..d848378d8e98 100644
--- a/sbin/ipf/ipnat/ipnat.4
+++ b/sbin/ipf/ipnat/ipnat.4
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.TH IPNAT 4
.SH NAME
ipnat \- Network Address Translation kernel interface
@@ -11,7 +10,6 @@ ipnat \- Network Address Translation kernel interface
.br
#include <netinet/ip_nat.h>
.SH IOCTLS
-.PP
To add and delete rules to the NAT list, two 'basic' ioctls are provided
for use. The ioctl's are called as:
.LP
diff --git a/sbin/ipf/ipnat/ipnat.5 b/sbin/ipf/ipnat/ipnat.5
index 81502946b82c..c6c8c2e54fc2 100644
--- a/sbin/ipf/ipnat/ipnat.5
+++ b/sbin/ipf/ipnat/ipnat.5
@@ -1,10 +1,8 @@
-.\" $FreeBSD$
.\"
.TH IPNAT 5
.SH NAME
ipnat, ipnat.conf \- IPFilter NAT file format
.SH DESCRIPTION
-.PP
The
.B ipnat.conf
file is used to specify rules for the Network Address Translation (NAT)
@@ -31,7 +29,6 @@ to text that appears before the "->" and the "right hand side" (RHS) for text
that appears after it. In essence, the LHS is the packet matching and the
RHS is the new data to be used.
.SH VARIABLES
-.PP
This configuration file, like all others used with IPFilter, supports the
use of variable substitution throughout the text.
.nf
@@ -150,7 +147,7 @@ For TCP connections exiting a connection such as PPPoE where the MTU is
slightly smaller than normal ethernet, it can be useful to reduce the
Maximum Segment Size (MSS) offered by the internal machines to match,
reducing the liklihood that the either end will attempt to send packets
-that are too big and result in fragmentation. This is acheived using the
+that are too big and result in fragmentation. This is achieved using the
.B mssclamp
option with TCP
.B map
@@ -221,7 +218,7 @@ that requires the destination port number to be 21 if this rule is to be
activated. The word "ftp" is the proxy identifier that the kernel will
try and resolve internally, "tcp" the protocol that packets must match.
.PP
-See below for a list of proxies and their relative staus.
+See below for a list of proxies and their relative status.
.PP
To associate NAT rules with filtering rules, it is possible to set and
match tags during either inbound or outbound processing. At present the
@@ -281,7 +278,6 @@ of (say) 172.192.0.2 wanted 260 simultaneous connections going out, they would
be limited to 252 with \fBmap-block\fP but would just \fImove on\fP to the next
IP address with the \fBmap\fP command.
.SS Extended matching
-.PP
If it is desirable to match on both the source and destination of a packet
before applying an address translation to it, this can be achieved by using
the same from-to syntax as is used in \fBipf.conf\fP(5). What follows
@@ -323,7 +319,6 @@ the defined pool only has /24's or /32's. Pools may also be used
.I wherever
the from-to syntax in \fBipnat.conf\fR(5) is allowed.
.SH INBOUND DESTINATION TRANSLATION (redirection)
-.PP
Redirection of packets is used to change the destination fields in a packet
and is supported for packets that are moving \fIin\fP on a network interface.
While the same general syntax for
@@ -337,7 +332,7 @@ a network or range of network addresses, so a rule written like this:
rdr le0 0/0 -> 192.168.1.0
.fi
.PP
-Will not spread packets across all 256 IP addresses in that class C network.
+Will not spread packets across all 256 IP addresses in that /24 subnet.
If you were to try a rule like this:
.nf
@@ -356,7 +351,7 @@ rdr le0 from 1.1.0.0/16 to any -> 192.168.1.3
rdr le0 ! from 1.1.0.0/16 to any -> 192.168.1.4
.fi
.PP
-If there is a consective set of addresses you wish to spread the packets
+If there is a consecutive set of addresses you wish to spread the packets
over, then this can be done in one of two ways, the word "range" optional
to preserve:
.nf
@@ -383,9 +378,9 @@ rdr le0 0/0 -> 192.168.1.5,192.168.1.7 round-robin
rdr le0 0/0 -> 192.168.1.9 round-robin
.fi
.PP
-If there are a large number of redirect rules and hosts being targetted
+If there are a large number of redirect rules and hosts being targeted
then it may be desirable to have all those from a single source address
-be targetted at the same destination address. To achieve this, the
+be targeted at the same destination address. To achieve this, the
word
.B sticky
is appended to the rule like this:
@@ -400,9 +395,9 @@ The
.B sticky
feature can only be combined with
.B round-robin
-and the use of comma.
+and the use of a comma.
.PP
-For TCP and UDP packets, it is possible to both match on the destiantion
+For TCP and UDP packets, it is possible to both match on the destination
port number and to modify it. For example, to change the destination port
from 80 to 3128, we would use a rule like this:
.nf
@@ -466,7 +461,6 @@ rdr le0,ppp0 9.8.7.6/32 port 80 -> 1.1.1.1,1.1.1.2 port 80 tcp
round-robin frag age 40/40 sticky mssclamp 1000 tag tagged
.fi
.SH REWRITING SOURCE AND DESTINATION
-.PP
Whilst the above two commands provide a lot of flexibility in changing
addressing fields in packets, often it can be of benefit to translate
\fIboth\fP source \fBand\fR destination at the same time or to change
@@ -550,7 +544,6 @@ rewrite from any to any port = 80 ->
src 1.1.2.3 - 1.1.2.6 dst 2.2.3.4 - 2.2.3.6;
.fi
.SH DIVERTING PACKETS
-.PP
If you'd like to send packets to a UDP socket rather than just another
computer to be decapsulated, this can be achieved using a
.B divert
@@ -573,7 +566,7 @@ On the LHS is a normal set of matching capabilities but on the RHS it is
a requirement to specify both the source and destination addresses and
ports.
.PP
-As this feature is intended to be used with targetting packets at sockets
+As this feature is intended to be used with targeting packets at sockets
and not IPFilter running on other systems, there is no rule provided to
\fIundivert\fR packets.
.TP
@@ -599,7 +592,6 @@ are flushed out, it is expected that the operator will similarly
flush the NAT table and thus NAT sessions are not removed when the
NAT rules are flushed out.
.SH RULE ORDERING
-.PP
.B NOTE:
Rules in
.B ipnat.conf
@@ -656,7 +648,6 @@ rdr le0 from 1.1.1.0/24 to 192.2.2.1 port 80 -> 127.0.0.1 3128 tcp
.PP
Then no packets will match the 2nd rule, they'll all match the first.
.SH IPv6
-.PP
In all of the examples above, where an IPv4 address is present, an IPv6
address can also be used. All rules must use either IPv4 addresses with
both halves of the NAT rule or IPv6 addresses for both halves. Mixing
@@ -668,7 +659,6 @@ For shorthand notations such as "0/32", the equivalent for IPv6 is
implicit direction that the address should be IPv6, not IPv4.
To be unambiguous with 0/0, for IPv6 use ::0/0.
.SH KERNEL PROXIES
-.PP
IP Filter comes with a few, simple, proxies built into the code that is loaded
into the kernel to allow secondary channels to be opened without forcing the
packets through a user program. The current state of the proxies is listed
diff --git a/sbin/ipf/ipnat/ipnat.8 b/sbin/ipf/ipnat/ipnat.8
index a49f33736b40..b3893f117709 100644
--- a/sbin/ipf/ipnat/ipnat.8
+++ b/sbin/ipf/ipnat/ipnat.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPNAT 8
.SH NAME
@@ -16,7 +15,6 @@ ipnat \- user interface to the NAT subsystem
]
.B \-f <\fIfilename\fP>
.SH DESCRIPTION
-.PP
\fBipnat\fP opens the filename given (treating "\-" as stdin) and parses the
file for a set of rules which are to be added or removed from the IP NAT.
.PP
diff --git a/sbin/ipf/ipnat/ipnat.c b/sbin/ipf/ipnat/ipnat.c
index 5558ef8693d0..8eb2e240f6cf 100644
--- a/sbin/ipf/ipnat/ipnat.c
+++ b/sbin/ipf/ipnat/ipnat.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -50,10 +49,6 @@
# define STRERROR(x) strerror(x)
-#if !defined(lint)
-static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#if SOLARIS
diff --git a/sbin/ipf/ipnat/ipnat_y.y b/sbin/ipf/ipnat/ipnat_y.y
index 175026b4083e..11f62c98aa8c 100644
--- a/sbin/ipf/ipnat/ipnat_y.y
+++ b/sbin/ipf/ipnat/ipnat_y.y
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/ippool/Makefile b/sbin/ipf/ippool/Makefile
index 622952be0477..8ed864ee9267 100644
--- a/sbin/ipf/ippool/Makefile
+++ b/sbin/ipf/ippool/Makefile
@@ -1,10 +1,9 @@
-# $FreeBSD$
-
PACKAGE= ipf
PROG= ippool
SRCS= ${GENHDRS} ippool_y.c ippool_l.c ippool.c
MAN= ippool.5 ippool.8
CFLAGS+= -I.
+CFLAGS+= -Wno-error=unused-but-set-variable
GENHDRS= ippool_l.h ippool_y.h
CLEANFILES+= ${GENHDRS} ippool_y.c ippool_l.c
diff --git a/sbin/ipf/ippool/Makefile.depend b/sbin/ipf/ippool/Makefile.depend
index cfe5ad5352e5..4d9091bff680 100644
--- a/sbin/ipf/ippool/Makefile.depend
+++ b/sbin/ipf/ippool/Makefile.depend
@@ -1,15 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libelf \
lib/libkvm \
sbin/ipf/libipf \
usr.bin/yacc.host \
diff --git a/sbin/ipf/ippool/ippool.5 b/sbin/ipf/ippool/ippool.5
index 4de19a4b3625..b45675bea069 100644
--- a/sbin/ipf/ippool/ippool.5
+++ b/sbin/ipf/ippool/ippool.5
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPPOOL 5
.SH NAME
@@ -39,7 +38,6 @@ heirarchical matching, so it is possible to define a subnet as matching
but then exclude specific addresses from it.
.SS
Evolving Configuration
-.PP
Over time the configuration syntax used by ippool.conf(5) has evolved.
Originally the syntax used was more verbose about what a particular
value was being used for, for example:
@@ -66,7 +64,6 @@ configuration syntax and all output using "ippool -l" will also be in the
new configuration syntax.
.SS
IPFilter devices and pools
-.PP
To cater to different administration styles, ipool.conf(5) allows you to
tie a pool to a specific role in IPFilter. The recognised role names are:
.HP
@@ -90,7 +87,6 @@ all
pools that are defined for the "all" role are available to all types of
rules, be they NAT rules in ipnat.conf(5) or firewall rules in ipf.conf(5).
.SH Address Pools
-.PP
An address pool can be used in ipf.conf(5) and ipnat.conf(5) for matching
the source or destination address of packets. They can be referred to either
by name or number and can hold an arbitrary number of address patterns to
@@ -109,7 +105,7 @@ only ever match an entry in a pool that is of the same address family.
The address pool searches the list of addresses configured for the best
match. The "best match" is considered to be the match that has the highest
number of bits set in the mask. Thus if both 2.2.0.0/16 and 2.2.2.0/24 are
-present in an address pool, the addres 2.2.2.1 will match 2.2.2.0/24 and
+present in an address pool, the address 2.2.2.1 will match 2.2.2.0/24 and
2.2.1.1 will match 2.2.0.0/16. The reason for this is to allow exceptions
to be added through the use of negative matching. In the following example,
the pool contains "2.2.0.0/16" and "!2.2.2.0/24", meaning that all packets
@@ -125,7 +121,7 @@ addresses from. To do this simply use a "file://" URL where you would
specify an actual IP address.
.PP
.nf
-pool ipf/tree (name rfc1918;) { file:///etc/ipf/rfc1918; };
+pool ipf/tree (name rfc1918;) { "file:///etc/ipf/rfc1918;" };
.fi
.PP
The contents of the file might look something like this:
@@ -164,7 +160,6 @@ block in from pool/microsoft to any
Note that there are limitations on the output returned by whois servers
so be aware that their output may not be 100% perfect for your goal.
.SH Destination Lists
-.PP
Destination lists are provided for use primarily with NAT redirect rules
(rdr). Their purpose is to allow more sophisticated methods of selecting
which host to send traffic to next than the simple round-robin technique
@@ -243,7 +238,6 @@ pool all/dstlist (name servers; policy weighted connection;)
{ bge0:1.1.1.2; bge0:1.1.1.4; bge1:1.1.1.5; bge1:1.1.1.9; };
.fi
.SH Group maps
-.PP
Group maps are provided to allow more efficient processing of packets
where there are a larger number of subnets and groups of rules for those
subnets. Group maps are used with "call" rules in ipf.conf(5) that
@@ -283,7 +277,6 @@ The limitation with group maps is that only the source address or the
destination address can be used to map the packet to the starting group,
not both, in your ipf.conf(5) file.
.SH Hash Tables
-.PP
The hash table is operationally similar to the address pool. It is
used as a store for a collection of address to match on, saving the
need to write a lengthy list of rules. As with address pools, searching
diff --git a/sbin/ipf/ippool/ippool.8 b/sbin/ipf/ippool/ippool.8
index bcc8f3cbd71d..c879c97b01dd 100644
--- a/sbin/ipf/ippool/ippool.8
+++ b/sbin/ipf/ippool/ippool.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPPOOL 8
.SH NAME
@@ -18,7 +17,7 @@ ippool \- user interface to the IPFilter pools
-F [-dv] [-o <role>] [-t <type>]
.br
.B ippool
--l [-dv] [-m <name>] [-t <type>] [-o <role>] [-M <core>] [-N <namelist>]
+-l [-dDv] [-m <name>] [-t <type>] [-o <role>] [-M <core>] [-N <namelist>]
.br
.B ippool
-r [-dnv] [-m <name>] [-o <role>] [-t <type>] -i <ipaddr>[/<netmask>]
@@ -29,7 +28,6 @@ ippool \- user interface to the IPFilter pools
.B ippool
-s [-dtv]
.SH DESCRIPTION
-.PP
.B Ippool
is used to manage information stored in the IP pools subsystem of IPFilter.
Configuration file information may be parsed and loaded into the kernel,
@@ -121,6 +119,10 @@ as a number of seconds.
When parsing a configuration file, rather than load new pool data into the
kernel, unload it.
.TP
+.B -D
+When used in conjuction with -l, dump the ippool configuration to stdout in
+a format that can be subsequently used as input into ippool -f.
+.TP
.SH FILES
.br
/dev/iplookup
diff --git a/sbin/ipf/ippool/ippool.c b/sbin/ipf/ippool/ippool.c
index 3e8918e1fcfa..797f83af1419 100644
--- a/sbin/ipf/ippool/ippool.c
+++ b/sbin/ipf/ippool/ippool.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -47,15 +46,15 @@ int poolnodecommand(int, int, char *[]);
int loadpoolfile(int, char *[], char *);
int poollist(int, char *[]);
void poollist_dead(int, char *, int, char *, char *);
-void poollist_live(int, char *, int, int);
+int poollist_live(int, char *, int, int);
int poolflush(int, char *[]);
int poolstats(int, char *[]);
int gettype(char *, u_int *);
int getrole(char *);
int setnodeaddr(int, int, void *ptr, char *arg);
-void showpools_live(int, int, ipf_pool_stat_t *, char *);
-void showhashs_live(int, int, iphtstat_t *, char *);
-void showdstls_live(int, int, ipf_dstl_stat_t *, char *);
+int showpools_live(int, int, ipf_pool_stat_t *, char *);
+int showhashs_live(int, int, iphtstat_t *, char *);
+int showdstls_live(int, int, ipf_dstl_stat_t *, char *);
int opts = 0;
int fd = -1;
@@ -670,12 +669,15 @@ poollist(int argc, char *argv[])
poolname = NULL;
role = IPL_LOGALL;
- while ((c = getopt(argc, argv, "dm:M:N:o:t:v")) != -1)
+ while ((c = getopt(argc, argv, "dDm:M:N:o:t:v")) != -1)
switch (c)
{
case 'd' :
opts |= OPT_DEBUG;
break;
+ case 'D' :
+ opts |= OPT_SAVEOUT;
+ break;
case 'm' :
poolname = optarg;
break;
@@ -740,9 +742,10 @@ poollist(int argc, char *argv[])
}
op.iplo_unit = role;
- if (live_kernel)
- poollist_live(role, poolname, type, fd);
- else
+ if (live_kernel) {
+ if (poollist_live(role, poolname, type, fd) != 0)
+ return (1);
+ } else
poollist_dead(role, poolname, type, kernel, core);
return (0);
}
@@ -817,7 +820,7 @@ poollist_dead(int role, char *poolname, int type, char *kernel, char *core)
}
-void
+int
poollist_live(int role, char *poolname, int type, int fd)
{
ipf_pool_stat_t plstat;
@@ -837,10 +840,11 @@ poollist_live(int role, char *poolname, int type, int fd)
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
- return;
+ return (1);
}
- showpools_live(fd, role, &plstat, poolname);
+ if (showpools_live(fd, role, &plstat, poolname))
+ return (1);
} else {
for (role = -1; role <= IPL_LOGMAX; role++) {
op.iplo_unit = role;
@@ -848,10 +852,11 @@ poollist_live(int role, char *poolname, int type, int fd)
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
- return;
+ return (1);
}
- showpools_live(fd, role, &plstat, poolname);
+ if (showpools_live(fd, role, &plstat, poolname))
+ return (1);
}
role = IPL_LOGALL;
@@ -873,9 +878,10 @@ poollist_live(int role, char *poolname, int type, int fd)
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
- return;
+ return (1);
}
- showhashs_live(fd, role, &htstat, poolname);
+ if (showhashs_live(fd, role, &htstat, poolname))
+ return (1);
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
@@ -883,10 +889,11 @@ poollist_live(int role, char *poolname, int type, int fd)
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
- return;
+ return (1);
}
- showhashs_live(fd, role, &htstat, poolname);
+ if (showhashs_live(fd, role, &htstat, poolname))
+ return(1);
}
role = IPL_LOGALL;
}
@@ -907,9 +914,10 @@ poollist_live(int role, char *poolname, int type, int fd)
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
- return;
+ return (1);
}
- showdstls_live(fd, role, &dlstat, poolname);
+ if (showdstls_live(fd, role, &dlstat, poolname))
+ return (1);
} else {
for (role = 0; role <= IPL_LOGMAX; role++) {
@@ -917,18 +925,20 @@ poollist_live(int role, char *poolname, int type, int fd)
c = ioctl(fd, SIOCLOOKUPSTAT, &op);
if (c == -1) {
ipferror(fd, "ioctl(SIOCLOOKUPSTAT)");
- return;
+ return (1);
}
- showdstls_live(fd, role, &dlstat, poolname);
+ if (showdstls_live(fd, role, &dlstat, poolname))
+ return (1);
}
role = IPL_LOGALL;
}
}
+ return (0);
}
-void
+int
showpools_live(int fd, int role, ipf_pool_stat_t *plstp, char *poolname)
{
ipflookupiter_t iter;
@@ -953,7 +963,7 @@ showpools_live(int fd, int role, ipf_pool_stat_t *plstp, char *poolname)
while (plstp->ipls_list[role + 1] != NULL) {
if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
ipferror(fd, "ioctl(SIOCLOOKUPITER)");
- break;
+ return (1);
}
if (((pool.ipo_flags & IPOOL_DELETE) == 0) ||
((opts & OPT_DEBUG) != 0))
@@ -961,10 +971,11 @@ showpools_live(int fd, int role, ipf_pool_stat_t *plstp, char *poolname)
plstp->ipls_list[role + 1] = pool.ipo_next;
}
+ return (0);
}
-void
+int
showhashs_live(int fd, int role, iphtstat_t *htstp, char *poolname)
{
ipflookupiter_t iter;
@@ -987,17 +998,18 @@ showhashs_live(int fd, int role, iphtstat_t *htstp, char *poolname)
while (htstp->iphs_tables != NULL) {
if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
ipferror(fd, "ioctl(SIOCLOOKUPITER)");
- break;
+ return (1);
}
printhash_live(&table, fd, poolname, opts, pool_fields);
htstp->iphs_tables = table.iph_next;
}
+ return (0);
}
-void
+int
showdstls_live(int fd, int role, ipf_dstl_stat_t *dlstp, char *poolname)
{
ipflookupiter_t iter;
@@ -1020,13 +1032,14 @@ showdstls_live(int fd, int role, ipf_dstl_stat_t *dlstp, char *poolname)
while (dlstp->ipls_list[role] != NULL) {
if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
ipferror(fd, "ioctl(SIOCLOOKUPITER)");
- break;
+ return (1);
}
printdstl_live(&table, fd, poolname, opts, pool_fields);
dlstp->ipls_list[role] = table.ipld_next;
}
+ return (0);
}
diff --git a/sbin/ipf/ippool/ippool_y.y b/sbin/ipf/ippool/ippool_y.y
index c798ff50596b..6baa48dfa01c 100644
--- a/sbin/ipf/ippool/ippool_y.y
+++ b/sbin/ipf/ippool/ippool_y.y
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/ipresend/Makefile b/sbin/ipf/ipresend/Makefile
index a4403d537547..f866891c4c97 100644
--- a/sbin/ipf/ipresend/Makefile
+++ b/sbin/ipf/ipresend/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= ipf
PROG= ipresend
SRCS= ipresend.c ip.c resend.c sbpf.c sock.c 44arp.c
diff --git a/sbin/ipf/ipresend/Makefile.depend b/sbin/ipf/ipresend/Makefile.depend
index a1632c6f3baa..b40d4509a124 100644
--- a/sbin/ipf/ipresend/Makefile.depend
+++ b/sbin/ipf/ipresend/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/ipf/ipscan/Makefile b/sbin/ipf/ipscan/Makefile
index 0c7c8783e785..1f62d796076e 100644
--- a/sbin/ipf/ipscan/Makefile
+++ b/sbin/ipf/ipscan/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= ipf
PROG= ipscan
SRCS= ${GENHDRS} ipscan_y.c
diff --git a/sbin/ipf/ipscan/ipscan.5 b/sbin/ipf/ipscan/ipscan.5
index 91bf9b0f5ebe..76738b607080 100644
--- a/sbin/ipf/ipscan/ipscan.5
+++ b/sbin/ipf/ipscan/ipscan.5
@@ -1,10 +1,8 @@
-.\" $FreeBSD$
.\"
.TH IPSCAN 5
.SH NAME
ipscan, ipscan.conf \- ipscan file format
.SH DESCRIPTION
-.PP
WARNING: This feature is to be considered experimental and may change
significantly until a final implementation is drawn up.
.PP
@@ -21,7 +19,7 @@ match-char ::= "*" | "?" | "."
.fi
.PP
In this example an ip-address is a dotted-quad IPv4 address and a port-number
-is a number betwee 1 and 65535, inclusive. The match string is must be of
+is a number between 1 and 65535, inclusive. The match string is must be of
same length as the literal string that it is matching (literal). The length
of either string is limited to 16 bytes.
.PP
diff --git a/sbin/ipf/ipscan/ipscan.8 b/sbin/ipf/ipscan/ipscan.8
index 513dc94a8050..da4068a1e8f2 100644
--- a/sbin/ipf/ipscan/ipscan.8
+++ b/sbin/ipf/ipscan/ipscan.8
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPSCAN 8
.SH NAME
@@ -11,7 +10,6 @@ ipscan \- user interface to the IPFilter content scanning
]
.B \-f <\fIfilename\fP>
.SH DESCRIPTION
-.PP
\fBipscan\fP opens the filename given (treating "\-" as stdin) and parses the
file to build up a content scanning configuration to load into the kernel.
Currently only the first 16 bytes of a connection can be compared.
diff --git a/sbin/ipf/ipscan/ipscan_y.y b/sbin/ipf/ipscan/ipscan_y.y
index 21d1b15aed70..b6693e294dae 100644
--- a/sbin/ipf/ipscan/ipscan_y.y
+++ b/sbin/ipf/ipscan/ipscan_y.y
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/ipsend/44arp.c b/sbin/ipf/ipsend/44arp.c
index e7a15b5d5cad..0a11c8732a12 100644
--- a/sbin/ipf/ipsend/44arp.c
+++ b/sbin/ipf/ipsend/44arp.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Based upon 4.4BSD's /usr/sbin/arp
diff --git a/sbin/ipf/ipsend/arp.c b/sbin/ipf/ipsend/arp.c
index 1d8f4213f246..a9409093213f 100644
--- a/sbin/ipf/ipsend/arp.c
+++ b/sbin/ipf/ipsend/arp.c
@@ -1,14 +1,9 @@
-/* $FreeBSD$ */
/*
* arp.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)arp.c 1.4 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/types.h>
#include <sys/socket.h>
# include <sys/sockio.h>
diff --git a/sbin/ipf/ipsend/dlcommon.c b/sbin/ipf/ipsend/dlcommon.c
index 86554660240d..a73f7df96d54 100644
--- a/sbin/ipf/ipsend/dlcommon.c
+++ b/sbin/ipf/ipsend/dlcommon.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Common (shared) DLPI test routines.
diff --git a/sbin/ipf/ipsend/dltest.h b/sbin/ipf/ipsend/dltest.h
index 086782c1fbb7..fe6e33735849 100644
--- a/sbin/ipf/ipsend/dltest.h
+++ b/sbin/ipf/ipsend/dltest.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Common DLPI Test Suite header file
diff --git a/sbin/ipf/ipsend/ip.c b/sbin/ipf/ipsend/ip.c
index 7c623103b901..8cdfca893d15 100644
--- a/sbin/ipf/ipsend/ip.c
+++ b/sbin/ipf/ipsend/ip.c
@@ -1,14 +1,9 @@
-/* $FreeBSD$ */
/*
* ip.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "%W% %G% (C)1995";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#include <netinet/in_systm.h>
@@ -266,7 +261,7 @@ send_tcp(int nfd, int mtu, ip_t *ip, struct in_addr gwip)
i = sizeof(struct tcpiphdr) / sizeof(long);
- if ((t2->th_flags == TH_SYN) && !ntohs(ip->ip_off) &&
+ if ((__tcp_get_flags(t2) == TH_SYN) && !ntohs(ip->ip_off) &&
(lbuf[i] != htonl(0x020405b4))) {
lbuf[i] = htonl(0x020405b4);
bcopy((char *)ip + hlen + thlen, (char *)ip + hlen + thlen + 4,
diff --git a/sbin/ipf/ipsend/ipresend.1 b/sbin/ipf/ipsend/ipresend.1
index 6761a183caea..e7714349e6af 100644
--- a/sbin/ipf/ipsend/ipresend.1
+++ b/sbin/ipf/ipsend/ipresend.1
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPRESEND 1
.SH NAME
@@ -21,7 +20,6 @@ ipresend \- resend IP packets out to network
<\fIfilename\fP>
]
.SH DESCRIPTION
-.PP
\fBipresend\fP was designed to allow packets to be resent, once captured,
back out onto the network for use in testing. \fIipresend\fP supports a
number of different file formats as input, including saved snoop/tcpdump
@@ -98,10 +96,8 @@ The input file is composed of text descriptions of IP packets.
.SH SEE ALSO
snoop(1m), tcpdump(8), etherfind(8c), ipftest(1), ipresend(1), iptest(1), bpf(4), dlpi(7p)
.SH DIAGNOSTICS
-.PP
Needs to be run as root.
.SH BUGS
-.PP
Not all of the input formats are sufficiently capable of introducing a
wide enough variety of packets for them to be all useful in testing.
If you find any, please send email to me at darrenr@pobox.com
diff --git a/sbin/ipf/ipsend/ipresend.c b/sbin/ipf/ipsend/ipresend.c
index c9e625f02e2a..c00367a4a586 100644
--- a/sbin/ipf/ipsend/ipresend.c
+++ b/sbin/ipf/ipsend/ipresend.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* ipresend.c (C) 1995-1998 Darren Reed
@@ -6,10 +5,6 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
*/
-#if !defined(lint)
-static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
diff --git a/sbin/ipf/ipsend/ipsend.1 b/sbin/ipf/ipsend/ipsend.1
index 7f0a8e39538a..3cbb991694b1 100644
--- a/sbin/ipf/ipsend/ipsend.1
+++ b/sbin/ipf/ipsend/ipsend.1
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPSEND 1
.SH NAME
@@ -36,12 +35,11 @@ ipsend \- sends IP packets
<\fIwindow\fP>
] <destination> [TCP-flags]
.SH DESCRIPTION
-.PP
\fBipsend\fP can be compiled in two ways. The first is used to send one-off
packets to a destination host, using command line options to specify various
attributes present in the headers. The \fIdestination\fP must be given as
the last command line option, except for when TCP flags are specified as
-a combination of A, S, F, U, P and R, last.
+a combination of A, S, F, U, P, R, E, W and e, last.
.PP
The other way it may be compiled, with DOSOCKET defined, is to allow an
attempt at making a TCP connection using a with ipsend resending the SYN
@@ -104,8 +102,6 @@ enable verbose mode.
.SH SEE ALSO
ipsend(1), ipresend(1), iptest(1), protocols(4), bpf(4), dlpi(7p)
.SH DIAGNOSTICS
-.PP
Needs to be run as root.
.SH BUGS
-.PP
If you find any, please send email to me at darrenr@pobox.com
diff --git a/sbin/ipf/ipsend/ipsend.5 b/sbin/ipf/ipsend/ipsend.5
index 346f4e7ced8f..67c456e54d34 100644
--- a/sbin/ipf/ipsend/ipsend.5
+++ b/sbin/ipf/ipsend/ipsend.5
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.TH IPSEND 5
.SH NAME
ipsend \- IP packet description language
@@ -8,7 +7,6 @@ text file which fits the grammar described below. The purpose of this
grammar is to allow IP packets to be described in an arbitary way which
also allows encapsulation to be so done to an arbitary level.
.SH GRAMMAR
-.LP
.nf
line ::= iface | arp | send | defrouter | ipv4line .
@@ -81,7 +79,6 @@ databodyopts ::= "len" number | "value" string | "file" filename .
icmpechoopts ::= "icmpseq" number | "icmpid" number .
.fi
.SH COMMANDS
-.PP
Before sending any packets or defining any packets, it is necessary to
describe the interface(s) which will be used to send packets out.
.TP
@@ -253,7 +250,8 @@ unset, it defaults to 0 and is automatically calculated.
.TP
.B flags <tcp-flags>
sets the TCP flags field to match the flags specified. Valid flags are
-"S" (SYN), "A" (ACK), "R" (RST), "F" (FIN), "U" (URG), "P" (PUSH).
+"S" (SYN), "A" (ACK), "R" (RST), "F" (FIN), "U" (URG), "P" (PUSH),
+"E" (ECE), "W" (CWR), "e" (AE).
.TP
.B opt
indicates that TCP header options follow. As TCP options are added to the
diff --git a/sbin/ipf/ipsend/ipsend.c b/sbin/ipf/ipsend/ipsend.c
index 1996c01dec6c..78a8ccaa3f30 100644
--- a/sbin/ipf/ipsend/ipsend.c
+++ b/sbin/ipf/ipsend/ipsend.c
@@ -1,13 +1,8 @@
-/* $FreeBSD$ */
/*
* ipsend.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipsend.c 1.5 12/10/95 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -370,22 +365,31 @@ main(int argc, char **argv)
switch(c)
{
case 'S' : case 's' :
- tcp->th_flags |= TH_SYN;
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_SYN);
break;
case 'A' : case 'a' :
- tcp->th_flags |= TH_ACK;
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_ACK);
break;
case 'F' : case 'f' :
- tcp->th_flags |= TH_FIN;
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_FIN);
break;
case 'R' : case 'r' :
- tcp->th_flags |= TH_RST;
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_RST);
break;
case 'P' : case 'p' :
- tcp->th_flags |= TH_PUSH;
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_PUSH);
break;
case 'U' : case 'u' :
- tcp->th_flags |= TH_URG;
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_URG);
+ break;
+ case 'E' :
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_ECE);
+ break;
+ case 'W' :
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_CWR);
+ break;
+ case 'e' :
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) | TH_AE);
break;
}
@@ -395,8 +399,8 @@ main(int argc, char **argv)
printf("Source: %s\n", inet_ntoa(ip->ip_src));
printf("Dest: %s\n", inet_ntoa(ip->ip_dst));
printf("Gateway: %s\n", inet_ntoa(gwip));
- if (ip->ip_p == IPPROTO_TCP && tcp->th_flags)
- printf("Flags: %#x\n", tcp->th_flags);
+ if (ip->ip_p == IPPROTO_TCP && __tcp_get_flags(tcp) != 0)
+ printf("Flags: %#x\n", __tcp_get_flags(tcp));
printf("mtu: %d\n", mtu);
if (ip->ip_p == IPPROTO_UDP) {
diff --git a/sbin/ipf/ipsend/ipsend.h b/sbin/ipf/ipsend/ipsend.h
index bfec90f1c5b3..6eb30e2be3b4 100644
--- a/sbin/ipf/ipsend/ipsend.h
+++ b/sbin/ipf/ipsend/ipsend.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* ipsend.h (C) 1997-1998 Darren Reed
@@ -8,7 +7,7 @@
* conditions, enough of the TCP header is missing for unpredictable
* results unless the filter is aware that this can happen.
*
- * The author provides this program as-is, with no gaurantee for its
+ * The author provides this program as-is, with no guarantee for its
* suitability for any specific purpose. The author takes no responsibility
* for the misuse/abuse of this program and provides it for the sole purpose
* of testing packet filter policies. This file maybe distributed freely
diff --git a/sbin/ipf/ipsend/ipsopt.c b/sbin/ipf/ipsend/ipsopt.c
index 0e053e2c75bb..ffad9c008461 100644
--- a/sbin/ipf/ipsend/ipsopt.c
+++ b/sbin/ipf/ipsend/ipsopt.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -6,10 +5,6 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
diff --git a/sbin/ipf/ipsend/iptest.1 b/sbin/ipf/ipsend/iptest.1
index 8f25f4abf256..5ccebc681cbc 100644
--- a/sbin/ipf/ipsend/iptest.1
+++ b/sbin/ipf/ipsend/iptest.1
@@ -1,4 +1,3 @@
-.\" $FreeBSD$
.\"
.TH IPTEST 1
.SH NAME
@@ -24,7 +23,6 @@ iptest \- automatically generate a packets to test IP functionality
<\fIsource\fP>
] <destination>
.SH DESCRIPTION
-.PP
\fBiptest\fP ...
.SH OPTIONS
.TP
@@ -99,5 +97,4 @@ Only one of the numeric test options may be given when \fIiptest\fP is run.
.PP
Needs to be run as root.
.SH BUGS
-.PP
If you find any, please send email to me at darrenr@pobox.com
diff --git a/sbin/ipf/ipsend/iptest.c b/sbin/ipf/ipsend/iptest.c
index ed92ab9306ea..db31168cd380 100644
--- a/sbin/ipf/ipsend/iptest.c
+++ b/sbin/ipf/ipsend/iptest.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* ipsend.c (C) 1995-1998 Darren Reed
@@ -6,10 +5,6 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
*/
-#if !defined(lint)
-static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
diff --git a/sbin/ipf/ipsend/iptests.c b/sbin/ipf/ipsend/iptests.c
index cbda02893162..6a72a0adfffd 100644
--- a/sbin/ipf/ipsend/iptests.c
+++ b/sbin/ipf/ipsend/iptests.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -6,10 +5,6 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
*/
-#if !defined(lint)
-static const char sccsid[] = "%W% %G% (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#if defined(__NetBSD__) && defined(__vax__)
@@ -79,7 +74,6 @@ typedef int boolean_t;
# include <netinet/in_pcb.h>
# endif
#include "ipsend.h"
-# include <netinet/tcp_timer.h>
# include <netinet/tcp_var.h>
#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106000000)
# define USE_NANOSLEEP
@@ -908,7 +902,6 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
int nfd, i;
t = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
- t->th_x2 = 0;
TCP_OFF_A(t, 0);
t->th_sport = htons(1);
t->th_dport = htons(1);
@@ -925,13 +918,12 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
if (!ptest || (ptest == 1)) {
/*
- * Test 1: flags variations, 0 - 3f
+ * Test 1: flags variations, 0 - 1ff
*/
TCP_OFF_A(t, sizeof(*t) >> 2);
printf("5.1 Test TCP flag combinations\n");
- for (i = 0; i <= (TH_URG|TH_ACK|TH_PUSH|TH_RST|TH_SYN|TH_FIN);
- i++) {
- t->th_flags = i;
+ for (i = 0; i <= TH_FLAGS; i++) {
+ __tcp_set_flags(t, i);
(void) send_tcp(nfd, mtu, ip, gwip);
printf("%d\r", i);
fflush(stdout);
@@ -941,7 +933,7 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
}
if (!ptest || (ptest == 2)) {
- t->th_flags = TH_SYN;
+ __tcp_set_flags(t, TH_SYN);
/*
* Test 2: seq = 0, seq = 1, seq = 0x7fffffff, seq=0x80000000,
* seq = 0xa000000, seq = 0xffffffff
@@ -984,7 +976,7 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
}
if (!ptest || (ptest == 3)) {
- t->th_flags = TH_ACK;
+ __tcp_set_flags(t, TH_ACK);
/*
* Test 3: ack = 0, ack = 1, ack = 0x7fffffff, ack = 0x8000000
* ack = 0xa000000, ack = 0xffffffff
@@ -1027,7 +1019,7 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
}
if (!ptest || (ptest == 4)) {
- t->th_flags = TH_SYN;
+ __tcp_set_flags(t, TH_SYN);
/*
* Test 4: win = 0, win = 32768, win = 65535
*/
@@ -1097,7 +1089,7 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
/*
* Test 5: urp
*/
- t->th_flags = TH_ACK|TH_URG;
+ __tcp_set_flags(t, TH_ACK|TH_URG);
printf("5.5.1 TCP Urgent pointer, sport %hu dport %hu\n",
ntohs(t->th_sport), ntohs(t->th_dport));
t->th_urp = htons(1);
@@ -1116,7 +1108,7 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
(void) send_tcp(nfd, mtu, ip, gwip);
PAUSE();
t->th_urp = 0;
- t->th_flags &= ~TH_URG;
+ __tcp_set_flags(t, __tcp_get_flags(t) & ~TH_URG);
ip->ip_len = sizeof(ip_t) + sizeof(tcphdr_t);
}
@@ -1124,7 +1116,7 @@ ip_test5(char *dev, int mtu, ip_t *ip, struct in_addr gwip, int ptest)
/*
* Test 6: data offset, off = 0, off is inside, off is outside
*/
- t->th_flags = TH_ACK;
+ __tcp_set_flags(t, TH_ACK);
printf("5.6.1 TCP off = 1-15, len = 40\n");
for (i = 1; i < 16; i++) {
TCP_OFF_A(t, ntohs(i));
@@ -1146,7 +1138,7 @@ skip_five_and_six:
TCP_OFF_A(t, 0);
if (!ptest || (ptest == 7)) {
- t->th_flags = TH_SYN;
+ __tcp_set_flags(t, TH_SYN);
/*
* Test 7: sport = 0, sport = 1, sport = 32767
* sport = 32768, sport = 65535
@@ -1184,7 +1176,7 @@ skip_five_and_six:
if (!ptest || (ptest == 8)) {
t->th_sport = htons(1);
- t->th_flags = TH_SYN;
+ __tcp_set_flags(t, TH_SYN);
/*
* Test 8: dport = 0, dport = 1, dport = 32767
* dport = 32768, dport = 65535
@@ -1226,7 +1218,7 @@ skip_five_and_six:
/* chose SMTP port 25 */
t->th_sport = htons(25);
t->th_dport = htons(25);
- t->th_flags = TH_SYN;
+ __tcp_set_flags(t, TH_SYN);
ip->ip_src = ip->ip_dst;
(void) send_tcp(nfd, mtu, ip, gwip);
fflush(stdout);
diff --git a/sbin/ipf/ipsend/resend.c b/sbin/ipf/ipsend/resend.c
index c3f86baaadc3..a306edddff19 100644
--- a/sbin/ipf/ipsend/resend.c
+++ b/sbin/ipf/ipsend/resend.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* resend.c (C) 1995-1998 Darren Reed
@@ -6,10 +5,6 @@
* See the IPFILTER.LICENCE file for details on licencing.
*
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)resend.c 1.3 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -55,9 +50,9 @@ dumppacket(ip_t *ip)
if (ip->ip_p == IPPROTO_TCP) {
printf(" seq %lu:%lu flags ",
(u_long)t->th_seq, (u_long)t->th_ack);
- for (j = 0, i = 1; i < 256; i *= 2, j++)
- if (t->th_flags & i)
- printf("%c", "FSRPAU--"[j]);
+ for (j = 0, i = 1; i < TH_FLAGS; i <<= 1, j++)
+ if (__tcp_get_flags(t) & i)
+ printf("%c", "FSRPAUEWe"[j]);
}
putchar('\n');
}
diff --git a/sbin/ipf/ipsend/sbpf.c b/sbin/ipf/ipsend/sbpf.c
index b46585f1f340..6d5d60292ce9 100644
--- a/sbin/ipf/ipsend/sbpf.c
+++ b/sbin/ipf/ipsend/sbpf.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* (C)opyright 1995-1998 Darren Reed. (from tcplog)
*
@@ -40,10 +39,6 @@
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)sbpf.c 1.3 8/25/95 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
/*
* the code herein is dervied from libpcap.
diff --git a/sbin/ipf/ipsend/sdlpi.c b/sbin/ipf/ipsend/sdlpi.c
index 5570495dd2d7..d4195c456622 100644
--- a/sbin/ipf/ipsend/sdlpi.c
+++ b/sbin/ipf/ipsend/sdlpi.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
@@ -39,10 +38,6 @@
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)sdlpi.c 1.3 10/30/95 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#define CHUNKSIZE 8192
#define BUFSPACE (4*CHUNKSIZE)
diff --git a/sbin/ipf/ipsend/snit.c b/sbin/ipf/ipsend/snit.c
index 187299436d2d..6dc9df06714f 100644
--- a/sbin/ipf/ipsend/snit.c
+++ b/sbin/ipf/ipsend/snit.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* (C)opyright 1992-1998 Darren Reed. (from tcplog)
@@ -39,10 +38,6 @@
#include "ipsend.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)snit.c 1.5 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#define CHUNKSIZE 8192
#define BUFSPACE (4*CHUNKSIZE)
diff --git a/sbin/ipf/ipsend/sock.c b/sbin/ipf/ipsend/sock.c
index f95538fd9824..7ffacc950d22 100644
--- a/sbin/ipf/ipsend/sock.c
+++ b/sbin/ipf/ipsend/sock.c
@@ -1,14 +1,9 @@
-/* $FreeBSD$ */
/*
* sock.c (C) 1995-1998 Darren Reed
*
* See the IPFILTER.LICENCE file for details on licencing.
*
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)sock.c 1.2 1/11/96 (C)1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
@@ -63,7 +58,6 @@ typedef int boolean_t;
#include <netinet/ip_var.h>
#define _WANT_INPCB
#include <netinet/in_pcb.h>
-#include <netinet/tcp_timer.h>
#define _WANT_TCPCB
#include <netinet/tcp_var.h>
#include <stdio.h>
diff --git a/sbin/ipf/ipsend/sockraw.c b/sbin/ipf/ipsend/sockraw.c
index 16384230f543..ab65f63753c7 100644
--- a/sbin/ipf/ipsend/sockraw.c
+++ b/sbin/ipf/ipsend/sockraw.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* (C)opyright 2000 Darren Reed.
@@ -29,9 +28,6 @@
#include <errno.h>
#include "ipsend.h"
-#if !defined(lint) && defined(LIBC_SCCS)
-static char sirix[] = "@(#)sirix.c 1.0 10/9/97 (C)1997 Marc Boucher";
-#endif
int
diff --git a/sbin/ipf/libipf/Makefile b/sbin/ipf/libipf/Makefile
index a8f43e24fb74..bdd56876dadd 100644
--- a/sbin/ipf/libipf/Makefile
+++ b/sbin/ipf/libipf/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= ipf
LIB= ipf
INTERNALLIB=
diff --git a/sbin/ipf/libipf/Makefile.depend b/sbin/ipf/libipf/Makefile.depend
index 55e67ede0b51..f9d041194c3e 100644
--- a/sbin/ipf/libipf/Makefile.depend
+++ b/sbin/ipf/libipf/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/ipf/libipf/addicmp.c b/sbin/ipf/libipf/addicmp.c
index da52f1caacfe..f84cae01644e 100644
--- a/sbin/ipf/libipf/addicmp.c
+++ b/sbin/ipf/libipf/addicmp.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/addipopt.c b/sbin/ipf/libipf/addipopt.c
index a6c699ddc701..ab0579d00063 100644
--- a/sbin/ipf/libipf/addipopt.c
+++ b/sbin/ipf/libipf/addipopt.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/bcopywrap.c b/sbin/ipf/libipf/bcopywrap.c
index 9eec27f4538c..e20462ea9b04 100644
--- a/sbin/ipf/libipf/bcopywrap.c
+++ b/sbin/ipf/libipf/bcopywrap.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/binprint.c b/sbin/ipf/libipf/binprint.c
index 131e3f62d481..8d09b347db2c 100644
--- a/sbin/ipf/libipf/binprint.c
+++ b/sbin/ipf/libipf/binprint.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/buildopts.c b/sbin/ipf/libipf/buildopts.c
index 7f2397bf7c95..27eb1b7323f0 100644
--- a/sbin/ipf/libipf/buildopts.c
+++ b/sbin/ipf/libipf/buildopts.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/checkrev.c b/sbin/ipf/libipf/checkrev.c
index 148acaff571b..ded9ce04d500 100644
--- a/sbin/ipf/libipf/checkrev.c
+++ b/sbin/ipf/libipf/checkrev.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/connecttcp.c b/sbin/ipf/libipf/connecttcp.c
index 5e0d86c1d098..7ab9d3430f58 100644
--- a/sbin/ipf/libipf/connecttcp.c
+++ b/sbin/ipf/libipf/connecttcp.c
@@ -10,7 +10,7 @@
#include <ctype.h>
/*
- * Format expected is one addres per line, at the start of each line.
+ * Format expected is one address per line, at the start of each line.
*/
int
connecttcp(char *server, int port)
diff --git a/sbin/ipf/libipf/count4bits.c b/sbin/ipf/libipf/count4bits.c
index 52942771f800..10e9d6bb2207 100644
--- a/sbin/ipf/libipf/count4bits.c
+++ b/sbin/ipf/libipf/count4bits.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/count6bits.c b/sbin/ipf/libipf/count6bits.c
index fd4f11226c0b..ff013046613c 100644
--- a/sbin/ipf/libipf/count6bits.c
+++ b/sbin/ipf/libipf/count6bits.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/debug.c b/sbin/ipf/libipf/debug.c
index 0e3276e21705..9fcdf98317bd 100644
--- a/sbin/ipf/libipf/debug.c
+++ b/sbin/ipf/libipf/debug.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/facpri.c b/sbin/ipf/libipf/facpri.c
index 3286248d3205..9325a03c8dc3 100644
--- a/sbin/ipf/libipf/facpri.c
+++ b/sbin/ipf/libipf/facpri.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -11,7 +10,7 @@
#include <stdio.h>
#include <string.h>
#include <limits.h>
-#include <sys/types.h>
+#include <sys/param.h>
#if !defined(__SVR4) && !defined(__svr4__)
#include <strings.h>
#endif
@@ -21,9 +20,6 @@
#include <syslog.h>
#include "facpri.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
typedef struct table {
@@ -80,7 +76,7 @@ fac_toname(int facpri)
fac = facpri & LOG_FACMASK;
j = fac >> 3;
- if (j < (sizeof(facs)/sizeof(facs[0]))) {
+ if (j < nitems(facs)) {
if (facs[j].value == fac)
return (facs[j].name);
}
diff --git a/sbin/ipf/libipf/facpri.h b/sbin/ipf/libipf/facpri.h
index 5698c0ebe047..dac5c591410c 100644
--- a/sbin/ipf/libipf/facpri.h
+++ b/sbin/ipf/libipf/facpri.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/fill6bits.c b/sbin/ipf/libipf/fill6bits.c
index b8f5914ef426..e9e8b7fe7099 100644
--- a/sbin/ipf/libipf/fill6bits.c
+++ b/sbin/ipf/libipf/fill6bits.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/flags.c b/sbin/ipf/libipf/flags.c
index 05fcc9874866..b476936e0dba 100644
--- a/sbin/ipf/libipf/flags.c
+++ b/sbin/ipf/libipf/flags.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -19,7 +18,10 @@
#ifndef TH_CWR
# define TH_CWR 0x80
#endif
+#ifndef TH_AE
+# define TH_AE 0x100
+#endif
-char flagset[] = "FSRPAUEC";
-u_char flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG,
- TH_ECN, TH_CWR };
+char flagset[] = "FSRPAUEWe";
+uint16_t flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG,
+ TH_ECN, TH_CWR, TH_AE };
diff --git a/sbin/ipf/libipf/gethost.c b/sbin/ipf/libipf/gethost.c
index aefdbbae9fb3..6ae34a577519 100644
--- a/sbin/ipf/libipf/gethost.c
+++ b/sbin/ipf/libipf/gethost.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/getifname.c b/sbin/ipf/libipf/getifname.c
index a2d9ef6885d1..970f2a6707bb 100644
--- a/sbin/ipf/libipf/getifname.c
+++ b/sbin/ipf/libipf/getifname.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/getnattype.c b/sbin/ipf/libipf/getnattype.c
index 3e3853208dc1..30bae7ce0216 100644
--- a/sbin/ipf/libipf/getnattype.c
+++ b/sbin/ipf/libipf/getnattype.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -10,9 +9,6 @@
#include "ipf.h"
#include "kmem.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
/*
diff --git a/sbin/ipf/libipf/getport.c b/sbin/ipf/libipf/getport.c
index ea52fad3234c..8b659b2761b3 100644
--- a/sbin/ipf/libipf/getport.c
+++ b/sbin/ipf/libipf/getport.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/getportproto.c b/sbin/ipf/libipf/getportproto.c
index 9f84ab21c476..637b000d8d51 100644
--- a/sbin/ipf/libipf/getportproto.c
+++ b/sbin/ipf/libipf/getportproto.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/getproto.c b/sbin/ipf/libipf/getproto.c
index 4d3f2d9e1ea2..139bfd3ee41a 100644
--- a/sbin/ipf/libipf/getproto.c
+++ b/sbin/ipf/libipf/getproto.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/getsumd.c b/sbin/ipf/libipf/getsumd.c
index 3d66d273f843..ede6f7ea134d 100644
--- a/sbin/ipf/libipf/getsumd.c
+++ b/sbin/ipf/libipf/getsumd.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/hostname.c b/sbin/ipf/libipf/hostname.c
index 3b179954bbff..1c3d3451b487 100644
--- a/sbin/ipf/libipf/hostname.c
+++ b/sbin/ipf/libipf/hostname.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/icmpcode.c b/sbin/ipf/libipf/icmpcode.c
index e898ebfa39a5..b7fc15451e08 100644
--- a/sbin/ipf/libipf/icmpcode.c
+++ b/sbin/ipf/libipf/icmpcode.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/inet_addr.c b/sbin/ipf/libipf/inet_addr.c
index 367c25f44d51..d64b3da41361 100644
--- a/sbin/ipf/libipf/inet_addr.c
+++ b/sbin/ipf/libipf/inet_addr.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* ++Copyright++ 1983, 1990, 1993
@@ -55,10 +54,6 @@
* --Copyright--
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
-static const char rcsid[] = "@(#)$Id: inet_addr.c,v 1.8.2.3 2004/12/09 19:41:20 darrenr Exp $";
-#endif /* LIBC_SCCS and not lint */
#include <sys/param.h>
#include <netinet/in.h>
diff --git a/sbin/ipf/libipf/initparse.c b/sbin/ipf/libipf/initparse.c
index c85d6d3ed69d..2cb8906555dd 100644
--- a/sbin/ipf/libipf/initparse.c
+++ b/sbin/ipf/libipf/initparse.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/interror.c b/sbin/ipf/libipf/interror.c
index ca97254cb382..981823ca6bb9 100644
--- a/sbin/ipf/libipf/interror.c
+++ b/sbin/ipf/libipf/interror.c
@@ -17,7 +17,7 @@ typedef struct {
static ipf_error_entry_t *find_error(int);
-#define IPF_NUM_ERRORS 475
+#define IPF_NUM_ERRORS 477
/*
* NO REUSE OF NUMBERS!
@@ -70,7 +70,7 @@ static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = {
{ 42, "ipfilter not enabled for NAT ioctl" },
{ 43, "ipfilter not enabled for state ioctl" },
{ 44, "ipfilter not enabled for auth ioctl" },
- { 45, "ipfilter not enbaled for sync ioctl" },
+ { 45, "ipfilter not enabled for sync ioctl" },
{ 46, "ipfilter not enabled for scan ioctl" },
{ 47, "ipfilter not enabled for lookup ioctl" },
{ 48, "unrecognised device minor number for ioctl" },
@@ -144,7 +144,7 @@ static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = {
{ 116, "error copying in match array" },
{ 117, "match array type is not IPFOBJ_IPFEXPR" },
{ 118, "bad size for match array" },
- { 119, "cannot allocate memory for match aray" },
+ { 119, "cannot allocate memory for match array" },
{ 120, "error copying in match array" },
{ 121, "error verifying contents of match array" },
{ 122, "need write permissions to set ipf lock status" },
@@ -206,7 +206,7 @@ static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = {
{ 30002, "could not malloc memory for new hash table" },
{ 30003, "error coping in hash table structure" },
{ 30004, "hash table already exists" },
- { 30005, "mismach between new hash table and operation unit" },
+ { 30005, "mismatch between new hash table and operation unit" },
{ 30006, "could not malloc memory for hash table base" },
{ 30007, "could not find hash table" },
{ 30008, "mismatch between hash table and operation unit" },
@@ -229,7 +229,7 @@ static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = {
{ 30025, "hash table size must be at least 1"},
{ 30026, "cannot allocate memory for hash table context" },
/* -------------------------------------------------------------------------- */
- { 40001, "invalid minor device numebr for log read" },
+ { 40001, "invalid minor device number for log read" },
{ 40002, "read size too small" },
{ 40003, "interrupted waiting for log data to read" },
{ 40004, "interrupted waiting for log data to read" },
@@ -276,7 +276,7 @@ static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = {
{ 50038, "invalid unit for lookup iterator" },
{ 50039, "invalid unit for lookup iterator" },
{ 50040, "could not find token for lookup iterator" },
- { 50041, "unrecognised object type for lookup interator" },
+ { 50041, "unrecognised object type for lookup iterator" },
{ 50042, "error copying in lookup delete node operation" },
/* -------------------------------------------------------------------------- */
{ 60001, "insufficient privilege for NAT write operation" },
@@ -333,7 +333,7 @@ log" },
{ 60051, "iterator error copying out NAT entry data" },
{ 60052, "iterator data supplied with NULL pointer" },
{ 60053, "unknown NAT iterator type" },
- { 60054, "unknwon next address type" },
+ { 60054, "unknown next address type" },
{ 60055, "iterator suppled with unknown type for get-next" },
{ 60056, "unknown lookup group for next address" },
{ 60057, "error copying out NAT log flush results" },
@@ -355,6 +355,7 @@ log" },
{ 60073, "unknown lookup group for next address (ipv6)" },
{ 60074, "unknown next address type (ipv6)" },
{ 60075, "one object at a time must be copied" },
+ { 60076, "NAT ioctl denied in jail without VNET" },
/* -------------------------------------------------------------------------- */
{ 70001, "incorrect object size to get pool stats" },
{ 70002, "could not malloc memory for new pool node" },
@@ -418,7 +419,7 @@ log" },
{ 100006, "" },
{ 100007, "" },
{ 100008, "need write permissions to flush state log" },
- { 100009, "erorr copyout results of flushing state log" },
+ { 100009, "error copyout results of flushing state log" },
{ 100010, "need write permissions to turn state logging on/off" },
{ 100011, "error copying in new state logging state" },
{ 100012, "error copying out current state logging state" },
@@ -516,6 +517,7 @@ log" },
{ 130015, "ipf_init_all failed" },
{ 130016, "finding pfil head failed" },
{ 130017, "ipfilter is already initialised and running" },
+ { 130018, "ioctl denied in jail without VNET" },
};
@@ -525,7 +527,7 @@ find_error(int errnum)
ipf_error_entry_t *ie;
int l = -1, r = IPF_NUM_ERRORS + 1, step;
- step = (r - l) / 2;;
+ step = (r - l) / 2;
while (step != 0) {
ie = ipf_errors + l + step;
@@ -536,7 +538,7 @@ find_error(int errnum)
r = step;
else
l = step;
- step = (r - l) / 2;;
+ step = (r - l) / 2;
}
return (NULL);
diff --git a/sbin/ipf/libipf/ionames.c b/sbin/ipf/libipf/ionames.c
index 9b586422a392..9b2442f4e6e3 100644
--- a/sbin/ipf/libipf/ionames.c
+++ b/sbin/ipf/libipf/ionames.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/ipf_dotuning.c b/sbin/ipf/libipf/ipf_dotuning.c
index 1db47d76eac1..74d5dd154aae 100644
--- a/sbin/ipf/libipf/ipf_dotuning.c
+++ b/sbin/ipf/libipf/ipf_dotuning.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -20,7 +19,7 @@ void ipf_dotuning(int fd, char *tuneargs, ioctlfunc_t iocfn)
bzero((char *)&tu, sizeof(tu));
obj.ipfo_rev = IPFILTER_VERSION;
- obj.ipfo_size = sizeof(tu);;
+ obj.ipfo_size = sizeof(tu);
obj.ipfo_ptr = (void *)&tu;
obj.ipfo_type = IPFOBJ_TUNEABLE;
diff --git a/sbin/ipf/libipf/ipft_hx.c b/sbin/ipf/libipf/ipft_hx.c
index a540b52da05d..98c0d1eb0114 100644
--- a/sbin/ipf/libipf/ipft_hx.c
+++ b/sbin/ipf/libipf/ipft_hx.c
@@ -1,14 +1,9 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipft_hx.c 1.1 3/9/96 (C) 1996 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <ctype.h>
diff --git a/sbin/ipf/libipf/ipft_pc.c b/sbin/ipf/libipf/ipft_pc.c
index 349b9390e745..ff4acd5d1753 100644
--- a/sbin/ipf/libipf/ipft_pc.c
+++ b/sbin/ipf/libipf/ipft_pc.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -10,9 +9,6 @@
#include "ipf.h"
#include "ipt.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
struct llc {
int lc_type;
diff --git a/sbin/ipf/libipf/ipft_tx.c b/sbin/ipf/libipf/ipft_tx.c
index 87215f5b7b6e..1e23f06be3fd 100644
--- a/sbin/ipf/libipf/ipft_tx.c
+++ b/sbin/ipf/libipf/ipft_tx.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -7,10 +6,6 @@
*
* $Id$
*/
-#if !defined(lint)
-static const char sccsid[] = "@(#)ipft_tx.c 1.7 6/5/96 (C) 1993 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include <ctype.h>
@@ -25,9 +20,9 @@ static int text_open(char *), text_close(void);
static int text_readip(mb_t *, char **, int *);
static int parseline(char *, ip_t *, char **, int *);
-static char myflagset[] = "FSRPAUEC";
-static u_char myflags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH,
- TH_ACK, TH_URG, TH_ECN, TH_CWR };
+static char myflagset[] = "FSRPAUEWe";
+static uint16_t myflags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH,
+ TH_ACK, TH_URG, TH_ECN, TH_CWR, TH_AE };
struct ipread iptext = { text_open, text_close, text_readip, R_DO_CKSUM };
static FILE *tfp = NULL;
@@ -270,15 +265,16 @@ parseline(char *line, ip_t *ip, char **ifn, int *out)
if (*cpp != NULL) {
char *s, *t;
- tcp->th_flags = 0;
+ __tcp_set_flags(tcp, 0);
for (s = *cpp; *s; s++)
- if ((t = strchr(myflagset, *s)))
- tcp->th_flags |= myflags[t-myflagset];
- if (tcp->th_flags)
+ if ((t = strchr(myflagset, *s)))
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) |
+ myflags[t-myflagset]);
+ if (__tcp_get_flags(tcp))
cpp++;
}
- if (tcp->th_flags & TH_URG)
+ if (__tcp_get_flags(tcp) & TH_URG)
tcp->th_urp = htons(1);
if (*cpp && !strncasecmp(*cpp, "seq=", 4)) {
@@ -441,15 +437,16 @@ parseipv6(char **cpp, ip6_t *ip6, char **ifn, int *out)
if (*cpp != NULL) {
char *s, *t;
- tcp->th_flags = 0;
+ __tcp_set_flags(tcp, 0);
for (s = *cpp; *s; s++)
- if ((t = strchr(myflagset, *s)))
- tcp->th_flags |= myflags[t-myflagset];
- if (tcp->th_flags)
+ if ((t = strchr(myflagset, *s)))
+ __tcp_set_flags(tcp, __tcp_get_flags(tcp) |
+ myflags[t-myflagset]);
+ if (__tcp_get_flags(tcp))
cpp++;
}
- if (tcp->th_flags & TH_URG)
+ if (__tcp_get_flags(tcp) & TH_URG)
tcp->th_urp = htons(1);
if (*cpp && !strncasecmp(*cpp, "seq=", 4)) {
diff --git a/sbin/ipf/libipf/ipoptsec.c b/sbin/ipf/libipf/ipoptsec.c
index 7617daec33dd..fad2a564371e 100644
--- a/sbin/ipf/libipf/ipoptsec.c
+++ b/sbin/ipf/libipf/ipoptsec.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/kmem.c b/sbin/ipf/libipf/kmem.c
index c39e36aa5add..6ebd0dee6b72 100644
--- a/sbin/ipf/libipf/kmem.c
+++ b/sbin/ipf/libipf/kmem.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -30,10 +29,6 @@
#include "kmem.h"
-#if !defined(lint)
-static const char sccsid[] = "@(#)kmem.c 1.4 1/12/96 (C) 1992 Darren Reed";
-static const char rcsid[] = "@(#)$Id$";
-#endif
diff --git a/sbin/ipf/libipf/kmem.h b/sbin/ipf/libipf/kmem.h
index bcf6a0be7e27..623d5760c614 100644
--- a/sbin/ipf/libipf/kmem.h
+++ b/sbin/ipf/libipf/kmem.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/kmemcpywrap.c b/sbin/ipf/libipf/kmemcpywrap.c
index fab86242c449..43f8833be72d 100644
--- a/sbin/ipf/libipf/kmemcpywrap.c
+++ b/sbin/ipf/libipf/kmemcpywrap.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/kvatoname.c b/sbin/ipf/libipf/kvatoname.c
index 47b226f13450..1e53cd9c2cd5 100644
--- a/sbin/ipf/libipf/kvatoname.c
+++ b/sbin/ipf/libipf/kvatoname.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/load_hash.c b/sbin/ipf/libipf/load_hash.c
index 63894a3cfa72..bfee0fc64642 100644
--- a/sbin/ipf/libipf/load_hash.c
+++ b/sbin/ipf/libipf/load_hash.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/load_hashnode.c b/sbin/ipf/libipf/load_hashnode.c
index 46e5552fdbab..12b11687710d 100644
--- a/sbin/ipf/libipf/load_hashnode.c
+++ b/sbin/ipf/libipf/load_hashnode.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -54,9 +53,28 @@ load_hashnode(int unit, char *name, iphtent_t *node, int ttl,
if (err != 0)
if (!(opts & OPT_DONOTHING)) {
- char msg[80];
+ char msg[255];
+ char ipaddr[80], mask_msg[10], mask[8];
- snprintf(msg, sizeof(msg), "%s node from lookup hash table", what);
+ inet_ntop(ipe.ipe_family,
+ ipe.ipe_addr.vptr, ipaddr,
+ sizeof(ipaddr));
+#ifdef USE_INET6
+ if (ipe.ipe_family == AF_INET) {
+#endif
+ inet_ntop(ipe.ipe_family,
+ ipe.ipe_mask.vptr, mask,
+ sizeof(mask));
+ mask_msg[0]='/';
+ mask_msg[1]='\0';
+ strlcat(mask_msg, mask, sizeof(mask_msg));
+#ifdef USE_INET6
+ } else {
+ mask_msg[0]='\0';
+ }
+#endif
+
+ snprintf(msg, sizeof(msg), "%s node from lookup hash table(%s) node(%s%s)", what, name, ipaddr, mask_msg);
return (ipf_perror_fd(pool_fd(), iocfunc, msg));
}
return (0);
diff --git a/sbin/ipf/libipf/load_http.c b/sbin/ipf/libipf/load_http.c
index 738a6f8006f9..7ad0bfd733bf 100644
--- a/sbin/ipf/libipf/load_http.c
+++ b/sbin/ipf/libipf/load_http.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -25,7 +24,7 @@
#define LOAD_BUFSIZE (MAX_URL_LEN * 2 + 128)
/*
- * Format expected is one addres per line, at the start of each line.
+ * Format expected is one address per line, at the start of each line.
*/
alist_t *
load_http(char *url)
diff --git a/sbin/ipf/libipf/load_pool.c b/sbin/ipf/libipf/load_pool.c
index c502f3dc77e0..0d90c81e81ff 100644
--- a/sbin/ipf/libipf/load_pool.c
+++ b/sbin/ipf/libipf/load_pool.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/load_poolnode.c b/sbin/ipf/libipf/load_poolnode.c
index 849bd60791a7..880a6cd1c681 100644
--- a/sbin/ipf/libipf/load_poolnode.c
+++ b/sbin/ipf/libipf/load_poolnode.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -53,11 +52,30 @@ load_poolnode(int role, char *name, ip_pool_node_t *node, int ttl,
if (err != 0) {
if ((opts & OPT_DONOTHING) == 0) {
- char msg[80];
+ char msg[255];
+ char ipaddr[80], mask_msg[10], mask[8];
- snprintf(msg, sizeof(msg), "%s pool node(%s/", what,
- inet_ntoa(pn.ipn_addr.adf_addr.in4));
- strcat(msg, inet_ntoa(pn.ipn_mask.adf_addr.in4));
+ inet_ntop(pn.ipn_addr.adf_family,
+ pn.ipn_addr.adf_addr.vptr, ipaddr,
+ sizeof(ipaddr));
+
+#ifdef USE_INET6
+ if (pn.ipn_mask.adf_family == AF_INET) {
+#endif
+ inet_ntop(pn.ipn_mask.adf_family,
+ pn.ipn_mask.adf_addr.vptr, mask,
+ sizeof(mask));
+ mask_msg[0]='/';
+ mask_msg[1]='\0';
+ strlcat(mask_msg, mask, sizeof(mask_msg));
+#ifdef USE_INET6
+ } else {
+ mask_msg[0]='\0';
+ }
+#endif
+
+ snprintf(msg, sizeof(msg), "%s pool(%s) node(%s%s)",
+ what, name, ipaddr, mask_msg);
return (ipf_perror_fd(pool_fd(), iocfunc, msg));
}
}
diff --git a/sbin/ipf/libipf/mutex_emul.c b/sbin/ipf/libipf/mutex_emul.c
index 3152d2e47013..d7f34671d953 100644
--- a/sbin/ipf/libipf/mutex_emul.c
+++ b/sbin/ipf/libipf/mutex_emul.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -85,10 +84,7 @@ eMmutex_init(eMmutex_t *mtx, char *who, char *file, int line)
void
-eMmutex_destroy(mtx, file, line)
- eMmutex_t *mtx;
- char *file;
- int line;
+eMmutex_destroy(eMmutex_t *mtx, char *file, int line)
{
if (mutex_debug & 1)
fprintf(mutex_file,
diff --git a/sbin/ipf/libipf/nametokva.c b/sbin/ipf/libipf/nametokva.c
index 6b86657eba97..06635238165c 100644
--- a/sbin/ipf/libipf/nametokva.c
+++ b/sbin/ipf/libipf/nametokva.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/nat_setgroupmap.c b/sbin/ipf/libipf/nat_setgroupmap.c
index 8a4b461c5a88..97a5211688c3 100644
--- a/sbin/ipf/libipf/nat_setgroupmap.c
+++ b/sbin/ipf/libipf/nat_setgroupmap.c
@@ -1,13 +1,9 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*/
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
#include "ipf.h"
diff --git a/sbin/ipf/libipf/ntomask.c b/sbin/ipf/libipf/ntomask.c
index 0947784106ba..3664d255254c 100644
--- a/sbin/ipf/libipf/ntomask.c
+++ b/sbin/ipf/libipf/ntomask.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/optname.c b/sbin/ipf/libipf/optname.c
index 1523d31b710a..93bf276c7818 100644
--- a/sbin/ipf/libipf/optname.c
+++ b/sbin/ipf/libipf/optname.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/optprint.c b/sbin/ipf/libipf/optprint.c
index f18ad00dba2a..a70ed28d611f 100644
--- a/sbin/ipf/libipf/optprint.c
+++ b/sbin/ipf/libipf/optprint.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/optprintv6.c b/sbin/ipf/libipf/optprintv6.c
index d043ff774031..e53a879fa439 100644
--- a/sbin/ipf/libipf/optprintv6.c
+++ b/sbin/ipf/libipf/optprintv6.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/optvalue.c b/sbin/ipf/libipf/optvalue.c
index 370a9d272ed2..44635b04a13a 100644
--- a/sbin/ipf/libipf/optvalue.c
+++ b/sbin/ipf/libipf/optvalue.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/parseipfexpr.c b/sbin/ipf/libipf/parseipfexpr.c
index 215e43b2978d..be86456e143b 100644
--- a/sbin/ipf/libipf/parseipfexpr.c
+++ b/sbin/ipf/libipf/parseipfexpr.c
@@ -75,7 +75,7 @@ parseipfexpr(char *line, char **errorptr)
for (ops = strtok(temp, ";"); ops != NULL; ops = strtok(NULL, ";")) {
arg = strchr(ops, '=');
if ((arg < ops + 2) || (arg == NULL)) {
- error = "bad 'arg' vlaue";
+ error = "bad 'arg' value";
goto parseerror;
}
@@ -93,11 +93,7 @@ parseipfexpr(char *line, char **errorptr)
break;
}
if (e->ipoe_word == NULL) {
- error = malloc(32);
- if (error != NULL) {
- snprintf(error, sizeof(error), "keyword (%.10s) not found",
- ops);
- }
+ asprintf(&error, "keyword (%.10s) not found", ops);
goto parseerror;
}
diff --git a/sbin/ipf/libipf/poolio.c b/sbin/ipf/libipf/poolio.c
index 765d37fae350..f12120fd5467 100644
--- a/sbin/ipf/libipf/poolio.c
+++ b/sbin/ipf/libipf/poolio.c
@@ -28,10 +28,7 @@ pool_open(void)
}
int
-pool_ioctl(iocfunc, cmd, ptr)
- ioctlfunc_t iocfunc;
- ioctlcmd_t cmd;
- void *ptr;
+pool_ioctl(ioctlfunc_t iocfunc, ioctlcmd_t cmd, void *ptr)
{
return (*iocfunc)(poolfd, cmd, ptr);
}
diff --git a/sbin/ipf/libipf/portname.c b/sbin/ipf/libipf/portname.c
index f567b26fc3fd..034c8255537d 100644
--- a/sbin/ipf/libipf/portname.c
+++ b/sbin/ipf/libipf/portname.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/print_toif.c b/sbin/ipf/libipf/print_toif.c
index 438207bf7e72..2dcaec7394f9 100644
--- a/sbin/ipf/libipf/print_toif.c
+++ b/sbin/ipf/libipf/print_toif.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printactiveaddr.c b/sbin/ipf/libipf/printactiveaddr.c
index 66b5b00aaf98..70deafa345e0 100644
--- a/sbin/ipf/libipf/printactiveaddr.c
+++ b/sbin/ipf/libipf/printactiveaddr.c
@@ -9,9 +9,6 @@
#include "ipf.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id: printactiveaddr.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $";
-#endif
void
diff --git a/sbin/ipf/libipf/printactivenat.c b/sbin/ipf/libipf/printactivenat.c
index 222f85a5818b..ba792d3b2be0 100644
--- a/sbin/ipf/libipf/printactivenat.c
+++ b/sbin/ipf/libipf/printactivenat.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -11,9 +10,6 @@
#include "ipf.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
static int proto_opened = 0;
diff --git a/sbin/ipf/libipf/printaps.c b/sbin/ipf/libipf/printaps.c
index 00e4db4cb2b8..df27c48b72c8 100644
--- a/sbin/ipf/libipf/printaps.c
+++ b/sbin/ipf/libipf/printaps.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -12,9 +11,6 @@
#include "kmem.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
void
diff --git a/sbin/ipf/libipf/printbuf.c b/sbin/ipf/libipf/printbuf.c
index 3a9281217f6a..0fef3c5de854 100644
--- a/sbin/ipf/libipf/printbuf.c
+++ b/sbin/ipf/libipf/printbuf.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printdstl_live.c b/sbin/ipf/libipf/printdstl_live.c
index 088448e6656d..72cb75a832c9 100644
--- a/sbin/ipf/libipf/printdstl_live.c
+++ b/sbin/ipf/libipf/printdstl_live.c
@@ -40,6 +40,9 @@ printdstl_live( ippool_dst_t *d, int fd, char *name, int opts,
if ((d->ipld_flags & IPHASH_DELETE) != 0)
PRINTF("# ");
+ if (opts & OPT_SAVEOUT)
+ PRINTF("{\n");
+
if ((opts & OPT_DEBUG) == 0)
PRINTF("\t{");
diff --git a/sbin/ipf/libipf/printdstlist.c b/sbin/ipf/libipf/printdstlist.c
index 2cf41ffe414c..497d7004c94c 100644
--- a/sbin/ipf/libipf/printdstlist.c
+++ b/sbin/ipf/libipf/printdstlist.c
@@ -42,6 +42,8 @@ printdstlist( ippool_dst_t *pp, copyfunc_t copyfunc, char *name, int opts,
return (NULL);
}
+ if (opts & OPT_SAVEOUT)
+ PRINTF("\t");
node = printdstlistnode(n, bcopywrap, opts, fields);
free(n);
diff --git a/sbin/ipf/libipf/printdstlistdata.c b/sbin/ipf/libipf/printdstlistdata.c
index 7940d2ae021b..546bf35cabf6 100644
--- a/sbin/ipf/libipf/printdstlistdata.c
+++ b/sbin/ipf/libipf/printdstlistdata.c
@@ -11,8 +11,7 @@
void
printdstlistdata( ippool_dst_t *pool, int opts)
{
-
- if ((opts & OPT_DEBUG) == 0) {
+ if ((opts & OPT_DEBUG) == 0 || opts & OPT_SAVEOUT) {
if ((pool->ipld_flags & IPDST_DELETE) != 0)
PRINTF("# ");
PRINTF("pool ");
@@ -24,7 +23,7 @@ printdstlistdata( ippool_dst_t *pool, int opts)
printunit(pool->ipld_unit);
- if ((opts & OPT_DEBUG) == 0) {
+ if ((opts & OPT_DEBUG) == 0 || opts & OPT_SAVEOUT) {
PRINTF("/dstlist (name %s;", pool->ipld_name);
if (pool->ipld_policy != IPLDP_NONE) {
PRINTF(" policy ");
diff --git a/sbin/ipf/libipf/printfr.c b/sbin/ipf/libipf/printfr.c
index 2ffb65f69207..f507c8065c82 100644
--- a/sbin/ipf/libipf/printfr.c
+++ b/sbin/ipf/libipf/printfr.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printfraginfo.c b/sbin/ipf/libipf/printfraginfo.c
index fcafdde707be..4693e9335ffb 100644
--- a/sbin/ipf/libipf/printfraginfo.c
+++ b/sbin/ipf/libipf/printfraginfo.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -14,7 +13,6 @@
void
printfraginfo(char *prefix, struct ipfr *ifr)
{
- frentry_t fr;
int family;
PRINTF("%s", prefix);
@@ -25,14 +23,8 @@ printfraginfo(char *prefix, struct ipfr *ifr)
PRINTF("inet");
family = AF_INET;
}
- fr.fr_flags = 0xffffffff;
PRINTF(" %s -> ", hostname(family, &ifr->ipfr_src));
-/*
- if (kmemcpy((char *)&fr, (u_long)ifr->ipfr_rule,
- sizeof(fr)) == -1)
- return;
- */
PRINTF("%s id %x ttl %lu pr %d pkts %u bytes %u seen0 %d ref %d\n",
hostname(family, &ifr->ipfr_dst), ifr->ipfr_id,
ifr->ipfr_ttl, ifr->ipfr_p, ifr->ipfr_pkts, ifr->ipfr_bytes,
diff --git a/sbin/ipf/libipf/printhash.c b/sbin/ipf/libipf/printhash.c
index 2db6ace81256..f5ebb57a1c33 100644
--- a/sbin/ipf/libipf/printhash.c
+++ b/sbin/ipf/libipf/printhash.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printhash_live.c b/sbin/ipf/libipf/printhash_live.c
index 3caaa5e022fe..427daa18316b 100644
--- a/sbin/ipf/libipf/printhash_live.c
+++ b/sbin/ipf/libipf/printhash_live.c
@@ -26,7 +26,9 @@ printhash_live(iphtable_t *hp, int fd, char *name, int opts, wordtab_t *fields)
if ((hp->iph_flags & IPHASH_DELETE) != 0)
PRINTF("# ");
- if ((opts & OPT_DEBUG) == 0)
+ if (opts & OPT_SAVEOUT)
+ PRINTF("{\n");
+ else if ((opts & OPT_DEBUG) == 0)
PRINTF("\t{");
obj.ipfo_rev = IPFILTER_VERSION;
@@ -50,6 +52,8 @@ printhash_live(iphtable_t *hp, int fd, char *name, int opts, wordtab_t *fields)
last = 1;
if (bcmp(&zero, &entry, sizeof(zero)) == 0)
break;
+ if (opts & OPT_SAVEOUT)
+ PRINTF("\t");
(void) printhashnode(hp, &entry, bcopywrap, opts, fields);
printed++;
}
@@ -59,7 +63,10 @@ printhash_live(iphtable_t *hp, int fd, char *name, int opts, wordtab_t *fields)
if (printed == 0)
putchar(';');
- if ((opts & OPT_DEBUG) == 0)
+ if ((opts & OPT_DEBUG) == 0 || (opts & OPT_SAVEOUT))
PRINTF(" };\n");
+
+ (void) ioctl(fd,SIOCIPFDELTOK, &iter.ili_key);
+
return (hp->iph_next);
}
diff --git a/sbin/ipf/libipf/printhashdata.c b/sbin/ipf/libipf/printhashdata.c
index 690243d63f1e..6fa62e67556d 100644
--- a/sbin/ipf/libipf/printhashdata.c
+++ b/sbin/ipf/libipf/printhashdata.c
@@ -12,7 +12,11 @@ void
printhashdata(iphtable_t *hp, int opts)
{
- if ((opts & OPT_DEBUG) == 0) {
+ if (opts & OPT_SAVEOUT) {
+ if ((hp->iph_flags & IPHASH_DELETE) == IPHASH_DELETE)
+ PRINTF("# ");
+ PRINTF("pool ");
+ } else if ((opts & OPT_DEBUG) == 0) {
if ((hp->iph_type & IPHASH_ANON) == IPHASH_ANON)
PRINTF("# 'anonymous' table refs %d\n", hp->iph_ref);
if ((hp->iph_flags & IPHASH_DELETE) == IPHASH_DELETE)
@@ -37,6 +41,8 @@ printhashdata(iphtable_t *hp, int opts)
}
PRINTF(" role=");
} else {
+ if ((hp->iph_flags & IPHASH_DELETE) == IPHASH_DELETE)
+ PRINTF("# ");
PRINTF("Hash Table %s: %s",
ISDIGIT(*hp->iph_name) ? "Number" : "Name",
hp->iph_name);
@@ -48,7 +54,16 @@ printhashdata(iphtable_t *hp, int opts)
printunit(hp->iph_unit);
- if ((opts & OPT_DEBUG) == 0) {
+ if ((opts & OPT_SAVEOUT)) {
+ if ((hp->iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP)
+ PRINTF("/hash");
+ PRINTF("(%s \"%s\"; size %lu;",
+ ISDIGIT(*hp->iph_name) ? "number" : "name",
+ hp->iph_name, (u_long)hp->iph_size);
+ if (hp->iph_seed != 0)
+ PRINTF(" seed %lu;", hp->iph_seed);
+ PRINTF(")\n", hp->iph_seed);
+ } else if ((opts & OPT_DEBUG) == 0) {
if ((hp->iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP)
PRINTF(" type=hash");
PRINTF(" %s=%s size=%lu",
diff --git a/sbin/ipf/libipf/printhashnode.c b/sbin/ipf/libipf/printhashnode.c
index 777083d456ac..b3c7140c84d3 100644
--- a/sbin/ipf/libipf/printhashnode.c
+++ b/sbin/ipf/libipf/printhashnode.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printhostmap.c b/sbin/ipf/libipf/printhostmap.c
index bdb15d84995f..bd8b71ceec16 100644
--- a/sbin/ipf/libipf/printhostmap.c
+++ b/sbin/ipf/libipf/printhostmap.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printhostmask.c b/sbin/ipf/libipf/printhostmask.c
index f5495458fa04..7f607dbedcfc 100644
--- a/sbin/ipf/libipf/printhostmask.c
+++ b/sbin/ipf/libipf/printhostmask.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printifname.c b/sbin/ipf/libipf/printifname.c
index e6a38a8692ad..4f19c30aef2a 100644
--- a/sbin/ipf/libipf/printifname.c
+++ b/sbin/ipf/libipf/printifname.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printip.c b/sbin/ipf/libipf/printip.c
index 7cf55f04afec..e4249541f946 100644
--- a/sbin/ipf/libipf/printip.c
+++ b/sbin/ipf/libipf/printip.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printlog.c b/sbin/ipf/libipf/printlog.c
index a04842530504..c9faf40595c9 100644
--- a/sbin/ipf/libipf/printlog.c
+++ b/sbin/ipf/libipf/printlog.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printmask.c b/sbin/ipf/libipf/printmask.c
index 1130c5190f58..bdb28d8ee4a2 100644
--- a/sbin/ipf/libipf/printmask.c
+++ b/sbin/ipf/libipf/printmask.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printnat.c b/sbin/ipf/libipf/printnat.c
index e778d9393d9a..0b032955c8d8 100644
--- a/sbin/ipf/libipf/printnat.c
+++ b/sbin/ipf/libipf/printnat.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -12,9 +11,6 @@
#include "kmem.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
/*
diff --git a/sbin/ipf/libipf/printnataddr.c b/sbin/ipf/libipf/printnataddr.c
index ee00b5b14d6c..e6003f0b076b 100644
--- a/sbin/ipf/libipf/printnataddr.c
+++ b/sbin/ipf/libipf/printnataddr.c
@@ -10,9 +10,6 @@
#include "kmem.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id: printnataddr.c,v 1.4.2.2 2012/07/22 08:04:24 darren_r Exp $";
-#endif
void
diff --git a/sbin/ipf/libipf/printpacket.c b/sbin/ipf/libipf/printpacket.c
index 9444f93fe840..f8407c3a3102 100644
--- a/sbin/ipf/libipf/printpacket.c
+++ b/sbin/ipf/libipf/printpacket.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -14,12 +13,12 @@
# define IP_OFFMASK 0x3fff
#endif
-
void
printpacket(int dir, mb_t *m)
{
u_short len, off;
tcphdr_t *tcp;
+ uint16_t tcpflags;
ip_t *ip;
ip = MTOD(m, ip_t *);
@@ -83,24 +82,27 @@ printpacket(int dir, mb_t *m)
if (!(off & IP_OFFMASK)) {
if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP)
PRINTF(",%d", ntohs(tcp->th_dport));
- if ((ip->ip_p == IPPROTO_TCP) && (tcp->th_flags != 0)) {
+ if ((ip->ip_p == IPPROTO_TCP) &&
+ ((tcpflags = __tcp_get_flags(tcp)) != 0)) {
putchar(' ');
- if (tcp->th_flags & TH_FIN)
+ if (tcpflags & TH_FIN)
putchar('F');
- if (tcp->th_flags & TH_SYN)
+ if (tcpflags & TH_SYN)
putchar('S');
- if (tcp->th_flags & TH_RST)
+ if (tcpflags & TH_RST)
putchar('R');
- if (tcp->th_flags & TH_PUSH)
+ if (tcpflags & TH_PUSH)
putchar('P');
- if (tcp->th_flags & TH_ACK)
+ if (tcpflags & TH_ACK)
putchar('A');
- if (tcp->th_flags & TH_URG)
+ if (tcpflags & TH_URG)
putchar('U');
- if (tcp->th_flags & TH_ECN)
+ if (tcpflags & TH_ECN)
putchar('E');
- if (tcp->th_flags & TH_CWR)
- putchar('C');
+ if (tcpflags & TH_CWR)
+ putchar('W');
+ if (tcpflags & TH_AE)
+ putchar('e');
}
}
diff --git a/sbin/ipf/libipf/printpacket6.c b/sbin/ipf/libipf/printpacket6.c
index 42d1a36b96b3..c015eabdada5 100644
--- a/sbin/ipf/libipf/printpacket6.c
+++ b/sbin/ipf/libipf/printpacket6.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printpool.c b/sbin/ipf/libipf/printpool.c
index b3bdd02b64b4..86f389c6cbaf 100644
--- a/sbin/ipf/libipf/printpool.c
+++ b/sbin/ipf/libipf/printpool.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printpool_live.c b/sbin/ipf/libipf/printpool_live.c
index 324deb629d0b..9bb19f2888b4 100644
--- a/sbin/ipf/libipf/printpool_live.c
+++ b/sbin/ipf/libipf/printpool_live.c
@@ -9,7 +9,7 @@
#include "netinet/ipl.h"
-ip_pool_t *
+void
printpool_live(ip_pool_t *pool, int fd, char *name, int opts,
wordtab_t *fields)
{
@@ -19,14 +19,16 @@ printpool_live(ip_pool_t *pool, int fd, char *name, int opts,
ipfobj_t obj;
if ((name != NULL) && strncmp(name, pool->ipo_name, FR_GROUPLEN))
- return (pool->ipo_next);
+ return;
if (fields == NULL)
printpooldata(pool, opts);
if ((pool->ipo_flags & IPOOL_DELETE) != 0)
PRINTF("# ");
- if ((opts & OPT_DEBUG) == 0)
+ if (opts & OPT_SAVEOUT)
+ PRINTF("{\n");
+ else if ((opts & OPT_DEBUG) == 0)
PRINTF("\t{");
obj.ipfo_rev = IPFILTER_VERSION;
@@ -48,9 +50,13 @@ printpool_live(ip_pool_t *pool, int fd, char *name, int opts,
while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) {
if (entry.ipn_next == NULL)
last = 1;
+ if (opts & OPT_SAVEOUT)
+ PRINTF("\t");
(void) printpoolnode(&entry, opts, fields);
if ((opts & OPT_DEBUG) == 0)
putchar(';');
+ if (opts & OPT_SAVEOUT)
+ PRINTF("\n");
printed++;
}
}
@@ -58,10 +64,12 @@ printpool_live(ip_pool_t *pool, int fd, char *name, int opts,
if (printed == 0)
putchar(';');
- if ((opts & OPT_DEBUG) == 0)
+ if (opts & OPT_SAVEOUT)
+ PRINTF("};\n");
+ else if ((opts & OPT_DEBUG) == 0)
PRINTF(" };\n");
(void) ioctl(fd,SIOCIPFDELTOK, &iter.ili_key);
- return (pool->ipo_next);
+ return;
}
diff --git a/sbin/ipf/libipf/printpooldata.c b/sbin/ipf/libipf/printpooldata.c
index ce754f9a89bb..b203522734be 100644
--- a/sbin/ipf/libipf/printpooldata.c
+++ b/sbin/ipf/libipf/printpooldata.c
@@ -12,7 +12,11 @@ void
printpooldata(ip_pool_t *pool, int opts)
{
- if ((opts & OPT_DEBUG) == 0) {
+ if (opts & OPT_SAVEOUT) {
+ if ((pool->ipo_flags & IPOOL_DELETE) != 0)
+ PRINTF("# ");
+ PRINTF("pool ");
+ } else if ((opts & OPT_DEBUG) == 0) {
if ((pool->ipo_flags & IPOOL_ANON) != 0)
PRINTF("# 'anonymous' tree %s\n", pool->ipo_name);
if ((pool->ipo_flags & IPOOL_DELETE) != 0)
@@ -32,7 +36,11 @@ printpooldata(ip_pool_t *pool, int opts)
printunit(pool->ipo_unit);
- if ((opts & OPT_DEBUG) == 0) {
+ if ((opts & OPT_SAVEOUT)) {
+ PRINTF("/tree (%s \"\%s\";)\n",
+ (!*pool->ipo_name || ISDIGIT(*pool->ipo_name)) ? \
+ "number" : "name", pool->ipo_name);
+ } else if ((opts & OPT_DEBUG) == 0) {
PRINTF(" type=tree %s=%s\n",
(!*pool->ipo_name || ISDIGIT(*pool->ipo_name)) ? \
"number" : "name", pool->ipo_name);
diff --git a/sbin/ipf/libipf/printpoolnode.c b/sbin/ipf/libipf/printpoolnode.c
index 023aca47c7ff..8cec3fcae757 100644
--- a/sbin/ipf/libipf/printpoolnode.c
+++ b/sbin/ipf/libipf/printpoolnode.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printportcmp.c b/sbin/ipf/libipf/printportcmp.c
index 556a3ac2fb0b..2e3ee471e3e2 100644
--- a/sbin/ipf/libipf/printportcmp.c
+++ b/sbin/ipf/libipf/printportcmp.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printproto.c b/sbin/ipf/libipf/printproto.c
index 7bc4952b3b7c..3d4c881ff6d0 100644
--- a/sbin/ipf/libipf/printproto.c
+++ b/sbin/ipf/libipf/printproto.c
@@ -7,9 +7,6 @@
#include "ipf.h"
-#if !defined(lint)
-static const char rcsid[] = "@(#)$Id$";
-#endif
void
diff --git a/sbin/ipf/libipf/printsbuf.c b/sbin/ipf/libipf/printsbuf.c
index c9c89ef6eb01..4d3de8468dee 100644
--- a/sbin/ipf/libipf/printsbuf.c
+++ b/sbin/ipf/libipf/printsbuf.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printstate.c b/sbin/ipf/libipf/printstate.c
index 1f135231ff58..3b6f6c3b07d4 100644
--- a/sbin/ipf/libipf/printstate.c
+++ b/sbin/ipf/libipf/printstate.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/printtcpflags.c b/sbin/ipf/libipf/printtcpflags.c
index d134fb4a3120..349e18be127e 100644
--- a/sbin/ipf/libipf/printtcpflags.c
+++ b/sbin/ipf/libipf/printtcpflags.c
@@ -4,10 +4,10 @@
void
printtcpflags(u_32_t tcpf, u_32_t tcpfm)
{
- u_char *t;
+ uint16_t *t;
char *s;
- if (tcpf & ~TCPF_ALL) {
+ if (tcpf & ~TH_FLAGS) {
PRINTF("0x%x", tcpf);
} else {
for (s = flagset, t = flags; *s; s++, t++) {
@@ -18,7 +18,7 @@ printtcpflags(u_32_t tcpf, u_32_t tcpfm)
if (tcpfm) {
(void)putchar('/');
- if (tcpfm & ~TCPF_ALL) {
+ if (tcpfm & ~TH_FLAGS) {
PRINTF("0x%x", tcpfm);
} else {
for (s = flagset, t = flags; *s; s++, t++)
diff --git a/sbin/ipf/libipf/printtunable.c b/sbin/ipf/libipf/printtunable.c
index b748efd5129a..8cd212a2b8b4 100644
--- a/sbin/ipf/libipf/printtunable.c
+++ b/sbin/ipf/libipf/printtunable.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/remove_hash.c b/sbin/ipf/libipf/remove_hash.c
index 3af2a3f427d7..c6778e372224 100644
--- a/sbin/ipf/libipf/remove_hash.c
+++ b/sbin/ipf/libipf/remove_hash.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/remove_hashnode.c b/sbin/ipf/libipf/remove_hashnode.c
index f6679d6acd95..95fada0a81e5 100644
--- a/sbin/ipf/libipf/remove_hashnode.c
+++ b/sbin/ipf/libipf/remove_hashnode.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/remove_pool.c b/sbin/ipf/libipf/remove_pool.c
index 0f67368b2b33..21d01fdbc0a4 100644
--- a/sbin/ipf/libipf/remove_pool.c
+++ b/sbin/ipf/libipf/remove_pool.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/remove_poolnode.c b/sbin/ipf/libipf/remove_poolnode.c
index b3c39aa21ec8..2d8caa158604 100644
--- a/sbin/ipf/libipf/remove_poolnode.c
+++ b/sbin/ipf/libipf/remove_poolnode.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/resetlexer.c b/sbin/ipf/libipf/resetlexer.c
index e6fbbce4ccc0..307ed657a46a 100644
--- a/sbin/ipf/libipf/resetlexer.c
+++ b/sbin/ipf/libipf/resetlexer.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/rwlock_emul.c b/sbin/ipf/libipf/rwlock_emul.c
index e15d9610887f..ec8a61c5cff2 100644
--- a/sbin/ipf/libipf/rwlock_emul.c
+++ b/sbin/ipf/libipf/rwlock_emul.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/tcp_flags.c b/sbin/ipf/libipf/tcp_flags.c
index e652819bebb1..9247933ee85b 100644
--- a/sbin/ipf/libipf/tcp_flags.c
+++ b/sbin/ipf/libipf/tcp_flags.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2000-2004 by Darren Reed.
@@ -10,13 +9,13 @@
#include "ipf.h"
-extern char flagset[];
-extern u_char flags[];
+extern char flagset[];
+extern uint16_t flags[];
-u_char tcp_flags(char *flgs, u_char *mask, int linenum)
+uint16_t tcp_flags(char *flgs, uint16_t *mask, int linenum)
{
- u_char tcpf = 0, tcpfm = 0;
+ uint16_t tcpf = 0, tcpfm = 0;
char *s;
s = strchr(flgs, '/');
@@ -38,9 +37,9 @@ u_char tcp_flags(char *flgs, u_char *mask, int linenum)
if (!tcpfm) {
if (tcpf == TH_SYN)
- tcpfm = 0xff & ~(TH_ECN|TH_CWR);
+ tcpfm = TH_FLAGS & ~(TH_ECN|TH_CWR);
else
- tcpfm = 0xff & ~(TH_ECN);
+ tcpfm = TH_FLAGS & ~(TH_ECN);
}
*mask = tcpfm;
return (tcpf);
diff --git a/sbin/ipf/libipf/tcpflags.c b/sbin/ipf/libipf/tcpflags.c
index ef2950836393..46b64e96deda 100644
--- a/sbin/ipf/libipf/tcpflags.c
+++ b/sbin/ipf/libipf/tcpflags.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -20,14 +19,17 @@
#ifndef TH_CWR
# define TH_CWR 0x80
#endif
+#ifndef TH_AE
+# define TH_AE 0x100
+#endif
-extern char flagset[];
-extern u_char flags[];
+extern char flagset[];
+extern uint16_t flags[];
-u_char tcpflags(char *flgs)
+uint16_t tcpflags(char *flgs)
{
- u_char tcpf = 0;
+ uint16_t tcpf = 0;
char *s, *t;
for (s = flgs; *s; s++) {
diff --git a/sbin/ipf/libipf/tcpoptnames.c b/sbin/ipf/libipf/tcpoptnames.c
index 24e41bb18b8b..3044f939438d 100644
--- a/sbin/ipf/libipf/tcpoptnames.c
+++ b/sbin/ipf/libipf/tcpoptnames.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/v6ionames.c b/sbin/ipf/libipf/v6ionames.c
index 9f1207f13431..485af14f7863 100644
--- a/sbin/ipf/libipf/v6ionames.c
+++ b/sbin/ipf/libipf/v6ionames.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/v6optvalue.c b/sbin/ipf/libipf/v6optvalue.c
index c0d13bc51d85..5d09ad1b584d 100644
--- a/sbin/ipf/libipf/v6optvalue.c
+++ b/sbin/ipf/libipf/v6optvalue.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipf/libipf/var.c b/sbin/ipf/libipf/var.c
index d3a03b6e46d7..0ccc888b3246 100644
--- a/sbin/ipf/libipf/var.c
+++ b/sbin/ipf/libipf/var.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
@@ -24,8 +23,7 @@ static variable_t *find_var(char *);
static char *expand_string(char *, int);
-static variable_t *find_var(name)
- char *name;
+static variable_t *find_var(char *name)
{
variable_t *v;
diff --git a/sbin/ipf/libipf/verbose.c b/sbin/ipf/libipf/verbose.c
index 47988c084516..cfa22083ed02 100644
--- a/sbin/ipf/libipf/verbose.c
+++ b/sbin/ipf/libipf/verbose.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/*
* Copyright (C) 2012 by Darren Reed.
diff --git a/sbin/ipfw/Makefile b/sbin/ipfw/Makefile
index c0b7e56226c4..418c0f613741 100644
--- a/sbin/ipfw/Makefile
+++ b/sbin/ipfw/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=ipfw
@@ -19,6 +17,9 @@ CFLAGS+=-DPF
LIBADD= jail util
MAN= ipfw.8
+HAS_TESTS=
+SUBDIR.${MK_TESTS}= tests
+
.include <bsd.prog.mk>
CWARNFLAGS+= -Wno-cast-align
diff --git a/sbin/ipfw/Makefile.depend b/sbin/ipfw/Makefile.depend
index 5700139d85dd..774db391da26 100644
--- a/sbin/ipfw/Makefile.depend
+++ b/sbin/ipfw/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
@@ -10,6 +8,7 @@ DIRDEPS = \
lib/libalias/libalias \
lib/libc \
lib/libcompiler_rt \
+ lib/libjail \
lib/libutil \
diff --git a/sbin/ipfw/altq.c b/sbin/ipfw/altq.c
index 081262fd3d80..edd6341acd23 100644
--- a/sbin/ipfw/altq.c
+++ b/sbin/ipfw/altq.c
@@ -17,8 +17,6 @@
*
* NEW command line interface for IP firewall facility
*
- * $FreeBSD$
- *
* altq interface
*/
diff --git a/sbin/ipfw/dummynet.c b/sbin/ipfw/dummynet.c
index 88367694a404..6714b2af3124 100644
--- a/sbin/ipfw/dummynet.c
+++ b/sbin/ipfw/dummynet.c
@@ -17,14 +17,12 @@
*
* This software is provided ``AS IS'' without any warranties of any kind.
*
- * $FreeBSD$
- *
* dummynet support
*/
#define NEW_AQM
#include <sys/limits.h>
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/socket.h>
/* XXX there are several sysctl leftover here */
#include <sys/sysctl.h>
@@ -473,7 +471,7 @@ print_flowset_parms(struct dn_fs *fs, char *prefix)
{
int l;
char qs[30];
- char plr[30];
+ char plr[40];
char red[200]; /* Display RED parameters */
l = fs->qsize;
@@ -484,9 +482,17 @@ print_flowset_parms(struct dn_fs *fs, char *prefix)
sprintf(qs, "%d B", l);
} else
sprintf(qs, "%3d sl.", l);
- if (fs->plr)
- sprintf(plr, "plr %f", 1.0 * fs->plr / (double)(0x7fffffff));
- else
+ if (fs->plr[0] || fs->plr[1]) {
+ if (fs->plr[1] == 0)
+ sprintf(plr, "plr %f",
+ 1.0 * fs->plr[0] / (double)(0x7fffffff));
+ else
+ sprintf(plr, "plr %f,%f,%f,%f",
+ 1.0 * fs->plr[0] / (double)(0x7fffffff),
+ 1.0 * fs->plr[1] / (double)(0x7fffffff),
+ 1.0 * fs->plr[2] / (double)(0x7fffffff),
+ 1.0 * fs->plr[3] / (double)(0x7fffffff));
+ } else
plr[0] = '\0';
if (fs->flags & DN_IS_RED) { /* RED parameters */
@@ -1395,7 +1401,7 @@ ipfw_config_pipe(int ac, char **av)
*/
if (p)
p->bandwidth = -1;
- for (j = 0; j < sizeof(fs->par)/sizeof(fs->par[0]); j++)
+ for (j = 0; j < nitems(fs->par); j++)
fs->par[j] = -1;
while (ac > 0) {
double d;
@@ -1410,13 +1416,27 @@ ipfw_config_pipe(int ac, char **av)
case TOK_PLR:
NEED(fs, "plr is only for pipes");
- NEED1("plr needs argument 0..1\n");
- d = strtod(av[0], NULL);
- if (d > 1)
- d = 1;
- else if (d < 0)
- d = 0;
- fs->plr = (int)(d*0x7fffffff);
+ NEED1("plr needs one or four arguments 0..1\n");
+ if ((end = strsep(&av[0], ","))) {
+ d = strtod(end, NULL);
+ d = (d < 0) ? 0 : (d <= 1) ? d : 1;
+ fs->plr[0] = (int)(d*0x7fffffff);
+ }
+ if ((end = strsep(&av[0], ","))) {
+ d = strtod(end, NULL);
+ d = (d < 0) ? 0 : (d <= 1) ? d : 1;
+ fs->plr[1] = (int)(d*0x7fffffff);
+ }
+ if ((end = strsep(&av[0], ","))) {
+ d = strtod(end, NULL);
+ d = (d < 0) ? 0 : (d <= 1) ? d : 1;
+ fs->plr[2] = (int)(d*0x7fffffff);
+ }
+ if ((end = strsep(&av[0], ","))) {
+ d = strtod(end, NULL);
+ d = (d < 0) ? 0 : (d <= 1) ? d : 1;
+ fs->plr[3] = (int)(d*0x7fffffff);
+ }
ac--; av++;
break;
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index db8a11525b4d..ddfdc35ce651 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,13 +1,11 @@
.\"
-.\" $FreeBSD$
-.\"
-.Dd June 4, 2022
+.Dd April 18, 2025
.Dt IPFW 8
.Os
.Sh NAME
.Nm ipfw , dnctl
.Nd User interface for firewall, traffic shaper, packet scheduler,
-in-kernel NAT.
+in-kernel NAT.\&
.Sh SYNOPSIS
.Ss FIREWALL CONFIGURATION
.Nm
@@ -42,10 +40,10 @@ in-kernel NAT.
.Ss SYSCTL SHORTCUTS
.Nm
.Cm enable
-.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
+.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive | skipto_cache
.Nm
.Cm disable
-.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive
+.Brq Cm firewall | altq | one_pass | debug | verbose | dyn_keepalive | skipto_cache
.Ss LOOKUP TABLES
.Nm
.Oo Cm set Ar N Oc Cm table Ar name Cm create Ar create-options
@@ -173,6 +171,8 @@ in-kernel NAT.
.Nm
.Cm internal iflist
.Nm
+.Cm internal monitor Op Ar filter-comment
+.Nm
.Cm internal talist
.Nm
.Cm internal vlist
@@ -333,8 +333,8 @@ When listing, show dynamic rules in addition to static ones.
When listing, show only dynamic states.
When deleting, delete only dynamic states.
.It Fl f
-Run without prompting for confirmation for commands that can cause problems if misused,
-i.e.,
+Run without prompting for confirmation for commands that can cause problems
+if misused, i.e.,
.Cm flush .
If there is no tty associated with the process, this is implied.
The
@@ -579,7 +579,7 @@ The format of firewall rules is the following:
.Op Cm set Ar set_number
.Op Cm prob Ar match_probability
.Ar action
-.Op Cm log Op Cm logamount Ar number
+.Op Cm log Op log_opts
.Op Cm altq Ar queue
.Oo
.Bro Cm tag | untag
@@ -696,8 +696,10 @@ side effects.
.It Cm log Op Cm logamount Ar number
Packets matching a rule with the
.Cm log
-keyword will be made available for logging in two ways:
-if the sysctl variable
+keyword will be made available for logging.
+Unless per-rule log destination is specified by
+.Cm logdst Ar logdst_spec
+option (see below), packets are logged in two ways: if the sysctl variable
.Va net.inet.ip.fw.verbose
is set to 0 (default), one can use
.Xr bpf 4
@@ -745,6 +747,47 @@ command.
Note: logging is done after all other packet matching conditions
have been successfully verified, and before performing the final
action (accept, deny, etc.) on the packet.
+.It Cm log Oo
+.Cm logamount Ar number
+.Oc Cm logdst Ar logdst_spec
+.Ar logdst_spec
+is a comma-separated list of log destinations for logging
+packets matching the rule.
+Destinations supported are:
+.Bl -tag -width indent
+.It Ar syslog
+Logs a packet to
+.Xr syslogd 8
+with a
+.Dv LOG_SECURITY
+facility.
+.It Ar ipfw0
+Logs a packet to the
+.Li ipfw0
+pseudo interface.
+.It Ar rtsock
+Logs a packet to the
+.Xr route 4
+socket.
+See the comments of
+.Fn ipfw_log_rtsock
+in ipfw source code for more
+information on the message's structure.
+.El
+.Pp
+Note:
+.Cm logamount
+limits a number of logging events rather than packets being logged.
+I.e. A packet matching a rule with
+.Bd -ragged -offset indent
+ ...
+.Cm log logamount
+100
+.Cm logdst
+syslog,ipfw0 ...
+.Ed
+.Pp
+will log upto 50 packets.
.It Cm tag Ar number
When a packet matches a rule with the
.Cm tag
@@ -759,7 +802,7 @@ A packet can have multiple tags at the same time.
Tags are "sticky", meaning once a tag is applied to a packet by a
matching rule it exists until explicit removal.
Tags are kept with the packet everywhere within the kernel, but are
-lost when packet leaves the kernel, for example, on transmitting
+lost when the packet leaves the kernel, for example, on transmitting
packet out to the network or sending packet to a
.Xr divert 4
socket.
@@ -793,6 +836,27 @@ keyword, the tag with the number
is searched among the tags attached to this packet and,
if found, removed from it.
Other tags bound to packet, if present, are left untouched.
+.It Cm setmark Ar value | tablearg
+When a packet matches a rule with the
+.Cm setmark
+keyword, a 32-bit numeric mark is assigned to the packet.
+The mark is an extension to the tags.
+As tags, mark is "sticky" so the value is kept the same within the kernel and
+is lost when the packet leaves the kernel.
+Unlike tags, mark can be matched as a lookup table key or compared with bitwise
+mask applied against another value.
+Each packet can have only one mark, so
+.Cm setmark
+always overwrites the previous mark value.
+.Pp
+The initial mark value is 0.
+To check the current mark value, use the
+.Cm mark
+rule option.
+Mark
+.Ar value
+can be entered as decimal or hexadecimal (if prefixed by 0x), and they
+are always printed as hexadecimal.
.It Cm altq Ar queue
When a packet matches a rule with the
.Cm altq
@@ -932,7 +996,7 @@ Pass packet to a
nat instance
(for network address translation, address redirect, etc.):
see the
-.Sx NETWORK ADDRESS TRANSLATION (NAT)
+.Sx NETWORK ADDRESS TRANSLATION (NAT)\&
Section for further information.
.It Cm nat64lsn Ar name
Pass packet to a stateful NAT64 instance (for IPv6/IPv4 network address and
@@ -945,14 +1009,14 @@ protocol translation): see the
.Sx IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION
Section for further information.
.It Cm nat64clat Ar name
-Pass packet to a CLAT NAT64 instance (for client-side IPv6/IPv4 network address and
-protocol translation): see the
+Pass packet to a CLAT NAT64 instance (for client-side IPv6/IPv4 network address
+and protocol translation): see the
.Sx IPv6/IPv4 NETWORK ADDRESS AND PROTOCOL TRANSLATION
Section for further information.
.It Cm nptv6 Ar name
Pass packet to a NPTv6 instance (for IPv6-to-IPv6 network prefix translation):
see the
-.Sx IPv6-to-IPv6 NETWORK PREFIX TRANSLATION (NPTv6)
+.Sx IPv6-to-IPv6 NETWORK PREFIX TRANSLATION (NPTv6)\&
Section for further information.
.It Cm pipe Ar pipe_nr
Pass packet to a
@@ -1080,7 +1144,7 @@ Send a copy of packets matching this rule to the
socket bound to port
.Ar port .
The search continues with the next rule.
-.It Cm unreach Ar code
+.It Cm unreach Ar code Op mtu
Discard packets that match this rule, and try to send an ICMP
unreachable notice with code
.Ar code ,
@@ -1093,6 +1157,12 @@ is a number from 0 to 255, or one of these aliases:
.Cm toshost , filter-prohib , host-precedence
or
.Cm precedence-cutoff .
+The
+.Cm needfrag
+code may have an optional
+.Ar mtu
+parameter.
+If specified, the MTU value will be put into generated ICMP packet.
The search terminates.
.It Cm unreach6 Ar code
Discard packets that match this rule, and try to send an ICMPv6
@@ -1180,6 +1250,8 @@ Supported values are:
.Pq Dv 100100 ,
.Cm af43
.Pq Dv 100110 ,
+.Cm va
+.Pq Dv 101100 ,
.Cm ef
.Pq Dv 101110 ,
.Cm be
@@ -1259,7 +1331,7 @@ protocol options, incoming or outgoing interfaces, etc.)
that the packet must match in order to be recognised.
In general, the patterns are connected by (implicit)
.Cm and
-operators -- i.e., all must match in order for the
+operators \(em i.e., all must match in order for the
rule to match.
Individual patterns can be prefixed by the
.Cm not
@@ -1368,11 +1440,21 @@ Matches any IPv4 or IPv6 address for which an entry exists in the lookup table
If an optional 32-bit unsigned
.Ar value
is also specified, an entry will match only if it has this value.
+If
+.Ar value
+is specified in form
+.Ar valtype=value ,
+then specified value type field will be checked.
+It can be
+.Ar skipto, pipe, fib, nat, dscp, tag, divert, netgraph, limit, nh4
+and
+.Ar mark.
+
See the
.Sx LOOKUP TABLES
section below for more information on lookup tables.
.El
-.It Ar addr-list : ip-addr Ns Op Ns , Ns Ar addr-list
+.It Ar addr-list : ip-addr Ns Op , Ns Ar addr-list
.It Ar ip-addr :
A host or subnet address specified in one of the following ways:
.Bl -tag -width indent
@@ -1388,7 +1470,7 @@ and mask width of
bits.
As an example, 1.2.3.4/25 or 1.2.3.0/25 will match
all IP numbers from 1.2.3.0 to 1.2.3.127 .
-.It Ar addr Ns : Ns Ar mask
+.It Ar addr : Ns Ar mask
Matches all addresses with base
.Ar addr
(specified as an IP address, a network number, or a hostname)
@@ -1405,7 +1487,7 @@ format for contiguous masks, which is more compact and less
error-prone.
.El
.It Ar addr-set : addr Ns Oo Ns / Ns Ar masklen Oc Ns Cm { Ns Ar list Ns Cm }
-.It Ar list : Bro Ar num | num-num Brc Ns Op Ns , Ns Ar list
+.It Ar list : Bro Ar num | num-num Brc Ns Op , Ns Ar list
Matches all addresses with base address
.Ar addr
(specified as an IP address, a network number, or a hostname)
@@ -1432,7 +1514,7 @@ or 1.2.3.0/24{128,35-55,89}
will match the following IP addresses:
.br
1.2.3.128, 1.2.3.35 to 1.2.3.55, 1.2.3.89 .
-.It Ar addr6-list : ip6-addr Ns Op Ns , Ns Ar addr6-list
+.It Ar addr6-list : ip6-addr Ns Op , Ns Ar addr6-list
.It Ar ip6-addr :
A host or subnet specified one of the following ways:
.Bl -tag -width indent
@@ -1837,7 +1919,8 @@ set of parameters as specified in the rule.
One or more
of source and destination addresses and ports can be
specified.
-.It Cm lookup Bro Cm dst-ip | dst-port | dst-mac | src-ip | src-port | src-mac | uid | jail Brc Ar name
+.It Cm lookup Bro Cm dst-ip | dst-port | dst-mac | src-ip | src-port | src-mac | uid |
+.Cm jail | dscp | mark | rulenum Brc Ar name
Search an entry in lookup table
.Ar name
that matches the field specified as argument.
@@ -1910,13 +1993,24 @@ However, this option doesn't imply an implicit
.Cm check-state
in contrast to
.Cm keep-state .
-.It Cm recv | xmit | via Brq Ar ifX | Ar if Ns Cm * | Ar table Ns Po Ar name Ns Oo , Ns Ar value Oc Pc | Ar ipno | Ar any
+.It Cm recv | xmit | via Brq Ar ifX | Ar ifmask | Ar table Ns Po Ar name Ns Oo , Ns Ar value Oc Pc | Ar ipno | Ar any
Matches packets received, transmitted or going through,
respectively, the interface specified by exact name
.Po Ar ifX Pc ,
-by device name
-.Po Ar if* Pc ,
+by device mask
+.Po Ar ifmask Pc ,
by IP address, or through some interface.
+.Pp
+Interface
+name may be matched against
+.Ar ifmask
+with
+.Xr fnmatch 3
+according to the rules used by the shell (f.e. tun*).
+See also the
+.Sx EXAMPLES
+section.
+.Pp
Table
.Ar name
may be used to match interface by its kernel ifindex.
@@ -1998,6 +2092,23 @@ specified in the same way as
Tags can be applied to the packet using
.Cm tag
rule action parameter (see it's description for details on tags).
+.It Cm mark Ar value[:bitmask] | tablearg[:bitmask]
+Matches packets whose mark is equal to
+.Ar value
+with optional
+.Ar bitmask
+applied to it.
+.Cm tablearg
+can also be used instead of an explicit
+.Ar value
+to match a value supplied by the last table lookup.
+.Pp
+Both
+.Ar value
+and
+.Ar bitmask
+can be entered as decimal or hexadecimal (if prefixed by 0x), and they
+are always printed as hexadecimal.
.It Cm tcpack Ar ack
TCP packets only.
Match if the TCP header acknowledgment number field is set to
@@ -2340,7 +2451,7 @@ The following value types are supported:
.Bl -tag -width indent
.It Ar value-mask : Ar value-type Ns Op , Ns Ar value-mask
.It Ar value-type : Ar skipto | pipe | fib | nat | dscp | tag | divert |
-.Ar netgraph | limit | ipv4
+.Ar netgraph | limit | ipv4 | ipv6 | mark
.It Cm skipto
rule number to jump to.
.It Cm pipe
@@ -2363,16 +2474,19 @@ maximum number of connections.
IPv4 nexthop to fwd packets to.
.It Cm ipv6
IPv6 nexthop to fwd packets to.
+.It Cm mark
+mark value to match/set.
.El
.Pp
The
.Cm tablearg
argument can be used with the following actions:
.Cm nat, pipe, queue, divert, tee, netgraph, ngtee, fwd, skipto, setfib ,
+.Cm setmark ,
action parameters:
.Cm tag, untag ,
rule options:
-.Cm limit, tagged .
+.Cm limit, tagged, mark .
.Pp
When used with the
.Cm skipto
@@ -2980,12 +3094,47 @@ needed for some experimental setups where you want to simulate
loss or congestion at a remote router.
.Pp
.It Cm plr Ar packet-loss-rate
+.It Cm plr Ar K,p,H,r
Packet loss rate.
Argument
.Ar packet-loss-rate
is a floating-point number between 0 and 1, with 0 meaning no
loss, 1 meaning 100% loss.
-The loss rate is internally represented on 31 bits.
+.Pp
+When invoked with four arguments, the simple Gilbert-Elliott
+channel model with two states (Good and Bad) is used.
+.Bd -literal -offset indent
+ r
+ .----------------.
+ v |
+ .------------. .------------.
+ | G | | B |
+ | drop (K) | | drop (H) |
+ '------------' '------------'
+ | ^
+ '----------------'
+ p
+
+.Ed
+This has the associated probabilities
+.Po Ar K
+and
+.Ar H Pc
+for the loss probability.
+This is different from the literature, where this model is described with
+probabilities of successful transmission k and h.
+However, converting from literature is easy:
+.Pp
+K = 1 - k ; H = 1 - h
+.Pp
+This is to retain consistency within the interface and allow the
+quick re-use of loss probability when giving only a single argument.
+In addition the state change probabilities
+.Po Ar p
+and
+.Ar r Pc
+are given.
+All of the above probabilities are internally represented on 31 bits.
.Pp
.It Cm queue Brq Ar slots | size Ns Cm Kbytes
Queue size, in
@@ -3100,8 +3249,8 @@ delay low.
At regular time intervals of
.Cm tupdate
.Ar time
-(15ms by default) a background process (re)calculates the probability based on queue delay
-deviations from
+(15ms by default) a background process (re)calculates the probability based on
+queue delay deviations from
.Cm target
.Ar time
(15ms by default) and queue delay trends.
@@ -3120,8 +3269,8 @@ delay deviations that is used in drop probability calculation.
0.125 is the default.
.It Cm beta Ar n
.Ar n
-is a floating point number between 0 and 7 which specifies is the weight of queue
-delay trend that is used in drop probability calculation.
+is a floating point number between 0 and 7 which specifies is the weight of
+queue delay trend that is used in drop probability calculation.
1.25 is the default.
.It Cm max_burst Ar time
The maximum period of time that PIE does not drop/mark packets.
@@ -3307,8 +3456,28 @@ Obey transparent proxy rules only, packet aliasing is not performed.
.It Cm skip_global
Skip instance in case of global state lookup (see below).
.It Cm port_range Ar lower-upper
-Set the aliasing ports between the ranges given. Upper port has to be greater
-than lower.
+Set the aliasing ports between the ranges given.
+Upper port has to be greater than lower.
+.It Cm udp_eim
+When enabled, UDP packets use endpoint-independent mapping (EIM) from RFC 4787
+("full cone" NAT of RFC 3489).
+All packets from the same internal address:port are mapped to the same NAT
+address:port, regardless of their destination address:port.
+If filtering rules allow, and if
+.Em deny_in
+is unset, any other external address:port can
+also send to the internal address:port through its mapped NAT address:port.
+This is more compatible with applications, and can reduce the need for port
+forwarding, but less scalable as each NAT address:port can only be
+concurrently used by at most one internal address:port.
+.Pp
+When disabled, UDP packets use endpoint-dependent mapping (EDM) ("symmetric"
+NAT).
+Each connection from a particular internal address:port to different
+external addresses:ports is mapped to a random and unpredictable NAT
+address:port.
+Two appplications behind EDM NATs can only connect to each other
+by port forwarding on the NAT, or tunnelling through an in-between server.
.El
.Pp
Some special values can be supplied instead of
@@ -3460,7 +3629,8 @@ The NAT64 instance will determine a destination IPv4 address from prefix
.It Cm states_chunks Ar number
The number of states chunks in single ports group.
Each ports group by default can keep 64 state entries in single chunk.
-The above value affects the maximum number of states that can be associated with single IPv4 alias address and port.
+The above value affects the maximum number of states that can be associated with
+a single IPv4 alias address and port.
The value must be power of 2, and up to 128.
.It Cm host_del_age Ar seconds
The number of seconds until the host entry for a IPv6 client will be deleted
@@ -3702,6 +3872,16 @@ or
.Xr kenv 1
before ipfw module gets loaded.
.Bl -tag -width indent
+.It Va net.inet.ip.fw.enable : No 1
+Enables the firewall.
+Setting this variable to 0 lets you run your machine without
+firewall even if compiled in.
+.It Va net.inet6.ip6.fw.enable : No 1
+provides the same functionality as above for the IPv6 case.
+.It Va net.link.ether.ipfw : No 0
+Controls whether layer2 packets are passed to
+.Nm .
+Default is no.
.It Va net.inet.ip.fw.default_to_accept : No 0
Defines ipfw last rule behavior.
This value overrides
@@ -4095,12 +4275,6 @@ Keep dynamic states on rule/set deletion.
States are relinked to default rule (65535).
This can be handly for ruleset reload.
Turned off by default.
-.It Va net.inet.ip.fw.enable : No 1
-Enables the firewall.
-Setting this variable to 0 lets you run your machine without
-firewall even if compiled in.
-.It Va net.inet6.ip6.fw.enable : No 1
-provides the same functionality as above for the IPv6 case.
.It Va net.inet.ip.fw.one_pass : No 1
When set, the packet exiting from the
.Nm dummynet
@@ -4117,10 +4291,6 @@ Enables verbose messages.
Limits the number of messages produced by a verbose firewall.
.It Va net.inet6.ip6.fw.deny_unknown_exthdrs : No 1
If enabled packets with unknown IPv6 Extension Headers will be denied.
-.It Va net.link.ether.ipfw : No 0
-Controls whether layer2 packets are passed to
-.Nm .
-Default is no.
.It Va net.link.bridge.ipfw : No 0
Controls whether bridged packets are passed to
.Nm .
@@ -4164,6 +4334,15 @@ sub-options:
Lists all interface which are currently tracked by
.Nm
with their in-kernel status.
+.It Cm monitor Op Ar filter-comment
+Capture messages from
+.Xr route 4
+socket, that were logged using rules with
+.Cm log Cm logdst Ar rtsock
+opcode. Optional
+.Ar filter-comment
+can be specified to show only those messages, that were logged
+by rules with specific rule comment.
.It Cm talist
List all table lookup algorithms currently available.
.El
@@ -4215,6 +4394,12 @@ of clients, as below:
.Dl "ipfw add deny ip from ${badguys} to any"
.Dl "... normal policies ..."
.Pp
+Allow any transit packets coming from single vlan 10 and
+going out to vlans 100-1000:
+.Pp
+.Dl "ipfw add 10 allow out recv vlan10 \e"
+.Dl "{ xmit vlan1000 or xmit \*qvlan[1-9]??\*q }"
+.Pp
The
.Cm verrevpath
option could be used to do automated anti-spoofing by adding the
@@ -4330,7 +4515,7 @@ and
.Cm defer-action
can be used to precisely control creation and checking of dynamic rules.
Example of usage of these options are provided in
-.Sx NETWORK ADDRESS TRANSLATION (NAT)
+.Sx NETWORK ADDRESS TRANSLATION (NAT)\&
Section.
.Pp
To limit the number of connections a user can open
@@ -4623,7 +4808,7 @@ Bear in mind that this is example only and it is not very useful by itself.
.Pp
On way out, after all checks place this rules:
.Pp
-.Dl "ipfw add allow record-state skip-action"
+.Dl "ipfw add allow record-state defer-action"
.Dl "ipfw add nat 1"
.Pp
And on way in there should be something like this:
@@ -4738,6 +4923,7 @@ can be changed in a similar way as for
.Sh SEE ALSO
.Xr cpp 1 ,
.Xr m4 1 ,
+.Xr fnmatch 3 ,
.Xr altq 4 ,
.Xr divert 4 ,
.Xr dummynet 4 ,
@@ -4818,7 +5004,7 @@ The syntax has grown over the years and sometimes it might be confusing.
Unfortunately, backward compatibility prevents cleaning up mistakes
made in the definition of the syntax.
.Pp
-.Em !!! WARNING !!!
+.Em !!! WARNING !!!\&
.Pp
Misconfiguring the firewall can put your computer in an unusable state,
possibly shutting down network services and requiring console access to
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 7d820698a25d..2addc0295f0f 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -16,8 +16,6 @@
* This software is provided ``AS IS'' without any warranties of any kind.
*
* NEW command line interface for IP firewall facility
- *
- * $FreeBSD$
*/
#include <sys/types.h>
@@ -49,6 +47,8 @@
#include <net/ethernet.h>
#include <net/if.h> /* only IFNAMSIZ */
+#include <net/if_dl.h>
+#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h> /* only n_short, n_long */
#include <netinet/ip.h>
@@ -190,6 +190,7 @@ struct _s_x f_ipdscp[] = {
{ "af42", IPTOS_DSCP_AF42 >> 2 }, /* 100100 */
{ "af43", IPTOS_DSCP_AF43 >> 2 }, /* 100110 */
{ "be", IPTOS_DSCP_CS0 >> 2 }, /* 000000 */
+ { "va", IPTOS_DSCP_VA >> 2 }, /* 101100 */
{ "ef", IPTOS_DSCP_EF >> 2 }, /* 101110 */
{ "cs0", IPTOS_DSCP_CS0 >> 2 }, /* 000000 */
{ "cs1", IPTOS_DSCP_CS1 >> 2 }, /* 001000 */
@@ -287,6 +288,13 @@ static struct _s_x rule_actions[] = {
{ "return", TOK_RETURN },
{ "eaction", TOK_EACTION },
{ "tcp-setmss", TOK_TCPSETMSS },
+ { "setmark", TOK_SETMARK },
+ { NULL, 0 } /* terminator */
+};
+
+static struct _s_x return_types[] = {
+ { "next-rulenum", RETURN_NEXT_RULENUM },
+ { "next-rule", RETURN_NEXT_RULE },
{ NULL, 0 } /* terminator */
};
@@ -300,7 +308,7 @@ static struct _s_x rule_action_params[] = {
/*
* The 'lookup' instruction accepts one of the following arguments.
- * Arguments are passed as v[1] in O_DST_LOOKUP options.
+ * Arguments are passed as o.arg1 and o->value in O_DST_LOOKUP option.
*/
static struct _s_x lookup_keys[] = {
{ "dst-ip", LOOKUP_DST_IP },
@@ -312,9 +320,30 @@ static struct _s_x lookup_keys[] = {
{ "uid", LOOKUP_UID },
{ "jail", LOOKUP_JAIL },
{ "dscp", LOOKUP_DSCP },
+ { "mark", LOOKUP_MARK },
+ { "rulenum", LOOKUP_RULENUM },
{ NULL, 0 },
};
+/*
+ * table(name,valuename=value) instruction accepts one of the
+ * following arguments as valuename.
+ */
+static struct _s_x tvalue_names[] = {
+ { "tag", TVALUE_TAG },
+ { "pipe", TVALUE_PIPE },
+ { "divert", TVALUE_DIVERT },
+ { "skipto", TVALUE_SKIPTO },
+ { "netgraph", TVALUE_NETGRAPH },
+ { "fib", TVALUE_FIB },
+ { "nat", TVALUE_NAT },
+ { "nh4", TVALUE_NH4 },
+ { "dscp", TVALUE_DSCP },
+ { "limit", TVALUE_LIMIT },
+ { "mark", TVALUE_MARK },
+ { NULL, 0 }
+};
+
static struct _s_x rule_options[] = {
{ "tagged", TOK_TAGGED },
{ "uid", TOK_UID },
@@ -390,6 +419,7 @@ static struct _s_x rule_options[] = {
{ "src-ip6", TOK_SRCIP6 },
{ "lookup", TOK_LOOKUP },
{ "flow", TOK_FLOW },
+ { "mark", TOK_MARK },
{ "defer-action", TOK_SKIPACTION },
{ "defer-immediate-action", TOK_SKIPACTION },
{ "//", TOK_COMMENT },
@@ -413,12 +443,12 @@ static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
static void ipfw_list_tifaces(void);
struct tidx;
-static uint16_t pack_object(struct tidx *tstate, const char *name, int otype);
-static uint16_t pack_table(struct tidx *tstate, const char *name);
+static uint32_t pack_object(struct tidx *tstate, const char *name, int otype);
+static uint32_t pack_table(struct tidx *tstate, const char *name);
-static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx);
+static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx);
static void object_sort_ctlv(ipfw_obj_ctlv *ctlv);
-static char *object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx,
+static char *object_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx,
uint16_t type);
int
@@ -583,6 +613,13 @@ stringnum_cmp(const char *a, const char *b)
return (strcmp(a, b));
}
+struct debug_header {
+ uint16_t cmd_type;
+ uint16_t spare1;
+ uint32_t opt_name;
+ uint32_t total_len;
+ uint32_t spare2;
+};
/*
* conditionally runs the command.
@@ -593,8 +630,18 @@ do_cmd(int optname, void *optval, uintptr_t optlen)
{
int i;
+ if (g_co.debug_only) {
+ struct debug_header dbg = {
+ .cmd_type = 1,
+ .opt_name = optname,
+ .total_len = optlen + sizeof(struct debug_header),
+ };
+ write(1, &dbg, sizeof(dbg));
+ write(1, optval, optlen);
+ }
+
if (g_co.test_only)
- return 0;
+ return (0);
if (ipfw_socket == -1)
ipfw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
@@ -613,7 +660,7 @@ do_cmd(int optname, void *optval, uintptr_t optlen)
} else {
i = setsockopt(ipfw_socket, IPPROTO_IP, optname, optval, optlen);
}
- return i;
+ return (i);
}
/*
@@ -630,6 +677,19 @@ int
do_set3(int optname, ip_fw3_opheader *op3, size_t optlen)
{
+ op3->opcode = optname;
+ op3->version = IP_FW3_OPVER; /* use last version */
+
+ if (g_co.debug_only) {
+ struct debug_header dbg = {
+ .cmd_type = 2,
+ .opt_name = optname,
+ .total_len = optlen, sizeof(struct debug_header),
+ };
+ write(1, &dbg, sizeof(dbg));
+ write(1, op3, optlen);
+ }
+
if (g_co.test_only)
return (0);
@@ -638,7 +698,6 @@ do_set3(int optname, ip_fw3_opheader *op3, size_t optlen)
if (ipfw_socket < 0)
err(EX_UNAVAILABLE, "socket");
- op3->opcode = optname;
return (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, optlen));
}
@@ -659,6 +718,19 @@ do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen)
int error;
socklen_t len;
+ op3->opcode = optname;
+ op3->version = IP_FW3_OPVER; /* use last version */
+
+ if (g_co.debug_only) {
+ struct debug_header dbg = {
+ .cmd_type = 3,
+ .opt_name = optname,
+ .total_len = *optlen + sizeof(struct debug_header),
+ };
+ write(1, &dbg, sizeof(dbg));
+ write(1, op3, *optlen);
+ }
+
if (g_co.test_only)
return (0);
@@ -667,7 +739,6 @@ do_get3(int optname, ip_fw3_opheader *op3, size_t *optlen)
if (ipfw_socket < 0)
err(EX_UNAVAILABLE, "socket");
- op3->opcode = optname;
len = *optlen;
error = getsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, &len);
@@ -1101,6 +1172,45 @@ fill_dscp(ipfw_insn *cmd, char *av, int cblen)
}
}
+/*
+ * Fill the body of the command with mark value and mask.
+ */
+static void
+fill_mark(ipfw_insn *cmd, char *av, int cblen)
+{
+ uint32_t *value, *mask;
+ char *value_str;
+
+ cmd->opcode = O_MARK;
+ cmd->len |= F_INSN_SIZE(ipfw_insn_u32) + 1;
+
+ CHECK_CMDLEN;
+
+ value = (uint32_t *)(cmd + 1);
+ mask = value + 1;
+
+ value_str = strsep(&av, ":");
+
+ if (strcmp(value_str, "tablearg") == 0) {
+ cmd->arg1 = IP_FW_TARG;
+ *value = 0;
+ } else {
+ /* This is not a tablearg */
+ cmd->arg1 |= 0x8000;
+ *value = strtoul(value_str, NULL, 0);
+ }
+ if (av)
+ *mask = strtoul(av, NULL, 0);
+ else
+ *mask = 0xFFFFFFFF;
+
+ if ((*value & *mask) != *value)
+ errx(EX_DATAERR, "Static mark value: some bits in value are"
+ " set that will be masked out by mask "
+ "(%#x & %#x) = %#x != %#x",
+ *value, *mask, (*value & *mask), *value);
+}
+
static struct _s_x icmpcodes[] = {
{ "net", ICMP_UNREACH_NET },
{ "host", ICMP_UNREACH_HOST },
@@ -1121,8 +1231,8 @@ static struct _s_x icmpcodes[] = {
{ NULL, 0 }
};
-static void
-fill_reject_code(u_short *codep, char *str)
+static uint16_t
+get_reject_code(const char *str)
{
int val;
char *s;
@@ -1132,8 +1242,7 @@ fill_reject_code(u_short *codep, char *str)
val = match_token(icmpcodes, str);
if (val < 0)
errx(EX_DATAERR, "unknown ICMP unreachable code ``%s''", str);
- *codep = val;
- return;
+ return (val);
}
static void
@@ -1205,6 +1314,15 @@ print_flags(struct buf_pr *bp, char const *name, const ipfw_insn *cmd,
}
}
+static void
+print_tvalue(struct buf_pr *bp, const ipfw_insn_table *cmd)
+{
+ const char *name;
+
+ name = match_value(tvalue_names, IPFW_TVALUE_TYPE(&cmd->o));
+ bprintf(bp, ",%s=%u", name != NULL ? name: "<invalid>", cmd->value);
+}
+
/*
* Print the ip address contained in a command.
@@ -1216,33 +1334,46 @@ print_ip(struct buf_pr *bp, const struct format_opts *fo,
struct hostent *he = NULL;
const struct in_addr *ia;
const uint32_t *a = ((const ipfw_insn_u32 *)cmd)->d;
- uint32_t len = F_LEN((const ipfw_insn *)cmd);
+ uint32_t len = F_LEN(&cmd->o);
char *t;
bprintf(bp, " ");
- if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) {
- const char *arg;
-
- arg = match_value(lookup_keys, a[1]);
- t = table_search_ctlv(fo->tstate,
- ((const ipfw_insn *)cmd)->arg1);
- bprintf(bp, "lookup %s %s", arg, t);
- return;
- }
- if (cmd->o.opcode == O_IP_SRC_ME || cmd->o.opcode == O_IP_DST_ME) {
+ switch (cmd->o.opcode) {
+ case O_IP_SRC_ME:
+ case O_IP_DST_ME:
bprintf(bp, "me");
return;
- }
- if (cmd->o.opcode == O_IP_SRC_LOOKUP ||
- cmd->o.opcode == O_IP_DST_LOOKUP) {
+
+ case O_IP_DST_LOOKUP:
+ if ((len == F_INSN_SIZE(ipfw_insn_kidx) ||
+ len == F_INSN_SIZE(ipfw_insn_table)) &&
+ IPFW_LOOKUP_TYPE(&cmd->o) != LOOKUP_NONE) {
+ const char *key;
+
+ key = match_value(lookup_keys,
+ IPFW_LOOKUP_TYPE(&cmd->o));
+ t = table_search_ctlv(fo->tstate,
+ insntoc(&cmd->o, kidx)->kidx);
+ if (len == F_INSN_SIZE(ipfw_insn_table)) {
+ bprintf(bp, "lookup %s:%#x %s",
+ (key != NULL ? key : "<invalid>"),
+ insntoc(&cmd->o, table)->value, t);
+ } else
+ bprintf(bp, "lookup %s %s", key != NULL ? key:
+ "<invalid>", t);
+ return;
+ }
+ /* FALLTHROUGH */
+ case O_IP_SRC_LOOKUP:
t = table_search_ctlv(fo->tstate,
- ((const ipfw_insn *)cmd)->arg1);
+ insntoc(&cmd->o, kidx)->kidx);
bprintf(bp, "table(%s", t);
- if (len == F_INSN_SIZE(ipfw_insn_u32))
- bprintf(bp, ",%u", *a);
+ if (len == F_INSN_SIZE(ipfw_insn_table))
+ print_tvalue(bp, insntoc(&cmd->o, table));
bprintf(bp, ")");
return;
}
+
if (cmd->o.opcode == O_IP_SRC_SET || cmd->o.opcode == O_IP_DST_SET) {
const uint32_t *map = (const uint32_t *)&cmd->mask;
struct in_addr addr;
@@ -1348,10 +1479,10 @@ print_mac_lookup(struct buf_pr *bp, const struct format_opts *fo,
bprintf(bp, " ");
- t = table_search_ctlv(fo->tstate, cmd->arg1);
+ t = table_search_ctlv(fo->tstate, insntoc(cmd, kidx)->kidx);
bprintf(bp, "table(%s", t);
- if (len == F_INSN_SIZE(ipfw_insn_u32))
- bprintf(bp, ",%u", ((const ipfw_insn_u32 *)cmd)->d[0]);
+ if (len == F_INSN_SIZE(ipfw_insn_table))
+ print_tvalue(bp, insntoc(cmd, table));
bprintf(bp, ")");
}
@@ -1418,10 +1549,9 @@ print_dscp(struct buf_pr *bp, const ipfw_insn_u32 *cmd)
}
}
-#define insntod(cmd, type) ((const ipfw_insn_ ## type *)(cmd))
struct show_state {
struct ip_fw_rule *rule;
- const ipfw_insn *eaction;
+ const ipfw_insn_kidx *eaction;
uint8_t *printed;
int flags;
#define HAVE_PROTO 0x0001
@@ -1504,7 +1634,7 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
switch (cmd->opcode) {
case O_PROB:
- d = 1.0 * insntod(cmd, u32)->d[0] / 0x7fffffff;
+ d = 1.0 * insntoc(cmd, u32)->d[0] / 0x7fffffff;
bprintf(bp, "prob %f ", d);
break;
case O_PROBE_STATE: /* no need to print anything here */
@@ -1517,30 +1647,36 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
case O_IP_SRC_SET:
if (state->flags & HAVE_SRCIP)
bprintf(bp, " src-ip");
- print_ip(bp, fo, insntod(cmd, ip));
+ print_ip(bp, fo, insntoc(cmd, ip));
break;
case O_IP_DST:
- case O_IP_DST_LOOKUP:
case O_IP_DST_MASK:
case O_IP_DST_ME:
case O_IP_DST_SET:
- if (state->flags & HAVE_DSTIP)
+ case O_IP_DST_LOOKUP:
+ /*
+ * Special handling for O_IP_DST_LOOKUP when
+ * lookup type is not LOOKUP_NONE.
+ */
+ if ((state->flags & HAVE_DSTIP) != 0 && (
+ cmd->opcode != O_IP_DST_LOOKUP ||
+ IPFW_LOOKUP_TYPE(cmd) == LOOKUP_NONE))
bprintf(bp, " dst-ip");
- print_ip(bp, fo, insntod(cmd, ip));
+ print_ip(bp, fo, insntoc(cmd, ip));
break;
case O_IP6_SRC:
case O_IP6_SRC_MASK:
case O_IP6_SRC_ME:
if (state->flags & HAVE_SRCIP)
bprintf(bp, " src-ip6");
- print_ip6(bp, insntod(cmd, ip6));
+ print_ip6(bp, insntoc(cmd, ip6));
break;
case O_IP6_DST:
case O_IP6_DST_MASK:
case O_IP6_DST_ME:
if (state->flags & HAVE_DSTIP)
bprintf(bp, " dst-ip6");
- print_ip6(bp, insntod(cmd, ip6));
+ print_ip6(bp, insntoc(cmd, ip6));
break;
case O_MAC_SRC_LOOKUP:
bprintf(bp, " src-mac");
@@ -1551,11 +1687,11 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
print_mac_lookup(bp, fo, cmd);
break;
case O_FLOW6ID:
- print_flow6id(bp, insntod(cmd, u32));
+ print_flow6id(bp, insntoc(cmd, u32));
break;
case O_IP_DSTPORT:
case O_IP_SRCPORT:
- print_newports(bp, insntod(cmd, u16), state->proto,
+ print_newports(bp, insntoc(cmd, u16), state->proto,
(state->flags & (HAVE_SRCIP | HAVE_DSTIP)) ==
(HAVE_SRCIP | HAVE_DSTIP) ? cmd->opcode: 0);
break;
@@ -1570,10 +1706,10 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
state->proto = cmd->arg1;
break;
case O_MACADDR2:
- print_mac(bp, insntod(cmd, mac));
+ print_mac(bp, insntoc(cmd, mac));
break;
case O_MAC_TYPE:
- print_newports(bp, insntod(cmd, u16),
+ print_newports(bp, insntoc(cmd, u16),
IPPROTO_ETHERTYPE, cmd->opcode);
break;
case O_FRAG:
@@ -1616,26 +1752,27 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
s = "recv";
else /* if (cmd->opcode == O_VIA) */
s = "via";
- switch (insntod(cmd, if)->name[0]) {
+ switch (insntoc(cmd, if)->name[0]) {
case '\0':
bprintf(bp, " %s %s", s,
- inet_ntoa(insntod(cmd, if)->p.ip));
+ inet_ntoa(insntoc(cmd, if)->p.ip));
break;
case '\1':
bprintf(bp, " %s table(%s)", s,
table_search_ctlv(fo->tstate,
- insntod(cmd, if)->p.kidx));
+ insntoc(cmd, if)->p.kidx));
break;
default:
bprintf(bp, " %s %s", s,
- insntod(cmd, if)->name);
+ insntoc(cmd, if)->name);
}
break;
case O_IP_FLOW_LOOKUP:
- s = table_search_ctlv(fo->tstate, cmd->arg1);
+ s = table_search_ctlv(fo->tstate,
+ insntoc(cmd, kidx)->kidx);
bprintf(bp, " flow table(%s", s);
- if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_u32))
- bprintf(bp, ",%u", insntod(cmd, u32)->d[0]);
+ if (F_LEN(cmd) == F_INSN_SIZE(ipfw_insn_table))
+ print_tvalue(bp, insntoc(cmd, table));
bprintf(bp, ")");
break;
case O_IPID:
@@ -1670,7 +1807,7 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
}
bprintf(bp, " %s %u", s, cmd->arg1);
} else
- print_newports(bp, insntod(cmd, u16), 0,
+ print_newports(bp, insntoc(cmd, u16), 0,
cmd->opcode);
break;
case O_IPVER:
@@ -1680,7 +1817,7 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
bprintf(bp, " ipprecedence %u", cmd->arg1 >> 5);
break;
case O_DSCP:
- print_dscp(bp, insntod(cmd, u32));
+ print_dscp(bp, insntoc(cmd, u32));
break;
case O_IPOPT:
print_flags(bp, "ipoptions", cmd, f_ipopts);
@@ -1689,7 +1826,7 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
print_flags(bp, "iptos", cmd, f_iptos);
break;
case O_ICMPTYPE:
- print_icmptypes(bp, insntod(cmd, u32));
+ print_icmptypes(bp, insntoc(cmd, u32));
break;
case O_ESTAB:
bprintf(bp, " established");
@@ -1702,30 +1839,30 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
break;
case O_TCPACK:
bprintf(bp, " tcpack %d",
- ntohl(insntod(cmd, u32)->d[0]));
+ ntohl(insntoc(cmd, u32)->d[0]));
break;
case O_TCPSEQ:
bprintf(bp, " tcpseq %d",
- ntohl(insntod(cmd, u32)->d[0]));
+ ntohl(insntoc(cmd, u32)->d[0]));
break;
case O_UID:
- pwd = getpwuid(insntod(cmd, u32)->d[0]);
+ pwd = getpwuid(insntoc(cmd, u32)->d[0]);
if (pwd != NULL)
bprintf(bp, " uid %s", pwd->pw_name);
else
bprintf(bp, " uid %u",
- insntod(cmd, u32)->d[0]);
+ insntoc(cmd, u32)->d[0]);
break;
case O_GID:
- grp = getgrgid(insntod(cmd, u32)->d[0]);
+ grp = getgrgid(insntoc(cmd, u32)->d[0]);
if (grp != NULL)
bprintf(bp, " gid %s", grp->gr_name);
else
bprintf(bp, " gid %u",
- insntod(cmd, u32)->d[0]);
+ insntoc(cmd, u32)->d[0]);
break;
case O_JAIL:
- bprintf(bp, " jail %d", insntod(cmd, u32)->d[0]);
+ bprintf(bp, " jail %d", insntoc(cmd, u32)->d[0]);
break;
case O_VERREVPATH:
bprintf(bp, " verrevpath");
@@ -1748,7 +1885,8 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
else
bprintf(bp, " record-state");
bprintf(bp, " :%s",
- object_search_ctlv(fo->tstate, cmd->arg1,
+ object_search_ctlv(fo->tstate,
+ insntoc(cmd, kidx)->kidx,
IPFW_TLV_STATE_NAME));
break;
case O_LIMIT:
@@ -1756,9 +1894,10 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
bprintf(bp, " limit");
else
bprintf(bp, " set-limit");
- print_limit_mask(bp, insntod(cmd, limit));
+ print_limit_mask(bp, insntoc(cmd, limit));
bprintf(bp, " :%s",
- object_search_ctlv(fo->tstate, cmd->arg1,
+ object_search_ctlv(fo->tstate,
+ insntoc(cmd, kidx)->kidx,
IPFW_TLV_STATE_NAME));
break;
case O_IP6:
@@ -1772,7 +1911,7 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
bprintf(bp, " ip4");
break;
case O_ICMP6TYPE:
- print_icmp6types(bp, insntod(cmd, u32));
+ print_icmp6types(bp, insntoc(cmd, u32));
break;
case O_EXT_HDR:
print_ext6hdr(bp, cmd);
@@ -1781,12 +1920,23 @@ print_instruction(struct buf_pr *bp, const struct format_opts *fo,
if (F_LEN(cmd) == 1)
bprint_uint_arg(bp, " tagged ", cmd->arg1);
else
- print_newports(bp, insntod(cmd, u16),
+ print_newports(bp, insntoc(cmd, u16),
0, O_TAGGED);
break;
case O_SKIP_ACTION:
bprintf(bp, " defer-immediate-action");
break;
+ case O_MARK:
+ bprintf(bp, " mark");
+ if (cmd->arg1 == IP_FW_TARG)
+ bprintf(bp, " tablearg");
+ else
+ bprintf(bp, " %#x", insntoc(cmd, u32)->d[0]);
+
+ if (insntoc(cmd, u32)->d[1] != 0xFFFFFFFF)
+ bprintf(bp, ":%#x", insntoc(cmd, u32)->d[1]);
+ break;
+
default:
bprintf(bp, " [opcode %d len %d]", cmd->opcode,
cmd->len);
@@ -1837,14 +1987,14 @@ print_fwd(struct buf_pr *bp, const ipfw_insn *cmd)
uint16_t port;
if (cmd->opcode == O_FORWARD_IP) {
- sa = insntod(cmd, sa);
+ sa = insntoc(cmd, sa);
port = sa->sa.sin_port;
if (sa->sa.sin_addr.s_addr == INADDR_ANY)
bprintf(bp, "fwd tablearg");
else
bprintf(bp, "fwd %s", inet_ntoa(sa->sa.sin_addr));
} else {
- sa6 = insntod(cmd, sa6);
+ sa6 = insntoc(cmd, sa6);
port = sa6->sa.sin6_port;
bprintf(bp, "fwd ");
if (getnameinfo((const struct sockaddr *)&sa6->sa,
@@ -1856,6 +2006,26 @@ print_fwd(struct buf_pr *bp, const ipfw_insn *cmd)
bprintf(bp, ",%u", port);
}
+static void
+print_logdst(struct buf_pr *bp, uint16_t arg1)
+{
+ char const *comma = "";
+
+ bprintf(bp, " logdst ");
+ if (arg1 & IPFW_LOG_SYSLOG) {
+ bprintf(bp, "%ssyslog", comma);
+ comma = ",";
+ }
+ if (arg1 & IPFW_LOG_IPFW0) {
+ bprintf(bp, "%sipfw0", comma);
+ comma = ",";
+ }
+ if (arg1 & IPFW_LOG_RTSOCK) {
+ bprintf(bp, "%srtsock", comma);
+ comma = ",";
+ }
+}
+
static int
print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
struct show_state *state, const ipfw_insn *cmd)
@@ -1867,8 +2037,9 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
switch (cmd->opcode) {
case O_CHECK_STATE:
bprintf(bp, "check-state");
- if (cmd->arg1 != 0)
- s = object_search_ctlv(fo->tstate, cmd->arg1,
+ if (insntoc(cmd, kidx)->kidx != 0)
+ s = object_search_ctlv(fo->tstate,
+ insntoc(cmd, kidx)->kidx,
IPFW_TLV_STATE_NAME);
else
s = NULL;
@@ -1890,6 +2061,10 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
bprintf(bp, "abort");
else if (cmd->arg1 == ICMP_UNREACH_HOST)
bprintf(bp, "reject");
+ else if (cmd->arg1 == ICMP_UNREACH_NEEDFRAG &&
+ cmd->len == F_INSN_SIZE(ipfw_insn_u16))
+ bprintf(bp, "needfrag %u",
+ insntoc(cmd, u16)->ports[0]);
else
print_reject_code(bp, cmd->arg1);
break;
@@ -1902,7 +2077,7 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
print_unreach6_code(bp, cmd->arg1);
break;
case O_SKIPTO:
- bprint_uint_arg(bp, "skipto ", cmd->arg1);
+ bprint_uint_arg(bp, "skipto ", insntoc(cmd, u32)->d[0]);
break;
case O_PIPE:
bprint_uint_arg(bp, "pipe ", cmd->arg1);
@@ -1927,15 +2102,16 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
print_fwd(bp, cmd);
break;
case O_LOG:
- if (insntod(cmd, log)->max_log > 0)
- bprintf(bp, " log logamount %d",
- insntod(cmd, log)->max_log);
- else
- bprintf(bp, " log");
+ bprintf(bp, " log");
+ if (insntoc(cmd, log)->max_log > 0)
+ bprintf(bp, " logamount %d",
+ insntoc(cmd, log)->max_log);
+ if (cmd->arg1 != IPFW_LOG_DEFAULT)
+ print_logdst(bp, cmd->arg1);
break;
case O_ALTQ:
#ifndef NO_ALTQ
- print_altq_cmd(bp, insntod(cmd, altq));
+ print_altq_cmd(bp, insntoc(cmd, altq));
#endif
break;
case O_TAG:
@@ -1964,8 +2140,9 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
* NOTE: in case when external action has no named
* instances support, the second opcode isn't needed.
*/
- state->eaction = cmd;
- s = object_search_ctlv(fo->tstate, cmd->arg1,
+ state->eaction = insntoc(cmd, kidx);
+ s = object_search_ctlv(fo->tstate,
+ state->eaction->kidx,
IPFW_TLV_EACTION);
if (match_token(rule_eactions, s) != -1)
bprintf(bp, "%s", s);
@@ -1985,11 +2162,12 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
* we calculate TLV type using IPFW_TLV_EACTION_NAME()
* macro.
*/
- s = object_search_ctlv(fo->tstate, cmd->arg1, 0);
+ s = object_search_ctlv(fo->tstate,
+ insntoc(cmd, kidx)->kidx, 0);
if (s == NULL)
s = object_search_ctlv(fo->tstate,
- cmd->arg1, IPFW_TLV_EACTION_NAME(
- state->eaction->arg1));
+ insntoc(cmd, kidx)->kidx, IPFW_TLV_EACTION_NAME(
+ state->eaction->kidx));
bprintf(bp, " %s", s);
break;
case O_EXTERNAL_DATA:
@@ -2004,7 +2182,7 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
bprintf(bp, " %u", cmd->arg1);
else
bprintf(bp, " %ubytes",
- cmd->len * sizeof(uint32_t));
+ (unsigned)(cmd->len * sizeof(uint32_t)));
break;
case O_SETDSCP:
if (cmd->arg1 == IP_FW_TARG) {
@@ -2021,10 +2199,18 @@ print_action_instruction(struct buf_pr *bp, const struct format_opts *fo,
bprintf(bp, "reass");
break;
case O_CALLRETURN:
- if (cmd->len & F_NOT)
- bprintf(bp, "return");
- else
- bprint_uint_arg(bp, "call ", cmd->arg1);
+ if (cmd->len & F_NOT) {
+ s = match_value(return_types, cmd->arg1);
+ bprintf(bp, "return %s", s ? s: "<invalid>");
+ } else
+ bprint_uint_arg(bp, "call ", insntoc(cmd, u32)->d[0]);
+ break;
+ case O_SETMARK:
+ if (cmd->arg1 == IP_FW_TARG) {
+ bprintf(bp, "setmark tablearg");
+ break;
+ }
+ bprintf(bp, "setmark %#x", insntoc(cmd, u32)->d[0]);
break;
default:
bprintf(bp, "** unrecognized action %d len %d ",
@@ -2130,9 +2316,16 @@ print_address(struct buf_pr *bp, struct format_opts *fo,
count = portcnt = 0;
for (l = state->rule->act_ofs, cmd = state->rule->cmd;
l > 0; l -= F_LEN(cmd), cmd += F_LEN(cmd)) {
- if (match_opcode(cmd->opcode, opcodes, nops))
+ if (match_opcode(cmd->opcode, opcodes, nops)) {
+ /*
+ * Special handling for O_IP_DST_LOOKUP when
+ * lookup type is not LOOKUP_NONE.
+ */
+ if (cmd->opcode == O_IP_DST_LOOKUP &&
+ IPFW_LOOKUP_TYPE(cmd) != LOOKUP_NONE)
+ continue;
count++;
- else if (cmd->opcode == portop)
+ } else if (cmd->opcode == portop)
portcnt++;
}
if (count == 0)
@@ -2170,7 +2363,7 @@ static const int action_opcodes[] = {
O_CHECK_STATE, O_ACCEPT, O_COUNT, O_DENY, O_REJECT,
O_UNREACH6, O_SKIPTO, O_PIPE, O_QUEUE, O_DIVERT, O_TEE,
O_NETGRAPH, O_NGTEE, O_FORWARD_IP, O_FORWARD_IP6, O_NAT,
- O_SETFIB, O_SETDSCP, O_REASS, O_CALLRETURN,
+ O_SETFIB, O_SETDSCP, O_REASS, O_CALLRETURN, O_SETMARK,
/* keep the following opcodes at the end of the list */
O_EXTERNAL_ACTION, O_EXTERNAL_INSTANCE, O_EXTERNAL_DATA
};
@@ -2189,6 +2382,12 @@ static const int dst_opcodes[] = {
O_IP_DST_SET, O_IP6_DST, O_IP6_DST_MASK, O_IP6_DST_ME
};
+#if IPFW_DEFAULT_RULE > 65535
+#define RULENUM_FORMAT "%06d"
+#else
+#define RULENUM_FORMAT "%05d"
+#endif
+
static void
show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
struct buf_pr *bp, struct ip_fw_rule *rule, struct ip_fw_bcounter *cntr)
@@ -2210,7 +2409,8 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
warn("init_show_state() failed");
return;
}
- bprintf(bp, "%05u ", rule->rulenum);
+
+ bprintf(bp, RULENUM_FORMAT " ", rule->rulenum);
/* only if counters are available */
if (cntr != NULL) {
@@ -2277,6 +2477,13 @@ show_static_rule(struct cmdline_opts *co, struct format_opts *fo,
if (rule->flags & IPFW_RULE_JUSTOPTS) {
state.flags |= HAVE_PROTO | HAVE_SRCIP | HAVE_DSTIP;
+ /*
+ * Print `proto ip` if all opcodes has been already printed.
+ */
+ if (memchr(state.printed, 0, rule->act_ofs) == NULL) {
+ bprintf(bp, " proto ip");
+ goto end;
+ }
goto justopts;
}
@@ -2313,23 +2520,21 @@ show_dyn_state(struct cmdline_opts *co, struct format_opts *fo,
{
struct protoent *pe;
struct in_addr a;
- uint16_t rulenum;
char buf[INET6_ADDRSTRLEN];
- if (d->expire == 0 && d->dyn_type != O_LIMIT_PARENT)
+ if (!d->expire && !(d->type == O_LIMIT_PARENT))
return;
- bcopy(&d->rule, &rulenum, sizeof(rulenum));
- bprintf(bp, "%05d", rulenum);
+ bprintf(bp, RULENUM_FORMAT, d->rulenum);
if (fo->pcwidth > 0 || fo->bcwidth > 0) {
bprintf(bp, " ");
pr_u64(bp, &d->pcnt, fo->pcwidth);
pr_u64(bp, &d->bcnt, fo->bcwidth);
bprintf(bp, "(%ds)", d->expire);
}
- switch (d->dyn_type) {
+ switch (d->type) {
case O_LIMIT_PARENT:
- bprintf(bp, " PARENT %d", d->count);
+ bprintf(bp, " PARENT %u", d->count);
break;
case O_LIMIT:
bprintf(bp, " LIMIT");
@@ -2421,9 +2626,8 @@ ipfw_sets_handler(char *av[])
ipfw_range_tlv rt;
const char *msg;
size_t size;
- uint32_t masks[2];
+ uint32_t masks[2], rulenum;
int i;
- uint16_t rulenum;
uint8_t cmd;
av++;
@@ -2474,7 +2678,7 @@ ipfw_sets_handler(char *av[])
if (av[0] == NULL || av[1] == NULL || av[2] == NULL ||
av[3] != NULL || _substrcmp(av[1], "to") != 0)
errx(EX_USAGE, "syntax: set move [rule] X to Y\n");
- rulenum = atoi(av[0]);
+ rulenum = (uint32_t)strtoul(av[0], NULL, 10);
rt.new_set = atoi(av[2]);
if (cmd == IP_FW_XMOVE) {
rt.start_rule = rulenum;
@@ -2527,6 +2731,18 @@ ipfw_sets_handler(char *av[])
errx(EX_USAGE, "invalid set command %s\n", *av);
}
+static void
+manage_skipto_cache(int op)
+{
+ ipfw_cmd_header req;
+
+ memset(&req, 0, sizeof(req));
+ req.size = sizeof(req);
+ req.cmd = op ? SKIPTO_CACHE_ENABLE : SKIPTO_CACHE_DISABLE;
+
+ do_set3(IP_FW_SKIPTO_CACHE, &req.opheader, sizeof(req));
+}
+
void
ipfw_sysctl_handler(char *av[], int which)
{
@@ -2551,6 +2767,8 @@ ipfw_sysctl_handler(char *av[], int which)
} else if (_substrcmp(*av, "dyn_keepalive") == 0) {
sysctlbyname("net.inet.ip.fw.dyn_keepalive", NULL, 0,
&which, sizeof(which));
+ } else if (_substrcmp(*av, "skipto_cache") == 0) {
+ manage_skipto_cache(which);
#ifndef NO_ALTQ
} else if (_substrcmp(*av, "altq") == 0) {
altq_set_enabled(which);
@@ -2569,7 +2787,6 @@ prepare_format_dyn(struct cmdline_opts *co, struct format_opts *fo,
{
ipfw_dyn_rule *d;
int width;
- uint8_t set;
d = (ipfw_dyn_rule *)_state;
/* Count _ALL_ states */
@@ -2578,13 +2795,9 @@ prepare_format_dyn(struct cmdline_opts *co, struct format_opts *fo,
if (fo->show_counters == 0)
return;
- if (co->use_set) {
- /* skip states from another set */
- bcopy((char *)&d->rule + sizeof(uint16_t), &set,
- sizeof(uint8_t));
- if (set != co->use_set - 1)
- return;
- }
+ /* skip states from another set */
+ if (co->use_set != 0 && d->set != co->use_set - 1)
+ return;
width = pr_u64(NULL, &d->pcnt, 0);
if (width > fo->pcwidth)
@@ -2712,24 +2925,17 @@ static void
list_dyn_state(struct cmdline_opts *co, struct format_opts *fo,
void *_arg, void *_state)
{
- uint16_t rulenum;
- uint8_t set;
ipfw_dyn_rule *d;
struct buf_pr *bp;
d = (ipfw_dyn_rule *)_state;
bp = (struct buf_pr *)_arg;
- bcopy(&d->rule, &rulenum, sizeof(rulenum));
- if (rulenum > fo->last)
+ if (d->rulenum > fo->last)
return;
- if (co->use_set) {
- bcopy((char *)&d->rule + sizeof(uint16_t),
- &set, sizeof(uint8_t));
- if (set != co->use_set - 1)
- return;
- }
- if (rulenum >= fo->first) {
+ if (co->use_set != 0 && d->set != co->use_set - 1)
+ return;
+ if (d->rulenum >= fo->first) {
show_dyn_state(co, fo, bp, d);
printf("%s\n", bp->buf);
bp_flush(bp);
@@ -2784,7 +2990,7 @@ ipfw_list(int ac, char *av[], int show_counters)
}
}
- /* get configuraion from kernel */
+ /* get configuration from kernel */
cfg = NULL;
sfo.show_counters = show_counters;
sfo.show_time = g_co.do_time;
@@ -3055,7 +3261,7 @@ eaction_check_name(const char *name)
return (0);
}
-static uint16_t
+static uint32_t
pack_object(struct tidx *tstate, const char *name, int otype)
{
ipfw_obj_ntlv *ntlv;
@@ -3092,7 +3298,7 @@ pack_object(struct tidx *tstate, const char *name, int otype)
return (ntlv->idx);
}
-static uint16_t
+static uint32_t
pack_table(struct tidx *tstate, const char *name)
{
@@ -3102,12 +3308,32 @@ pack_table(struct tidx *tstate, const char *name)
return (pack_object(tstate, name, IPFW_TLV_TBL_NAME));
}
+static void
+fill_table_value(ipfw_insn *cmd, char *s)
+{
+ char *p;
+ int i;
+
+ p = strchr(s, '=');
+ if (p != NULL) {
+ *p++ = '\0';
+ i = match_token(tvalue_names, s);
+ if (i == -1)
+ errx(EX_USAGE,
+ "format: unknown table value name %s", s);
+ } else {
+ i = TVALUE_TAG;
+ p = s;
+ }
+
+ IPFW_SET_TVALUE_TYPE(cmd, i);
+ insntod(cmd, table)->value = strtoul(p, NULL, 0);
+}
+
void
-fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode,
- struct tidx *tstate)
+fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate)
{
- uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
- uint16_t uidx;
+ ipfw_insn_kidx *c = insntod(cmd, kidx);
char *p;
if ((p = strchr(av + 6, ')')) == NULL)
@@ -3117,19 +3343,19 @@ fill_table(struct _ipfw_insn *cmd, char *av, uint8_t opcode,
if (p)
*p++ = '\0';
- if ((uidx = pack_table(tstate, av + 6)) == 0)
+ if ((c->kidx = pack_table(tstate, av + 6)) == 0)
errx(EX_DATAERR, "Invalid table name: %s", av + 6);
cmd->opcode = opcode;
- cmd->arg1 = uidx;
if (p) {
- cmd->len |= F_INSN_SIZE(ipfw_insn_u32);
- d[0] = strtoul(p, NULL, 0);
- } else
- cmd->len |= F_INSN_SIZE(ipfw_insn);
+ cmd->len |= F_INSN_SIZE(ipfw_insn_table);
+ fill_table_value(cmd, p);
+ } else {
+ IPFW_SET_LOOKUP_TYPE(cmd, LOOKUP_NONE);
+ cmd->len |= F_INSN_SIZE(ipfw_insn_kidx);
+ }
}
-
/*
* fills the addr and mask fields in the instruction as appropriate from av.
* Update length as appropriate.
@@ -3360,7 +3586,7 @@ ipfw_delete(char *av[])
{
ipfw_range_tlv rt;
char *sep;
- int i, j;
+ uint32_t i, j;
int exitval = EX_OK;
int do_set = 0;
@@ -3393,8 +3619,8 @@ ipfw_delete(char *av[])
rt.set = i & 31;
rt.flags = IPFW_RCFLAG_SET;
} else {
- rt.start_rule = i & 0xffff;
- rt.end_rule = j & 0xffff;
+ rt.start_rule = i;
+ rt.end_rule = j;
if (rt.start_rule == 0 && rt.end_rule == 0)
rt.flags |= IPFW_RCFLAG_ALL;
else
@@ -3419,7 +3645,7 @@ ipfw_delete(char *av[])
if (g_co.do_quiet)
continue;
if (rt.start_rule != rt.end_rule)
- warnx("no rules rules in %u-%u range",
+ warnx("no rules in %u-%u range",
rt.start_rule, rt.end_rule);
else
warnx("rule %u not found",
@@ -3431,7 +3657,6 @@ ipfw_delete(char *av[])
exit(exitval);
}
-
/*
* fill the interface structure. We do not check the name as we can
* create interfaces dynamically, so checking them at insert time
@@ -3443,7 +3668,7 @@ static void
fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate)
{
char *p;
- uint16_t uidx;
+ uint32_t uidx;
cmd->name[0] = '\0';
cmd->o.len |= F_INSN_SIZE(ipfw_insn_if);
@@ -3751,6 +3976,8 @@ static struct _s_x f_reserved_keywords[] = {
{ "to", TOK_OR },
{ "via", TOK_OR },
{ "{", TOK_OR },
+ { "lookup", TOK_OR },
+ { "tagged", TOK_OR },
{ NULL, 0 } /* terminator */
};
@@ -3831,6 +4058,77 @@ add_dst(ipfw_insn *cmd, char *av, u_char proto, int cblen, struct tidx *tstate)
return ret;
}
+static uint16_t
+parse_logdst(char *logdst_iter)
+{
+ char *token;
+ uint16_t ret;
+
+ ret = IPFW_LOG_DEFAULT;
+ while ((token = strsep(&logdst_iter, ",")) != NULL) {
+ if (_substrcmp(token, "syslog") == 0) {
+ ret |= IPFW_LOG_SYSLOG;
+ continue;
+ }
+ if (_substrcmp(token, "ipfw0") == 0) {
+ /* XXX add multiple ipfw* */
+ ret |= IPFW_LOG_IPFW0;
+ continue;
+ }
+ if (_substrcmp(token, "rtsock") == 0) {
+ ret |= IPFW_LOG_RTSOCK;
+ continue;
+ }
+ errx(EX_DATAERR,
+ "unsupported logdst token");
+ }
+ return (ret);
+}
+
+static inline uint32_t
+arg_or_targ_relaxed(const char *arg, const char *action, uint32_t maxarg)
+{
+ uint32_t arg1 = (uint32_t)(-1);
+
+ if (arg == NULL)
+ errx(EX_USAGE, "missing argument for %s", action);
+ if (isdigit(arg[0])) {
+ arg1 = strtoul(arg, NULL, 10);
+ if (arg1 < IPFW_ARG_MIN || arg1 > maxarg)
+ errx(EX_DATAERR, "illegal argument %s(%u) for %s",
+ arg, arg1, action);
+ } else if (_substrcmp(arg, "tablearg") == 0)
+ arg1 = IP_FW_TARG;
+ return (arg1);
+}
+
+static inline uint32_t
+arg_or_targ(const char *arg, const char *action)
+{
+ uint32_t arg1 = arg_or_targ_relaxed(arg, action, IPFW_ARG_MAX);
+
+ if (arg1 == (uint32_t)(-1))
+ errx(EX_DATAERR, "illegal argument %s(%u) for %s",
+ arg, arg1, action);
+ return (arg1);
+}
+
+static uint16_t
+get_divert_port(const char *arg, const char *action)
+{
+ uint32_t arg1 = arg_or_targ_relaxed(arg, action, IPFW_ARG_MAX);
+
+ if (arg1 != (uint32_t)(-1))
+ return (arg1);
+
+ struct servent *s;
+ setservent(1);
+ s = getservbyname(arg, "divert");
+ if (s == NULL)
+ errx(EX_DATAERR, "illegal divert/tee port");
+ return (ntohs(s->s_port));
+}
+
/*
* Parse arguments and assemble the microinstructions which make up a rule.
* Rules are added into the 'rulebuf' and then copied in the correct order
@@ -3888,8 +4186,8 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
rblen = *rbufsize / sizeof(uint32_t);
rblen -= sizeof(struct ip_fw_rule) / sizeof(uint32_t);
- ablen = sizeof(actbuf) / sizeof(actbuf[0]);
- cblen = sizeof(cmdbuf) / sizeof(cmdbuf[0]);
+ ablen = nitems(actbuf);
+ cblen = nitems(cmdbuf);
cblen -= F_INSN_SIZE(ipfw_insn_u32) + 1;
#define CHECK_RBUFLEN(len) { CHECK_LENGTH(rblen, len); rblen -= len; }
@@ -3932,18 +4230,20 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
case TOK_CHECKSTATE:
have_state = action;
action->opcode = O_CHECK_STATE;
+ action->len = F_INSN_SIZE(ipfw_insn_kidx);
+ CHECK_ACTLEN;
if (*av == NULL ||
match_token(rule_options, *av) == TOK_COMMENT) {
- action->arg1 = pack_object(tstate,
+ insntod(have_state, kidx)->kidx = pack_object(tstate,
default_state_name, IPFW_TLV_STATE_NAME);
break;
}
if (*av[0] == ':') {
if (strcmp(*av + 1, "any") == 0)
- action->arg1 = 0;
+ insntod(have_state, kidx)->kidx = 0;
else if (state_check_name(*av + 1) == 0)
- action->arg1 = pack_object(tstate, *av + 1,
- IPFW_TLV_STATE_NAME);
+ insntod(have_state, kidx)->kidx = pack_object(
+ tstate, *av + 1, IPFW_TLV_STATE_NAME);
else
errx(EX_DATAERR, "Invalid state name %s",
*av);
@@ -3990,14 +4290,25 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
case TOK_UNREACH:
action->opcode = O_REJECT;
NEED1("missing reject code");
- fill_reject_code(&action->arg1, *av);
+ action->arg1 = get_reject_code(*av);
av++;
+ if (action->arg1 == ICMP_UNREACH_NEEDFRAG && isdigit(**av)) {
+ uint16_t mtu;
+
+ mtu = strtoul(*av, NULL, 10);
+ if (mtu < 68 || mtu >= IP_MAXPACKET)
+ errx(EX_DATAERR, "illegal argument for %s",
+ *(av - 1));
+ action->len = F_INSN_SIZE(ipfw_insn_u16);
+ insntod(action, u16)->ports[0] = mtu;
+ av++;
+ }
break;
case TOK_UNREACH6:
action->opcode = O_UNREACH6;
NEED1("missing unreach code");
- fill_unreach6_code(&action->arg1, *av);
+ action->arg1 = get_unreach6_code(*av);
av++;
break;
@@ -4009,55 +4320,56 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
action->opcode = O_NAT;
action->len = F_INSN_SIZE(ipfw_insn_nat);
CHECK_ACTLEN;
- if (*av != NULL && _substrcmp(*av, "global") == 0) {
+ if (*av != NULL && _substrcmp(*av, "global") == 0)
action->arg1 = IP_FW_NAT44_GLOBAL;
- av++;
- break;
- } else
- goto chkarg;
+ else
+ action->arg1 = arg_or_targ(av[0], *(av - 1));
+ av++;
+ break;
case TOK_QUEUE:
action->opcode = O_QUEUE;
- goto chkarg;
+ action->arg1 = arg_or_targ(av[0], *(av - 1));
+ av++;
+ break;
case TOK_PIPE:
action->opcode = O_PIPE;
- goto chkarg;
+ action->arg1 = arg_or_targ(av[0], *(av - 1));
+ av++;
+ break;
case TOK_SKIPTO:
action->opcode = O_SKIPTO;
- goto chkarg;
+ action->len = F_INSN_SIZE(ipfw_insn_u32);
+ CHECK_ACTLEN;
+ insntod(action, u32)->d[0] =
+ arg_or_targ_relaxed(av[0], *(av - 1), IPFW_DEFAULT_RULE);
+ av++;
+ break;
case TOK_NETGRAPH:
action->opcode = O_NETGRAPH;
- goto chkarg;
+ action->arg1 = arg_or_targ(av[0], *(av - 1));
+ av++;
+ break;
case TOK_NGTEE:
action->opcode = O_NGTEE;
- goto chkarg;
+ action->arg1 = arg_or_targ(av[0], *(av - 1));
+ av++;
+ break;
case TOK_DIVERT:
action->opcode = O_DIVERT;
- goto chkarg;
+ action->arg1 = get_divert_port(av[0], *(av - 1));
+ av++;
+ break;
case TOK_TEE:
action->opcode = O_TEE;
- goto chkarg;
+ action->arg1 = get_divert_port(av[0], *(av - 1));
+ av++;
+ break;
case TOK_CALL:
action->opcode = O_CALLRETURN;
-chkarg:
- if (!av[0])
- errx(EX_USAGE, "missing argument for %s", *(av - 1));
- if (isdigit(**av)) {
- action->arg1 = strtoul(*av, NULL, 10);
- if (action->arg1 <= 0 || action->arg1 >= IP_FW_TABLEARG)
- errx(EX_DATAERR, "illegal argument for %s",
- *(av - 1));
- } else if (_substrcmp(*av, "tablearg") == 0) {
- action->arg1 = IP_FW_TARG;
- } else if (i == TOK_DIVERT || i == TOK_TEE) {
- struct servent *s;
- setservent(1);
- s = getservbyname(av[0], "divert");
- if (s != NULL)
- action->arg1 = ntohs(s->s_port);
- else
- errx(EX_DATAERR, "illegal divert/tee port");
- } else
- errx(EX_DATAERR, "illegal argument for %s", *(av - 1));
+ action->len = F_INSN_SIZE(ipfw_insn_u32);
+ CHECK_ACTLEN;
+ insntod(action, u32)->d[0] =
+ arg_or_targ_relaxed(av[0], *(av - 1), IPFW_DEFAULT_RULE);
av++;
break;
@@ -4225,17 +4537,51 @@ chkarg:
break;
case TOK_RETURN:
- fill_cmd(action, O_CALLRETURN, F_NOT, 0);
+ action->opcode = O_CALLRETURN;
+ action->len = F_INSN_SIZE(ipfw_insn_u32) | F_NOT;
+ CHECK_ACTLEN;
+ if (*av != NULL) {
+ /*
+ * Return type is optional.
+ * By default we use RETURN_NEXT_RULENUM.
+ */
+ i = match_token(return_types, *av);
+ if (i >= 0) {
+ action->arg1 = i;
+ av++;
+ } else
+ action->arg1 = RETURN_NEXT_RULENUM;
+ }
+ break;
+
+ case TOK_SETMARK: {
+ action->opcode = O_SETMARK;
+ action->len = F_INSN_SIZE(ipfw_insn_u32);
+ NEED1("missing mark");
+ if (strcmp(*av, "tablearg") == 0) {
+ action->arg1 = IP_FW_TARG;
+ } else {
+ insntod(action, u32)->d[0] = strtoul(*av, NULL, 0);
+ /* This is not a tablearg */
+ action->arg1 |= 0x8000;
+ }
+ av++;
+ CHECK_CMDLEN;
break;
+ }
case TOK_TCPSETMSS: {
u_long mss;
- uint16_t idx;
+ uint32_t idx;
idx = pack_object(tstate, "tcp-setmss", IPFW_TLV_EACTION);
if (idx == 0)
errx(EX_DATAERR, "pack_object failed");
- fill_cmd(action, O_EXTERNAL_ACTION, 0, idx);
+ action->opcode = O_EXTERNAL_ACTION;
+ action->len = F_INSN_SIZE(ipfw_insn_kidx);
+ CHECK_ACTLEN;
+ insntod(action, kidx)->kidx = idx;
+
NEED1("Missing MSS value");
action = next_cmd(action, &ablen);
action->len = 1;
@@ -4261,7 +4607,7 @@ chkarg:
* syntax.
*/
case TOK_EACTION: {
- uint16_t idx;
+ uint32_t idx;
NEED1("Missing eaction name");
if (eaction_check_name(*av) != 0)
@@ -4269,12 +4615,13 @@ chkarg:
idx = pack_object(tstate, *av, IPFW_TLV_EACTION);
if (idx == 0)
errx(EX_DATAERR, "pack_object failed");
- fill_cmd(action, O_EXTERNAL_ACTION, 0, idx);
+ action->opcode = O_EXTERNAL_ACTION;
+ action->len = F_INSN_SIZE(ipfw_insn_kidx);
+ CHECK_ACTLEN;
+ insntod(action, kidx)->kidx = idx;
+
av++;
NEED1("Missing eaction instance name");
- action = next_cmd(action, &ablen);
- action->len = 1;
- CHECK_ACTLEN;
if (eaction_check_name(*av) != 0)
errx(EX_DATAERR, "Invalid eaction instance name %s",
*av);
@@ -4286,7 +4633,11 @@ chkarg:
idx = pack_object(tstate, *av, 0);
if (idx == 0)
errx(EX_DATAERR, "pack_object failed");
- fill_cmd(action, O_EXTERNAL_INSTANCE, 0, idx);
+ action = next_cmd(action, &ablen);
+ action->opcode = O_EXTERNAL_INSTANCE;
+ action->len = F_INSN_SIZE(ipfw_insn_kidx);
+ CHECK_ACTLEN;
+ insntod(action, kidx)->kidx = idx;
av++;
}
}
@@ -4314,6 +4665,15 @@ chkarg:
cmd->len = F_INSN_SIZE(ipfw_insn_log);
CHECK_CMDLEN;
cmd->opcode = O_LOG;
+ cmd->arg1 = IPFW_LOG_DEFAULT;
+ /* logdst before logamount */
+ if (av[0] && _substrcmp(*av, "logdst") == 0) {
+ av++;
+ NEED1("logdst requires argument");
+ cmd->arg1 = parse_logdst(*av);
+ av++;
+ }
+
if (av[0] && _substrcmp(*av, "logamount") == 0) {
av++;
NEED1("logamount requires argument");
@@ -4335,6 +4695,14 @@ chkarg:
"net.inet.ip.fw.verbose_limit");
}
}
+
+ /* logdst after logamount */
+ if (av[0] && _substrcmp(*av, "logdst") == 0) {
+ av++;
+ NEED1("logdst requires argument");
+ cmd->arg1 = parse_logdst(*av);
+ av++;
+ }
}
break;
@@ -4647,7 +5015,7 @@ read_options:
case TOK_VIA:
NEED1("recv, xmit, via require interface name"
" or address");
- fill_iface((ipfw_insn_if *)cmd, av[0], cblen, tstate);
+ fill_iface(insntod(cmd, if), av[0], cblen, tstate);
av++;
if (F_LEN(cmd) == 0) /* not a valid address */
break;
@@ -4857,7 +5225,7 @@ read_options:
case TOK_KEEPSTATE:
case TOK_RECORDSTATE: {
- uint16_t uidx;
+ uint32_t uidx;
if (open_par)
errx(EX_USAGE, "keep-state or record-state cannot be part "
@@ -4877,13 +5245,16 @@ read_options:
IPFW_TLV_STATE_NAME);
have_state = cmd;
have_rstate = i == TOK_RECORDSTATE;
- fill_cmd(cmd, O_KEEP_STATE, 0, uidx);
+ cmd->opcode = O_KEEP_STATE;
+ cmd->len = F_INSN_SIZE(ipfw_insn_kidx);
+ CHECK_CMDLEN;
+ insntod(have_state, kidx)->kidx = uidx;
break;
}
case TOK_LIMIT:
case TOK_SETLIMIT: {
- ipfw_insn_limit *c = (ipfw_insn_limit *)cmd;
+ ipfw_insn_limit *c = insntod(cmd, limit);
int val;
if (open_par)
@@ -4895,10 +5266,10 @@ read_options:
have_state = cmd;
have_rstate = i == TOK_SETLIMIT;
+ cmd->opcode = O_LIMIT;
cmd->len = F_INSN_SIZE(ipfw_insn_limit);
CHECK_CMDLEN;
- cmd->opcode = O_LIMIT;
- c->limit_mask = c->conn_limit = 0;
+ c->limit_mask = c->conn_limit = c->kidx = 0;
while ( av[0] != NULL ) {
if ((val = match_token(limit_masks, *av)) <= 0)
@@ -4918,11 +5289,11 @@ read_options:
if (state_check_name(*av + 1) != 0)
errx(EX_DATAERR,
"Invalid state name %s", *av);
- cmd->arg1 = pack_object(tstate, *av + 1,
+ c->kidx = pack_object(tstate, *av + 1,
IPFW_TLV_STATE_NAME);
av++;
} else
- cmd->arg1 = pack_object(tstate,
+ c->kidx = pack_object(tstate,
default_state_name, IPFW_TLV_STATE_NAME);
break;
}
@@ -5079,24 +5450,55 @@ read_options:
break;
case TOK_LOOKUP: {
- ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd;
+ /* optional mask for some LOOKUP types */
+ ipfw_insn_table *c = insntod(cmd, table);
+ char *lkey;
if (!av[0] || !av[1])
- errx(EX_USAGE, "format: lookup argument tablenum");
+ errx(EX_USAGE,
+ "format: lookup argument tablenum");
cmd->opcode = O_IP_DST_LOOKUP;
- cmd->len |= F_INSN_SIZE(ipfw_insn) + 2;
- i = match_token(lookup_keys, *av);
- if (i == -1)
- errx(EX_USAGE, "format: cannot lookup on %s", *av);
- __PAST_END(c->d, 1) = i;
- av++;
- if ((i = pack_table(tstate, *av)) == 0)
- errx(EX_DATAERR, "Invalid table name: %s", *av);
+ lkey = strsep(av, ":");
+ i = match_token(lookup_keys, lkey);
+ if (i == -1)
+ errx(EX_USAGE,
+ "format: cannot lookup on %s", lkey);
+ /* masked lookup key */
+ if (*av != NULL) {
+ switch (i) {
+ case LOOKUP_DST_PORT:
+ case LOOKUP_SRC_PORT:
+ case LOOKUP_UID:
+ case LOOKUP_JAIL:
+ case LOOKUP_DSCP:
+ case LOOKUP_MARK:
+ case LOOKUP_RULENUM:
+ break;
+ default:
+ errx(EX_USAGE,
+ "masked lookup is not supported "
+ "for %s", lkey);
+ }
+ cmd->len |= F_INSN_SIZE(ipfw_insn_table);
+ c->value = strtoul(*av, NULL, 0);
+ if (c->value == 0)
+ errx(EX_USAGE,
+ "all-zeroes bitmask for lookup "
+ "is meaningless");
+ } else {
+ cmd->len |= F_INSN_SIZE(ipfw_insn_kidx);
+ }
+ CHECK_CMDLEN;
- cmd->arg1 = i;
+ IPFW_SET_LOOKUP_TYPE(cmd, i);
av++;
- }
+ c->kidx = pack_table(tstate, *av);
+ if (c->kidx == 0)
+ errx(EX_DATAERR,
+ "Invalid table name: %s", *av);
+ av++;
+ }
break;
case TOK_FLOW:
NEED1("missing table name");
@@ -5115,6 +5517,12 @@ read_options:
fill_cmd(cmd, O_SKIP_ACTION, 0, 0);
break;
+ case TOK_MARK:
+ NEED1("missing mark value:mask");
+ fill_mark(cmd, *av, cblen);
+ av++;
+ break;
+
default:
errx(EX_USAGE, "unrecognised option [%d] %s\n", i, s);
}
@@ -5153,7 +5561,9 @@ done:
* generate O_PROBE_STATE if necessary
*/
if (have_state && have_state->opcode != O_CHECK_STATE && !have_rstate) {
- fill_cmd(dst, O_PROBE_STATE, 0, have_state->arg1);
+ dst->opcode = O_PROBE_STATE;
+ dst->len = F_INSN_SIZE(ipfw_insn_kidx);
+ insntod(dst, kidx)->kidx = insntod(have_state, kidx)->kidx;
dst = next_cmd(dst, &rblen);
}
@@ -5275,7 +5685,7 @@ object_sort_ctlv(ipfw_obj_ctlv *ctlv)
}
struct object_kt {
- uint16_t uidx;
+ uint32_t uidx;
uint16_t type;
};
static int
@@ -5309,7 +5719,7 @@ compare_object_kntlv(const void *k, const void *v)
* Returns table name or NULL.
*/
static char *
-object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx, uint16_t type)
+object_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx, uint16_t type)
{
ipfw_obj_ntlv *ntlv;
struct object_kt key;
@@ -5327,7 +5737,7 @@ object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx, uint16_t type)
}
static char *
-table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx)
+table_search_ctlv(ipfw_obj_ctlv *ctlv, uint32_t idx)
{
return (object_search_ctlv(ctlv, idx, IPFW_TLV_TBL_NAME));
@@ -5548,6 +5958,7 @@ static struct _s_x intcmds[] = {
{ "iflist", TOK_IFLIST },
{ "olist", TOK_OLIST },
{ "vlist", TOK_VLIST },
+ { "monitor", TOK_MONITOR },
{ NULL, 0 }
};
@@ -5622,6 +6033,134 @@ ipfw_list_objects(int ac __unused, char *av[] __unused)
free(olh);
}
+static void
+bprint_sa(struct buf_pr *bp, const struct sockaddr *sa)
+{
+ struct sockaddr_storage ss;
+ char buf[INET6_ADDRSTRLEN];
+
+ memset(&ss, 0, sizeof(ss));
+ if (sa->sa_len == 0)
+ ss.ss_family = sa->sa_family;
+ else
+ memcpy(&ss, sa, sa->sa_len);
+
+ /* set ss_len in case it was shortened */
+ switch (sa->sa_family) {
+ case AF_INET:
+ ss.ss_len = sizeof(struct sockaddr_in);
+ break;
+ default:
+ ss.ss_len = sizeof(struct sockaddr_in6);
+ }
+ if (getnameinfo((const struct sockaddr *)&ss, ss.ss_len,
+ buf, sizeof(buf), NULL, 0, NI_NUMERICHOST) != 0) {
+ bprintf(bp, "bad-addr");
+ return;
+ }
+ bprintf(bp, "%s", buf);
+}
+
+static void
+ipfw_rtsock_monitor(const char *filter)
+{
+ char msg[2048], buf[32];
+ struct timespec tp;
+ struct tm tm;
+ struct buf_pr bp;
+ struct rt_msghdr *hdr;
+ struct sockaddr *sa;
+ struct sockaddr_dl *sdl;
+ ipfwlog_rtsock_hdr_v2 *loghdr;
+ ssize_t nread;
+ size_t msglen;
+ int rtsock;
+
+ rtsock = socket(PF_ROUTE, SOCK_RAW, AF_IPFWLOG);
+ if (rtsock < 0)
+ err(EX_UNAVAILABLE, "socket(AF_IPFWLOG)");
+ bp_alloc(&bp, 4096);
+ for (;;) {
+ nread = read(rtsock, msg, sizeof(msg));
+ if (nread < 0) {
+ warn("read()");
+ continue;
+ }
+ msglen = nread;
+ if (msglen < sizeof(*hdr))
+ continue;
+
+ hdr = (struct rt_msghdr *)msg;
+ if (hdr->rtm_version != RTM_VERSION ||
+ hdr->rtm_type != RTM_IPFWLOG ||
+ (hdr->rtm_addrs & (1 << RTAX_DST)) == 0 ||
+ (hdr->rtm_addrs & (1 << RTAX_GATEWAY)) == 0 ||
+ (hdr->rtm_addrs & (1 << RTAX_NETMASK)) == 0)
+ continue;
+
+ msglen -= sizeof(*hdr);
+ sdl = (struct sockaddr_dl *)(hdr + 1);
+ if (msglen < sizeof(*sdl) || msglen < SA_SIZE(sdl) ||
+ sdl->sdl_family != AF_IPFWLOG ||
+ sdl->sdl_type != 2 /* version */ ||
+ sdl->sdl_alen != sizeof(*loghdr))
+ continue;
+
+ msglen -= SA_SIZE(sdl);
+ loghdr = (ipfwlog_rtsock_hdr_v2 *)sdl->sdl_data;
+ /* filter by rule comment. MAX_COMMENT_LEN = 80 */
+ if (filter != NULL &&
+ strncmp(filter, loghdr->comment, 80) != 0)
+ continue;
+
+ sa = (struct sockaddr *)((char *)sdl + SA_SIZE(sdl));
+ if (msglen < SA_SIZE(sa))
+ continue;
+
+ msglen -= SA_SIZE(sa);
+ bp_flush(&bp);
+
+ clock_gettime(CLOCK_REALTIME, &tp);
+ localtime_r(&tp.tv_sec, &tm);
+ strftime(buf, sizeof(buf), "%T", &tm);
+ bprintf(&bp, "%s.%03ld AF %s", buf, tp.tv_nsec / 1000000,
+ sa->sa_family == AF_INET ? "IPv4" : "IPv6");
+
+ bprintf(&bp, " %s >",
+ ether_ntoa((const struct ether_addr *)loghdr->ether_shost));
+ bprintf(&bp, " %s, ",
+ ether_ntoa((const struct ether_addr *)loghdr->ether_dhost));
+ bprint_sa(&bp, sa);
+
+ sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
+ if (msglen < SA_SIZE(sa))
+ continue;
+
+ msglen -= SA_SIZE(sa);
+ bprintf(&bp, " > ");
+ bprint_sa(&bp, sa);
+ bprintf(&bp, ", set %u, rulenum %u, targ 0x%08x, "
+ "%scmd[op %d, len %d, arg1 0x%04x], mark 0x%08x",
+ sdl->sdl_index, loghdr->rulenum, loghdr->tablearg,
+ (loghdr->cmd.len & F_NOT) ? "!": "",
+ loghdr->cmd.opcode, F_LEN(&loghdr->cmd),
+ loghdr->cmd.arg1, loghdr->mark);
+
+ sa = (struct sockaddr *)((char *)sa + SA_SIZE(sa));
+ if ((hdr->rtm_addrs & (1 << RTAX_GENMASK)) != 0 &&
+ msglen >= SA_SIZE(sa)) {
+ msglen -= SA_SIZE(sa);
+ bprintf(&bp, ", nh ");
+ bprint_sa(&bp, sa);
+ }
+ if (sdl->sdl_nlen > 0)
+ bprintf(&bp, " // %s", loghdr->comment);
+ printf("%s\n", bp.buf);
+ }
+ bp_free(&bp);
+ close(rtsock);
+}
+
void
ipfw_internal_handler(int ac, char *av[])
{
@@ -5646,6 +6185,10 @@ ipfw_internal_handler(int ac, char *av[])
case TOK_VLIST:
ipfw_list_values(ac, av);
break;
+ case TOK_MONITOR:
+ av++;
+ ipfw_rtsock_monitor(*av);
+ break;
}
}
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index dd7699987434..f19ea59c1bb4 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -16,8 +16,6 @@
* This software is provided ``AS IS'' without any warranties of any kind.
*
* NEW command line interface for IP firewall facility
- *
- * $FreeBSD$
*/
enum cmdline_prog {
@@ -48,6 +46,7 @@ struct cmdline_opts {
int test_only; /* only check syntax */
int comment_only; /* only print action and comment */
int verbose; /* be verbose on some commands */
+ int debug_only; /* output ioctl i/o on stdout */
/* The options below can have multiple values. */
@@ -276,6 +275,7 @@ enum tokens {
TOK_UNLOCK,
TOK_VLIST,
TOK_OLIST,
+ TOK_MONITOR,
TOK_MISSING,
TOK_ORFLUSH,
@@ -306,6 +306,8 @@ enum tokens {
TOK_LOGOFF,
TOK_PRIVATE,
TOK_PRIVATEOFF,
+ TOK_SWAPCONF,
+ TOK_SWAPCONFOFF,
/* NAT64 CLAT tokens */
TOK_NAT64CLAT,
@@ -321,7 +323,11 @@ enum tokens {
TOK_TCPSETMSS,
+ TOK_MARK,
+ TOK_SETMARK,
+
TOK_SKIPACTION,
+ TOK_UDP_EIM,
};
/*
@@ -342,7 +348,7 @@ struct buf_pr {
int pr_u64(struct buf_pr *bp, void *pd, int width);
int bp_alloc(struct buf_pr *b, size_t size);
void bp_free(struct buf_pr *b);
-int bprintf(struct buf_pr *b, const char *format, ...);
+int bprintf(struct buf_pr *b, const char *format, ...) __printflike(2, 3);
/* memory allocation support */
@@ -444,7 +450,7 @@ struct _ipfw_insn *add_dstip6(struct _ipfw_insn *cmd, char *av, int cblen,
struct tidx *tstate);
void fill_flow6(struct _ipfw_insn_u32 *cmd, char *av, int cblen);
-void fill_unreach6_code(u_short *codep, char *str);
+uint16_t get_unreach6_code(const char *str);
void fill_icmp6types(struct _ipfw_insn_icmp6 *cmd, char *av, int cblen);
int fill_ext6hdr(struct _ipfw_insn *cmd, char *av);
@@ -460,5 +466,5 @@ int table_check_name(const char *tablename);
void ipfw_list_ta(int ac, char *av[]);
void ipfw_list_values(int ac, char *av[]);
void table_fill_ntlv(struct _ipfw_obj_ntlv *ntlv, const char *name,
- uint8_t set, uint16_t uidx);
+ uint8_t set, uint32_t uidx);
diff --git a/sbin/ipfw/ipv6.c b/sbin/ipfw/ipv6.c
index eea313572f34..e6139976e6cb 100644
--- a/sbin/ipfw/ipv6.c
+++ b/sbin/ipfw/ipv6.c
@@ -17,8 +17,6 @@
*
* NEW command line interface for IP firewall facility
*
- * $FreeBSD$
- *
* ipv6 support
*/
@@ -55,8 +53,8 @@ static struct _s_x icmp6codes[] = {
{ NULL, 0 }
};
-void
-fill_unreach6_code(u_short *codep, char *str)
+uint16_t
+get_unreach6_code(const char *str)
{
int val;
char *s;
@@ -66,8 +64,7 @@ fill_unreach6_code(u_short *codep, char *str)
val = match_token(icmp6codes, str);
if (val < 0)
errx(EX_DATAERR, "unknown ICMPv6 unreachable code ``%s''", str);
- *codep = val;
- return;
+ return (val);
}
void
diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c
index 1b9c7f324a9c..92c593f4f09e 100644
--- a/sbin/ipfw/main.c
+++ b/sbin/ipfw/main.c
@@ -16,8 +16,6 @@
* This software is provided ``AS IS'' without any warranties of any kind.
*
* Command line interface for IP firewall facility
- *
- * $FreeBSD$
*/
#include <sys/wait.h>
@@ -30,6 +28,7 @@
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
+#include <libgen.h>
#include "ipfw2.h"
@@ -44,7 +43,7 @@ help(void)
"add [num] [set N] [prob x] RULE-BODY\n"
"{pipe|queue} N config PIPE-BODY\n"
"[pipe|queue] {zero|delete|show} [N{,N}]\n"
-"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|unreg_cgn|\n"
+"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|unreg_cgn|udp_eim|\n"
" reset|reverse|proxy_only|redirect_addr linkspec|\n"
" redirect_port linkspec|redirect_proto linkspec|\n"
" port_range lower-upper}\n"
@@ -276,7 +275,7 @@ ipfw_main(int oldac, char **oldav)
optind = optreset = 1; /* restart getopt() */
if (is_ipfw()) {
- while ((ch = getopt(ac, av, "abcdDefhinNp:qs:STtv")) != -1)
+ while ((ch = getopt(ac, av, "abcdDefhinNp:qs:STtvx")) != -1)
switch (ch) {
case 'a':
do_acct = 1;
@@ -353,6 +352,10 @@ ipfw_main(int oldac, char **oldav)
g_co.verbose = 1;
break;
+ case 'x': /* debug output */
+ g_co.debug_only = 1;
+ break;
+
default:
free(save_av);
return 1;
@@ -682,7 +685,7 @@ main(int ac, char *av[])
}
#endif
- if (strcmp(av[0], "dnctl") == 0)
+ if (strcmp("dnctl", basename(av[0])) == 0)
g_co.prog = cmdline_prog_dnctl;
else
g_co.prog = cmdline_prog_ipfw;
diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c
index 1076e1038b8a..db74abaab233 100644
--- a/sbin/ipfw/nat.c
+++ b/sbin/ipfw/nat.c
@@ -17,8 +17,6 @@
*
* NEW command line interface for IP firewall facility
*
- * $FreeBSD$
- *
* In-kernel nat support
*/
@@ -69,6 +67,7 @@ static struct _s_x nat_params[] = {
{ "redirect_addr", TOK_REDIR_ADDR },
{ "redirect_port", TOK_REDIR_PORT },
{ "redirect_proto", TOK_REDIR_PROTO },
+ { "udp_eim", TOK_UDP_EIM },
{ NULL, 0 } /* terminator */
};
@@ -678,6 +677,9 @@ nat_show_cfg(struct nat44_cfg_nat *n, void *arg __unused)
} else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
printf(" proxy_only");
n->mode &= ~PKT_ALIAS_PROXY_ONLY;
+ } else if (n->mode & PKT_ALIAS_UDP_EIM) {
+ printf(" udp_eim");
+ n->mode &= ~PKT_ALIAS_UDP_EIM;
}
}
/* Print all the redirect's data configuration. */
@@ -823,6 +825,7 @@ ipfw_config_nat(int ac, char **av)
case TOK_RESET_ADDR:
case TOK_ALIAS_REV:
case TOK_PROXY_ONLY:
+ case TOK_UDP_EIM:
break;
case TOK_REDIR_ADDR:
if (ac1 < 2)
@@ -929,6 +932,9 @@ ipfw_config_nat(int ac, char **av)
case TOK_PROXY_ONLY:
n->mode |= PKT_ALIAS_PROXY_ONLY;
break;
+ case TOK_UDP_EIM:
+ n->mode |= PKT_ALIAS_UDP_EIM;
+ break;
/*
* All the setup_redir_* functions work directly in
* the final buffer, see above for details.
@@ -1074,7 +1080,6 @@ nat_foreach(nat_cb_t *f, void *arg, int sort)
struct nat44_cfg_nat *cfg;
size_t sz;
uint32_t i;
- int error;
/* Start with reasonable default */
sz = sizeof(*olh) + 16 * sizeof(struct nat44_cfg_nat);
@@ -1097,7 +1102,7 @@ nat_foreach(nat_cb_t *f, void *arg, int sort)
cfg = (struct nat44_cfg_nat*)(olh + 1);
for (i = 0; i < olh->count; i++) {
- error = f(cfg, arg); /* Ignore errors for now */
+ (void)f(cfg, arg); /* Ignore errors for now */
cfg = (struct nat44_cfg_nat *)((caddr_t)cfg +
olh->objsize);
}
diff --git a/sbin/ipfw/nat64clat.c b/sbin/ipfw/nat64clat.c
index 962fe7064f8d..63fa7dae14e2 100644
--- a/sbin/ipfw/nat64clat.c
+++ b/sbin/ipfw/nat64clat.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Yandex LLC
* Copyright (c) 2019 Andrey V. Elsukov <ae@FreeBSD.org>
@@ -27,9 +27,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
@@ -505,7 +502,6 @@ nat64clat_foreach(nat64clat_cb_t *f, const char *name, uint8_t set, int sort)
ipfw_nat64clat_cfg *cfg;
size_t sz;
uint32_t i;
- int error;
/* Start with reasonable default */
sz = sizeof(*olh) + 16 * sizeof(*cfg);
@@ -528,7 +524,7 @@ nat64clat_foreach(nat64clat_cb_t *f, const char *name, uint8_t set, int sort)
cfg = (ipfw_nat64clat_cfg *)(olh + 1);
for (i = 0; i < olh->count; i++) {
- error = f(cfg, name, set); /* Ignore errors for now */
+ (void)f(cfg, name, set); /* Ignore errors for now */
cfg = (ipfw_nat64clat_cfg *)((caddr_t)cfg +
olh->objsize);
}
diff --git a/sbin/ipfw/nat64lsn.c b/sbin/ipfw/nat64lsn.c
index ff36181815d9..fe3ff8e0fdb8 100644
--- a/sbin/ipfw/nat64lsn.c
+++ b/sbin/ipfw/nat64lsn.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2015-2019 Yandex LLC
* Copyright (c) 2015-2016 Alexander V. Chernikov <melifaro@FreeBSD.org>
@@ -27,9 +27,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
@@ -383,6 +380,8 @@ static struct _s_x nat64newcmds[] = {
{ "-log", TOK_LOGOFF },
{ "allow_private", TOK_PRIVATE },
{ "-allow_private", TOK_PRIVATEOFF },
+ { "swap_conf", TOK_SWAPCONF },
+ { "-swap_conf", TOK_SWAPCONFOFF },
/* for compatibility with old configurations */
{ "max_ports", TOK_MAX_PORTS }, /* unused */
{ NULL, 0 }
@@ -517,6 +516,12 @@ nat64lsn_create(const char *name, uint8_t set, int ac, char **av)
case TOK_PRIVATEOFF:
cfg->flags &= ~NAT64_ALLOW_PRIVATE;
break;
+ case TOK_SWAPCONF:
+ cfg->flags |= NAT64LSN_ALLOW_SWAPCONF;
+ break;
+ case TOK_SWAPCONFOFF:
+ cfg->flags &= ~NAT64LSN_ALLOW_SWAPCONF;
+ break;
}
}
@@ -634,6 +639,12 @@ nat64lsn_config(const char *name, uint8_t set, int ac, char **av)
case TOK_PRIVATEOFF:
cfg->flags &= ~NAT64_ALLOW_PRIVATE;
break;
+ case TOK_SWAPCONF:
+ cfg->flags |= NAT64LSN_ALLOW_SWAPCONF;
+ break;
+ case TOK_SWAPCONFOFF:
+ cfg->flags &= ~NAT64LSN_ALLOW_SWAPCONF;
+ break;
default:
errx(EX_USAGE, "Can't change %s option", opt);
}
@@ -799,6 +810,8 @@ nat64lsn_show_cb(ipfw_nat64lsn_cfg *cfg, const char *name, uint8_t set)
printf(" icmp_age %u", cfg->st_icmp_ttl);
if (g_co.verbose || cfg->jmaxlen != NAT64LSN_JMAXLEN)
printf(" jmaxlen %u", cfg->jmaxlen);
+ if (cfg->flags & NAT64LSN_ALLOW_SWAPCONF)
+ printf(" swap_conf");
if (cfg->flags & NAT64_LOG)
printf(" log");
if (cfg->flags & NAT64_ALLOW_PRIVATE)
@@ -853,7 +866,6 @@ nat64lsn_foreach(nat64lsn_cb_t *f, const char *name, uint8_t set, int sort)
ipfw_nat64lsn_cfg *cfg;
size_t sz;
uint32_t i;
- int error;
/* Start with reasonable default */
sz = sizeof(*olh) + 16 * sizeof(ipfw_nat64lsn_cfg);
@@ -877,7 +889,7 @@ nat64lsn_foreach(nat64lsn_cb_t *f, const char *name, uint8_t set, int sort)
cfg = (ipfw_nat64lsn_cfg *)(olh + 1);
for (i = 0; i < olh->count; i++) {
- error = f(cfg, name, set); /* Ignore errors for now */
+ (void)f(cfg, name, set); /* Ignore errors for now */
cfg = (ipfw_nat64lsn_cfg *)((caddr_t)cfg +
olh->objsize);
}
diff --git a/sbin/ipfw/nat64stl.c b/sbin/ipfw/nat64stl.c
index e82ec202b5c6..b6c970001f5c 100644
--- a/sbin/ipfw/nat64stl.c
+++ b/sbin/ipfw/nat64stl.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2015-2019 Yandex LLC
* Copyright (c) 2015-2019 Andrey V. Elsukov <ae@FreeBSD.org>
@@ -26,9 +26,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
@@ -521,7 +518,6 @@ nat64stl_foreach(nat64stl_cb_t *f, const char *name, uint8_t set, int sort)
ipfw_nat64stl_cfg *cfg;
size_t sz;
uint32_t i;
- int error;
/* Start with reasonable default */
sz = sizeof(*olh) + 16 * sizeof(*cfg);
@@ -544,7 +540,7 @@ nat64stl_foreach(nat64stl_cb_t *f, const char *name, uint8_t set, int sort)
cfg = (ipfw_nat64stl_cfg *)(olh + 1);
for (i = 0; i < olh->count; i++) {
- error = f(cfg, name, set); /* Ignore errors for now */
+ (void)f(cfg, name, set); /* Ignore errors for now */
cfg = (ipfw_nat64stl_cfg *)((caddr_t)cfg +
olh->objsize);
}
diff --git a/sbin/ipfw/nptv6.c b/sbin/ipfw/nptv6.c
index f2ebbdb65185..eee6109a3d9e 100644
--- a/sbin/ipfw/nptv6.c
+++ b/sbin/ipfw/nptv6.c
@@ -25,9 +25,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/socket.h>
@@ -156,10 +153,10 @@ static struct _s_x nptv6newcmds[] = {
{ NULL, 0 }
};
-
static void
nptv6_parse_prefix(const char *arg, struct in6_addr *prefix, int *len)
{
+ long plen;
char *p, *l;
p = strdup(arg);
@@ -170,13 +167,15 @@ nptv6_parse_prefix(const char *arg, struct in6_addr *prefix, int *len)
if (inet_pton(AF_INET6, p, prefix) != 1)
errx(EX_USAGE, "Bad prefix: %s", p);
if (l != NULL) {
- *len = (int)strtol(l, &l, 10);
- if (*l != '\0' || *len <= 0 || *len > 64)
+ plen = strtol(l, &l, 10);
+ if (*l != '\0' || plen < 8 || plen > 64)
errx(EX_USAGE, "Bad prefix length: %s", arg);
+ *len = plen;
} else
*len = 0;
free(p);
}
+
/*
* Creates new nptv6 instance
* ipfw nptv6 <NAME> create int_prefix <prefix> ext_prefix <prefix>
@@ -192,10 +191,10 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
struct in6_addr mask;
ipfw_nptv6_cfg *cfg;
ipfw_obj_lheader *olh;
- int tcmd, flags, plen;
+ int tcmd, flags, iplen, eplen, pplen;
char *p;
- plen = 0;
+ iplen = eplen = pplen = 0;
memset(buf, 0, sizeof(buf));
olh = (ipfw_obj_lheader *)buf;
cfg = (ipfw_nptv6_cfg *)(olh + 1);
@@ -208,10 +207,8 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
switch (tcmd) {
case TOK_INTPREFIX:
NEED1("IPv6 prefix required");
- nptv6_parse_prefix(*av, &cfg->internal, &plen);
+ nptv6_parse_prefix(*av, &cfg->internal, &iplen);
flags |= NPTV6_HAS_INTPREFIX;
- if (plen > 0)
- goto check_prefix;
ac--; av++;
break;
case TOK_EXTPREFIX:
@@ -219,10 +216,8 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
errx(EX_USAGE,
"Only one ext_prefix or ext_if allowed");
NEED1("IPv6 prefix required");
- nptv6_parse_prefix(*av, &cfg->external, &plen);
+ nptv6_parse_prefix(*av, &cfg->external, &eplen);
flags |= NPTV6_HAS_EXTPREFIX;
- if (plen > 0)
- goto check_prefix;
ac--; av++;
break;
case TOK_EXTIF:
@@ -239,24 +234,29 @@ nptv6_create(const char *name, uint8_t set, int ac, char *av[])
break;
case TOK_PREFIXLEN:
NEED1("IPv6 prefix length required");
- plen = strtol(*av, &p, 10);
-check_prefix:
- if (*p != '\0' || plen < 8 || plen > 64)
+ pplen = strtol(*av, &p, 10);
+ if (*p != '\0' || pplen < 8 || pplen > 64)
errx(EX_USAGE, "wrong prefix length: %s", *av);
- /* RFC 6296 Sec. 3.1 */
- if (cfg->plen > 0 && cfg->plen != plen) {
- warnx("Prefix length mismatch (%d vs %d). "
- "It was extended up to %d",
- cfg->plen, plen, MAX(plen, cfg->plen));
- plen = MAX(plen, cfg->plen);
- }
- cfg->plen = plen;
- flags |= NPTV6_HAS_PREFIXLEN;
ac--; av++;
break;
}
}
+ /* RFC 6296 Sec. 3.1 */
+ if (pplen != 0) {
+ if ((eplen != 0 && eplen != pplen) ||
+ (iplen != 0 && iplen != pplen))
+ errx(EX_USAGE, "prefix length mismatch");
+ cfg->plen = pplen;
+ flags |= NPTV6_HAS_PREFIXLEN;
+ } else if (eplen != 0 || iplen != 0) {
+ if (eplen != 0 && iplen != 0 && eplen != iplen)
+ errx(EX_USAGE, "prefix length mismatch");
+ warnx("use prefixlen instead");
+ cfg->plen = eplen ? eplen : iplen;
+ flags |= NPTV6_HAS_PREFIXLEN;
+ }
+
/* Check validness */
if ((flags & NPTV6_HAS_INTPREFIX) != NPTV6_HAS_INTPREFIX)
errx(EX_USAGE, "int_prefix required");
@@ -420,7 +420,6 @@ nptv6_foreach(nptv6_cb_t *f, const char *name, uint8_t set, int sort)
ipfw_nptv6_cfg *cfg;
size_t sz;
uint32_t i;
- int error;
/* Start with reasonable default */
sz = sizeof(*olh) + 16 * sizeof(*cfg);
@@ -442,7 +441,7 @@ nptv6_foreach(nptv6_cb_t *f, const char *name, uint8_t set, int sort)
cfg = (ipfw_nptv6_cfg *)(olh + 1);
for (i = 0; i < olh->count; i++) {
- error = f(cfg, name, set);
+ (void)f(cfg, name, set);
cfg = (ipfw_nptv6_cfg *)((caddr_t)cfg + olh->objsize);
}
free(olh);
diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c
index 9e6390492e96..245c0c9e0399 100644
--- a/sbin/ipfw/tables.c
+++ b/sbin/ipfw/tables.c
@@ -12,8 +12,6 @@
* This software is provided ``AS IS'' without any warranties of any kind.
*
* in-kernel ipfw tables support.
- *
- * $FreeBSD$
*/
@@ -106,6 +104,7 @@ static struct _s_x tablevaltypes[] = {
{ "limit", IPFW_VTYPE_LIMIT },
{ "ipv4", IPFW_VTYPE_NH4 },
{ "ipv6", IPFW_VTYPE_NH6 },
+ { "mark", IPFW_VTYPE_MARK },
{ NULL, 0 }
};
@@ -313,7 +312,7 @@ ipfw_table_handler(int ac, char *av[])
void
table_fill_ntlv(ipfw_obj_ntlv *ntlv, const char *name, uint8_t set,
- uint16_t uidx)
+ uint32_t uidx)
{
ntlv->head.type = IPFW_TLV_TBL_NAME;
@@ -916,7 +915,7 @@ table_do_modify_record(int cmd, ipfw_obj_header *oh,
memcpy(pbuf, oh, sizeof(*oh));
oh = (ipfw_obj_header *)pbuf;
- oh->opheader.version = 1;
+ oh->opheader.version = 1; /* Current version */
ctlv = (ipfw_obj_ctlv *)(oh + 1);
ctlv->count = count;
@@ -1090,8 +1089,6 @@ table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add,
if (error == 0)
return;
- /* Get real OS error */
- error = errno;
/* Try to provide more human-readable error */
switch (error) {
@@ -1407,7 +1404,6 @@ guess_key_type(char *key, uint8_t *ptype)
{
char *p;
struct in6_addr addr;
- uint32_t kv;
if (ishexnumber(*key) != 0 || *key == ':') {
/* Remove / if exists */
@@ -1423,7 +1419,7 @@ guess_key_type(char *key, uint8_t *ptype)
} else {
/* Port or any other key */
/* Skip non-base 10 entries like 'fa1' */
- kv = strtol(key, &p, 10);
+ (void)strtol(key, &p, 10);
if (*p == '\0') {
*ptype = IPFW_TABLE_NUMBER;
return (0);
@@ -1662,6 +1658,11 @@ tentry_fill_value(ipfw_obj_header *oh __unused, ipfw_obj_tentry *tent,
}
etype = "ipv6";
break;
+ case IPFW_VTYPE_MARK:
+ v->mark = strtol(n, &e, 16);
+ if (*e != '\0')
+ etype = "mark";
+ break;
}
if (etype != NULL)
@@ -1706,7 +1707,6 @@ tables_foreach(table_cb_t *f, void *arg, int sort)
ipfw_xtable_info *info;
size_t sz;
uint32_t i;
- int error;
/* Start with reasonable default */
sz = sizeof(*olh) + 16 * sizeof(ipfw_xtable_info);
@@ -1731,7 +1731,7 @@ tables_foreach(table_cb_t *f, void *arg, int sort)
info = (ipfw_xtable_info *)(olh + 1);
for (i = 0; i < olh->count; i++) {
if (g_co.use_set == 0 || info->set == g_co.use_set - 1)
- error = f(info, arg);
+ (void)f(info, arg);
info = (ipfw_xtable_info *)((caddr_t)info +
olh->objsize);
}
@@ -1878,6 +1878,9 @@ table_show_value(char *buf, size_t bufsize, ipfw_table_value *v,
NI_NUMERICHOST) == 0)
l = snprintf(buf, sz, "%s,", abuf);
break;
+ case IPFW_VTYPE_MARK:
+ l = snprintf(buf, sz, "%#x,", v->mark);
+ break;
}
buf += l;
@@ -2034,37 +2037,17 @@ ipfw_list_ta(int ac __unused, char *av[] __unused)
}
-/* Copy of current kernel table_value structure */
-struct _table_value {
- uint32_t tag; /* O_TAG/O_TAGGED */
- uint32_t pipe; /* O_PIPE/O_QUEUE */
- uint16_t divert; /* O_DIVERT/O_TEE */
- uint16_t skipto; /* skipto, CALLRET */
- uint32_t netgraph; /* O_NETGRAPH/O_NGTEE */
- uint32_t fib; /* O_SETFIB */
- uint32_t nat; /* O_NAT */
- uint32_t nh4;
- uint8_t dscp;
- uint8_t spare0;
- uint16_t spare1;
- /* -- 32 bytes -- */
- struct in6_addr nh6;
- uint32_t limit; /* O_LIMIT */
- uint32_t zoneid;
- uint64_t refcnt; /* Number of references */
-};
-
static int
compare_values(const void *_a, const void *_b)
{
- const struct _table_value *a, *b;
+ const ipfw_table_value *a, *b;
- a = (const struct _table_value *)_a;
- b = (const struct _table_value *)_b;
+ a = (const ipfw_table_value *)_a;
+ b = (const ipfw_table_value *)_b;
- if (a->spare1 < b->spare1)
+ if (a->kidx < b->kidx)
return (-1);
- else if (a->spare1 > b->spare1)
+ else if (a->kidx > b->kidx)
return (1);
return (0);
@@ -2075,7 +2058,7 @@ ipfw_list_values(int ac __unused, char *av[] __unused)
{
char buf[128];
ipfw_obj_lheader *olh;
- struct _table_value *v;
+ ipfw_table_value *v;
uint32_t i, vmask;
int error;
@@ -2087,13 +2070,13 @@ ipfw_list_values(int ac __unused, char *av[] __unused)
table_print_valheader(buf, sizeof(buf), vmask);
printf("HEADER: %s\n", buf);
- v = (struct _table_value *)(olh + 1);
+ v = (ipfw_table_value *)(olh + 1);
qsort(v, olh->count, olh->objsize, compare_values);
for (i = 0; i < olh->count; i++) {
table_show_value(buf, sizeof(buf), (ipfw_table_value *)v,
vmask, 0);
- printf("[%u] refs=%lu %s\n", v->spare1, (u_long)v->refcnt, buf);
- v = (struct _table_value *)((caddr_t)v + olh->objsize);
+ printf("[%u] refs=%lu %s\n", v->kidx, (u_long)v->refcnt, buf);
+ v = (ipfw_table_value *)((caddr_t)v + olh->objsize);
}
free(olh);
diff --git a/sbin/ipfw/tests/Makefile b/sbin/ipfw/tests/Makefile
new file mode 100644
index 000000000000..e2d4dab2729a
--- /dev/null
+++ b/sbin/ipfw/tests/Makefile
@@ -0,0 +1,6 @@
+PACKAGE= tests
+
+ATF_TESTS_PYTEST+= test_add_rule.py
+ATF_TESTS_SH+= ipfw_test
+
+.include <bsd.test.mk>
diff --git a/sbin/ipfw/tests/ipfw_test.sh b/sbin/ipfw/tests/ipfw_test.sh
new file mode 100644
index 000000000000..c7993c430a3d
--- /dev/null
+++ b/sbin/ipfw/tests/ipfw_test.sh
@@ -0,0 +1,107 @@
+#
+# Copyright (c) 2025 Dag-Erling Smørgrav <des@FreeBSD.org>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+. $(atf_get_srcdir)/../../sys/common/vnet.subr
+
+atf_test_case nptv6 cleanup
+nptv6_head()
+{
+ atf_set "descr" "Test creation of NPTv6 rules"
+ atf_set "require.user" "root"
+ atf_set "require.kmods" "ipfw_nptv6"
+}
+nptv6_body()
+{
+ vnet_init
+ local jail=ipfw_$(atf_get ident)
+ local epair=$(vnet_mkepair)
+ vnet_mkjail ${jail} ${epair}a
+
+ local rule="xyzzy"
+ local int="2001:db8:1::"
+ local ext="2001:db8:2::"
+
+ atf_check jexec ${jail} \
+ ifconfig "${epair}"a inet6 ${ext}1/64 up
+
+ # This is how it's supposed to be used
+ atf_check jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_prefix ${ext} prefixlen 64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_prefix $ext prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # Specify external interface rather than network
+ atf_check jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_if ${epair}a prefixlen 64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_if ${epair}a prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # This should also work
+ atf_check jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext}/64 prefixlen 64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_prefix $ext prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # This should also work, although it's not encouraged
+ atf_check -e match:"use prefixlen instead" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext}/64
+ atf_check -o inline:\
+"nptv6 $rule int_prefix $int ext_prefix $ext prefixlen 64\n" \
+ jexec ${jail} ipfw nptv6 all list
+ atf_check jexec ${jail} ipfw nptv6 all destroy
+
+ # These should all fail
+ atf_check -s not-exit:0 -e match:"one ext_prefix or ext_if" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_prefix ${ext} ext_if ${epair}a
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"one ext_prefix or ext_if" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_if ${epair}a ext_prefix ${ext}
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/48 ext_prefix ${ext}/64
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext}/64 prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_prefix ${ext} prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int} ext_prefix ${ext}/64 prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+
+ atf_check -s not-exit:0 -e match:"prefix length mismatch" \
+ jexec ${jail} ipfw nptv6 ${rule} create \
+ int_prefix ${int}/64 ext_if ${epair}a prefixlen 48
+ atf_check -o empty jexec ${jail} ipfw nptv6 all list
+}
+nptv6_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case nptv6
+}
diff --git a/sbin/ipfw/tests/test_add_rule.py b/sbin/ipfw/tests/test_add_rule.py
new file mode 100755
index 000000000000..c2c4bf0b360c
--- /dev/null
+++ b/sbin/ipfw/tests/test_add_rule.py
@@ -0,0 +1,493 @@
+import errno
+import json
+import os
+import socket
+import struct
+import subprocess
+import sys
+from ctypes import c_byte
+from ctypes import c_char
+from ctypes import c_int
+from ctypes import c_long
+from ctypes import c_uint32
+from ctypes import c_uint8
+from ctypes import c_ulong
+from ctypes import c_ushort
+from ctypes import sizeof
+from ctypes import Structure
+from enum import Enum
+from typing import Any
+from typing import Dict
+from typing import List
+from typing import NamedTuple
+from typing import Optional
+from typing import Union
+
+import pytest
+from atf_python.sys.netpfil.ipfw.insns import Icmp6RejectCode
+from atf_python.sys.netpfil.ipfw.insns import IcmpRejectCode
+from atf_python.sys.netpfil.ipfw.insns import Insn
+from atf_python.sys.netpfil.ipfw.insns import InsnComment
+from atf_python.sys.netpfil.ipfw.insns import InsnEmpty
+from atf_python.sys.netpfil.ipfw.insns import InsnIp
+from atf_python.sys.netpfil.ipfw.insns import InsnIp6
+from atf_python.sys.netpfil.ipfw.insns import InsnPorts
+from atf_python.sys.netpfil.ipfw.insns import InsnProb
+from atf_python.sys.netpfil.ipfw.insns import InsnProto
+from atf_python.sys.netpfil.ipfw.insns import InsnReject
+from atf_python.sys.netpfil.ipfw.insns import InsnTable
+from atf_python.sys.netpfil.ipfw.insns import InsnU32
+from atf_python.sys.netpfil.ipfw.insns import IpFwOpcode
+from atf_python.sys.netpfil.ipfw.ioctl import CTlv
+from atf_python.sys.netpfil.ipfw.ioctl import CTlvRule
+from atf_python.sys.netpfil.ipfw.ioctl import IpFwTlvType
+from atf_python.sys.netpfil.ipfw.ioctl import IpFwXRule
+from atf_python.sys.netpfil.ipfw.ioctl import NTlv
+from atf_python.sys.netpfil.ipfw.ioctl import Op3CmdType
+from atf_python.sys.netpfil.ipfw.ioctl import RawRule
+from atf_python.sys.netpfil.ipfw.ipfw import DebugIoReader
+from atf_python.sys.netpfil.ipfw.utils import enum_from_int
+from atf_python.utils import BaseTest
+
+
+IPFW_PATH = "/sbin/ipfw"
+
+
+def differ(w_obj, g_obj, w_stack=[], g_stack=[]):
+ if bytes(w_obj) == bytes(g_obj):
+ return True
+ num_objects = 0
+ for i, w_child in enumerate(w_obj.obj_list):
+ if i >= len(g_obj.obj_list):
+ print("MISSING object from chain {}".format(" / ".join(w_stack)))
+ w_child.print_obj()
+ print("==========================")
+ return False
+ g_child = g_obj.obj_list[i]
+ if bytes(w_child) == bytes(g_child):
+ num_objects += 1
+ continue
+ w_stack.append(w_obj.obj_name)
+ g_stack.append(g_obj.obj_name)
+ if not differ(w_child, g_child, w_stack, g_stack):
+ return False
+ break
+ if num_objects == len(w_obj.obj_list) and num_objects < len(g_obj.obj_list):
+ g_child = g_obj.obj_list[num_objects]
+ print("EXTRA object from chain {}".format(" / ".join(g_stack)))
+ g_child.print_obj()
+ print("==========================")
+ return False
+ print("OBJECTS DIFFER")
+ print("WANTED CHAIN: {}".format(" / ".join(w_stack)))
+ w_obj.print_obj()
+ w_obj.print_obj_hex()
+ print("==========================")
+ print("GOT CHAIN: {}".format(" / ".join(g_stack)))
+ g_obj.print_obj()
+ g_obj.print_obj_hex()
+ print("==========================")
+ return False
+
+
+class TestAddRule(BaseTest):
+ def compile_rule(self, out):
+ tlvs = []
+ if "objs" in out:
+ tlvs.append(CTlv(IpFwTlvType.IPFW_TLV_TBLNAME_LIST, out["objs"]))
+ rule = RawRule(rulenum=out.get("rulenum", 0), obj_list=out["insns"])
+ tlvs.append(CTlvRule(obj_list=[rule]))
+ return IpFwXRule(Op3CmdType.IP_FW_XADD, tlvs)
+
+ def verify_rule(self, in_data: str, out_data):
+ # Prepare the desired output
+ expected = self.compile_rule(out_data)
+
+ reader = DebugIoReader(IPFW_PATH)
+ ioctls = reader.get_records(in_data)
+ assert len(ioctls) == 1 # Only 1 ioctl request expected
+ got = ioctls[0]
+
+ if not differ(expected, got):
+ print("=> CMD: {}".format(in_data))
+ print("=> WANTED:")
+ expected.print_obj()
+ print("==========================")
+ print("=> GOT:")
+ got.print_obj()
+ print("==========================")
+ assert bytes(got) == bytes(expected)
+
+ @pytest.mark.parametrize(
+ "rule",
+ [
+ pytest.param(
+ {
+ "in": "add 200 allow ip from any to any",
+ "out": {
+ "insns": [InsnEmpty(IpFwOpcode.O_ACCEPT)],
+ "rulenum": 200,
+ },
+ },
+ id="test_rulenum",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from { 1.2.3.4 or 2.3.4.5 } to any",
+ "out": {
+ "insns": [
+ InsnIp(IpFwOpcode.O_IP_SRC, ip="1.2.3.4", is_or=True),
+ InsnIp(IpFwOpcode.O_IP_SRC, ip="2.3.4.5"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_or",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from table(AAA) to table(BBB)",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"),
+ NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"),
+ ],
+ "insns": [
+ InsnU32(IpFwOpcode.O_IP_SRC_LOOKUP, u32=1),
+ InsnU32(IpFwOpcode.O_IP_DST_LOOKUP, u32=2),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_tables",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from any to 1.2.3.4 // test comment",
+ "out": {
+ "insns": [
+ InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"),
+ InsnComment(comment="test comment"),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_comment",
+ ),
+ pytest.param(
+ {
+ "in": "add tcp-setmss 123 ip from any to 1.2.3.4",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_EACTION, idx=1, name="tcp-setmss"),
+ ],
+ "insns": [
+ InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"),
+ InsnU32(IpFwOpcode.O_EXTERNAL_ACTION, u32=1),
+ Insn(IpFwOpcode.O_EXTERNAL_DATA, arg1=123),
+ ],
+ },
+ },
+ id="test_eaction_tcp-setmss",
+ ),
+ pytest.param(
+ {
+ "in": "add eaction ntpv6 AAA ip from any to 1.2.3.4",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_EACTION, idx=1, name="ntpv6"),
+ NTlv(0, idx=2, name="AAA"),
+ ],
+ "insns": [
+ InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"),
+ InsnU32(IpFwOpcode.O_EXTERNAL_ACTION, u32=1),
+ InsnU32(IpFwOpcode.O_EXTERNAL_INSTANCE, u32=2),
+ ],
+ },
+ },
+ id="test_eaction_ntp",
+ ),
+ pytest.param(
+ {
+ "in": "add // test comment",
+ "out": {
+ "insns": [
+ InsnComment(comment="test comment"),
+ Insn(IpFwOpcode.O_COUNT),
+ ],
+ },
+ },
+ id="test_action_comment",
+ ),
+ pytest.param(
+ {
+ "in": "add check-state :OUT // test comment",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_STATE_NAME, idx=1, name="OUT"),
+ ],
+ "insns": [
+ InsnComment(comment="test comment"),
+ InsnU32(IpFwOpcode.O_CHECK_STATE, u32=1),
+ ],
+ },
+ },
+ id="test_check_state",
+ ),
+ pytest.param(
+ {
+ "in": "add allow tcp from any to any keep-state :OUT",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_STATE_NAME, idx=1, name="OUT"),
+ ],
+ "insns": [
+ InsnU32(IpFwOpcode.O_PROBE_STATE, u32=1),
+ Insn(IpFwOpcode.O_PROTO, arg1=6),
+ InsnU32(IpFwOpcode.O_KEEP_STATE, u32=1),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_keep_state",
+ ),
+ pytest.param(
+ {
+ "in": "add allow tcp from any to any record-state",
+ "out": {
+ "objs": [
+ NTlv(IpFwTlvType.IPFW_TLV_STATE_NAME, idx=1, name="default"),
+ ],
+ "insns": [
+ Insn(IpFwOpcode.O_PROTO, arg1=6),
+ InsnU32(IpFwOpcode.O_KEEP_STATE, u32=1),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ],
+ },
+ },
+ id="test_record_state",
+ ),
+ ],
+ )
+ def test_add_rule(self, rule):
+ """Tests if the compiled rule is sane and matches the spec"""
+ self.verify_rule(rule["in"], rule["out"])
+
+ @pytest.mark.parametrize(
+ "action",
+ [
+ pytest.param(("allow", InsnEmpty(IpFwOpcode.O_ACCEPT)), id="test_allow"),
+ pytest.param(
+ (
+ "abort",
+ Insn(IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_REJECT_ABORT),
+ ),
+ id="abort",
+ ),
+ pytest.param(
+ (
+ "abort6",
+ Insn(
+ IpFwOpcode.O_UNREACH6, arg1=Icmp6RejectCode.ICMP6_UNREACH_ABORT
+ ),
+ ),
+ id="abort6",
+ ),
+ pytest.param(("accept", InsnEmpty(IpFwOpcode.O_ACCEPT)), id="accept"),
+ pytest.param(("deny", InsnEmpty(IpFwOpcode.O_DENY)), id="deny"),
+ pytest.param(
+ (
+ "reject",
+ Insn(IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_HOST),
+ ),
+ id="reject",
+ ),
+ pytest.param(
+ (
+ "reset",
+ Insn(IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_REJECT_RST),
+ ),
+ id="reset",
+ ),
+ pytest.param(
+ (
+ "reset6",
+ Insn(IpFwOpcode.O_UNREACH6, arg1=Icmp6RejectCode.ICMP6_UNREACH_RST),
+ ),
+ id="reset6",
+ ),
+ pytest.param(
+ (
+ "unreach port",
+ InsnReject(
+ IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_PORT
+ ),
+ ),
+ id="unreach_port",
+ ),
+ pytest.param(
+ (
+ "unreach port",
+ InsnReject(
+ IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_PORT
+ ),
+ ),
+ id="unreach_port",
+ ),
+ pytest.param(
+ (
+ "unreach needfrag",
+ InsnReject(
+ IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_NEEDFRAG
+ ),
+ ),
+ id="unreach_needfrag",
+ ),
+ pytest.param(
+ (
+ "unreach needfrag 1420",
+ InsnReject(
+ IpFwOpcode.O_REJECT,
+ arg1=IcmpRejectCode.ICMP_UNREACH_NEEDFRAG,
+ mtu=1420,
+ ),
+ ),
+ id="unreach_needfrag_mtu",
+ ),
+ pytest.param(
+ (
+ "unreach6 port",
+ Insn(
+ IpFwOpcode.O_UNREACH6,
+ arg1=Icmp6RejectCode.ICMP6_DST_UNREACH_NOPORT,
+ ),
+ ),
+ id="unreach6_port",
+ ),
+ pytest.param(("count", InsnEmpty(IpFwOpcode.O_COUNT)), id="count"),
+ # TOK_NAT
+ pytest.param(
+ ("queue 42", Insn(IpFwOpcode.O_QUEUE, arg1=42)), id="queue_42"
+ ),
+ pytest.param(("pipe 42", Insn(IpFwOpcode.O_PIPE, arg1=42)), id="pipe_42"),
+ pytest.param(
+ ("skipto 42", InsnU32(IpFwOpcode.O_SKIPTO, u32=42)), id="skipto_42"
+ ),
+ pytest.param(
+ ("netgraph 42", Insn(IpFwOpcode.O_NETGRAPH, arg1=42)), id="netgraph_42"
+ ),
+ pytest.param(
+ ("ngtee 42", Insn(IpFwOpcode.O_NGTEE, arg1=42)), id="ngtee_42"
+ ),
+ pytest.param(
+ ("divert 42", Insn(IpFwOpcode.O_DIVERT, arg1=42)), id="divert_42"
+ ),
+ pytest.param(
+ ("divert natd", Insn(IpFwOpcode.O_DIVERT, arg1=8668)), id="divert_natd"
+ ),
+ pytest.param(("tee 42", Insn(IpFwOpcode.O_TEE, arg1=42)), id="tee_42"),
+ pytest.param(
+ ("call 420", InsnU32(IpFwOpcode.O_CALLRETURN, u32=420)), id="call_420"
+ ),
+ # TOK_FORWARD
+ pytest.param(
+ ("setfib 1", Insn(IpFwOpcode.O_SETFIB, arg1=1 | 0x8000)),
+ id="setfib_1",
+ marks=pytest.mark.skip("needs net.fibs>1"),
+ ),
+ pytest.param(
+ ("setdscp 42", Insn(IpFwOpcode.O_SETDSCP, arg1=42 | 0x8000)),
+ id="setdscp_42",
+ ),
+ pytest.param(("reass", InsnEmpty(IpFwOpcode.O_REASS)), id="reass"),
+ pytest.param(
+ ("return", InsnU32(IpFwOpcode.O_CALLRETURN, is_not=True)), id="return"
+ ),
+ ],
+ )
+ def test_add_action(self, action):
+ """Tests if the rule action is compiled properly"""
+ rule_in = "add {} ip from any to any".format(action[0])
+ rule_out = {"insns": [action[1]]}
+ self.verify_rule(rule_in, rule_out)
+
+ @pytest.mark.parametrize(
+ "insn",
+ [
+ pytest.param(
+ {
+ "in": "add prob 0.7 allow ip from any to any",
+ "out": InsnProb(prob=0.7),
+ },
+ id="test_prob",
+ ),
+ pytest.param(
+ {
+ "in": "add allow tcp from any to any",
+ "out": InsnProto(arg1=6),
+ },
+ id="test_proto",
+ ),
+ pytest.param(
+ {
+ "in": "add allow ip from any to any 57",
+ "out": InsnPorts(IpFwOpcode.O_IP_DSTPORT, port_pairs=[57, 57]),
+ },
+ id="test_ports",
+ ),
+ ],
+ )
+ def test_add_single_instruction(self, insn):
+ """Tests if the compiled rule is sane and matches the spec"""
+
+ # Prepare the desired output
+ out = {
+ "insns": [insn["out"], InsnEmpty(IpFwOpcode.O_ACCEPT)],
+ }
+ self.verify_rule(insn["in"], out)
+
+ @pytest.mark.parametrize(
+ "opcode",
+ [
+ pytest.param(IpFwOpcode.O_IP_SRCPORT, id="src"),
+ pytest.param(IpFwOpcode.O_IP_DSTPORT, id="dst"),
+ ],
+ )
+ @pytest.mark.parametrize(
+ "params",
+ [
+ pytest.param(
+ {
+ "in": "57",
+ "out": [(57, 57)],
+ },
+ id="test_single",
+ ),
+ pytest.param(
+ {
+ "in": "57-59",
+ "out": [(57, 59)],
+ },
+ id="test_range",
+ ),
+ pytest.param(
+ {
+ "in": "57-59,41",
+ "out": [(57, 59), (41, 41)],
+ },
+ id="test_ranges",
+ ),
+ ],
+ )
+ def test_add_ports(self, params, opcode):
+ if opcode == IpFwOpcode.O_IP_DSTPORT:
+ txt = "add allow ip from any to any " + params["in"]
+ else:
+ txt = "add allow ip from any " + params["in"] + " to any"
+ out = {
+ "insns": [
+ InsnPorts(opcode, port_pairs=params["out"]),
+ InsnEmpty(IpFwOpcode.O_ACCEPT),
+ ]
+ }
+ self.verify_rule(txt, out)
diff --git a/sbin/kldconfig/Makefile b/sbin/kldconfig/Makefile
index 3efb34f8a252..f4afce242e90 100644
--- a/sbin/kldconfig/Makefile
+++ b/sbin/kldconfig/Makefile
@@ -23,7 +23,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
PACKAGE=runtime
diff --git a/sbin/kldconfig/Makefile.depend b/sbin/kldconfig/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/kldconfig/Makefile.depend
+++ b/sbin/kldconfig/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/kldconfig/kldconfig.8 b/sbin/kldconfig/kldconfig.8
index 5fdf461c7b69..e835e4c16df1 100644
--- a/sbin/kldconfig/kldconfig.8
+++ b/sbin/kldconfig/kldconfig.8
@@ -23,8 +23,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd September 29, 2020
.Dt KLDCONFIG 8
.Os
diff --git a/sbin/kldconfig/kldconfig.c b/sbin/kldconfig/kldconfig.c
index 2dbd88b3ad3d..570ca5cbf713 100644
--- a/sbin/kldconfig/kldconfig.c
+++ b/sbin/kldconfig/kldconfig.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2001 Peter Pentchev
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/queue.h>
diff --git a/sbin/kldload/Makefile b/sbin/kldload/Makefile
index 13c0f0ec5abf..cacca26feba8 100644
--- a/sbin/kldload/Makefile
+++ b/sbin/kldload/Makefile
@@ -23,7 +23,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
PACKAGE=runtime
diff --git a/sbin/kldload/Makefile.depend b/sbin/kldload/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/kldload/Makefile.depend
+++ b/sbin/kldload/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/kldload/kldload.8 b/sbin/kldload/kldload.8
index a008b187c367..0dea7838d75c 100644
--- a/sbin/kldload/kldload.8
+++ b/sbin/kldload/kldload.8
@@ -23,9 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd February 11, 2021
+.Dd December 20, 2023
.Dt KLDLOAD 8
.Os
.Sh NAME
@@ -116,6 +114,7 @@ Only those modules necessary for booting the system, including those
required for mounting the root filesystem, should be handled by
.Xr loader.conf 5 .
.Sh SEE ALSO
+.Xr kenv 1 ,
.Xr kldload 2 ,
.Xr loader.conf 5 ,
.Xr rc.conf 5 ,
diff --git a/sbin/kldload/kldload.c b/sbin/kldload/kldload.c
index a8e43fdd1f92..82469a2d40f3 100644
--- a/sbin/kldload/kldload.c
+++ b/sbin/kldload/kldload.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/linker.h>
diff --git a/sbin/kldstat/Makefile b/sbin/kldstat/Makefile
index 2d0c4437dc05..2d0ae05e2600 100644
--- a/sbin/kldstat/Makefile
+++ b/sbin/kldstat/Makefile
@@ -23,7 +23,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
PACKAGE=runtime
diff --git a/sbin/kldstat/Makefile.depend b/sbin/kldstat/Makefile.depend
index 991757ecadc0..678747db6f2c 100644
--- a/sbin/kldstat/Makefile.depend
+++ b/sbin/kldstat/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/kldstat/kldstat.8 b/sbin/kldstat/kldstat.8
index d3f33027a193..09094da3741d 100644
--- a/sbin/kldstat/kldstat.8
+++ b/sbin/kldstat/kldstat.8
@@ -1,4 +1,6 @@
.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
.\" Copyright (c) 1997 Doug Rabson
.\" All rights reserved.
.\"
@@ -23,9 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd January 19, 2016
+.Dd January 4, 2025
.Dt KLDSTAT 8
.Os
.Sh NAME
@@ -50,22 +50,22 @@ utility displays the status of any files dynamically linked into the
kernel.
.Pp
The following options are available:
-.Bl -tag -width indentXX
+.Bl -tag -width "-n filename"
+.It Fl d
+Show the module specific data (as int, unsigned int and unsigned long)
.It Fl h
Display the size field in a human-readable form, using unit suffixes
instead of hex values.
-.It Fl v
-Be more verbose.
-.It Fl d
-Show the module specific data (as int, unsigned int and unsigned long)
.It Fl i Ar id
Display the status of only the file with this ID.
+.It Fl m Ar modname
+Display the status of only the module with this modname.
.It Fl n Ar filename
Display the status of only the file with this filename.
.It Fl q
-Only check if file is loaded or compiled into the kernel.
-.It Fl m Ar modname
-Display the status of only the module with this modname.
+Quietly check if file is loaded or compiled into the kernel.
+.It Fl v
+Be more verbose.
.El
.Sh EXIT STATUS
.Ex -std
diff --git a/sbin/kldstat/kldstat.c b/sbin/kldstat/kldstat.c
index b8e4fd6e4b5d..3a90f1c97eb4 100644
--- a/sbin/kldstat/kldstat.c
+++ b/sbin/kldstat/kldstat.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/module.h>
@@ -38,7 +35,7 @@ __FBSDID("$FreeBSD$");
#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>
-#include <strings.h>
+#include <string.h>
#include <unistd.h>
#define PTR_WIDTH ((int)(sizeof(void *) * 2 + 2))
@@ -54,7 +51,7 @@ printmod(int modid)
{
struct module_stat stat;
- bzero(&stat, sizeof(stat));
+ memset(&stat, 0, sizeof(stat));
stat.version = sizeof(struct module_stat);
if (modstat(modid, &stat) < 0) {
warn("can't stat module id %d", modid);
diff --git a/sbin/kldunload/Makefile b/sbin/kldunload/Makefile
index 5688f790941e..28819bb0a6f5 100644
--- a/sbin/kldunload/Makefile
+++ b/sbin/kldunload/Makefile
@@ -23,7 +23,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
PACKAGE=runtime
diff --git a/sbin/kldunload/Makefile.depend b/sbin/kldunload/Makefile.depend
index cae7e645ef6a..93249906da4f 100644
--- a/sbin/kldunload/Makefile.depend
+++ b/sbin/kldunload/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
lib/${CSU_DIR} \
lib/libc \
diff --git a/sbin/kldunload/kldunload.8 b/sbin/kldunload/kldunload.8
index 5e371e6fc5a0..9a65b59075b3 100644
--- a/sbin/kldunload/kldunload.8
+++ b/sbin/kldunload/kldunload.8
@@ -23,8 +23,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd February 27, 2006
.Dt KLDUNLOAD 8
.Os
diff --git a/sbin/kldunload/kldunload.c b/sbin/kldunload/kldunload.c
index 637b9f623893..69739d0f4afe 100644
--- a/sbin/kldunload/kldunload.c
+++ b/sbin/kldunload/kldunload.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997 Doug Rabson
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/linker.h>
diff --git a/sbin/ldconfig/Makefile b/sbin/ldconfig/Makefile
index 070c2c3d6901..621be3937ec0 100644
--- a/sbin/ldconfig/Makefile
+++ b/sbin/ldconfig/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=runtime
PROG= ldconfig
SRCS= elfhints.c ldconfig.c
diff --git a/sbin/ldconfig/Makefile.depend b/sbin/ldconfig/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/ldconfig/Makefile.depend
+++ b/sbin/ldconfig/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/ldconfig/elfhints.c b/sbin/ldconfig/elfhints.c
index 81236feec5ca..97499e398c9d 100644
--- a/sbin/ldconfig/elfhints.c
+++ b/sbin/ldconfig/elfhints.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1998 John D. Polstra
* All rights reserved.
@@ -24,11 +24,10 @@
* 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/endian.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -50,11 +49,12 @@
static void add_dir(const char *, const char *, bool);
static void read_dirs_from_file(const char *, const char *);
-static void read_elf_hints(const char *, bool);
+static void read_elf_hints(const char *, bool, bool);
static void write_elf_hints(const char *);
static const char *dirs[MAXDIRS];
static int ndirs;
+static bool is_be;
bool insecure;
static void
@@ -97,7 +97,7 @@ list_elf_hints(const char *hintsfile)
int i;
int nlibs;
- read_elf_hints(hintsfile, 1);
+ read_elf_hints(hintsfile, true, false);
printf("%s:\n", hintsfile);
printf("\tsearch directories:");
for (i = 0; i < ndirs; i++)
@@ -185,8 +185,11 @@ read_dirs_from_file(const char *hintsfile, const char *listfile)
fclose(fp);
}
+/* Convert between native byte order and forced little resp. big endian. */
+#define COND_SWAP(n) (is_be ? be32toh(n) : le32toh(n))
+
static void
-read_elf_hints(const char *hintsfile, bool must_exist)
+read_elf_hints(const char *hintsfile, bool must_exist, bool force_be)
{
int fd;
struct stat s;
@@ -195,6 +198,7 @@ read_elf_hints(const char *hintsfile, bool must_exist)
char *strtab;
char *dirlist;
char *p;
+ int hdr_version;
if ((fd = open(hintsfile, O_RDONLY)) == -1) {
if (errno == ENOENT && !must_exist)
@@ -216,14 +220,18 @@ read_elf_hints(const char *hintsfile, bool must_exist)
close(fd);
hdr = (struct elfhints_hdr *)mapbase;
- if (hdr->magic != ELFHINTS_MAGIC)
+ is_be = hdr->magic == htobe32(ELFHINTS_MAGIC);
+ if (COND_SWAP(hdr->magic) != ELFHINTS_MAGIC)
errx(1, "\"%s\": invalid file format", hintsfile);
- if (hdr->version != 1)
+ if (force_be && !is_be)
+ errx(1, "\"%s\": incompatible endianness requested", hintsfile);
+ hdr_version = COND_SWAP(hdr->version);
+ if (hdr_version != 1)
errx(1, "\"%s\": unrecognized file version (%d)", hintsfile,
- hdr->version);
+ hdr_version);
- strtab = (char *)mapbase + hdr->strtab;
- dirlist = strtab + hdr->dirlist;
+ strtab = (char *)mapbase + COND_SWAP(hdr->strtab);
+ dirlist = strtab + COND_SWAP(hdr->dirlist);
if (*dirlist != '\0')
while ((p = strsep(&dirlist, ":")) != NULL)
@@ -231,13 +239,19 @@ read_elf_hints(const char *hintsfile, bool must_exist)
}
void
-update_elf_hints(const char *hintsfile, int argc, char **argv, bool merge)
+update_elf_hints(const char *hintsfile, int argc, char **argv, bool merge,
+ bool force_be)
{
struct stat s;
int i;
+ /*
+ * Create little-endian hints files on all architectures unless
+ * ldconfig has been invoked with the -B option.
+ */
+ is_be = force_be;
if (merge)
- read_elf_hints(hintsfile, false);
+ read_elf_hints(hintsfile, false, force_be);
for (i = 0; i < argc; i++) {
if (stat(argv[i], &s) == -1)
warn("warning: %s", argv[i]);
@@ -267,9 +281,9 @@ write_elf_hints(const char *hintsfile)
if ((fp = fdopen(fd, "wb")) == NULL)
err(1, "fdopen(%s)", tempname);
- hdr.magic = ELFHINTS_MAGIC;
- hdr.version = 1;
- hdr.strtab = sizeof hdr;
+ hdr.magic = COND_SWAP(ELFHINTS_MAGIC);
+ hdr.version = COND_SWAP(1);
+ hdr.strtab = COND_SWAP(sizeof hdr);
hdr.strsize = 0;
hdr.dirlist = 0;
memset(hdr.spare, 0, sizeof hdr.spare);
@@ -280,8 +294,10 @@ write_elf_hints(const char *hintsfile)
for (i = 1; i < ndirs; i++)
hdr.strsize += 1 + strlen(dirs[i]);
}
- hdr.dirlistlen = hdr.strsize;
+ hdr.dirlistlen = COND_SWAP(hdr.strsize);
hdr.strsize++; /* For the null terminator */
+ /* convert in-place from native to target endianness */
+ hdr.strsize = COND_SWAP(hdr.strsize);
/* Write the header. */
if (fwrite(&hdr, 1, sizeof hdr, fp) != sizeof hdr)
diff --git a/sbin/ldconfig/ldconfig.8 b/sbin/ldconfig/ldconfig.8
index 7718f018bc70..cf7037b86bd6 100644
--- a/sbin/ldconfig/ldconfig.8
+++ b/sbin/ldconfig/ldconfig.8
@@ -1,7 +1,7 @@
.\"
.\" Copyright (c) 1993 Paul Kranenburg
.\" All rights reserved.
-.\" Copyright (c) 2021 The FreeBSD Foundation, Inc.
+.\" Copyright (c) 2021 The FreeBSD Foundation
.\"
.\" Portions of this documentation were written by
.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship
@@ -32,9 +32,7 @@
.\" (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 May 15, 2021
+.Dd April 20, 2024
.Dt LDCONFIG 8
.Os
.Sh NAME
@@ -43,7 +41,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl 32
-.Op Fl Rimrv
+.Op Fl BRimr
.Op Fl f Ar hints_file
.Op Ar directory | Ar
.Sh DESCRIPTION
@@ -107,6 +105,12 @@ Generate the hints for 32-bit ABI shared libraries
on 64-bit systems that support running 32-bit binaries.
.It Fl elf
Ignored for backwards compatibility.
+.It Fl B
+Force writing big-endian binary data to the hints file.
+The default is to create hints files in little-endian byte-order on all
+architectures.
+Reading of and merging into hints files preserves the endianness of the
+existing hints file.
.It Fl R
Appends pathnames on the command line to the directory list from
the hints file.
@@ -128,9 +132,14 @@ on the standard output.
The hints file is not modified.
.Pp
Scan and print all libraries found on the directories list.
-.It Fl v
-Switch on verbose mode.
.El
+.Pp
+The historic options
+.Fl elf ,
+.Fl s ,
+and
+.Fl v
+are accepted but ignored.
.Sh SECURITY
Special care must be taken when loading shared libraries into the address
space of
@@ -147,21 +156,23 @@ Thus,
serves to specify the trusted collection of directories from which
shared objects can be safely loaded.
.Sh FILES
-.Bl -tag -width /var/run/ld-elf.so.hintsxxx -compact
+.Bl -tag -width /usr/local/libdata/ldconfig/* -compact
.It Pa /var/run/ld-elf.so.hints
Standard hints file for the ELF dynamic linker.
-.It Pa /etc/ld-elf.so.conf
-Conventional configuration file containing directory names for
-invocations with
-.Fl elf .
.It Pa /var/run/ld-elf32.so.hints
-Conventional configuration files containing directory names for
-invocations with
+Hints file for 32 bit libraries on 64 bit architectures, processed by
+ldconfig when invoked with
.Fl 32 .
+.It Pa /etc/ld-elf.so.conf
+Optional file with names of directories to be included in the standard
+hints file when booting to multi-user mode.
+.It Pa /usr/local/libdata/ldconfig/*
+Additional files with names of directories provided by optional ports
+or packages.
.El
.Sh SEE ALSO
.Xr ld 1 ,
-.Xr ld-elf.so.1 ,
+.Xr ld-elf.so.1 1 ,
.Xr link 5
.Sh HISTORY
A
diff --git a/sbin/ldconfig/ldconfig.c b/sbin/ldconfig/ldconfig.c
index b30404fba7db..7700fd1f4574 100644
--- a/sbin/ldconfig/ldconfig.c
+++ b/sbin/ldconfig/ldconfig.c
@@ -50,16 +50,16 @@
#include "ldconfig.h"
#include "rtld_paths.h"
-static void usage(void);
+static void usage(void) __dead2;
int
main(int argc, char **argv)
{
const char *hints_file;
int c;
- bool is_32, justread, merge, rescan, verbose;
+ bool is_32, justread, merge, rescan, force_be;
- is_32 = justread = merge = rescan = verbose = false;
+ force_be = is_32 = justread = merge = rescan = false;
while (argc > 1) {
if (strcmp(argv[1], "-aout") == 0) {
@@ -77,11 +77,14 @@ main(int argc, char **argv)
}
if (is_32)
- hints_file = _PATH_ELF32_HINTS;
+ hints_file = __PATH_ELF_HINTS("32");
else
hints_file = _PATH_ELF_HINTS;
- while((c = getopt(argc, argv, "Rf:imrsv")) != -1) {
+ while((c = getopt(argc, argv, "BRf:imrsv")) != -1) {
switch (c) {
+ case 'B':
+ force_be = true;
+ break;
case 'R':
rescan = true;
break;
@@ -101,7 +104,7 @@ main(int argc, char **argv)
/* was nostd */
break;
case 'v':
- verbose = true;
+ /* was verbose */
break;
default:
usage();
@@ -115,7 +118,7 @@ main(int argc, char **argv)
if (argc == optind)
rescan = true;
update_elf_hints(hints_file, argc - optind,
- argv + optind, merge || rescan);
+ argv + optind, merge || rescan, force_be);
}
exit(0);
}
@@ -124,7 +127,7 @@ static void
usage(void)
{
fprintf(stderr,
- "usage: ldconfig [-32] [-elf] [-Rimrv] [-f hints_file] "
+ "usage: ldconfig [-32] [-BRimr] [-f hints_file]"
"[directory | file ...]\n");
exit(1);
}
diff --git a/sbin/ldconfig/ldconfig.h b/sbin/ldconfig/ldconfig.h
index 8aff4e6a5ef2..aa7ad810bacd 100644
--- a/sbin/ldconfig/ldconfig.h
+++ b/sbin/ldconfig/ldconfig.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1998 John D. Polstra
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 LDCONFIG_H
@@ -38,7 +36,7 @@ extern bool insecure; /* -i flag, needed here for elfhints.c */
__BEGIN_DECLS
void list_elf_hints(const char *);
-void update_elf_hints(const char *, int, char **, bool);
+void update_elf_hints(const char *, int, char **, bool, bool);
__END_DECLS
#endif
diff --git a/sbin/md5/Makefile b/sbin/md5/Makefile
index e499967d23d5..ed87ff84876b 100644
--- a/sbin/md5/Makefile
+++ b/sbin/md5/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/9/93
-# $FreeBSD$
-
PACKAGE=runtime
PROG= md5
@@ -17,6 +14,8 @@ LINKS= ${BINDIR}/md5 ${BINDIR}/md5sum \
${BINDIR}/md5 ${BINDIR}/sha384sum \
${BINDIR}/md5 ${BINDIR}/sha512 \
${BINDIR}/md5 ${BINDIR}/sha512sum \
+ ${BINDIR}/md5 ${BINDIR}/sha512t224 \
+ ${BINDIR}/md5 ${BINDIR}/sha512t224sum \
${BINDIR}/md5 ${BINDIR}/sha512t256 \
${BINDIR}/md5 ${BINDIR}/sha512t256sum \
${BINDIR}/md5 ${BINDIR}/skein256 \
@@ -39,6 +38,8 @@ MLINKS= md5.1 md5sum.1 \
md5.1 sha384sum.1 \
md5.1 sha512.1 \
md5.1 sha512sum.1 \
+ md5.1 sha512t224.1 \
+ md5.1 sha512t224sum.1 \
md5.1 sha512t256.1 \
md5.1 sha512t256sum.1 \
md5.1 skein256.1 \
@@ -48,18 +49,27 @@ MLINKS= md5.1 md5sum.1 \
md5.1 skein1024.1 \
md5.1 skein1024sum.1
+# md5 can also emulate the shasum script that comes with Perl, except
+# that, in bits input mode, it can only handle input lengths that are
+# a multiple of 8 (see manual page).
+#LINKS+= ${BINDIR}/md5 ${BINDIR}/shasum
+#MLINKS+= md5.1 shasum.1
+
LIBADD= md
-.ifndef(BOOTSTRAPPING)
+.include <src.opts.mk>
+
+.if ${MK_CASPER} != "no" && !defined(RESCUE) && !defined(BOOTSTRAPPING)
# Avoid depending on capsicum during bootstrap. caph_limit_stdout() is not
# available when building for Linux/MacOS or older FreeBSD hosts.
# We need to bootstrap md5 when building on Linux since the md5sum command there
# produces different output.
CFLAGS+=-DHAVE_CAPSICUM
+CFLAGS+=-DWITH_CASPER
+LIBADD+= casper
+LIBADD+= cap_fileargs
.endif
-.include <src.opts.mk>
-
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/sbin/md5/Makefile.depend b/sbin/md5/Makefile.depend
index 18541d6a1857..61733f6b057b 100644
--- a/sbin/md5/Makefile.depend
+++ b/sbin/md5/Makefile.depend
@@ -1,13 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcapsicum \
+ lib/libcasper/libcasper \
+ lib/libcasper/services/cap_fileargs \
lib/libcompiler_rt \
lib/libmd \
diff --git a/sbin/md5/Makefile.depend.host b/sbin/md5/Makefile.depend.host
new file mode 100644
index 000000000000..d8305953a160
--- /dev/null
+++ b/sbin/md5/Makefile.depend.host
@@ -0,0 +1,11 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ lib/libmd \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/md5/md5.1 b/sbin/md5/md5.1
index 899e49ba3517..b530292c8269 100644
--- a/sbin/md5/md5.1
+++ b/sbin/md5/md5.1
@@ -1,12 +1,14 @@
-.\" $FreeBSD$
-.Dd Feb 5, 2022
+.Dd March 12, 2024
.Dt MD5 1
.Os
.Sh NAME
-.Nm md5 , sha1 , sha224 , sha256 , sha384 , sha512 , sha512t256 , rmd160 ,
-.Nm skein256 , skein512 , skein1024 ,
-.Nm md5sum , sha1sum , sha224sum , sha256sum , sha384sum , sha512sum ,
-.Nm sha512t256sum , rmd160sum , skein256sum , skein512sum , skein1024sum
+.Nm md5 , sha1 , sha224 , sha256 , sha384 ,
+.Nm sha512 , sha512t224 , sha512t256 ,
+.Nm rmd160 , skein256 , skein512 , skein1024 ,
+.Nm md5sum , sha1sum , sha224sum , sha256sum , sha384sum ,
+.Nm sha512sum , sha512t224sum , sha512t256sum ,
+.Nm rmd160sum , skein256sum , skein512sum , skein1024sum ,
+.Nm shasum
.Nd calculate a message-digest fingerprint (checksum) for a file
.Sh SYNOPSIS
.Nm
@@ -16,16 +18,44 @@
.Op Ar
.Pp
.Nm md5sum
-.Op Fl pqrtx
-.Op Fl c Ar file
-.Op Fl s Ar string
+.Op Fl bctwz
+.Op Fl -binary
+.Op Fl -check
+.Op Fl -help
+.Op Fl -ignore-missing
+.Op Fl -quiet
+.Op Fl -status
+.Op Fl -strict
+.Op Fl -tag
+.Op Fl -text
+.Op Fl -version
+.Op Fl -warn
+.Op Fl -zero
.Op Ar
.Pp
(All other hashes have the same options and usage.)
+.Pp
+.Nm shasum
+.Op Fl 0bchqstUvw
+.Op Fl -01
+.Op Fl a | -algorithm Ar alg
+.Op Fl -binary
+.Op Fl -check
+.Op Fl -help
+.Op Fl -ignore-missing
+.Op Fl -quiet
+.Op Fl -status
+.Op Fl -strict
+.Op Fl -tag
+.Op Fl -text
+.Op Fl -UNIVERSAL
+.Op Fl -version
+.Op Fl -warn
+.Op Ar
.Sh DESCRIPTION
The
-.Nm md5 , sha1 , sha224 , sha256 , sha384 , sha512 , sha512t256 , rmd160 ,
-.Nm skein256 , skein512 ,
+.Nm md5 , sha1 , sha224 , sha256 , sha384 , sha512 , sha512t224 , sha512t256 ,
+.Nm rmd160 , skein256 , skein512 ,
and
.Nm skein1024
utilities take as input a message of arbitrary length and produce as
@@ -34,15 +64,26 @@ output a
or
.Dq message digest
of the input.
+.Pp
The
.Nm md5sum , sha1sum , sha224sum , sha256sum , sha384sum , sha512sum ,
-.Nm sha512t256sum , rmd160sum , skein256sum , skein512sum ,
+.Nm sha512t224sum , sha512t256sum , rmd160sum , skein256sum , skein512sum ,
and
.Nm skein1024sum
-utilities do the same, but default to the reversed format of
-the
-.Fl r
-flag.
+utilities do the same, but with command-line options and an output
+format that match those of their similary named GNU utilities.
+.Pp
+The
+.Nm shasum
+utility does the same, but with command-line options and an output
+format that match those of the similarly named utility that ships with
+Perl.
+.Pp
+In all cases, each file listed on the command line is processed separately.
+If no files are listed on the command line, or a file name is given as
+.Pa - ,
+input is taken from stdin instead.
+.Pp
It is conjectured that it is computationally infeasible to
produce two messages having the same message digest, or to produce any
message having a given prespecified target message digest.
@@ -68,72 +109,179 @@ On 64-bit hardware, this algorithm is approximately 50% faster than SHA-256 but
with the same level of security.
The hashes are not interchangeable.
.Pp
+SHA-512t224 is identical to SHA-512t256, but with the digest truncated
+to 224 bits.
+.Pp
It is recommended that all new applications use SHA-512 or SKEIN-512
instead of one of the other hash functions.
-.Pp
-The following options may be used in any combination and must
-precede any files named on the command line.
-The hexadecimal checksum of each file listed on the command line is printed
-after the options are processed.
+.Ss BSD OPTIONS
+The following options are available in BSD mode, i.e. when the program
+is invoked with a name that does not end in
+.Dq sum :
.Bl -tag -width indent
-.It Fl b
-Make the
-.Nm -sum
-programs separate hash and digest with a blank followed by an asterisk instead
-of by 2 blank characters for full compatibility with the output generated by the
-coreutils versions of these programs.
-.It Fl c Ar string
-If the program was called with a name that does not end in
-.Nm sum ,
-compare the digest of the file against this string.
-.Pq Note that this option is not yet useful if multiple files are specified.
-.It Fl c Ar file
-If the program was called with a name that does end in
-.Nm sum ,
-the file passed as argument must contain digest lines generated by the same
-digest algorithm with or without the
-.Fl r
-option
-.Pq i.e. in either classical BSD format or in GNU coreutils format .
-A line with the file name followed by a colon
-.Dq ":"
-and either OK or FAILED is written for each well-formed line in the digest file.
-If applicable, the number of failed comparisons and the number of lines that were
-skipped since they were not well-formed are printed at the end.
-The
+.It Fl c Ar string , Fl -check= Ns Ar string
+Compare the digest of the file against this string.
+If combined with the
.Fl q
-option can be used to quiesce the output unless there are mismatched entries in
-the digest.
-.Pp
-.It Fl s Ar string
-Print a checksum of the given
-.Ar string .
-.It Fl p
+or
+.Fl -quiet
+option, the calculated digest is printed in addition to the exit status being set.
+.Pq Note that this option is not yet useful if multiple files are specified.
+.It Fl p , -passthrough
Echo stdin to stdout and append the checksum to stdout.
-.It Fl q
+In this mode, any files specified on the command line are silently ignored.
+.It Fl q , -quiet
Quiet mode \(em only the checksum is printed out.
Overrides the
.Fl r
+or
+.Fl -reverse
option.
-.It Fl r
+.It Fl r , -reverse
Reverses the format of the output.
This helps with visual diffs.
Does nothing
when combined with the
.Fl ptx
options.
-.It Fl t
+.It Fl s Ar string , Fl -string= Ns Ar string
+Print a checksum of the given
+.Ar string .
+In this mode, any files specified on the command line are silently ignored.
+.It Fl t , Fl -time-trial
Run a built-in time trial.
For the
.Nm -sum
versions, this is a nop for compatibility with coreutils.
-.It Fl x
+.It Fl x , Fl -self-test
Run a built-in test script.
.El
+.Ss GNU OPTIONS
+The following options are available in GNU mode, i.e. when the program
+is invoked with a name that ends in
+.Dq sum :
+.Bl -tag -width indent
+.It Fl b , Fl -binary
+Read files in binary mode.
+.It Fl c , Fl -check
+The file passed as arguments must contain digest lines generated by the same
+digest algorithm in either classical BSD format or in GNU coreutils format.
+A line with the file name followed by a colon
+.Dq ":"
+and either OK or FAILED is written for each well-formed line in the digest file.
+If applicable, the number of failed comparisons and the number of lines that were
+skipped since they were not well-formed are printed at the end.
+The
+.Fl -quiet
+option can be used to quiesce the output unless there are mismatched entries in
+the digest.
+.It Fl -help
+Print a usage message and exit.
+.It Fl -ignore-missing
+When verifying checksums, ignore files for which checksums are given
+but which aren't found on disk.
+.It Fl -quiet
+When verifying checksums, do not print anything unless the
+verification fails.
+.It Fl -status
+When verifying checksums, do not print anything at all.
+The exit code will reflect whether verification succeeded.
+.It Fl -strict
+When verifying checksums, fail if the input is malformed.
+.It Fl -tag
+Produce BSD-style output.
+.It Fl t , Fl -text
+Read files in text mode.
+This is the default.
+Note that this implementation does not differentiate between binary
+and text mode.
+.It Fl -version
+Print version information and exit.
+.It Fl w , Fl -warn
+When verifying checksums, warn about malformed input.
+.It Fl z , Fl -zero
+Terminate output lines with NUL rather than with newline.
+.El
+.Ss PERL OPTIONS
+The following options are available in Perl mode, i.e. when the program
+is invoked with the name
+.Dq shasum :
+.Bl -tag -width indent
+.It Fl 0 , Fl -01
+Read files in bits mode: ASCII
+.Sq 0
+and
+.Sq 1
+characters correspond to 0 and 1 bits, respectively, and all other
+characters are ignored.
+See
+.Sx BUGS .
+.It Fl a Ar alg , Fl -algorithm Ar alg
+Use the specified algorithm:
+.Dq 1
+for SHA-1 (default),
+.Dq xxx
+for
+.Va xxx Ns -bit
+SHA-2 (e.g.
+.Dq 256
+for SHA-256)
+or
+.Dq xxxyyy
+for
+.Va xxx Ns -bit
+SHA-2 truncated to
+.Va yyy
+bits (e.g.
+.Dq 512224
+for SHA-512/224).
+.It Fl b , Fl -binary
+Read files in binary mode.
+.It Fl c , Fl -check
+The file passed as arguments must contain digest lines generated by the same
+digest algorithm in either classical BSD format or in GNU coreutils format.
+A line with the file name followed by a colon
+.Dq ":"
+and either OK or FAILED is written for each well-formed line in the digest file.
+If applicable, the number of failed comparisons and the number of lines that were
+skipped since they were not well-formed are printed at the end.
+The
+.Fl -quiet
+option can be used to quiesce the output unless there are mismatched entries in
+the digest.
+.It Fl -help
+Print a usage message and exit.
+.It Fl -ignore-missing
+When verifying checksums, ignore files for which checksums are given
+but which aren't found on disk.
+.It Fl -quiet
+When verifying checksums, do not print anything unless the
+verification fails.
+.It Fl -status
+When verifying checksums, do not print anything at all.
+The exit code will reflect whether verification succeeded.
+.It Fl -strict
+When verifying checksums, fail if the input is malformed.
+.It Fl -tag
+Produce BSD-style output.
+.It Fl t , Fl -text
+Read files in text mode.
+This is the default.
+Note that this implementation does not differentiate between binary
+and text mode.
+.It Fl U , Fl -UNIVERSAL
+Read files in universal mode: any CR-LF pair, as well as any CR not
+followed by LF, is translated to LF before the digest is computed.
+.It Fl -version
+Print version information and exit.
+.It Fl w , Fl -warn
+When verifying checksums, warn about malformed input.
+.El
.Sh EXIT STATUS
The
-.Nm md5 , sha1 , sha224 , sha256 , sha512 , sha512t256 , rmd160 ,
-.Nm skein256 , skein512 ,
+.Nm md5 , sha1 , sha224 , sha256 , sha384 , sha512 ,
+.Nm sha512t224 , sha512t256 ,
+.Nm rmd160 , skein256 , skein512 ,
and
.Nm skein1024
utilities exit 0 on success,
@@ -141,6 +289,16 @@ utilities exit 0 on success,
and 2 if at least one file does not have the same hash as the
.Fl c
option.
+.Pp
+The
+.Nm md5sum , sha1sum , sha224sum , sha256sum , sha384sum , sha512sum ,
+.Nm sha512t224sum , sha512t256sum ,
+.Nm rmd160 , skein256 , skein512 , skein1024
+and
+.Nm shasum
+utilities exit 0 on success and 1 if at least one of the input files
+could not be read or, when verifying checksums, does not have the
+expected checksum.
.Sh EXAMPLES
Calculate the MD5 checksum of the string
.Dq Hello .
@@ -161,11 +319,22 @@ Calculate the checksum of multiple files reversing the output:
$ md5 -r /boot/loader.conf /etc/rc.conf
ada5f60f23af88ff95b8091d6d67bef6 /boot/loader.conf
d80bf36c332dc0fdc479366ec3fa44cd /etc/rc.conf
-.Pd
-The
-.Nm -sum
-variants put 2 blank characters between hash and file name for full compatibility
-with the coreutils versions of these commands.
+.Ed
+.Pp
+This is almost but not quite identical to the output from GNU mode:
+.Bd -literal -offset indent
+$ md5sum /boot/loader.conf /etc/rc.conf
+ada5f60f23af88ff95b8091d6d67bef6 /boot/loader.conf
+d80bf36c332dc0fdc479366ec3fa44cd /etc/rc.conf
+.Ed
+.Pp
+Note the two spaces between hash and file name.
+If binary mode is requested, they are instead separated by a space and
+an asterisk:
+.Bd -literal -offset indent
+$ md5sum -b /boot/loader.conf /etc/rc.conf
+ada5f60f23af88ff95b8091d6d67bef6 */boot/loader.conf
+d80bf36c332dc0fdc479366ec3fa44cd */etc/rc.conf
.Ed
.Pp
Write the digest for
@@ -189,9 +358,7 @@ $ md5 -c randomstring /boot/loader.conf
MD5 (/boot/loader.conf) = ada5f60f23af88ff95b8091d6d67bef6 [ Failed ]
.Ed
.Pp
-If invoked with a name ending in
-.Nm -sum
-the
+In GNU mode, the
.Fl c
option does not compare against a hash string passed as parameter.
Instead, it expects a digest file, as created under the name
@@ -200,15 +367,16 @@ for
.Pa /boot/loader.conf
in the example above.
.Bd -literal -offset indent
-$ md5 -c digest /boot/loader.conf
+$ md5sum -c digest
/boot/loader.conf: OK
.Ed
.Pp
-The digest file may contain any number of lines in the format generated with or without the
-.Fl r
-option
-.Pq i.e. in either classical BSD format or in GNU coreutils format .
-If a hash value does not match the file, FAILED is printed instead of OK.
+The digest file may contain any number of lines in the format
+generated in either BSD or GNU mode.
+If a hash value does not match the file,
+.Dq FAILED
+is printed instead of
+.Dq OK .
.Sh SEE ALSO
.Xr cksum 1 ,
.Xr md5 3 ,
@@ -244,13 +412,29 @@ Secure Hash Standard (SHS):
The RIPEMD-160 page:
.Pa https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
.Sh BUGS
-All of the utilities that end in
-.Sq sum
-are intended to be compatible with the GNU coreutils programs.
-However, the long option functionality is not provided.
+In bits mode, the original
+.Nm shasum
+script is capable of processing inputs of arbitrary length.
+This implementation is not, and will issue an error if the input
+length is not a multiple of eight bits.
.Sh ACKNOWLEDGMENTS
-This program is placed in the public domain for free general use by
-RSA Data Security.
+.An -nosplit
+This utility was originally derived from a program which was placed in
+the public domain for free general use by RSA Data Security.
.Pp
-Support for SHA-1 and RIPEMD-160 has been added by
+Support for SHA-1 and RIPEMD-160 was added by
.An Oliver Eikemeier Aq Mt eik@FreeBSD.org .
+.Pp
+Support for SHA-2 was added by
+.An Colin Percival Aq Mt cperciva@FreeBSD.org
+and
+.An Allan Jude Aq Mt allanjude@FreeBSD.org .
+.Pp
+Support for SKEIN was added by
+.An Allan Jude Aq Mt allanjude@FreeBSD.org .
+.Pp
+Compatibility with GNU coreutils was added by
+.An Warner Losh Aq Mt imp@FreeBSD.org
+and much expanded by
+.An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org ,
+who also added Perl compatibility.
diff --git a/sbin/md5/md5.c b/sbin/md5/md5.c
index 7235e6e0a39f..10ffae53c775 100644
--- a/sbin/md5/md5.c
+++ b/sbin/md5/md5.c
@@ -17,16 +17,17 @@
* documentation and/or software.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
#include <sys/param.h>
-#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <md5.h>
+#include <osreldate.h>
#include <ripemd.h>
#include <sha.h>
#include <sha224.h>
@@ -45,6 +46,8 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_CAPSICUM
#include <sys/capsicum.h>
#include <capsicum_helpers.h>
+#include <libcasper.h>
+#include <casper/cap_fileargs.h>
#endif
/*
@@ -54,16 +57,20 @@ __FBSDID("$FreeBSD$");
#define TEST_BLOCK_COUNT 100000
#define MDTESTCOUNT 8
-static int bflag;
-static int cflag;
-static int pflag;
-static int qflag;
-static int rflag;
-static int sflag;
-static int skip;
+static char *progname;
+
+static bool cflag;
+static bool pflag;
+static bool qflag;
+static bool sflag;
+static bool wflag;
+static bool strict;
+static bool skip;
+static bool ignoreMissing;
static char* checkAgainst;
static int checksFailed;
-static int failed;
+static bool failed;
+static int endl = '\n';
typedef void (DIGEST_Init)(void *);
typedef void (DIGEST_Update)(void *, const unsigned char *, size_t);
@@ -75,6 +82,7 @@ extern const char *SHA224_TestOutput[MDTESTCOUNT];
extern const char *SHA256_TestOutput[MDTESTCOUNT];
extern const char *SHA384_TestOutput[MDTESTCOUNT];
extern const char *SHA512_TestOutput[MDTESTCOUNT];
+extern const char *SHA512t224_TestOutput[MDTESTCOUNT];
extern const char *SHA512t256_TestOutput[MDTESTCOUNT];
extern const char *RIPEMD160_TestOutput[MDTESTCOUNT];
extern const char *SKEIN256_TestOutput[MDTESTCOUNT];
@@ -83,21 +91,22 @@ extern const char *SKEIN1024_TestOutput[MDTESTCOUNT];
typedef struct Algorithm_t {
const char *progname;
+ const char *perlname;
const char *name;
const char *(*TestOutput)[MDTESTCOUNT];
DIGEST_Init *Init;
DIGEST_Update *Update;
DIGEST_End *End;
char *(*Data)(const void *, unsigned int, char *);
- char *(*Fd)(int, char *);
} Algorithm_t;
static void MD5_Update(MD5_CTX *, const unsigned char *, size_t);
-static void MDOutput(const Algorithm_t *, char *, char **);
+static char *MDInput(const Algorithm_t *, FILE *, char *, bool);
+static void MDOutput(const Algorithm_t *, char *, const char *);
static void MDTimeTrial(const Algorithm_t *);
static void MDTestSuite(const Algorithm_t *);
-static char *MDFilter(const Algorithm_t *, char*, int);
static void usage(const Algorithm_t *);
+static void version(void);
typedef union {
MD5_CTX md5;
@@ -120,44 +129,156 @@ typedef union {
/* algorithm function table */
static const struct Algorithm_t Algorithm[] = {
- { "md5", "MD5", &MD5TestOutput, (DIGEST_Init*)&MD5Init,
+ { "md5", NULL, "MD5",
+ &MD5TestOutput, (DIGEST_Init*)&MD5Init,
(DIGEST_Update*)&MD5_Update, (DIGEST_End*)&MD5End,
- &MD5Data, &MD5Fd },
- { "sha1", "SHA1", &SHA1_TestOutput, (DIGEST_Init*)&SHA1_Init,
+ &MD5Data },
+ { "sha1", "1", "SHA1",
+ &SHA1_TestOutput, (DIGEST_Init*)&SHA1_Init,
(DIGEST_Update*)&SHA1_Update, (DIGEST_End*)&SHA1_End,
- &SHA1_Data, &SHA1_Fd },
- { "sha224", "SHA224", &SHA224_TestOutput, (DIGEST_Init*)&SHA224_Init,
+ &SHA1_Data },
+ { "sha224", "224", "SHA224",
+ &SHA224_TestOutput, (DIGEST_Init*)&SHA224_Init,
(DIGEST_Update*)&SHA224_Update, (DIGEST_End*)&SHA224_End,
- &SHA224_Data, &SHA224_Fd },
- { "sha256", "SHA256", &SHA256_TestOutput, (DIGEST_Init*)&SHA256_Init,
+ &SHA224_Data },
+ { "sha256", "256", "SHA256",
+ &SHA256_TestOutput, (DIGEST_Init*)&SHA256_Init,
(DIGEST_Update*)&SHA256_Update, (DIGEST_End*)&SHA256_End,
- &SHA256_Data, &SHA256_Fd },
- { "sha384", "SHA384", &SHA384_TestOutput, (DIGEST_Init*)&SHA384_Init,
+ &SHA256_Data },
+ { "sha384", "384", "SHA384",
+ &SHA384_TestOutput, (DIGEST_Init*)&SHA384_Init,
(DIGEST_Update*)&SHA384_Update, (DIGEST_End*)&SHA384_End,
- &SHA384_Data, &SHA384_Fd },
- { "sha512", "SHA512", &SHA512_TestOutput, (DIGEST_Init*)&SHA512_Init,
+ &SHA384_Data },
+ { "sha512", "512", "SHA512",
+ &SHA512_TestOutput, (DIGEST_Init*)&SHA512_Init,
(DIGEST_Update*)&SHA512_Update, (DIGEST_End*)&SHA512_End,
- &SHA512_Data, &SHA512_Fd },
- { "sha512t256", "SHA512t256", &SHA512t256_TestOutput, (DIGEST_Init*)&SHA512_256_Init,
+ &SHA512_Data },
+ { "sha512t224", "512224", "SHA512t224",
+ &SHA512t224_TestOutput, (DIGEST_Init*)&SHA512_224_Init,
+ (DIGEST_Update*)&SHA512_224_Update, (DIGEST_End*)&SHA512_224_End,
+ &SHA512_224_Data },
+ { "sha512t256", "512256", "SHA512t256",
+ &SHA512t256_TestOutput, (DIGEST_Init*)&SHA512_256_Init,
(DIGEST_Update*)&SHA512_256_Update, (DIGEST_End*)&SHA512_256_End,
- &SHA512_256_Data, &SHA512_256_Fd },
- { "rmd160", "RMD160", &RIPEMD160_TestOutput,
+ &SHA512_256_Data },
+ { "rmd160", NULL, "RMD160",
+ &RIPEMD160_TestOutput,
(DIGEST_Init*)&RIPEMD160_Init, (DIGEST_Update*)&RIPEMD160_Update,
- (DIGEST_End*)&RIPEMD160_End, &RIPEMD160_Data, &RIPEMD160_Fd },
- { "skein256", "Skein256", &SKEIN256_TestOutput,
+ (DIGEST_End*)&RIPEMD160_End, &RIPEMD160_Data },
+ { "skein256", NULL, "Skein256",
+ &SKEIN256_TestOutput,
(DIGEST_Init*)&SKEIN256_Init, (DIGEST_Update*)&SKEIN256_Update,
- (DIGEST_End*)&SKEIN256_End, &SKEIN256_Data, &SKEIN256_Fd },
- { "skein512", "Skein512", &SKEIN512_TestOutput,
+ (DIGEST_End*)&SKEIN256_End, &SKEIN256_Data },
+ { "skein512", NULL, "Skein512",
+ &SKEIN512_TestOutput,
(DIGEST_Init*)&SKEIN512_Init, (DIGEST_Update*)&SKEIN512_Update,
- (DIGEST_End*)&SKEIN512_End, &SKEIN512_Data, &SKEIN512_Fd },
- { "skein1024", "Skein1024", &SKEIN1024_TestOutput,
+ (DIGEST_End*)&SKEIN512_End, &SKEIN512_Data },
+ { "skein1024", NULL, "Skein1024",
+ &SKEIN1024_TestOutput,
(DIGEST_Init*)&SKEIN1024_Init, (DIGEST_Update*)&SKEIN1024_Update,
- (DIGEST_End*)&SKEIN1024_End, &SKEIN1024_Data, &SKEIN1024_Fd }
+ (DIGEST_End*)&SKEIN1024_End, &SKEIN1024_Data },
+ { }
+};
+
+static int digest = -1;
+static unsigned int malformed;
+
+static enum mode {
+ mode_bsd,
+ mode_gnu,
+ mode_perl,
+} mode = mode_bsd;
+
+static enum input_mode {
+ input_binary = '*',
+ input_text = ' ',
+ input_universal = 'U',
+ input_bits = '^',
+} input_mode = input_binary;
+
+static enum output_mode {
+ output_bare,
+ output_tagged,
+ output_reverse,
+ output_gnu,
+} output_mode = output_tagged;
+
+enum optval {
+ opt_end = -1,
+ /* ensure we don't collide with shortopts */
+ opt_dummy = CHAR_MAX,
+ /* BSD options */
+ opt_check,
+ opt_passthrough,
+ opt_quiet,
+ opt_reverse,
+ opt_string,
+ opt_time_trial,
+ opt_self_test,
+ /* GNU options */
+ opt_binary,
+ opt_help,
+ opt_ignore_missing,
+ opt_status,
+ opt_strict,
+ opt_tag,
+ opt_text,
+ opt_warn,
+ opt_version,
+ opt_zero,
+ /* Perl options */
+ opt_algorithm,
+ opt_bits,
+ opt_universal,
};
-static unsigned digest;
-static unsigned malformed;
-static bool gnu_emu = false;
+static const struct option bsd_longopts[] = {
+ { "check", required_argument, 0, opt_check },
+ { "passthrough", no_argument, 0, opt_passthrough },
+ { "quiet", no_argument, 0, opt_quiet },
+ { "reverse", no_argument, 0, opt_reverse },
+ { "string", required_argument, 0, opt_string },
+ { "time-trial", no_argument, 0, opt_time_trial },
+ { "self-test", no_argument, 0, opt_self_test },
+ { }
+};
+static const char *bsd_shortopts = "bc:pqrs:tx";
+
+static const struct option gnu_longopts[] = {
+ { "binary", no_argument, 0, opt_binary },
+ { "check", no_argument, 0, opt_check },
+ { "help", no_argument, 0, opt_help },
+ { "ignore-missing", no_argument, 0, opt_ignore_missing },
+ { "quiet", no_argument, 0, opt_quiet },
+ { "status", no_argument, 0, opt_status },
+ { "strict", no_argument, 0, opt_strict },
+ { "tag", no_argument, 0, opt_tag },
+ { "text", no_argument, 0, opt_text },
+ { "version", no_argument, 0, opt_version },
+ { "warn", no_argument, 0, opt_warn },
+ { "zero", no_argument, 0, opt_zero },
+ { }
+};
+static const char *gnu_shortopts = "bctwz";
+
+static const struct option perl_longopts[] = {
+ { "algorithm", required_argument, 0, opt_algorithm },
+ { "binary", no_argument, 0, opt_binary },
+ { "check", no_argument, 0, opt_check },
+ { "help", no_argument, 0, opt_help },
+ { "ignore-missing", no_argument, 0, opt_ignore_missing },
+ { "quiet", no_argument, 0, opt_quiet },
+ { "status", no_argument, 0, opt_status },
+ { "strict", no_argument, 0, opt_strict },
+ { "tag", no_argument, 0, opt_tag },
+ { "text", no_argument, 0, opt_text },
+ { "UNIVERSAL", no_argument, 0, opt_universal },
+ { "version", no_argument, 0, opt_version },
+ { "warn", no_argument, 0, opt_warn },
+ { "01", no_argument, 0, opt_bits },
+ { }
+};
+static const char *perl_shortopts = "0a:bchqstUvw";
static void
MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len)
@@ -166,80 +287,103 @@ MD5_Update(MD5_CTX *c, const unsigned char *data, size_t len)
}
struct chksumrec {
- char *filename;
- char *chksum;
- struct chksumrec *next;
+ char *filename;
+ enum input_mode input_mode;
+ char *chksum;
+ struct chksumrec *next;
};
static struct chksumrec *head = NULL;
static struct chksumrec **next = &head;
+static unsigned int numrecs;
#define PADDING 7 /* extra padding for "SHA512t256 (...) = ...\n" style */
#define CHKFILELINELEN (HEX_DIGEST_LENGTH + MAXPATHLEN + PADDING)
-static int gnu_check(const char *checksumsfile)
+static void
+gnu_check(const char *checksumsfile)
{
- FILE *inp;
- char linebuf[CHKFILELINELEN];
- int linelen;
- int lineno;
- char *filename;
- char *hashstr;
- struct chksumrec *rec;
- const char *digestname;
- int digestnamelen;
- int hashstrlen;
-
- if ((inp = fopen(checksumsfile, "r")) == NULL)
+ FILE *inp;
+ char *linebuf = NULL;
+ size_t linecap;
+ ssize_t linelen;
+ int lineno;
+ char *filename;
+ char *hashstr;
+ struct chksumrec *rec;
+ const char *digestname;
+ size_t digestnamelen;
+ size_t hashstrlen;
+ struct stat st;
+
+ if (strcmp(checksumsfile, "-") == 0)
+ inp = stdin;
+ else if ((inp = fopen(checksumsfile, "r")) == NULL)
err(1, "%s", checksumsfile);
digestname = Algorithm[digest].name;
digestnamelen = strlen(digestname);
hashstrlen = strlen(*(Algorithm[digest].TestOutput[0]));
- lineno = 1;
- while (fgets(linebuf, sizeof(linebuf), inp) != NULL) {
- linelen = strlen(linebuf) - 1;
- if (linelen <= 0)
- break;
- if (linebuf[linelen] != '\n')
- errx(1, "malformed input line %d (len=%d)", lineno, linelen);
+ lineno = 0;
+ linecap = CHKFILELINELEN;
+ while ((linelen = getline(&linebuf, &linecap, inp)) > 0) {
+ lineno++;
+ while (linelen > 0 && linebuf[linelen - 1] == '\n')
+ linelen--;
linebuf[linelen] = '\0';
filename = linebuf + digestnamelen + 2;
hashstr = linebuf + linelen - hashstrlen;
/*
* supported formats:
* BSD: <DigestName> (<Filename>): <Digest>
- * GNU: <Digest> [ *]<Filename>
+ * GNU: <Digest> [ *U^]<Filename>
*/
- if (linelen >= digestnamelen + hashstrlen + 6 &&
+ if ((size_t)linelen >= digestnamelen + hashstrlen + 6 &&
strncmp(linebuf, digestname, digestnamelen) == 0 &&
strncmp(filename - 2, " (", 2) == 0 &&
- strncmp(hashstr - 4, ") = ", 4) == 0) {
+ strncmp(hashstr - 4, ") = ", 4) == 0 &&
+ strspn(hashstr, "0123456789ABCDEFabcdef") == hashstrlen) {
*(hashstr - 4) = '\0';
- } else if (linelen >= hashstrlen + 3 &&
+ } else if ((size_t)linelen >= hashstrlen + 3 &&
+ strspn(linebuf, "0123456789ABCDEFabcdef") == hashstrlen &&
linebuf[hashstrlen] == ' ') {
linebuf[hashstrlen] = '\0';
hashstr = linebuf;
filename = linebuf + hashstrlen + 1;
- if (*filename == ' ' || *filename == '*')
- filename++;
} else {
+ if (wflag) {
+ warnx("%s: %d: improperly formatted "
+ "%s checksum line",
+ checksumsfile, lineno,
+ mode == mode_perl ? "SHA" : digestname);
+ }
malformed++;
continue;
}
- rec = malloc(sizeof (*rec));
+ rec = malloc(sizeof(*rec));
if (rec == NULL)
errx(1, "malloc failed");
+
+ if ((*filename == '*' || *filename == ' ' ||
+ *filename == 'U' || *filename == '^') &&
+ lstat(filename, &st) != 0 &&
+ lstat(filename + 1, &st) == 0) {
+ rec->filename = strdup(filename + 1);
+ rec->input_mode = (enum input_mode)*filename;
+ } else {
+ rec->filename = strdup(filename);
+ rec->input_mode = input_mode;
+ }
+
rec->chksum = strdup(hashstr);
- rec->filename = strdup(filename);
if (rec->chksum == NULL || rec->filename == NULL)
errx(1, "malloc failed");
rec->next = NULL;
*next = rec;
next = &rec->next;
- lineno++;
+ numrecs++;
}
- fclose(inp);
- return (lineno - 1);
+ if (inp != stdin)
+ fclose(inp);
}
/* Main driver.
@@ -255,20 +399,22 @@ int
main(int argc, char *argv[])
{
#ifdef HAVE_CAPSICUM
- cap_rights_t rights;
+ cap_rights_t rights;
+ fileargs_t *fa = NULL;
#endif
- int ch, fd;
- char *p, *string;
- char buf[HEX_DIGEST_LENGTH];
- size_t len;
- char *progname;
- struct chksumrec *rec;
- int numrecs;
-
- if ((progname = strrchr(argv[0], '/')) == NULL)
- progname = argv[0];
- else
- progname++;
+ const struct option *longopts;
+ const char *shortopts;
+ FILE *f;
+ int i, opt;
+ char *p, *string = NULL;
+ char buf[HEX_DIGEST_LENGTH];
+ size_t len;
+ struct chksumrec *rec;
+
+ if ((progname = strrchr(argv[0], '/')) == NULL)
+ progname = argv[0];
+ else
+ progname++;
/*
* GNU coreutils has a number of programs named *sum. These produce
@@ -280,59 +426,150 @@ main(int argc, char *argv[])
* since that means 'text file' there (though it's a nop in coreutils
* on unix-like systems). The -c flag conflicts, so it's just disabled
* in this mode (though in the future it might be implemented).
+ *
+ * We also strive to be compatible with the shasum script which is
+ * included in Perl. It is roughly equivalent to the GNU offering
+ * but uses a command-line argument to select the algorithm, and
+ * supports only SHA-1 and SHA-2.
*/
len = strlen(progname);
- if (len > 3 && strcmp(progname + len - 3, "sum") == 0) {
+ if (strcmp(progname, "shasum") == 0) {
+ mode = mode_perl;
+ input_mode = input_text;
+ output_mode = output_gnu;
+ digest = 1;
+ longopts = perl_longopts;
+ shortopts = perl_shortopts;
+ } else if (len > 3 && strcmp(progname + len - 3, "sum") == 0) {
len -= 3;
- rflag = 1;
- gnu_emu = true;
+ mode = mode_gnu;
+ input_mode = input_text;
+ /*
+ * The historical behavior in GNU emulation mode is
+ * output_reverse, however this not true to the original
+ * and the flag that was used to force the correct output
+ * was -b, which means something else (input_binary) in
+ * GNU land. Switch to the correct behavior.
+ */
+ output_mode = output_gnu;
+ longopts = gnu_longopts;
+ shortopts = gnu_shortopts;
+ } else {
+ mode = mode_bsd;
+ input_mode = input_binary;
+ output_mode = output_tagged;
+ longopts = bsd_longopts;
+ shortopts = bsd_shortopts;
}
- for (digest = 0; digest < sizeof(Algorithm)/sizeof(*Algorithm); digest++)
- if (strncasecmp(Algorithm[digest].progname, progname, len) == 0)
- break;
+ if (digest < 0) {
+ for (digest = 0; Algorithm[digest].progname != NULL; digest++)
+ if (strncasecmp(Algorithm[digest].progname, progname, len) == 0)
+ break;
- if (digest == sizeof(Algorithm)/sizeof(*Algorithm))
- digest = 0;
+ if (Algorithm[digest].progname == NULL)
+ digest = 0;
+ }
- failed = 0;
+ failed = false;
checkAgainst = NULL;
checksFailed = 0;
- skip = 0;
- while ((ch = getopt(argc, argv, "bc:pqrs:tx")) != -1)
- switch (ch) {
+ skip = false;
+ while ((opt = getopt_long(argc, argv, shortopts, longopts, NULL)) != opt_end)
+ switch (opt) {
+ case opt_bits:
+ case '0':
+ input_mode = input_bits;
+ break;
+ case opt_algorithm:
+ case 'a':
+ for (i = 0; Algorithm[i].progname != NULL; i++) {
+ if (Algorithm[i].perlname != NULL &&
+ strcasecmp(Algorithm[i].perlname, optarg) == 0) {
+ digest = i;
+ break;
+ }
+ }
+ if (Algorithm[i].progname == NULL)
+ usage(&Algorithm[digest]);
+ break;
+ case opt_binary:
case 'b':
- bflag = 1;
+ /* in BSD mode, -b is now a no-op */
+ if (mode != mode_bsd)
+ input_mode = input_binary;
break;
+ case opt_check:
case 'c':
- cflag = 1;
- if (gnu_emu)
- numrecs = gnu_check(optarg);
- else
+ cflag = true;
+ if (mode == mode_bsd)
checkAgainst = optarg;
break;
+ case opt_passthrough:
case 'p':
- pflag = 1;
+ pflag = true;
break;
+ case opt_quiet:
case 'q':
- qflag = 1;
+ output_mode = output_bare;
+ qflag = true;
break;
+ case opt_reverse:
case 'r':
- rflag = 1;
+ if (!qflag)
+ output_mode = output_reverse;
+ break;
+ case opt_status:
+ sflag = true;
+ break;
+ case opt_strict:
+ strict = 1;
break;
case 's':
- sflag = 1;
+ if (mode == mode_perl) {
+ sflag = true;
+ break;
+ }
+ /* fall through */
+ case opt_string:
+ output_mode = output_bare;
string = optarg;
break;
+ case opt_tag:
+ output_mode = output_tagged;
+ break;
+ case opt_time_trial:
+ case opt_text:
case 't':
- if (!gnu_emu) {
+ if (mode == mode_bsd) {
MDTimeTrial(&Algorithm[digest]);
- skip = 1;
- } /* else: text mode is a nop */
+ skip = true;
+ } else {
+ input_mode = input_text;
+ }
break;
+ case opt_universal:
+ case 'U':
+ input_mode = input_universal;
+ break;
+ case opt_version:
+ version();
+ break;
+ case opt_warn:
+ case 'w':
+ wflag = true;
+ break;
+ case opt_self_test:
case 'x':
MDTestSuite(&Algorithm[digest]);
- skip = 1;
+ skip = true;
+ break;
+ case opt_zero:
+ case 'z':
+ endl = '\0';
+ break;
+ case opt_ignore_missing:
+ ignoreMissing = true;
break;
default:
usage(&Algorithm[digest]);
@@ -341,16 +578,21 @@ main(int argc, char *argv[])
argv += optind;
#ifdef HAVE_CAPSICUM
- if (caph_limit_stdout() < 0 || caph_limit_stderr() < 0)
+ if (caph_limit_stdio() < 0)
err(1, "unable to limit rights for stdio");
#endif
- if (cflag && gnu_emu) {
+ if (cflag && mode != mode_bsd) {
/*
- * Replace argv by an array of filenames from the digest file
+ * Read digest files into a linked list, then replace argv
+ * with an array of the filenames from that list.
*/
+ if (argc < 1)
+ usage(&Algorithm[digest]);
+ while (argc--)
+ gnu_check(*argv++);
argc = 0;
- argv = (char**)calloc(sizeof(char *), numrecs + 1);
+ argv = calloc(numrecs + 1, sizeof(char *));
for (rec = head; rec != NULL; rec = rec->next) {
argv[argc] = rec->filename;
argc++;
@@ -359,101 +601,205 @@ main(int argc, char *argv[])
rec = head;
}
- if (*argv) {
- do {
- if ((fd = open(*argv, O_RDONLY)) < 0) {
- warn("%s", *argv);
- failed++;
- continue;
- }
- /*
- * XXX Enter capability mode on the last argv file.
- * When a casper file service or other approach is
- * available, switch to that and enter capability mode
- * earlier.
- */
- if (*(argv + 1) == NULL) {
#ifdef HAVE_CAPSICUM
- cap_rights_init(&rights, CAP_READ);
- if (caph_rights_limit(fd, &rights) < 0 ||
- caph_enter() < 0)
- err(1, "capsicum");
+ fa = fileargs_init(argc, argv, O_RDONLY, 0,
+ cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL), FA_OPEN | FA_LSTAT);
+ if (fa == NULL)
+ err(1, "Unable to initialize casper");
+ if (caph_enter_casper() < 0)
+ err(1, "Unable to enter capability mode");
#endif
- }
- if (cflag && gnu_emu) {
+
+ if (*argv && !pflag && string == NULL) {
+ do {
+ const char *filename = *argv;
+ const char *filemode = "rb";
+
+ if (cflag && mode != mode_bsd) {
+ input_mode = rec->input_mode;
checkAgainst = rec->chksum;
rec = rec->next;
}
- p = Algorithm[digest].Fd(fd, buf);
- (void)close(fd);
- MDOutput(&Algorithm[digest], p, argv);
- } while (*++argv);
- } else if (!cflag && !sflag && !skip) {
+ if (input_mode == input_text)
+ filemode = "r";
+ if (strcmp(filename, "-") == 0) {
+ f = stdin;
+ } else {
#ifdef HAVE_CAPSICUM
- if (caph_limit_stdin() < 0 || caph_enter() < 0)
- err(1, "capsicum");
+ f = fileargs_fopen(fa, filename, filemode);
+#else
+ f = fopen(filename, filemode);
#endif
- p = MDFilter(&Algorithm[digest], (char *)&buf, pflag);
- MDOutput(&Algorithm[digest], p, NULL);
- } else if (sflag) {
+ }
+ if (f == NULL) {
+ if (errno != ENOENT || !(cflag && ignoreMissing)) {
+ warn("%s", filename);
+ failed = true;
+ }
+ continue;
+ }
+ p = MDInput(&Algorithm[digest], f, buf, false);
+ if (f != stdin)
+ (void)fclose(f);
+ MDOutput(&Algorithm[digest], p, filename);
+ } while (*++argv);
+ } else if (!cflag && string == NULL && !skip) {
+ if (mode == mode_bsd)
+ output_mode = output_bare;
+ p = MDInput(&Algorithm[digest], stdin, buf, pflag);
+ MDOutput(&Algorithm[digest], p, "-");
+ } else if (string != NULL) {
len = strlen(string);
p = Algorithm[digest].Data(string, len, buf);
- MDOutput(&Algorithm[digest], p, &string);
+ MDOutput(&Algorithm[digest], p, string);
}
- if (gnu_emu) {
- if (malformed > 0)
+ if (cflag && mode != mode_bsd) {
+ if (!sflag && malformed > 1)
warnx("WARNING: %d lines are improperly formatted", malformed);
- if (checksFailed > 0)
+ else if (!sflag && malformed > 0)
+ warnx("WARNING: %d line is improperly formatted", malformed);
+ if (!sflag && checksFailed > 1)
warnx("WARNING: %d computed checksums did NOT match", checksFailed);
+ else if (!sflag && checksFailed > 0)
+ warnx("WARNING: %d computed checksum did NOT match", checksFailed);
+ if (checksFailed != 0 || (strict && malformed > 0))
+ return (1);
}
- if (failed != 0)
+#ifdef HAVE_CAPSICUM
+ fileargs_free(fa);
+#endif
+ if (failed)
return (1);
- if (checksFailed != 0)
+ if (checksFailed > 0)
return (2);
return (0);
}
/*
+ * Common input handling
+ */
+static char *
+MDInput(const Algorithm_t *alg, FILE *f, char *buf, bool tee)
+{
+ char block[4096];
+ DIGEST_CTX context;
+ char *end, *p, *q;
+ size_t len;
+ int bits;
+ uint8_t byte;
+ bool cr = false;
+
+ alg->Init(&context);
+ while ((len = fread(block, 1, sizeof(block), f)) > 0) {
+ switch (input_mode) {
+ case input_binary:
+ case input_text:
+ if (tee && fwrite(block, 1, len, stdout) != len)
+ err(1, "stdout");
+ alg->Update(&context, block, len);
+ break;
+ case input_universal:
+ end = block + len;
+ for (p = q = block; p < end; p = q) {
+ if (cr) {
+ if (*p == '\n')
+ p++;
+ if (tee && putchar('\n') == EOF)
+ err(1, "stdout");
+ alg->Update(&context, "\n", 1);
+ cr = false;
+ }
+ for (q = p; q < end && *q != '\r'; q++)
+ /* nothing */;
+ if (q > p) {
+ if (tee &&
+ fwrite(p, 1, q - p, stdout) !=
+ (size_t)(q - p))
+ err(1, "stdout");
+ alg->Update(&context, p, q - p);
+ }
+ if (q < end && *q == '\r') {
+ cr = true;
+ q++;
+ }
+ }
+ break;
+ case input_bits:
+ end = block + len;
+ bits = byte = 0;
+ for (p = block; p < end; p++) {
+ if (*p == '0' || *p == '1') {
+ byte <<= 1;
+ byte |= *p - '0';
+ if (++bits == 8) {
+ if (tee && putchar(byte) == EOF)
+ err(1, "stdout");
+ alg->Update(&context, &byte, 1);
+ bits = byte = 0;
+ }
+ }
+ }
+ break;
+ }
+ }
+ if (ferror(f)) {
+ alg->End(&context, buf);
+ return (NULL);
+ }
+ if (cr) {
+ if (tee && putchar('\n') == EOF)
+ err(1, "stdout");
+ alg->Update(&context, "\n", 1);
+ }
+ if (input_mode == input_bits && bits != 0)
+ errx(1, "input length was not a multiple of 8");
+ return (alg->End(&context, buf));
+}
+
+/*
* Common output handling
*/
static void
-MDOutput(const Algorithm_t *alg, char *p, char *argv[])
+MDOutput(const Algorithm_t *alg, char *p, const char *name)
{
bool checkfailed = false;
if (p == NULL) {
- warn("%s", *argv);
- failed++;
+ warn("%s", name);
+ failed = true;
+ } else if (cflag && mode != mode_bsd) {
+ checkfailed = strcasecmp(checkAgainst, p) != 0;
+ if (!sflag && (!qflag || checkfailed))
+ printf("%s: %s%c", name, checkfailed ? "FAILED" : "OK",
+ endl);
} else {
- /*
- * If argv is NULL we are reading from stdin, where the output
- * format has always been just the hash.
- */
- if (cflag && gnu_emu) {
- checkfailed = strcasecmp(checkAgainst, p) != 0;
- if (!qflag || checkfailed)
- printf("%s: %s\n", *argv, checkfailed ? "FAILED" : "OK");
- } else if (qflag || argv == NULL) {
- printf("%s\n", p);
- } else {
- if (rflag)
- if (gnu_emu)
- if (bflag)
- printf("%s *%s", p, *argv);
- else
- printf("%s %s", p, *argv);
- else
- printf("%s %s", p, *argv);
- else
- printf("%s (%s) = %s", alg->name, *argv, p);
- if (checkAgainst) {
- checkfailed = strcasecmp(checkAgainst, p) != 0;
- if (!qflag && checkfailed)
- printf(" [ Failed ]");
+ switch (output_mode) {
+ case output_bare:
+ printf("%s", p);
+ break;
+ case output_gnu:
+ printf("%s %c%s", p, input_mode, name);
+ break;
+ case output_reverse:
+ printf("%s %s", p, name);
+ break;
+ case output_tagged:
+ if (mode == mode_perl &&
+ strncmp(alg->name, "SHA512t", 7) == 0) {
+ printf("%.6s/%s", alg->name, alg->name + 7);
+ } else {
+ printf("%s", alg->name);
}
- printf("\n");
+ printf(" (%s) = %s", name, p);
+ break;
}
+ if (checkAgainst) {
+ checkfailed = strcasecmp(checkAgainst, p) != 0;
+ if (!qflag && checkfailed)
+ printf(" [ Failed ]");
+ }
+ printf("%c", endl);
}
if (checkfailed)
checksFailed++;
@@ -583,6 +929,17 @@ const char *SHA512_TestOutput[MDTESTCOUNT] = {
"e8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3"
};
+const char *SHA512t224_TestOutput[MDTESTCOUNT] = {
+ "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4",
+ "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327",
+ "4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa",
+ "ad1a4db188fe57064f4f24609d2a83cd0afb9b398eb2fcaeaae2c564",
+ "ff83148aa07ec30655c1b40aff86141c0215fe2a54f767d3f38743d8",
+ "a8b4b9174b99ffc67d6f49be9981587b96441051e16e6dd036b140d3",
+ "ae988faaa47e401a45f704d1272d99702458fea2ddc6582827556dd2",
+ "b3c3b945249b0c8c94aba76ea887bcaad5401665a1fbeb384af4d06b"
+};
+
const char *SHA512t256_TestOutput[MDTESTCOUNT] = {
"c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",
"455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8",
@@ -652,40 +1009,36 @@ MDTestSuite(const Algorithm_t *alg)
printf(" - verified correct\n");
} else {
printf(" - INCORRECT RESULT!\n");
- failed++;
+ failed = true;
}
}
}
-/*
- * Digests the standard input and prints the result.
- */
-static char *
-MDFilter(const Algorithm_t *alg, char *buf, int tee)
+static void
+usage(const Algorithm_t *alg)
{
- DIGEST_CTX context;
- unsigned int len;
- unsigned char buffer[BUFSIZ];
- char *p;
- alg->Init(&context);
- while ((len = fread(buffer, 1, BUFSIZ, stdin))) {
- if (tee && len != fwrite(buffer, 1, len, stdout))
- err(1, "stdout");
- alg->Update(&context, buffer, len);
+ switch (mode) {
+ case mode_gnu:
+ fprintf(stderr, "usage: %ssum [-bctwz] [files ...]\n", alg->progname);
+ break;
+ case mode_perl:
+ fprintf(stderr, "usage: shasum [-0bchqstUvw] [-a alg] [files ...]\n");
+ break;
+ default:
+ fprintf(stderr, "usage: %s [-pqrtx] [-c string] [-s string] [files ...]\n",
+ alg->progname);
}
- p = alg->End(&context, buf);
-
- return (p);
+ exit(1);
}
static void
-usage(const Algorithm_t *alg)
+version(void)
{
-
- if (gnu_emu)
- fprintf(stderr, "usage: %ssum [-pqrtx] [-c file] [-s string] [files ...]\n", alg->progname);
- else
- fprintf(stderr, "usage: %s [-pqrtx] [-c string] [-s string] [files ...]\n", alg->progname);
- exit(1);
+ if (mode == mode_gnu)
+ printf("%s (FreeBSD) ", progname);
+ printf("%d.%d\n",
+ __FreeBSD_version / 100000,
+ (__FreeBSD_version / 1000) % 100);
+ exit(0);
}
diff --git a/sbin/md5/tests/1.inp b/sbin/md5/tests/1.inp
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/sbin/md5/tests/1.inp
+++ /dev/null
diff --git a/sbin/md5/tests/1.sha512-p.chk b/sbin/md5/tests/1.sha512-p.chk
deleted file mode 100644
index c2f1924ca315..000000000000
--- a/sbin/md5/tests/1.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
diff --git a/sbin/md5/tests/1.sha512sum-p.chk b/sbin/md5/tests/1.sha512sum-p.chk
deleted file mode 100644
index c2f1924ca315..000000000000
--- a/sbin/md5/tests/1.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
diff --git a/sbin/md5/tests/2.inp b/sbin/md5/tests/2.inp
deleted file mode 100644
index 2e65efe2a145..000000000000
--- a/sbin/md5/tests/2.inp
+++ /dev/null
@@ -1 +0,0 @@
-a \ No newline at end of file
diff --git a/sbin/md5/tests/2.sha512-p.chk b/sbin/md5/tests/2.sha512-p.chk
deleted file mode 100644
index be4d8addd112..000000000000
--- a/sbin/md5/tests/2.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-a1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
diff --git a/sbin/md5/tests/2.sha512sum-p.chk b/sbin/md5/tests/2.sha512sum-p.chk
deleted file mode 100644
index be4d8addd112..000000000000
--- a/sbin/md5/tests/2.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-a1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
diff --git a/sbin/md5/tests/3.inp b/sbin/md5/tests/3.inp
deleted file mode 100644
index f2ba8f84ab5c..000000000000
--- a/sbin/md5/tests/3.inp
+++ /dev/null
@@ -1 +0,0 @@
-abc \ No newline at end of file
diff --git a/sbin/md5/tests/3.sha512-p.chk b/sbin/md5/tests/3.sha512-p.chk
deleted file mode 100644
index 3971db2fddea..000000000000
--- a/sbin/md5/tests/3.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-abcddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
diff --git a/sbin/md5/tests/3.sha512sum-p.chk b/sbin/md5/tests/3.sha512sum-p.chk
deleted file mode 100644
index 3971db2fddea..000000000000
--- a/sbin/md5/tests/3.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-abcddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
diff --git a/sbin/md5/tests/4.inp b/sbin/md5/tests/4.inp
deleted file mode 100644
index e407fe0e6143..000000000000
--- a/sbin/md5/tests/4.inp
+++ /dev/null
@@ -1 +0,0 @@
-message digest \ No newline at end of file
diff --git a/sbin/md5/tests/4.sha512-p.chk b/sbin/md5/tests/4.sha512-p.chk
deleted file mode 100644
index cd5bad00b50d..000000000000
--- a/sbin/md5/tests/4.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-message digest107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c
diff --git a/sbin/md5/tests/4.sha512sum-p.chk b/sbin/md5/tests/4.sha512sum-p.chk
deleted file mode 100644
index cd5bad00b50d..000000000000
--- a/sbin/md5/tests/4.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-message digest107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c
diff --git a/sbin/md5/tests/5.inp b/sbin/md5/tests/5.inp
deleted file mode 100644
index e85d5b45283a..000000000000
--- a/sbin/md5/tests/5.inp
+++ /dev/null
@@ -1 +0,0 @@
-abcdefghijklmnopqrstuvwxyz \ No newline at end of file
diff --git a/sbin/md5/tests/5.sha512-p.chk b/sbin/md5/tests/5.sha512-p.chk
deleted file mode 100644
index 77f97a5a0117..000000000000
--- a/sbin/md5/tests/5.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-abcdefghijklmnopqrstuvwxyz4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1
diff --git a/sbin/md5/tests/5.sha512sum-p.chk b/sbin/md5/tests/5.sha512sum-p.chk
deleted file mode 100644
index 77f97a5a0117..000000000000
--- a/sbin/md5/tests/5.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-abcdefghijklmnopqrstuvwxyz4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1
diff --git a/sbin/md5/tests/6.inp b/sbin/md5/tests/6.inp
deleted file mode 100644
index 9f75c3756298..000000000000
--- a/sbin/md5/tests/6.inp
+++ /dev/null
@@ -1 +0,0 @@
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \ No newline at end of file
diff --git a/sbin/md5/tests/6.sha512-p.chk b/sbin/md5/tests/6.sha512-p.chk
deleted file mode 100644
index d14aad405215..000000000000
--- a/sbin/md5/tests/6.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567891e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894
diff --git a/sbin/md5/tests/6.sha512sum-p.chk b/sbin/md5/tests/6.sha512sum-p.chk
deleted file mode 100644
index d14aad405215..000000000000
--- a/sbin/md5/tests/6.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567891e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894
diff --git a/sbin/md5/tests/7.inp b/sbin/md5/tests/7.inp
deleted file mode 100644
index 15e0acf537d8..000000000000
--- a/sbin/md5/tests/7.inp
+++ /dev/null
@@ -1 +0,0 @@
-12345678901234567890123456789012345678901234567890123456789012345678901234567890 \ No newline at end of file
diff --git a/sbin/md5/tests/7.sha512-p.chk b/sbin/md5/tests/7.sha512-p.chk
deleted file mode 100644
index efd5828f95ff..000000000000
--- a/sbin/md5/tests/7.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-1234567890123456789012345678901234567890123456789012345678901234567890123456789072ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843
diff --git a/sbin/md5/tests/7.sha512sum-p.chk b/sbin/md5/tests/7.sha512sum-p.chk
deleted file mode 100644
index efd5828f95ff..000000000000
--- a/sbin/md5/tests/7.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-1234567890123456789012345678901234567890123456789012345678901234567890123456789072ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843
diff --git a/sbin/md5/tests/8.inp b/sbin/md5/tests/8.inp
deleted file mode 100644
index 689a689eceea..000000000000
--- a/sbin/md5/tests/8.inp
+++ /dev/null
@@ -1 +0,0 @@
-MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt \ No newline at end of file
diff --git a/sbin/md5/tests/8.sha512-p.chk b/sbin/md5/tests/8.sha512-p.chk
deleted file mode 100644
index d53bfc56d752..000000000000
--- a/sbin/md5/tests/8.sha512-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubte8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3
diff --git a/sbin/md5/tests/8.sha512sum-p.chk b/sbin/md5/tests/8.sha512sum-p.chk
deleted file mode 100644
index d53bfc56d752..000000000000
--- a/sbin/md5/tests/8.sha512sum-p.chk
+++ /dev/null
@@ -1 +0,0 @@
-MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubte8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3
diff --git a/sbin/md5/tests/Makefile b/sbin/md5/tests/Makefile
index 93f3913c687d..03c4da684eba 100644
--- a/sbin/md5/tests/Makefile
+++ b/sbin/md5/tests/Makefile
@@ -1,42 +1,7 @@
-# $FreeBSD$
-
.include <bsd.own.mk>
PACKAGE= tests
-TEST_DIR= ${SRCTOP}/sbin/md5/tests
-
-.PATH: ${TEST_DIR}
-
-FILESGROUPS+= FILESinputs
-FILESinputsPACKAGE= ${PACKAGE}
-FILESinputsDIR= ${TESTSDIR}
-FILESinputs!= echo ${TEST_DIR}/*.inp
-
-FILESGROUPS+= FILESchkfiles
-FILESchkfilesPACKAGE= ${PACKAGE}
-FILESchkfilesDIR= ${TESTSDIR}
-FILESchkfiles!= echo ${TEST_DIR}/*.chk
-
-FILESGROUPS+= FILESdigests
-FILESdigestsPACKAGE= ${PACKAGE}
-FILESdigestsDIR= ${TESTSDIR}
-FILESdigests!= echo ${TEST_DIR}/*.digest
-
-FILESGROUPS+= FILESparam
-FILESparamPACKAGE= ${PACKAGE}
-FILESparamDIR= ${TESTSDIR}
-FILESparam!= echo ${TEST_DIR}/*.txt
-
-PLAIN_TESTS_SH+= self-test
-PLAIN_TESTS_SH+= bsd-c-test
-PLAIN_TESTS_SH+= bsd-p-test
-PLAIN_TESTS_SH+= bsd-s-test
-PLAIN_TESTS_SH+= coreutils-c-test
-
-.SUFFIXES: .SH
-
-.SH.sh:
- sed 's|%%TESTSBASE%%|${TESTSBASE}|g' ${.ALLSRC} > ${.TARGET}
+ATF_TESTS_SH+= md5_test
.include <bsd.test.mk>
diff --git a/sbin/md5/tests/Makefile.depend b/sbin/md5/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/sbin/md5/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/md5/tests/algorithms.txt b/sbin/md5/tests/algorithms.txt
index 88f0ff5b783a..304d86bd4d4c 100644
--- a/sbin/md5/tests/algorithms.txt
+++ b/sbin/md5/tests/algorithms.txt
@@ -5,6 +5,7 @@ sha224
sha256
sha384
sha512
+sha512t224
sha512t256
skein1024
skein256
diff --git a/sbin/md5/tests/bsd-c-test.SH b/sbin/md5/tests/bsd-c-test.SH
deleted file mode 100644
index 0327b95f0c0e..000000000000
--- a/sbin/md5/tests/bsd-c-test.SH
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-exitcode=0
-
-testloop () {
- opt=$1
-
- while read algorithm; do
- n=0
- for f in %%TESTSBASE%%/sbin/md5/*.inp; do
- n=$((n + 1))
- expected=$(head -$n %%TESTSBASE%%/sbin/md5/$algorithm.digest | tail -1 | cut -w -f4)
- hash=$($algorithm $opt -c "$expected" $f) || exitcode=1
- done
- done < %%TESTSBASE%%/sbin/md5/algorithms.txt
-}
-
-testloop ""
-testloop -q
-testloop -r
-testloop -qr
-
-exit $exitcode
diff --git a/sbin/md5/tests/bsd-p-test.SH b/sbin/md5/tests/bsd-p-test.SH
deleted file mode 100644
index 77a725377e2c..000000000000
--- a/sbin/md5/tests/bsd-p-test.SH
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-exitcode=0
-
-testloop () {
- opt=$1
- sum=$2
-
- for algorithm in sha512; do
- for f in %%TESTSBASE%%/sbin/md5/*.inp; do
- outbase=$(basename $f .inp)
- $algorithm$sum $opt -p < $f > $outbase.out
- diff %%TESTSBASE%%/sbin/md5/$outbase.$algorithm$sum-p.chk $outbase.out || exitcode=1
- done
- done
-}
-
-testloop "" ""
-testloop -q ""
-testloop -qr ""
-testloop "" sum
-testloop -q sum
-
-exit $exitcode
diff --git a/sbin/md5/tests/bsd-s-test.SH b/sbin/md5/tests/bsd-s-test.SH
deleted file mode 100644
index 83267711137f..000000000000
--- a/sbin/md5/tests/bsd-s-test.SH
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-
-exitcode=0
-
-testloop () {
- opt=$1
- sum=$2
- field=$3
-
- while read algorithm; do
- n=0
- for f in %%TESTSBASE%%/sbin/md5/*.inp; do
- n=$((n + 1))
- read text < $f
- hash=$($algorithm$sum $opt -s "$text" | cut -d= -f$field)
- hash=$(echo $hash | cut -w -f1)
- expected=$(head -$n %%TESTSBASE%%/sbin/md5/$algorithm.digest | tail -1 | cut -w -f4)
- [ "$hash" = "$expected" ] || exitcode=1
- done
- done < %%TESTSBASE%%/sbin/md5/algorithms.txt
-}
-
-testloop "" "" 2
-testloop -q "" 1
-testloop -r "" 1
-testloop -qr "" 1
-testloop "" sum 1
-testloop -q sum 1
-
-exit $exitcode
diff --git a/sbin/md5/tests/coreutils-c-test.SH b/sbin/md5/tests/coreutils-c-test.SH
deleted file mode 100644
index 5996e533c627..000000000000
--- a/sbin/md5/tests/coreutils-c-test.SH
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-/bin/cp %%TESTSBASE%%/sbin/md5/*.inp . || exit 127
-
-exitcode=0
-
-testloop () {
- opt=$1
-
- while read algorithm; do
- ${algorithm}sum -c %%TESTSBASE%%/sbin/md5/${algorithm}.digest || exitcode=1
- ${algorithm}sum -c %%TESTSBASE%%/sbin/md5/${algorithm}sum.digest || exitcode=1
- done < %%TESTSBASE%%/sbin/md5/algorithms.txt
-}
-
-testloop ""
-testloop -q
-testloop -r
-testloop -qr
-
-exit $exitcode
diff --git a/sbin/md5/tests/md5.digest b/sbin/md5/tests/md5.digest
deleted file mode 100644
index 38b8dcb6e705..000000000000
--- a/sbin/md5/tests/md5.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-MD5 (1.inp) = d41d8cd98f00b204e9800998ecf8427e
-MD5 (2.inp) = 0cc175b9c0f1b6a831c399e269772661
-MD5 (3.inp) = 900150983cd24fb0d6963f7d28e17f72
-MD5 (4.inp) = f96b697d7cb7938d525a2f31aaf161d0
-MD5 (5.inp) = c3fcd3d76192e4007dfb496cca67e13b
-MD5 (6.inp) = d174ab98d277d9f5a5611c2c9f419d9f
-MD5 (7.inp) = 57edf4a22be3c955ac49da2e2107b67a
-MD5 (8.inp) = b50663f41d44d92171cb9976bc118538
diff --git a/sbin/md5/tests/md5_test.sh b/sbin/md5/tests/md5_test.sh
new file mode 100644
index 000000000000..34bdf43f13ea
--- /dev/null
+++ b/sbin/md5/tests/md5_test.sh
@@ -0,0 +1,409 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2022 Kyle Evans <kevans@FreeBSD.org>
+# Copyright (c) 2023 Klara, 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.
+#
+# 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.
+#
+
+n=8
+algorithms="md5 sha1 sha224 sha256 sha384 sha512 sha512t224 sha512t256 rmd160 skein256 skein512 skein1024"
+
+name_bsd_md5="MD5"
+name_bsd_sha1="SHA1"
+name_bsd_sha224="SHA224"
+name_bsd_sha256="SHA256"
+name_bsd_sha384="SHA384"
+name_bsd_sha512="SHA512"
+name_bsd_sha512t224="SHA512t224"
+name_bsd_sha512t256="SHA512t256"
+name_bsd_rmd160="RMD160"
+name_bsd_skein256="Skein256"
+name_bsd_skein512="Skein512"
+name_bsd_skein1024="Skein1024"
+
+name_perl_sha1="SHA1"
+name_perl_sha224="SHA224"
+name_perl_sha256="SHA256"
+name_perl_sha384="SHA384"
+name_perl_sha512="SHA512"
+name_perl_sha512t224="SHA512/224"
+name_perl_sha512t256="SHA512/256"
+
+alg_perl_sha1=""
+alg_perl_sha224="-a 224"
+alg_perl_sha256="-a 256"
+alg_perl_sha384="-a 384"
+alg_perl_sha512="-a 512"
+alg_perl_sha512t224="-a 512224"
+alg_perl_sha512t256="-a 512256"
+
+inp_1=""
+inp_2="a"
+inp_3="abc"
+inp_4="message digest"
+inp_5="abcdefghijklmnopqrstuvwxyz"
+inp_6="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+inp_7="12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+inp_8="MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt"
+
+out_1_md5="d41d8cd98f00b204e9800998ecf8427e"
+out_2_md5="0cc175b9c0f1b6a831c399e269772661"
+out_3_md5="900150983cd24fb0d6963f7d28e17f72"
+out_4_md5="f96b697d7cb7938d525a2f31aaf161d0"
+out_5_md5="c3fcd3d76192e4007dfb496cca67e13b"
+out_6_md5="d174ab98d277d9f5a5611c2c9f419d9f"
+out_7_md5="57edf4a22be3c955ac49da2e2107b67a"
+out_8_md5="b50663f41d44d92171cb9976bc118538"
+
+out_1_sha1="da39a3ee5e6b4b0d3255bfef95601890afd80709"
+out_2_sha1="86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"
+out_3_sha1="a9993e364706816aba3e25717850c26c9cd0d89d"
+out_4_sha1="c12252ceda8be8994d5fa0290a47231c1d16aae3"
+out_5_sha1="32d10c7b8cf96570ca04ce37f2a19d84240d3a89"
+out_6_sha1="761c457bf73b14d27e9e9265c46f4b4dda11f940"
+out_7_sha1="50abf5706a150990a08b2c5ea40fa0e585554732"
+out_8_sha1="18eca4333979c4181199b7b4fab8786d16cf2846"
+
+out_1_sha224="d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f"
+out_2_sha224="abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5"
+out_3_sha224="23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"
+out_4_sha224="2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb"
+out_5_sha224="45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2"
+out_6_sha224="bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9"
+out_7_sha224="b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e"
+out_8_sha224="5ae55f3779c8a1204210d7ed7689f661fbe140f96f272ab79e19d470"
+
+out_1_sha256="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
+out_2_sha256="ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"
+out_3_sha256="ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
+out_4_sha256="f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"
+out_5_sha256="71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73"
+out_6_sha256="db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0"
+out_7_sha256="f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e"
+out_8_sha256="e6eae09f10ad4122a0e2a4075761d185a272ebd9f5aa489e998ff2f09cbfdd9f"
+
+out_1_sha384="38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
+out_2_sha384="54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31"
+out_3_sha384="cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"
+out_4_sha384="473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5"
+out_5_sha384="feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4"
+out_6_sha384="1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84"
+out_7_sha384="b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026"
+out_8_sha384="99428d401bf4abcd4ee0695248c9858b7503853acfae21a9cffa7855f46d1395ef38596fcd06d5a8c32d41a839cc5dfb"
+
+out_1_sha512="cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
+out_2_sha512="1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"
+out_3_sha512="ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"
+out_4_sha512="107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c"
+out_5_sha512="4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1"
+out_6_sha512="1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894"
+out_7_sha512="72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843"
+out_8_sha512="e8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3"
+
+out_1_sha512t224="6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4"
+out_2_sha512t224="d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327"
+out_3_sha512t224="4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa"
+out_4_sha512t224="ad1a4db188fe57064f4f24609d2a83cd0afb9b398eb2fcaeaae2c564"
+out_5_sha512t224="ff83148aa07ec30655c1b40aff86141c0215fe2a54f767d3f38743d8"
+out_6_sha512t224="a8b4b9174b99ffc67d6f49be9981587b96441051e16e6dd036b140d3"
+out_7_sha512t224="ae988faaa47e401a45f704d1272d99702458fea2ddc6582827556dd2"
+out_8_sha512t224="b3c3b945249b0c8c94aba76ea887bcaad5401665a1fbeb384af4d06b"
+
+out_1_sha512t256="c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a"
+out_2_sha512t256="455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8"
+out_3_sha512t256="53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"
+out_4_sha512t256="0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb"
+out_5_sha512t256="fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26"
+out_6_sha512t256="cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8"
+out_7_sha512t256="2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148"
+out_8_sha512t256="dd095fc859b336c30a52548b3dc59fcc0d1be8616ebcf3368fad23107db2d736"
+
+out_1_rmd160="9c1185a5c5e9fc54612808977ee8f548b2258d31"
+out_2_rmd160="0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"
+out_3_rmd160="8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"
+out_4_rmd160="5d0689ef49d2fae572b881b123a85ffa21595f36"
+out_5_rmd160="f71c27109c692c1b56bbdceb5b9d2865b3708dbc"
+out_6_rmd160="b0e20b6e3116640286ed3a87a5713079b21f5189"
+out_7_rmd160="9b752e45573d4b39f4dbd3323cab82bf63326bfb"
+out_8_rmd160="5feb69c6bf7c29d95715ad55f57d8ac5b2b7dd32"
+
+out_1_skein256="c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba"
+out_2_skein256="7fba44ff1a31d71a0c1f82e6e82fb5e9ac6c92a39c9185b9951fed82d82fe635"
+out_3_skein256="258bdec343b9fde1639221a5ae0144a96e552e5288753c5fec76c05fc2fc1870"
+out_4_skein256="4d2ce0062b5eb3a4db95bc1117dd8aa014f6cd50fdc8e64f31f7d41f9231e488"
+out_5_skein256="46d8440685461b00e3ddb891b2ecc6855287d2bd8834a95fb1c1708b00ea5e82"
+out_6_skein256="7c5eb606389556b33d34eb2536459528dc0af97adbcd0ce273aeb650f598d4b2"
+out_7_skein256="4def7a7e5464a140ae9c3a80279fbebce4bd00f9faad819ab7e001512f67a10d"
+out_8_skein256="d9c017dbe355f318d036469eb9b5fbe129fc2b5786a9dc6746a516eab6fe0126"
+
+out_1_skein512="bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a"
+out_2_skein512="b1cd8d33f61b3737adfd59bb13ad82f4a9548e92f22956a8976cca3fdb7fee4fe91698146c4197cec85d38b83c5d93bdba92c01fd9a53870d0c7f967bc62bdce"
+out_3_skein512="8f5dd9ec798152668e35129496b029a960c9a9b88662f7f9482f110b31f9f93893ecfb25c009baad9e46737197d5630379816a886aa05526d3a70df272d96e75"
+out_4_skein512="15b73c158ffb875fed4d72801ded0794c720b121c0c78edf45f900937e6933d9e21a3a984206933d504b5dbb2368000411477ee1b204c986068df77886542fcc"
+out_5_skein512="23793ad900ef12f9165c8080da6fdfd2c8354a2929b8aadf83aa82a3c6470342f57cf8c035ec0d97429b626c4d94f28632c8f5134fd367dca5cf293d2ec13f8c"
+out_6_skein512="0c6bed927e022f5ddcf81877d42e5f75798a9f8fd3ede3d83baac0a2f364b082e036c11af35fe478745459dd8f5c0b73efe3c56ba5bb2009208d5a29cc6e469c"
+out_7_skein512="2ca9fcffb3456f297d1b5f407014ecb856f0baac8eb540f534b1f187196f21e88f31103128c2f03fcc9857d7a58eb66f9525e2302d88833ee069295537a434ce"
+out_8_skein512="1131f2aaa0e97126c9314f9f968cc827259bbfabced2943bb8c9274448998fb3b78738b4580dd500c76105fd3c03e465e1414f2c29664286b1f79d3e51128125"
+
+out_1_skein1024="0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6"
+out_2_skein1024="6ab4c4ba9814a3d976ec8bffa7fcc638ceba0544a97b3c98411323ffd2dc936315d13dc93c13c4e88cda6f5bac6f2558b2d8694d3b6143e40d644ae43ca940685cb37f809d3d0550c56cba8036dee729a4f8fb960732e59e64d57f7f7710f8670963cdcdc95b41daab4855fcf8b6762a64b173ee61343a2c7689af1d293eba97"
+out_3_skein1024="35a599a0f91abcdb4cb73c19b8cb8d947742d82c309137a7caed29e8e0a2ca7a9ff9a90c34c1908cc7e7fd99bb15032fb86e76df21b72628399b5f7c3cc209d7bb31c99cd4e19465622a049afbb87c03b5ce3888d17e6e667279ec0aa9b3e2712624c01b5f5bbe1a564220bdcf6990af0c2539019f313fdd7406cca3892a1f1f"
+out_4_skein1024="ea891f5268acd0fac97467fc1aa89d1ce8681a9992a42540e53babee861483110c2d16f49e73bac27653ff173003e40cfb08516cd34262e6af95a5d8645c9c1abb3e813604d508b8511b30f9a5c1b352aa0791c7d2f27b2706dccea54bc7de6555b5202351751c3299f97c09cf89c40f67187e2521c0fad82b30edbb224f0458"
+out_5_skein1024="f23d95c2a25fbcd0e797cd058fec39d3c52d2b5afd7a9af1df934e63257d1d3dcf3246e7329c0f1104c1e51e3d22e300507b0c3b9f985bb1f645ef49835080536becf83788e17fed09c9982ba65c3cb7ffe6a5f745b911c506962adf226e435c42f6f6bc08d288f9c810e807e3216ef444f3db22744441deefa4900982a1371f"
+out_6_skein1024="cf3889e8a8d11bfd3938055d7d061437962bc5eac8ae83b1b71c94be201b8cf657fdbfc38674997a008c0c903f56a23feb3ae30e012377f1cfa080a9ca7fe8b96138662653fb3335c7d06595bf8baf65e215307532094cfdfa056bd8052ab792a3944a2adaa47b30335b8badb8fe9eb94fe329cdca04e58bbc530f0af709f469"
+out_7_skein1024="cf21a613620e6c119eca31fdfaad449a8e02f95ca256c21d2a105f8e4157048f9fe1e897893ea18b64e0e37cb07d5ac947f27ba544caf7cbc1ad094e675aed77a366270f7eb7f46543bccfa61c526fd628408058ed00ed566ac35a9761d002e629c4fb0d430b2f4ad016fcc49c44d2981c4002da0eecc42144160e2eaea4855a"
+out_8_skein1024="e6799b78db54085a2be7ff4c8007f147fa88d326abab30be0560b953396d8802feee9a15419b48a467574e9283be15685ca8a079ee52b27166b64dd70b124b1d4e4f6aca37224c3f2685e67e67baef9f94b905698adc794a09672aba977a61b20966912acdb08c21a2c37001785355dc884751a21f848ab36e590331ff938138"
+
+for alg in $algorithms ; do
+ eval "
+atf_test_case self_test_${alg}
+self_test_${alg}_head() {
+ atf_set descr \"self-test for \$name_bsd_${alg}\"
+ atf_set require.progs \"${alg}\"
+}
+self_test_${alg}_body() {
+ atf_check -o ignore ${alg} --self-test
+}
+"
+ for i in $(seq $n) ; do
+ eval "
+atf_test_case bsd_${alg}_vec${i}
+bsd_${alg}_vec${i}_head() {
+ atf_set descr \"BSD mode \$name_bsd_${alg} test vector ${i}\"
+ atf_set require.progs \"${alg}\"
+}
+bsd_${alg}_vec${i}_body() {
+ printf '%s' \"\$inp_${i}\" >in
+ atf_check -o inline:\"\$out_${i}_${alg}\n\" ${alg} <in
+ atf_check -o inline:\"\$name_bsd_${alg} (in) = \$out_${i}_${alg}\n\" ${alg} in
+ atf_check -o inline:\"\$name_bsd_${alg} (-) = \$out_${i}_${alg}\n\" ${alg} - <in
+ atf_check -o inline:\"\$out_${i}_${alg} in\n\" ${alg} -r in
+ atf_check -o inline:\"\$out_${i}_${alg} -\n\" ${alg} -r - <in
+ # -q overrides -r regardless of order
+ for opt in -q -qr -rq ; do
+ atf_check -o inline:\"\$out_${i}_${alg}\n\" ${alg} \${opt} in
+ done
+ atf_check -o inline:\"\$inp_${i}\$out_${i}_${alg}\n\" ${alg} -p <in
+ atf_check -o inline:\"\$out_${i}_${alg}\n\" ${alg} -s \"\$inp_${i}\"
+}
+"
+ eval "
+atf_test_case gnu_${alg}_vec${i}
+gnu_${alg}_vec${i}_head() {
+ atf_set descr \"GNU mode \$name_bsd_${alg} test vector ${i}\"
+ atf_set require.progs \"${alg}sum\"
+}
+gnu_${alg}_vec${i}_body() {
+ printf '%s' \"\$inp_${i}\" >in
+ atf_check -o inline:\"\$out_${i}_${alg} -\n\" ${alg}sum <in
+ atf_check -o inline:\"\$out_${i}_${alg} *-\n\" ${alg}sum -b <in
+ atf_check -o inline:\"\$out_${i}_${alg} in\n\" ${alg}sum in
+ atf_check -o inline:\"\$out_${i}_${alg} -\n\" ${alg}sum - <in
+ atf_check -o inline:\"\$out_${i}_${alg} *in\n\" ${alg}sum -b in
+ atf_check -o inline:\"\$out_${i}_${alg} *-\n\" ${alg}sum -b - <in
+ atf_check -o inline:\"\$name_bsd_${alg} (in) = \$out_${i}_${alg}\n\" ${alg}sum --tag in
+ atf_check -o inline:\"\$name_bsd_${alg} (-) = \$out_${i}_${alg}\n\" ${alg}sum --tag - <in
+ atf_check -o inline:\"\$out_${i}_${alg} in\0\" ${alg}sum -z in
+ atf_check -o inline:\"\$out_${i}_${alg} -\0\" ${alg}sum -z - <in
+}
+"
+ eval "
+atf_test_case perl_${alg}_vec${i}
+perl_${alg}_vec${i}_head() {
+ atf_set descr \"Perl mode \$name_bsd_${alg} test vector ${i}\"
+ atf_set require.progs \"shasum\"
+}
+perl_${alg}_vec${i}_body() {
+ [ -n \"\$name_perl_${alg}\" ] || atf_skip \"shasum does not support ${alg}\"
+ printf '%s' \"\$inp_${i}\" >in
+ atf_check -o inline:\"\$out_${i}_${alg} -\n\" shasum \$alg_perl_${alg} <in
+ atf_check -o inline:\"\$out_${i}_${alg} *-\n\" shasum \$alg_perl_${alg} -b <in
+ atf_check -o inline:\"\$out_${i}_${alg} U-\n\" shasum \$alg_perl_${alg} -U <in
+ atf_check -o inline:\"\$out_${i}_${alg} in\n\" shasum \$alg_perl_${alg} in
+ atf_check -o inline:\"\$out_${i}_${alg} -\n\" shasum \$alg_perl_${alg} - <in
+ atf_check -o inline:\"\$out_${i}_${alg} *in\n\" shasum \$alg_perl_${alg} -b in
+ atf_check -o inline:\"\$out_${i}_${alg} *-\n\" shasum \$alg_perl_${alg} -b - <in
+ atf_check -o inline:\"\$out_${i}_${alg} Uin\n\" shasum \$alg_perl_${alg} -U in
+ atf_check -o inline:\"\$out_${i}_${alg} U-\n\" shasum \$alg_perl_${alg} -U - <in
+ atf_check -o inline:\"\$name_perl_${alg} (in) = \$out_${i}_${alg}\n\" shasum \$alg_perl_${alg} --tag in
+ atf_check -o inline:\"\$name_perl_${alg} (-) = \$out_${i}_${alg}\n\" shasum \$alg_perl_${alg} --tag - <in
+}
+"
+ done
+ eval "
+atf_test_case gnu_check_${alg}
+gnu_check_${alg}_head() {
+ atf_set descr \"GNU mode check test for \$name_bsd_${alg}\"
+ atf_set require.progs \"${alg}sum\"
+}
+gnu_check_${alg}_body() {
+ :>digests
+ :>stdout
+ :>stderr
+ rv=0
+ printf '%s' \"\$inp_2\" >inp2
+ printf '%s inp%d\n' \"\$out_2_${alg}\" 2 >>digests
+ printf 'inp%d: OK\n' 2 >>stdout
+ atf_check -o file:stdout -e file:stderr -s exit:$rv ${alg}sum -c digests
+ printf '%s' \"\$inp_3\" >inp3
+ printf '%s inp%d\n' \"malformed\" 3 >>digests
+ printf '%ssum: WARNING: 1 line is improperly formatted\n' ${alg} >>stderr
+ rv=1
+ atf_check -o file:stdout -e file:stderr -s exit:$rv ${alg}sum -c digests
+ printf '%s' \"\$inp_4\" >inp4
+ printf '%s inp%d\n' \"\$out_4_${alg}\" 4 | tr abcdef fedcba >>digests
+ printf 'inp%d: FAILED\n' 4 >>stdout
+ printf '%ssum: WARNING: 1 computed checksum did NOT match\n' ${alg} >>stderr
+ atf_check -o file:stdout -e file:stderr -s exit:$rv ${alg}sum -c digests
+ grep -v OK stdout >quiet
+ atf_check -o file:quiet -e file:stderr -s exit:$rv ${alg}sum --check --quiet digests
+ atf_check -s exit:$rv ${alg}sum --check --status digests
+}
+"
+ eval "
+atf_test_case perl_check_${alg}
+perl_check_${alg}_head() {
+ atf_set descr \"Perl mode check test for \$name_bsd_${alg}\"
+ atf_set require.progs \"shasum\"
+}
+perl_check_${alg}_body() {
+ [ -n \"\$name_perl_${alg}\" ] || atf_skip \"shasum does not support ${alg}\"
+ :>digests
+ :>stdout
+ :>stderr
+ rv=0
+ printf '%s' \"\$inp_2\" >inp2
+ printf '%s inp%d\n' \"\$out_2_${alg}\" 2 >>digests
+ printf 'inp%d: OK\n' 2 >>stdout
+ atf_check -o file:stdout -e file:stderr -s exit:$rv shasum \$alg_perl_${alg} -c digests
+ printf '%s' \"\$inp_3\" >inp3
+ printf '%s inp%d\n' \"malformed\" 3 >>digests
+ printf 'shasum: WARNING: 1 line is improperly formatted\n' >>stderr
+ rv=1
+ atf_check -o file:stdout -e file:stderr -s exit:$rv shasum \$alg_perl_${alg} -c digests
+ printf '%s' \"\$inp_4\" >inp4
+ printf '%s inp%d\n' \"\$out_4_${alg}\" 4 | tr abcdef fedcba >>digests
+ printf 'inp%d: FAILED\n' 4 >>stdout
+ printf 'shasum: WARNING: 1 computed checksum did NOT match\n' >>stderr
+ atf_check -o file:stdout -e file:stderr -s exit:$rv shasum \$alg_perl_${alg} -c digests
+ grep -v OK stdout >quiet
+ atf_check -o file:quiet -e file:stderr -s exit:$rv shasum \$alg_perl_${alg} --check --quiet digests
+ atf_check -s exit:$rv shasum \$alg_perl_${alg} --check --status digests
+}
+"
+done
+
+atf_test_case gnu_bflag
+gnu_bflag_head()
+{
+ atf_set descr "Verify GNU binary mode"
+ atf_set require.progs "sha256sum"
+}
+gnu_bflag_body()
+{
+ echo foo >a
+ echo bar >b
+
+ (sha256 -q a | tr -d '\n'; echo " *a") > expected
+ (sha256 -q b | tr -d '\n'; echo " *b") >> expected
+
+ atf_check -o file:expected sha256sum -b a b
+ atf_check -o file:expected sha256sum --binary a b
+}
+
+atf_test_case gnu_cflag
+gnu_cflag_head()
+{
+ atf_set descr "Verify handling of missing files in GNU check mode"
+ atf_set require.progs "sha256sum"
+}
+gnu_cflag_body()
+{
+
+ # Verify that the *sum -c mode works even if some files are missing.
+ # PR 267722 identified that we would never advance past the first record
+ # to check against. As a result, things like checking the published
+ # checksums for the install media became a more manual process again if
+ # you didn't download all of the images.
+ for i in 2 3 4 ; do
+ eval "printf '%s inp%d\n' \"\$out_${i}_sha256\" ${i}"
+ done >digests
+ for combo in "2 3 4" "3 4" "2 4" "2 3" "2" "3" "4" ""; do
+ rm -f inp2 inp3 inp4
+ :> expected
+ cnt=0
+ for i in ${combo}; do
+ eval "printf '%s' \"\$inp_${i}\"" > inp${i}
+ printf "inp%d: OK\n" ${i} >> expected
+ cnt=$((cnt + 1))
+ done
+
+ err=0
+ [ "$cnt" -eq 3 ] || err=1
+ atf_check -o file:expected -e ignore -s exit:${err} \
+ sha256sum -c digests
+ atf_check -o file:expected -e ignore -s exit:0 \
+ sha256sum --ignore-missing -c digests
+ done
+
+}
+
+atf_test_case gnu_cflag_mode
+gnu_cflag_mode_head()
+{
+ atf_set descr "Verify handling of input modes in GNU check mode"
+ atf_set require.progs "sha1sum"
+}
+gnu_cflag_mode_body()
+{
+ printf "The Magic Words are 01010011 01001111\r\n" >input
+ # The first line is malformed per GNU coreutils but matches
+ # what we produce when mode == mode_bsd && output_mode ==
+ # output_reverse (i.e. `sha1 -r`) so we want to support it.
+ cat >digests <<EOF
+53d88300dfb2be42f0ef25e3d9de798e31bb7e69 input
+53d88300dfb2be42f0ef25e3d9de798e31bb7e69 *input
+53d88300dfb2be42f0ef25e3d9de798e31bb7e69 input
+2290cf6ba4ac5387e520088de760b71a523871b0 ^input
+c1065e0d2bbc1c67dcecee0187d61316fb9c5582 Uinput
+EOF
+ atf_check sha1sum --quiet --check digests
+}
+
+atf_init_test_cases()
+{
+ for alg in $algorithms ; do
+ atf_add_test_case self_test_${alg}
+ for i in $(seq $n) ; do
+ atf_add_test_case bsd_${alg}_vec${i}
+ atf_add_test_case gnu_${alg}_vec${i}
+ atf_add_test_case perl_${alg}_vec${i}
+ done
+ atf_add_test_case gnu_check_${alg}
+ atf_add_test_case perl_check_${alg}
+ done
+ atf_add_test_case gnu_bflag
+ atf_add_test_case gnu_cflag
+ atf_add_test_case gnu_cflag_mode
+}
diff --git a/sbin/md5/tests/md5sum.digest b/sbin/md5/tests/md5sum.digest
deleted file mode 100644
index c560afa0d7f0..000000000000
--- a/sbin/md5/tests/md5sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-d41d8cd98f00b204e9800998ecf8427e 1.inp
-0cc175b9c0f1b6a831c399e269772661 2.inp
-900150983cd24fb0d6963f7d28e17f72 3.inp
-f96b697d7cb7938d525a2f31aaf161d0 4.inp
-c3fcd3d76192e4007dfb496cca67e13b 5.inp
-d174ab98d277d9f5a5611c2c9f419d9f 6.inp
-57edf4a22be3c955ac49da2e2107b67a 7.inp
-b50663f41d44d92171cb9976bc118538 8.inp
diff --git a/sbin/md5/tests/rmd160.digest b/sbin/md5/tests/rmd160.digest
deleted file mode 100644
index b2ffd3c0ce45..000000000000
--- a/sbin/md5/tests/rmd160.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-RMD160 (1.inp) = 9c1185a5c5e9fc54612808977ee8f548b2258d31
-RMD160 (2.inp) = 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe
-RMD160 (3.inp) = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc
-RMD160 (4.inp) = 5d0689ef49d2fae572b881b123a85ffa21595f36
-RMD160 (5.inp) = f71c27109c692c1b56bbdceb5b9d2865b3708dbc
-RMD160 (6.inp) = b0e20b6e3116640286ed3a87a5713079b21f5189
-RMD160 (7.inp) = 9b752e45573d4b39f4dbd3323cab82bf63326bfb
-RMD160 (8.inp) = 5feb69c6bf7c29d95715ad55f57d8ac5b2b7dd32
diff --git a/sbin/md5/tests/rmd160sum.digest b/sbin/md5/tests/rmd160sum.digest
deleted file mode 100644
index 4864ff39e050..000000000000
--- a/sbin/md5/tests/rmd160sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-9c1185a5c5e9fc54612808977ee8f548b2258d31 1.inp
-0bdc9d2d256b3ee9daae347be6f4dc835a467ffe 2.inp
-8eb208f7e05d987a9b044a8e98c6b087f15a0bfc 3.inp
-5d0689ef49d2fae572b881b123a85ffa21595f36 4.inp
-f71c27109c692c1b56bbdceb5b9d2865b3708dbc 5.inp
-b0e20b6e3116640286ed3a87a5713079b21f5189 6.inp
-9b752e45573d4b39f4dbd3323cab82bf63326bfb 7.inp
-5feb69c6bf7c29d95715ad55f57d8ac5b2b7dd32 8.inp
diff --git a/sbin/md5/tests/self-test.SH b/sbin/md5/tests/self-test.SH
deleted file mode 100644
index 33bd5569c23c..000000000000
--- a/sbin/md5/tests/self-test.SH
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-while read algorithm; do
- $algorithm -x > self-test.$algorithm.out || exitcode=$?
- diff %%TESTSBASE%%/sbin/md5/self-test.$algorithm.chk self-test.$algorithm.out
-done < %%TESTSBASE%%/sbin/md5/algorithms.txt
-
-exit $exitcode
diff --git a/sbin/md5/tests/self-test.md5.chk b/sbin/md5/tests/self-test.md5.chk
deleted file mode 100644
index d4eb05560b53..000000000000
--- a/sbin/md5/tests/self-test.md5.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-MD5 test suite:
-MD5 ("") = d41d8cd98f00b204e9800998ecf8427e - verified correct
-MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 - verified correct
-MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 - verified correct
-MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 - verified correct
-MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b - verified correct
-MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f - verified correct
-MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a - verified correct
-MD5 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = b50663f41d44d92171cb9976bc118538 - verified correct
diff --git a/sbin/md5/tests/self-test.rmd160.chk b/sbin/md5/tests/self-test.rmd160.chk
deleted file mode 100644
index a0680ac7f647..000000000000
--- a/sbin/md5/tests/self-test.rmd160.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-RMD160 test suite:
-RMD160 ("") = 9c1185a5c5e9fc54612808977ee8f548b2258d31 - verified correct
-RMD160 ("a") = 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe - verified correct
-RMD160 ("abc") = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc - verified correct
-RMD160 ("message digest") = 5d0689ef49d2fae572b881b123a85ffa21595f36 - verified correct
-RMD160 ("abcdefghijklmnopqrstuvwxyz") = f71c27109c692c1b56bbdceb5b9d2865b3708dbc - verified correct
-RMD160 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = b0e20b6e3116640286ed3a87a5713079b21f5189 - verified correct
-RMD160 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 9b752e45573d4b39f4dbd3323cab82bf63326bfb - verified correct
-RMD160 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = 5feb69c6bf7c29d95715ad55f57d8ac5b2b7dd32 - verified correct
diff --git a/sbin/md5/tests/self-test.sh_inp b/sbin/md5/tests/self-test.sh_inp
deleted file mode 100644
index 33bd5569c23c..000000000000
--- a/sbin/md5/tests/self-test.sh_inp
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-while read algorithm; do
- $algorithm -x > self-test.$algorithm.out || exitcode=$?
- diff %%TESTSBASE%%/sbin/md5/self-test.$algorithm.chk self-test.$algorithm.out
-done < %%TESTSBASE%%/sbin/md5/algorithms.txt
-
-exit $exitcode
diff --git a/sbin/md5/tests/self-test.sha1.chk b/sbin/md5/tests/self-test.sha1.chk
deleted file mode 100644
index e463947feb36..000000000000
--- a/sbin/md5/tests/self-test.sha1.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-SHA1 test suite:
-SHA1 ("") = da39a3ee5e6b4b0d3255bfef95601890afd80709 - verified correct
-SHA1 ("a") = 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 - verified correct
-SHA1 ("abc") = a9993e364706816aba3e25717850c26c9cd0d89d - verified correct
-SHA1 ("message digest") = c12252ceda8be8994d5fa0290a47231c1d16aae3 - verified correct
-SHA1 ("abcdefghijklmnopqrstuvwxyz") = 32d10c7b8cf96570ca04ce37f2a19d84240d3a89 - verified correct
-SHA1 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 761c457bf73b14d27e9e9265c46f4b4dda11f940 - verified correct
-SHA1 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 50abf5706a150990a08b2c5ea40fa0e585554732 - verified correct
-SHA1 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = 18eca4333979c4181199b7b4fab8786d16cf2846 - verified correct
diff --git a/sbin/md5/tests/self-test.sha224.chk b/sbin/md5/tests/self-test.sha224.chk
deleted file mode 100644
index e74cccafa6d7..000000000000
--- a/sbin/md5/tests/self-test.sha224.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-SHA224 test suite:
-SHA224 ("") = d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f - verified correct
-SHA224 ("a") = abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5 - verified correct
-SHA224 ("abc") = 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 - verified correct
-SHA224 ("message digest") = 2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb - verified correct
-SHA224 ("abcdefghijklmnopqrstuvwxyz") = 45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2 - verified correct
-SHA224 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9 - verified correct
-SHA224 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e - verified correct
-SHA224 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = 5ae55f3779c8a1204210d7ed7689f661fbe140f96f272ab79e19d470 - verified correct
diff --git a/sbin/md5/tests/self-test.sha256.chk b/sbin/md5/tests/self-test.sha256.chk
deleted file mode 100644
index ba640b6a9217..000000000000
--- a/sbin/md5/tests/self-test.sha256.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-SHA256 test suite:
-SHA256 ("") = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 - verified correct
-SHA256 ("a") = ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb - verified correct
-SHA256 ("abc") = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad - verified correct
-SHA256 ("message digest") = f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650 - verified correct
-SHA256 ("abcdefghijklmnopqrstuvwxyz") = 71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 - verified correct
-SHA256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0 - verified correct
-SHA256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e - verified correct
-SHA256 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = e6eae09f10ad4122a0e2a4075761d185a272ebd9f5aa489e998ff2f09cbfdd9f - verified correct
diff --git a/sbin/md5/tests/self-test.sha384.chk b/sbin/md5/tests/self-test.sha384.chk
deleted file mode 100644
index a493cadc1964..000000000000
--- a/sbin/md5/tests/self-test.sha384.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-SHA384 test suite:
-SHA384 ("") = 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b - verified correct
-SHA384 ("a") = 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31 - verified correct
-SHA384 ("abc") = cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 - verified correct
-SHA384 ("message digest") = 473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5 - verified correct
-SHA384 ("abcdefghijklmnopqrstuvwxyz") = feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4 - verified correct
-SHA384 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84 - verified correct
-SHA384 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026 - verified correct
-SHA384 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = 99428d401bf4abcd4ee0695248c9858b7503853acfae21a9cffa7855f46d1395ef38596fcd06d5a8c32d41a839cc5dfb - verified correct
diff --git a/sbin/md5/tests/self-test.sha512.chk b/sbin/md5/tests/self-test.sha512.chk
deleted file mode 100644
index f36e455cdaa5..000000000000
--- a/sbin/md5/tests/self-test.sha512.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-SHA512 test suite:
-SHA512 ("") = cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e - verified correct
-SHA512 ("a") = 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75 - verified correct
-SHA512 ("abc") = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f - verified correct
-SHA512 ("message digest") = 107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c - verified correct
-SHA512 ("abcdefghijklmnopqrstuvwxyz") = 4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1 - verified correct
-SHA512 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894 - verified correct
-SHA512 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843 - verified correct
-SHA512 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = e8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3 - verified correct
diff --git a/sbin/md5/tests/self-test.sha512t256.chk b/sbin/md5/tests/self-test.sha512t256.chk
deleted file mode 100644
index 25612ace484a..000000000000
--- a/sbin/md5/tests/self-test.sha512t256.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-SHA512t256 test suite:
-SHA512t256 ("") = c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a - verified correct
-SHA512t256 ("a") = 455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8 - verified correct
-SHA512t256 ("abc") = 53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23 - verified correct
-SHA512t256 ("message digest") = 0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb - verified correct
-SHA512t256 ("abcdefghijklmnopqrstuvwxyz") = fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26 - verified correct
-SHA512t256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8 - verified correct
-SHA512t256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148 - verified correct
-SHA512t256 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = dd095fc859b336c30a52548b3dc59fcc0d1be8616ebcf3368fad23107db2d736 - verified correct
diff --git a/sbin/md5/tests/self-test.skein1024.chk b/sbin/md5/tests/self-test.skein1024.chk
deleted file mode 100644
index 8cfc5997afde..000000000000
--- a/sbin/md5/tests/self-test.skein1024.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-Skein1024 test suite:
-Skein1024 ("") = 0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6 - verified correct
-Skein1024 ("a") = 6ab4c4ba9814a3d976ec8bffa7fcc638ceba0544a97b3c98411323ffd2dc936315d13dc93c13c4e88cda6f5bac6f2558b2d8694d3b6143e40d644ae43ca940685cb37f809d3d0550c56cba8036dee729a4f8fb960732e59e64d57f7f7710f8670963cdcdc95b41daab4855fcf8b6762a64b173ee61343a2c7689af1d293eba97 - verified correct
-Skein1024 ("abc") = 35a599a0f91abcdb4cb73c19b8cb8d947742d82c309137a7caed29e8e0a2ca7a9ff9a90c34c1908cc7e7fd99bb15032fb86e76df21b72628399b5f7c3cc209d7bb31c99cd4e19465622a049afbb87c03b5ce3888d17e6e667279ec0aa9b3e2712624c01b5f5bbe1a564220bdcf6990af0c2539019f313fdd7406cca3892a1f1f - verified correct
-Skein1024 ("message digest") = ea891f5268acd0fac97467fc1aa89d1ce8681a9992a42540e53babee861483110c2d16f49e73bac27653ff173003e40cfb08516cd34262e6af95a5d8645c9c1abb3e813604d508b8511b30f9a5c1b352aa0791c7d2f27b2706dccea54bc7de6555b5202351751c3299f97c09cf89c40f67187e2521c0fad82b30edbb224f0458 - verified correct
-Skein1024 ("abcdefghijklmnopqrstuvwxyz") = f23d95c2a25fbcd0e797cd058fec39d3c52d2b5afd7a9af1df934e63257d1d3dcf3246e7329c0f1104c1e51e3d22e300507b0c3b9f985bb1f645ef49835080536becf83788e17fed09c9982ba65c3cb7ffe6a5f745b911c506962adf226e435c42f6f6bc08d288f9c810e807e3216ef444f3db22744441deefa4900982a1371f - verified correct
-Skein1024 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = cf3889e8a8d11bfd3938055d7d061437962bc5eac8ae83b1b71c94be201b8cf657fdbfc38674997a008c0c903f56a23feb3ae30e012377f1cfa080a9ca7fe8b96138662653fb3335c7d06595bf8baf65e215307532094cfdfa056bd8052ab792a3944a2adaa47b30335b8badb8fe9eb94fe329cdca04e58bbc530f0af709f469 - verified correct
-Skein1024 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = cf21a613620e6c119eca31fdfaad449a8e02f95ca256c21d2a105f8e4157048f9fe1e897893ea18b64e0e37cb07d5ac947f27ba544caf7cbc1ad094e675aed77a366270f7eb7f46543bccfa61c526fd628408058ed00ed566ac35a9761d002e629c4fb0d430b2f4ad016fcc49c44d2981c4002da0eecc42144160e2eaea4855a - verified correct
-Skein1024 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = e6799b78db54085a2be7ff4c8007f147fa88d326abab30be0560b953396d8802feee9a15419b48a467574e9283be15685ca8a079ee52b27166b64dd70b124b1d4e4f6aca37224c3f2685e67e67baef9f94b905698adc794a09672aba977a61b20966912acdb08c21a2c37001785355dc884751a21f848ab36e590331ff938138 - verified correct
diff --git a/sbin/md5/tests/self-test.skein256.chk b/sbin/md5/tests/self-test.skein256.chk
deleted file mode 100644
index 41d1fdcb8cc8..000000000000
--- a/sbin/md5/tests/self-test.skein256.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-Skein256 test suite:
-Skein256 ("") = c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba - verified correct
-Skein256 ("a") = 7fba44ff1a31d71a0c1f82e6e82fb5e9ac6c92a39c9185b9951fed82d82fe635 - verified correct
-Skein256 ("abc") = 258bdec343b9fde1639221a5ae0144a96e552e5288753c5fec76c05fc2fc1870 - verified correct
-Skein256 ("message digest") = 4d2ce0062b5eb3a4db95bc1117dd8aa014f6cd50fdc8e64f31f7d41f9231e488 - verified correct
-Skein256 ("abcdefghijklmnopqrstuvwxyz") = 46d8440685461b00e3ddb891b2ecc6855287d2bd8834a95fb1c1708b00ea5e82 - verified correct
-Skein256 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 7c5eb606389556b33d34eb2536459528dc0af97adbcd0ce273aeb650f598d4b2 - verified correct
-Skein256 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 4def7a7e5464a140ae9c3a80279fbebce4bd00f9faad819ab7e001512f67a10d - verified correct
-Skein256 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = d9c017dbe355f318d036469eb9b5fbe129fc2b5786a9dc6746a516eab6fe0126 - verified correct
diff --git a/sbin/md5/tests/self-test.skein512.chk b/sbin/md5/tests/self-test.skein512.chk
deleted file mode 100644
index 437220e17adb..000000000000
--- a/sbin/md5/tests/self-test.skein512.chk
+++ /dev/null
@@ -1,9 +0,0 @@
-Skein512 test suite:
-Skein512 ("") = bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a - verified correct
-Skein512 ("a") = b1cd8d33f61b3737adfd59bb13ad82f4a9548e92f22956a8976cca3fdb7fee4fe91698146c4197cec85d38b83c5d93bdba92c01fd9a53870d0c7f967bc62bdce - verified correct
-Skein512 ("abc") = 8f5dd9ec798152668e35129496b029a960c9a9b88662f7f9482f110b31f9f93893ecfb25c009baad9e46737197d5630379816a886aa05526d3a70df272d96e75 - verified correct
-Skein512 ("message digest") = 15b73c158ffb875fed4d72801ded0794c720b121c0c78edf45f900937e6933d9e21a3a984206933d504b5dbb2368000411477ee1b204c986068df77886542fcc - verified correct
-Skein512 ("abcdefghijklmnopqrstuvwxyz") = 23793ad900ef12f9165c8080da6fdfd2c8354a2929b8aadf83aa82a3c6470342f57cf8c035ec0d97429b626c4d94f28632c8f5134fd367dca5cf293d2ec13f8c - verified correct
-Skein512 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 0c6bed927e022f5ddcf81877d42e5f75798a9f8fd3ede3d83baac0a2f364b082e036c11af35fe478745459dd8f5c0b73efe3c56ba5bb2009208d5a29cc6e469c - verified correct
-Skein512 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 2ca9fcffb3456f297d1b5f407014ecb856f0baac8eb540f534b1f187196f21e88f31103128c2f03fcc9857d7a58eb66f9525e2302d88833ee069295537a434ce - verified correct
-Skein512 ("MD5 has not yet (2001-09-03) been broken, but sufficient attacks have been made that its security is in some doubt") = 1131f2aaa0e97126c9314f9f968cc827259bbfabced2943bb8c9274448998fb3b78738b4580dd500c76105fd3c03e465e1414f2c29664286b1f79d3e51128125 - verified correct
diff --git a/sbin/md5/tests/sha1.digest b/sbin/md5/tests/sha1.digest
deleted file mode 100644
index 10ce642c0883..000000000000
--- a/sbin/md5/tests/sha1.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-SHA1 (1.inp) = da39a3ee5e6b4b0d3255bfef95601890afd80709
-SHA1 (2.inp) = 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
-SHA1 (3.inp) = a9993e364706816aba3e25717850c26c9cd0d89d
-SHA1 (4.inp) = c12252ceda8be8994d5fa0290a47231c1d16aae3
-SHA1 (5.inp) = 32d10c7b8cf96570ca04ce37f2a19d84240d3a89
-SHA1 (6.inp) = 761c457bf73b14d27e9e9265c46f4b4dda11f940
-SHA1 (7.inp) = 50abf5706a150990a08b2c5ea40fa0e585554732
-SHA1 (8.inp) = 18eca4333979c4181199b7b4fab8786d16cf2846
diff --git a/sbin/md5/tests/sha1sum.digest b/sbin/md5/tests/sha1sum.digest
deleted file mode 100644
index d82d2889ff5d..000000000000
--- a/sbin/md5/tests/sha1sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-da39a3ee5e6b4b0d3255bfef95601890afd80709 1.inp
-86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 2.inp
-a9993e364706816aba3e25717850c26c9cd0d89d 3.inp
-c12252ceda8be8994d5fa0290a47231c1d16aae3 4.inp
-32d10c7b8cf96570ca04ce37f2a19d84240d3a89 5.inp
-761c457bf73b14d27e9e9265c46f4b4dda11f940 6.inp
-50abf5706a150990a08b2c5ea40fa0e585554732 7.inp
-18eca4333979c4181199b7b4fab8786d16cf2846 8.inp
diff --git a/sbin/md5/tests/sha224.digest b/sbin/md5/tests/sha224.digest
deleted file mode 100644
index a1007511a978..000000000000
--- a/sbin/md5/tests/sha224.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-SHA224 (1.inp) = d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f
-SHA224 (2.inp) = abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5
-SHA224 (3.inp) = 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7
-SHA224 (4.inp) = 2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb
-SHA224 (5.inp) = 45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2
-SHA224 (6.inp) = bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9
-SHA224 (7.inp) = b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e
-SHA224 (8.inp) = 5ae55f3779c8a1204210d7ed7689f661fbe140f96f272ab79e19d470
diff --git a/sbin/md5/tests/sha224sum.digest b/sbin/md5/tests/sha224sum.digest
deleted file mode 100644
index 37fd833032fb..000000000000
--- a/sbin/md5/tests/sha224sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f 1.inp
-abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5 2.inp
-23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 3.inp
-2cb21c83ae2f004de7e81c3c7019cbcb65b71ab656b22d6d0c39b8eb 4.inp
-45a5f72c39c5cff2522eb3429799e49e5f44b356ef926bcf390dccc2 5.inp
-bff72b4fcb7d75e5632900ac5f90d219e05e97a7bde72e740db393d9 6.inp
-b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e 7.inp
-5ae55f3779c8a1204210d7ed7689f661fbe140f96f272ab79e19d470 8.inp
diff --git a/sbin/md5/tests/sha256.digest b/sbin/md5/tests/sha256.digest
deleted file mode 100644
index b6c4411261a8..000000000000
--- a/sbin/md5/tests/sha256.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-SHA256 (1.inp) = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
-SHA256 (2.inp) = ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
-SHA256 (3.inp) = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
-SHA256 (4.inp) = f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650
-SHA256 (5.inp) = 71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73
-SHA256 (6.inp) = db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0
-SHA256 (7.inp) = f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e
-SHA256 (8.inp) = e6eae09f10ad4122a0e2a4075761d185a272ebd9f5aa489e998ff2f09cbfdd9f
diff --git a/sbin/md5/tests/sha256sum.digest b/sbin/md5/tests/sha256sum.digest
deleted file mode 100644
index 35ce99a0c6c1..000000000000
--- a/sbin/md5/tests/sha256sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 1.inp
-ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb 2.inp
-ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 3.inp
-f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650 4.inp
-71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 5.inp
-db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0 6.inp
-f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e 7.inp
-e6eae09f10ad4122a0e2a4075761d185a272ebd9f5aa489e998ff2f09cbfdd9f 8.inp
diff --git a/sbin/md5/tests/sha384.digest b/sbin/md5/tests/sha384.digest
deleted file mode 100644
index b56ef8b708e4..000000000000
--- a/sbin/md5/tests/sha384.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-SHA384 (1.inp) = 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b
-SHA384 (2.inp) = 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31
-SHA384 (3.inp) = cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7
-SHA384 (4.inp) = 473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5
-SHA384 (5.inp) = feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4
-SHA384 (6.inp) = 1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84
-SHA384 (7.inp) = b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026
-SHA384 (8.inp) = 99428d401bf4abcd4ee0695248c9858b7503853acfae21a9cffa7855f46d1395ef38596fcd06d5a8c32d41a839cc5dfb
diff --git a/sbin/md5/tests/sha384sum.digest b/sbin/md5/tests/sha384sum.digest
deleted file mode 100644
index 7d669e0dda08..000000000000
--- a/sbin/md5/tests/sha384sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b 1.inp
-54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31 2.inp
-cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 3.inp
-473ed35167ec1f5d8e550368a3db39be54639f828868e9454c239fc8b52e3c61dbd0d8b4de1390c256dcbb5d5fd99cd5 4.inp
-feb67349df3db6f5924815d6c3dc133f091809213731fe5c7b5f4999e463479ff2877f5f2936fa63bb43784b12f3ebb4 5.inp
-1761336e3f7cbfe51deb137f026f89e01a448e3b1fafa64039c1464ee8732f11a5341a6f41e0c202294736ed64db1a84 6.inp
-b12932b0627d1c060942f5447764155655bd4da0c9afa6dd9b9ef53129af1b8fb0195996d2de9ca0df9d821ffee67026 7.inp
-99428d401bf4abcd4ee0695248c9858b7503853acfae21a9cffa7855f46d1395ef38596fcd06d5a8c32d41a839cc5dfb 8.inp
diff --git a/sbin/md5/tests/sha512.digest b/sbin/md5/tests/sha512.digest
deleted file mode 100644
index dd82845b8131..000000000000
--- a/sbin/md5/tests/sha512.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-SHA512 (1.inp) = cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
-SHA512 (2.inp) = 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
-SHA512 (3.inp) = ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
-SHA512 (4.inp) = 107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c
-SHA512 (5.inp) = 4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1
-SHA512 (6.inp) = 1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894
-SHA512 (7.inp) = 72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843
-SHA512 (8.inp) = e8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3
diff --git a/sbin/md5/tests/sha512sum.digest b/sbin/md5/tests/sha512sum.digest
deleted file mode 100644
index 55bbd509e4df..000000000000
--- a/sbin/md5/tests/sha512sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e 1.inp
-1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75 2.inp
-ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f 3.inp
-107dbf389d9e9f71a3a95f6c055b9251bc5268c2be16d6c13492ea45b0199f3309e16455ab1e96118e8a905d5597b72038ddb372a89826046de66687bb420e7c 4.inp
-4dbff86cc2ca1bae1e16468a05cb9881c97f1753bce3619034898faa1aabe429955a1bf8ec483d7421fe3c1646613a59ed5441fb0f321389f77f48a879c7b1f1 5.inp
-1e07be23c26a86ea37ea810c8ec7809352515a970e9253c26f536cfc7a9996c45c8370583e0a78fa4a90041d71a4ceab7423f19c71b9d5a3e01249f0bebd5894 6.inp
-72ec1ef1124a45b047e8b7c75a932195135bb61de24ec0d1914042246e0aec3a2354e093d76f3048b456764346900cb130d2a4fd5dd16abb5e30bcb850dee843 7.inp
-e8a835195e039708b13d9131e025f4441dbdc521ce625f245a436dcd762f54bf5cb298d96235e6c6a304e087ec8189b9512cbdf6427737ea82793460c367b9c3 8.inp
diff --git a/sbin/md5/tests/sha512t256.digest b/sbin/md5/tests/sha512t256.digest
deleted file mode 100644
index 3e7df9eb98db..000000000000
--- a/sbin/md5/tests/sha512t256.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-SHA512t256 (1.inp) = c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a
-SHA512t256 (2.inp) = 455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8
-SHA512t256 (3.inp) = 53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23
-SHA512t256 (4.inp) = 0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb
-SHA512t256 (5.inp) = fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26
-SHA512t256 (6.inp) = cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8
-SHA512t256 (7.inp) = 2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148
-SHA512t256 (8.inp) = dd095fc859b336c30a52548b3dc59fcc0d1be8616ebcf3368fad23107db2d736
diff --git a/sbin/md5/tests/sha512t256sum.digest b/sbin/md5/tests/sha512t256sum.digest
deleted file mode 100644
index 425e31006d6e..000000000000
--- a/sbin/md5/tests/sha512t256sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a 1.inp
-455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8 2.inp
-53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23 3.inp
-0cf471fd17ed69d990daf3433c89b16d63dec1bb9cb42a6094604ee5d7b4e9fb 4.inp
-fc3189443f9c268f626aea08a756abe7b726b05f701cb08222312ccfd6710a26 5.inp
-cdf1cc0effe26ecc0c13758f7b4a48e000615df241284185c39eb05d355bb9c8 6.inp
-2c9fdbc0c90bdd87612ee8455474f9044850241dc105b1e8b94b8ddf5fac9148 7.inp
-dd095fc859b336c30a52548b3dc59fcc0d1be8616ebcf3368fad23107db2d736 8.inp
diff --git a/sbin/md5/tests/skein1024.digest b/sbin/md5/tests/skein1024.digest
deleted file mode 100644
index dea354221b26..000000000000
--- a/sbin/md5/tests/skein1024.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-Skein1024 (1.inp) = 0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6
-Skein1024 (2.inp) = 6ab4c4ba9814a3d976ec8bffa7fcc638ceba0544a97b3c98411323ffd2dc936315d13dc93c13c4e88cda6f5bac6f2558b2d8694d3b6143e40d644ae43ca940685cb37f809d3d0550c56cba8036dee729a4f8fb960732e59e64d57f7f7710f8670963cdcdc95b41daab4855fcf8b6762a64b173ee61343a2c7689af1d293eba97
-Skein1024 (3.inp) = 35a599a0f91abcdb4cb73c19b8cb8d947742d82c309137a7caed29e8e0a2ca7a9ff9a90c34c1908cc7e7fd99bb15032fb86e76df21b72628399b5f7c3cc209d7bb31c99cd4e19465622a049afbb87c03b5ce3888d17e6e667279ec0aa9b3e2712624c01b5f5bbe1a564220bdcf6990af0c2539019f313fdd7406cca3892a1f1f
-Skein1024 (4.inp) = ea891f5268acd0fac97467fc1aa89d1ce8681a9992a42540e53babee861483110c2d16f49e73bac27653ff173003e40cfb08516cd34262e6af95a5d8645c9c1abb3e813604d508b8511b30f9a5c1b352aa0791c7d2f27b2706dccea54bc7de6555b5202351751c3299f97c09cf89c40f67187e2521c0fad82b30edbb224f0458
-Skein1024 (5.inp) = f23d95c2a25fbcd0e797cd058fec39d3c52d2b5afd7a9af1df934e63257d1d3dcf3246e7329c0f1104c1e51e3d22e300507b0c3b9f985bb1f645ef49835080536becf83788e17fed09c9982ba65c3cb7ffe6a5f745b911c506962adf226e435c42f6f6bc08d288f9c810e807e3216ef444f3db22744441deefa4900982a1371f
-Skein1024 (6.inp) = cf3889e8a8d11bfd3938055d7d061437962bc5eac8ae83b1b71c94be201b8cf657fdbfc38674997a008c0c903f56a23feb3ae30e012377f1cfa080a9ca7fe8b96138662653fb3335c7d06595bf8baf65e215307532094cfdfa056bd8052ab792a3944a2adaa47b30335b8badb8fe9eb94fe329cdca04e58bbc530f0af709f469
-Skein1024 (7.inp) = cf21a613620e6c119eca31fdfaad449a8e02f95ca256c21d2a105f8e4157048f9fe1e897893ea18b64e0e37cb07d5ac947f27ba544caf7cbc1ad094e675aed77a366270f7eb7f46543bccfa61c526fd628408058ed00ed566ac35a9761d002e629c4fb0d430b2f4ad016fcc49c44d2981c4002da0eecc42144160e2eaea4855a
-Skein1024 (8.inp) = e6799b78db54085a2be7ff4c8007f147fa88d326abab30be0560b953396d8802feee9a15419b48a467574e9283be15685ca8a079ee52b27166b64dd70b124b1d4e4f6aca37224c3f2685e67e67baef9f94b905698adc794a09672aba977a61b20966912acdb08c21a2c37001785355dc884751a21f848ab36e590331ff938138
diff --git a/sbin/md5/tests/skein1024sum.digest b/sbin/md5/tests/skein1024sum.digest
deleted file mode 100644
index dca058ab55b7..000000000000
--- a/sbin/md5/tests/skein1024sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6 1.inp
-6ab4c4ba9814a3d976ec8bffa7fcc638ceba0544a97b3c98411323ffd2dc936315d13dc93c13c4e88cda6f5bac6f2558b2d8694d3b6143e40d644ae43ca940685cb37f809d3d0550c56cba8036dee729a4f8fb960732e59e64d57f7f7710f8670963cdcdc95b41daab4855fcf8b6762a64b173ee61343a2c7689af1d293eba97 2.inp
-35a599a0f91abcdb4cb73c19b8cb8d947742d82c309137a7caed29e8e0a2ca7a9ff9a90c34c1908cc7e7fd99bb15032fb86e76df21b72628399b5f7c3cc209d7bb31c99cd4e19465622a049afbb87c03b5ce3888d17e6e667279ec0aa9b3e2712624c01b5f5bbe1a564220bdcf6990af0c2539019f313fdd7406cca3892a1f1f 3.inp
-ea891f5268acd0fac97467fc1aa89d1ce8681a9992a42540e53babee861483110c2d16f49e73bac27653ff173003e40cfb08516cd34262e6af95a5d8645c9c1abb3e813604d508b8511b30f9a5c1b352aa0791c7d2f27b2706dccea54bc7de6555b5202351751c3299f97c09cf89c40f67187e2521c0fad82b30edbb224f0458 4.inp
-f23d95c2a25fbcd0e797cd058fec39d3c52d2b5afd7a9af1df934e63257d1d3dcf3246e7329c0f1104c1e51e3d22e300507b0c3b9f985bb1f645ef49835080536becf83788e17fed09c9982ba65c3cb7ffe6a5f745b911c506962adf226e435c42f6f6bc08d288f9c810e807e3216ef444f3db22744441deefa4900982a1371f 5.inp
-cf3889e8a8d11bfd3938055d7d061437962bc5eac8ae83b1b71c94be201b8cf657fdbfc38674997a008c0c903f56a23feb3ae30e012377f1cfa080a9ca7fe8b96138662653fb3335c7d06595bf8baf65e215307532094cfdfa056bd8052ab792a3944a2adaa47b30335b8badb8fe9eb94fe329cdca04e58bbc530f0af709f469 6.inp
-cf21a613620e6c119eca31fdfaad449a8e02f95ca256c21d2a105f8e4157048f9fe1e897893ea18b64e0e37cb07d5ac947f27ba544caf7cbc1ad094e675aed77a366270f7eb7f46543bccfa61c526fd628408058ed00ed566ac35a9761d002e629c4fb0d430b2f4ad016fcc49c44d2981c4002da0eecc42144160e2eaea4855a 7.inp
-e6799b78db54085a2be7ff4c8007f147fa88d326abab30be0560b953396d8802feee9a15419b48a467574e9283be15685ca8a079ee52b27166b64dd70b124b1d4e4f6aca37224c3f2685e67e67baef9f94b905698adc794a09672aba977a61b20966912acdb08c21a2c37001785355dc884751a21f848ab36e590331ff938138 8.inp
diff --git a/sbin/md5/tests/skein256.digest b/sbin/md5/tests/skein256.digest
deleted file mode 100644
index ee17f8df1532..000000000000
--- a/sbin/md5/tests/skein256.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-Skein256 (1.inp) = c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba
-Skein256 (2.inp) = 7fba44ff1a31d71a0c1f82e6e82fb5e9ac6c92a39c9185b9951fed82d82fe635
-Skein256 (3.inp) = 258bdec343b9fde1639221a5ae0144a96e552e5288753c5fec76c05fc2fc1870
-Skein256 (4.inp) = 4d2ce0062b5eb3a4db95bc1117dd8aa014f6cd50fdc8e64f31f7d41f9231e488
-Skein256 (5.inp) = 46d8440685461b00e3ddb891b2ecc6855287d2bd8834a95fb1c1708b00ea5e82
-Skein256 (6.inp) = 7c5eb606389556b33d34eb2536459528dc0af97adbcd0ce273aeb650f598d4b2
-Skein256 (7.inp) = 4def7a7e5464a140ae9c3a80279fbebce4bd00f9faad819ab7e001512f67a10d
-Skein256 (8.inp) = d9c017dbe355f318d036469eb9b5fbe129fc2b5786a9dc6746a516eab6fe0126
diff --git a/sbin/md5/tests/skein256sum.digest b/sbin/md5/tests/skein256sum.digest
deleted file mode 100644
index 2e1c8d1bc60d..000000000000
--- a/sbin/md5/tests/skein256sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba 1.inp
-7fba44ff1a31d71a0c1f82e6e82fb5e9ac6c92a39c9185b9951fed82d82fe635 2.inp
-258bdec343b9fde1639221a5ae0144a96e552e5288753c5fec76c05fc2fc1870 3.inp
-4d2ce0062b5eb3a4db95bc1117dd8aa014f6cd50fdc8e64f31f7d41f9231e488 4.inp
-46d8440685461b00e3ddb891b2ecc6855287d2bd8834a95fb1c1708b00ea5e82 5.inp
-7c5eb606389556b33d34eb2536459528dc0af97adbcd0ce273aeb650f598d4b2 6.inp
-4def7a7e5464a140ae9c3a80279fbebce4bd00f9faad819ab7e001512f67a10d 7.inp
-d9c017dbe355f318d036469eb9b5fbe129fc2b5786a9dc6746a516eab6fe0126 8.inp
diff --git a/sbin/md5/tests/skein512.digest b/sbin/md5/tests/skein512.digest
deleted file mode 100644
index 6b2e9ad0f723..000000000000
--- a/sbin/md5/tests/skein512.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-Skein512 (1.inp) = bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a
-Skein512 (2.inp) = b1cd8d33f61b3737adfd59bb13ad82f4a9548e92f22956a8976cca3fdb7fee4fe91698146c4197cec85d38b83c5d93bdba92c01fd9a53870d0c7f967bc62bdce
-Skein512 (3.inp) = 8f5dd9ec798152668e35129496b029a960c9a9b88662f7f9482f110b31f9f93893ecfb25c009baad9e46737197d5630379816a886aa05526d3a70df272d96e75
-Skein512 (4.inp) = 15b73c158ffb875fed4d72801ded0794c720b121c0c78edf45f900937e6933d9e21a3a984206933d504b5dbb2368000411477ee1b204c986068df77886542fcc
-Skein512 (5.inp) = 23793ad900ef12f9165c8080da6fdfd2c8354a2929b8aadf83aa82a3c6470342f57cf8c035ec0d97429b626c4d94f28632c8f5134fd367dca5cf293d2ec13f8c
-Skein512 (6.inp) = 0c6bed927e022f5ddcf81877d42e5f75798a9f8fd3ede3d83baac0a2f364b082e036c11af35fe478745459dd8f5c0b73efe3c56ba5bb2009208d5a29cc6e469c
-Skein512 (7.inp) = 2ca9fcffb3456f297d1b5f407014ecb856f0baac8eb540f534b1f187196f21e88f31103128c2f03fcc9857d7a58eb66f9525e2302d88833ee069295537a434ce
-Skein512 (8.inp) = 1131f2aaa0e97126c9314f9f968cc827259bbfabced2943bb8c9274448998fb3b78738b4580dd500c76105fd3c03e465e1414f2c29664286b1f79d3e51128125
diff --git a/sbin/md5/tests/skein512sum.digest b/sbin/md5/tests/skein512sum.digest
deleted file mode 100644
index 3ee9b67038ad..000000000000
--- a/sbin/md5/tests/skein512sum.digest
+++ /dev/null
@@ -1,8 +0,0 @@
-bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af41fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a 1.inp
-b1cd8d33f61b3737adfd59bb13ad82f4a9548e92f22956a8976cca3fdb7fee4fe91698146c4197cec85d38b83c5d93bdba92c01fd9a53870d0c7f967bc62bdce 2.inp
-8f5dd9ec798152668e35129496b029a960c9a9b88662f7f9482f110b31f9f93893ecfb25c009baad9e46737197d5630379816a886aa05526d3a70df272d96e75 3.inp
-15b73c158ffb875fed4d72801ded0794c720b121c0c78edf45f900937e6933d9e21a3a984206933d504b5dbb2368000411477ee1b204c986068df77886542fcc 4.inp
-23793ad900ef12f9165c8080da6fdfd2c8354a2929b8aadf83aa82a3c6470342f57cf8c035ec0d97429b626c4d94f28632c8f5134fd367dca5cf293d2ec13f8c 5.inp
-0c6bed927e022f5ddcf81877d42e5f75798a9f8fd3ede3d83baac0a2f364b082e036c11af35fe478745459dd8f5c0b73efe3c56ba5bb2009208d5a29cc6e469c 6.inp
-2ca9fcffb3456f297d1b5f407014ecb856f0baac8eb540f534b1f187196f21e88f31103128c2f03fcc9857d7a58eb66f9525e2302d88833ee069295537a434ce 7.inp
-1131f2aaa0e97126c9314f9f968cc827259bbfabced2943bb8c9274448998fb3b78738b4580dd500c76105fd3c03e465e1414f2c29664286b1f79d3e51128125 8.inp
diff --git a/sbin/mdconfig/Makefile b/sbin/mdconfig/Makefile
index 1cf610cb5939..bd835df0daec 100644
--- a/sbin/mdconfig/Makefile
+++ b/sbin/mdconfig/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=runtime
diff --git a/sbin/mdconfig/Makefile.depend b/sbin/mdconfig/Makefile.depend
index 7cae0ca03e1e..841351303dbc 100644
--- a/sbin/mdconfig/Makefile.depend
+++ b/sbin/mdconfig/Makefile.depend
@@ -1,18 +1,14 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
lib/libdevstat \
- lib/libexpat \
lib/libgeom \
lib/libkvm \
- lib/libsbuf \
lib/libutil \
diff --git a/sbin/mdconfig/mdconfig.8 b/sbin/mdconfig/mdconfig.8
index 775823fd0bc7..9a86a9c686fd 100644
--- a/sbin/mdconfig/mdconfig.8
+++ b/sbin/mdconfig/mdconfig.8
@@ -31,13 +31,9 @@
.\" 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.
-.\"
-.\" @(#)vnconfig.8 8.1 (Berkeley) 6/5/93
.\" from: src/usr.sbin/vnconfig/vnconfig.8,v 1.19 2000/12/27 15:30:29
.\"
-.\" $FreeBSD$
-.\"
-.Dd August 27, 2021
+.Dd June 1, 2024
.Dt MDCONFIG 8
.Os
.Sh NAME
@@ -234,8 +230,6 @@ option tends to waste memory by giving unwanted double caching,
but it saves time if there is memory to spare.
.It Oo Cm no Oc Ns Cm reserve
Allocate and reserve all needed storage from the start, rather than as needed.
-.It Oo Cm no Oc Ns Cm cluster
-Enable clustering on this disk.
.It Oo Cm no Oc Ns Cm compress
Enable/disable compression features to reduce memory usage.
.It Oo Cm no Oc Ns Cm force
@@ -337,7 +331,7 @@ mdconfig -rs 2g -u md3
.Ed
.Pp
Create a 1 gigabyte swap backed disk, initialize an
-.Xr ffs 7
+.Xr ffs 4
file system on it, and mount it on
.Pa /tmp :
.Bd -literal -offset indent
@@ -370,8 +364,8 @@ mount /dev/md1.nop /mnt
.Xr fpathconf 2 ,
.Xr fspacectl 2 ,
.Xr open 2 ,
+.Xr ffs 4 ,
.Xr md 4 ,
-.Xr ffs 7 ,
.Xr gpart 8 ,
.Xr mdmfs 8 ,
.Xr malloc 9 ,
diff --git a/sbin/mdconfig/mdconfig.c b/sbin/mdconfig/mdconfig.c
index 9f4f3fc3a392..4b03dd81e591 100644
--- a/sbin/mdconfig/mdconfig.c
+++ b/sbin/mdconfig/mdconfig.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2000-2004 Poul-Henning Kamp <phk@FreeBSD.org>
* Copyright (c) 2012 The FreeBSD Foundation
@@ -28,8 +28,6 @@
* 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>
@@ -58,15 +56,16 @@
static struct md_ioctl mdio;
static enum {UNSET, ATTACH, DETACH, RESIZE, LIST} action = UNSET;
-static int nflag;
+static int md_fd, nflag;
-static void usage(void);
+static void usage(void) __dead2;
static void md_set_file(const char *);
static int md_find(const char *, const char *);
static int md_query(const char *, const int, const char *);
static int md_list(const char *, int, const char *);
static char *geom_config_get(struct gconf *g, const char *name);
static void md_prthumanval(char *length);
+static void print_options(const char *s, const char *);
#define OPT_VERBOSE 0x01
#define OPT_UNIT 0x02
@@ -88,11 +87,11 @@ usage(void)
" mdconfig -l [-v] [-n] [-f file] [-u unit]\n"
" mdconfig file\n");
fprintf(stderr, "\t\ttype = {malloc, vnode, swap}\n");
- fprintf(stderr, "\t\toption = {cache, cluster, compress, force,\n");
- fprintf(stderr, "\t\t mustdealloc, readonly, reserve, ro,\n");
- fprintf(stderr, "\t\t verify}\n");
+ fprintf(stderr, "\t\toption = {async, cache, compress,\n");
+ fprintf(stderr, "\t\t force, mustdealloc, readonly, ro,\n");
+ fprintf(stderr, "\t\t reserve, verify}\n");
fprintf(stderr, "\t\tsize = %%d (512 byte blocks), %%db (B),\n");
- fprintf(stderr, "\t\t %%dk (kB), %%dm (MB), %%dg (GB), \n");
+ fprintf(stderr, "\t\t %%dk (kB), %%dm (MB), %%dg (GB),\n");
fprintf(stderr, "\t\t %%dt (TB), or %%dp (PB)\n");
exit(1);
}
@@ -100,7 +99,7 @@ usage(void)
int
main(int argc, char **argv)
{
- int ch, fd, i, vflag;
+ int ch, i, vflag;
char *p;
char *fflag = NULL, *sflag = NULL, *tflag = NULL, *uflag = NULL;
@@ -157,13 +156,13 @@ main(int argc, char **argv)
mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS;
} else if (!strcmp(optarg, "vnode")) {
mdio.md_type = MD_VNODE;
- mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
+ mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS;
} else if (!strcmp(optarg, "swap")) {
mdio.md_type = MD_SWAP;
- mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
+ mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS;
} else if (!strcmp(optarg, "null")) {
mdio.md_type = MD_NULL;
- mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS;
+ mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS;
} else
errx(1, "unknown type: %s", optarg);
break;
@@ -183,10 +182,15 @@ main(int argc, char **argv)
mdio.md_options |= MD_CACHE;
else if (!strcmp(optarg, "nocache"))
mdio.md_options &= ~MD_CACHE;
- else if (!strcmp(optarg, "cluster"))
- mdio.md_options |= MD_CLUSTER;
- else if (!strcmp(optarg, "nocluster"))
- mdio.md_options &= ~MD_CLUSTER;
+ /*
+ * For backwards-compatibility, continue to recognize
+ * "cluster"
+ */
+ else if (!strcmp(optarg, "cluster") ||
+ !strcmp(optarg, "nocluster"))
+ {
+ warnx("Option cluster is ignored");
+ }
else if (!strcmp(optarg, "compress"))
mdio.md_options |= MD_COMPRESS;
else if (!strcmp(optarg, "nocompress"))
@@ -283,13 +287,11 @@ main(int argc, char **argv)
if (fflag != NULL || argc > 0) {
/* Imply ``-t vnode'' */
mdio.md_type = MD_VNODE;
- mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT |
- MD_COMPRESS;
+ mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS;
} else if (sflag != NULL) {
/* Imply ``-t swap'' */
mdio.md_type = MD_SWAP;
- mdio.md_options |= MD_CLUSTER | MD_AUTOUNIT |
- MD_COMPRESS;
+ mdio.md_options |= MD_AUTOUNIT | MD_COMPRESS;
} else
errx(1, "unable to determine type");
}
@@ -368,12 +370,12 @@ main(int argc, char **argv)
if (!kld_isloaded("g_md") && kld_load("geom_md") == -1)
err(1, "failed to load geom_md module");
- fd = open(_PATH_DEV MDCTL_NAME, O_RDWR, 0);
- if (fd < 0)
+ md_fd = open(_PATH_DEV MDCTL_NAME, O_RDWR, 0);
+ if (md_fd < 0)
err(1, "open(%s%s)", _PATH_DEV, MDCTL_NAME);
if (action == ATTACH) {
- i = ioctl(fd, MDIOCATTACH, &mdio);
+ i = ioctl(md_fd, MDIOCATTACH, &mdio);
if (i < 0)
err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME);
if (mdio.md_options & MD_AUTOUNIT)
@@ -381,13 +383,13 @@ main(int argc, char **argv)
} else if (action == DETACH) {
if (mdio.md_options & MD_AUTOUNIT)
errx(1, "-d requires -u");
- i = ioctl(fd, MDIOCDETACH, &mdio);
+ i = ioctl(md_fd, MDIOCDETACH, &mdio);
if (i < 0)
err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME);
} else if (action == RESIZE) {
if (mdio.md_options & MD_AUTOUNIT)
errx(1, "-r requires -u");
- i = ioctl(fd, MDIOCRESIZE, &mdio);
+ i = ioctl(md_fd, MDIOCRESIZE, &mdio);
if (i < 0)
err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME);
} else if (action == LIST) {
@@ -401,11 +403,67 @@ main(int argc, char **argv)
return (md_query(uflag, vflag, fflag));
} else
usage();
- close(fd);
+ close(md_fd);
return (0);
}
static void
+print_options(const char *dev, const char *file)
+{
+ struct md_ioctl mdiox;
+ int unit;
+ const char *sep = "";
+
+ if (sscanf(dev, "md%d", &unit) != 1)
+ err(1, "invalid device: %s", dev);
+
+ memset(&mdiox, 0, sizeof(mdiox));
+ mdiox.md_version = MDIOVERSION;
+ mdiox.md_unit = unit;
+ mdiox.md_file = file[0] == '-' ? NULL : strdup(file);
+
+ if (ioctl(md_fd, MDIOCQUERY, &mdiox) < 0)
+ err(1, "ioctl(%s%s)", _PATH_DEV, MDCTL_NAME);
+
+ if (mdiox.md_file != NULL)
+ free(mdiox.md_file);
+
+ printf("\t");
+ if (mdiox.md_options & MD_ASYNC) {
+ printf("%sasync", sep);
+ sep = ",";
+ }
+ if (mdiox.md_options & MD_CACHE) {
+ printf("%scache", sep);
+ sep = ",";
+ }
+ if (mdiox.md_options & MD_COMPRESS) {
+ printf("%scompress", sep);
+ sep = ",";
+ }
+ if (mdiox.md_options & MD_FORCE) {
+ printf("%sforce", sep);
+ sep = ",";
+ }
+ if (mdiox.md_options & MD_READONLY) {
+ printf("%sreadonly", sep);
+ sep = ",";
+ }
+ if (mdiox.md_options & MD_RESERVE) {
+ printf("%sreserve", sep);
+ sep = ",";
+ }
+ if (mdiox.md_options & MD_VERIFY) {
+ printf("%sverify", sep);
+ sep = ",";
+ }
+ if (mdiox.md_options & MD_MUSTDEALLOC) {
+ printf("%smustdealloc", sep);
+ sep = ",";
+ }
+}
+
+static void
md_set_file(const char *fn)
{
struct stat sb;
@@ -502,11 +560,12 @@ md_list(const char *units, int opt, const char *fflag)
if (file == NULL)
file = "-";
printf("\t%s", file);
- file = NULL;
label = geom_config_get(gc, "label");
if (label == NULL)
- label = "";
+ label = "-";
printf("\t%s", label);
+ print_options(pp->lg_name, file);
+ file = label = NULL;
}
opt |= OPT_DONE;
if ((opt & OPT_LIST) && !(opt & OPT_VERBOSE))
diff --git a/sbin/mdconfig/tests/Makefile b/sbin/mdconfig/tests/Makefile
index 6c179fcf59ad..a3841f8f0dd0 100644
--- a/sbin/mdconfig/tests/Makefile
+++ b/sbin/mdconfig/tests/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
ATF_TESTS_SH= mdconfig_test
TEST_METADATA.mdconfig_test+= required_user="root"
diff --git a/sbin/mdconfig/tests/Makefile.depend b/sbin/mdconfig/tests/Makefile.depend
index f80275d86ab1..11aba52f82cf 100644
--- a/sbin/mdconfig/tests/Makefile.depend
+++ b/sbin/mdconfig/tests/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/mdconfig/tests/mdconfig_test.sh b/sbin/mdconfig/tests/mdconfig_test.sh
index c3a5f85e341b..cc29c188cbd8 100755
--- a/sbin/mdconfig/tests/mdconfig_test.sh
+++ b/sbin/mdconfig/tests/mdconfig_test.sh
@@ -21,7 +21,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
check_diskinfo()
@@ -275,24 +274,44 @@ attach_size_rounddown()
attach_size_rounddown_body()
{
local md
- local ss=8192
- local ms=$(($ss + 4096))
- local ms2=$((2 * $ss + 4096))
+ local pgsz=$(pagesize)
+ local ss=$(($pgsz * 2))
+ local ms=$(($ss + $pgsz))
+ local ms2=$((2 * $ss + $pgsz))
- # Use a sector size that's a likely multiple of PAGE_SIZE, as md(4)
+ # Use a sector size that's a multiple of the kernel page size, as md(4)
# expects that for swap MDs.
atf_check -s exit:0 -o save:mdconfig.out -e empty \
-x "mdconfig -a -t swap -S $ss -s ${ms}b"
md=$(cat mdconfig.out)
- # 12288 bytes should be rounded down to one sector.
- check_diskinfo "$md" 8192 1 $ss
+ # one sector plus one page should be rounded down to one sector.
+ check_diskinfo "$md" $ss 1 $ss
# Resize and verify that the new size was also rounded down.
atf_check -s exit:0 -o empty -e empty \
-x "mdconfig -r -u ${md#md} -s ${ms2}b"
- check_diskinfo "$md" 16384 2 $ss
+ check_diskinfo "$md" $((2 * $ss)) 2 $ss
}
-attach_size_rounddown()
+attach_size_rounddown_cleanup()
+{
+ cleanup_common
+}
+
+atf_test_case query_verbose cleanup
+query_verbose()
+{
+ atf_set "descr" "mdconfig -lv should print device details"
+}
+query_verbose_body()
+{
+ atf_check -s exit:0 -o save:mdconfig.out \
+ -x 'mdconfig -a -t swap -s 1m -o reserve -o force'
+ md=$(cat mdconfig.out)
+ atf_check -s exit:0 \
+ -o match:"$md[[:space:]]+swap[[:space:]]+1024K[[:space:]]+[-][[:space:]]+[-][[:space:]]+force,reserve" \
+ -x "mdconfig -lv -u $md"
+}
+query_verbose_cleanup()
{
cleanup_common
}
@@ -308,4 +327,5 @@ atf_init_test_cases()
atf_add_test_case attach_swap
atf_add_test_case attach_with_specific_unit_number
atf_add_test_case attach_size_rounddown
+ atf_add_test_case query_verbose
}
diff --git a/sbin/mdmfs/Makefile b/sbin/mdmfs/Makefile
index e8d2d7b46f3f..0665dfcc20a3 100644
--- a/sbin/mdmfs/Makefile
+++ b/sbin/mdmfs/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=runtime
PROG= mdmfs
LINKS= ${BINDIR}/${PROG} ${BINDIR}/mount_mfs
diff --git a/sbin/mdmfs/Makefile.depend b/sbin/mdmfs/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/mdmfs/Makefile.depend
+++ b/sbin/mdmfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mdmfs/mdmfs.8 b/sbin/mdmfs/mdmfs.8
index 05bc97f002c6..ff5b78068299 100644
--- a/sbin/mdmfs/mdmfs.8
+++ b/sbin/mdmfs/mdmfs.8
@@ -23,8 +23,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd October 31, 2019
.Dt MDMFS 8
.Os
@@ -34,7 +32,7 @@
.Nd configure and mount an in-memory file system using the
.Xr md 4
driver or the
-.Xr tmpfs 5
+.Xr tmpfs 4
filesystem
.Sh SYNOPSIS
.Nm
@@ -63,7 +61,7 @@ filesystem
The
.Nm
utility is designed to be a work-alike and look-alike of the deprecated
-.Xr mount_mfs 8 .
+.Nm mount_mfs .
The end result is essentially the same,
but is accomplished in a completely different way.
Based on
@@ -71,7 +69,7 @@ Based on
the
.Nm
utility either creates a
-.Xr tmpfs 5
+.Xr tmpfs 4
filesystem, or it configures an
.Xr md 4
disk using
@@ -93,7 +91,7 @@ When
is `auto',
.Nm
uses
-.Xr tmpfs 5
+.Xr tmpfs 4
if it is present in the kernel or can be loaded as a module,
otherwise it falls back to using
.Xr md 4
@@ -104,14 +102,14 @@ When
is `tmpfs',
.Nm
mounts a
-.Xr tmpfs 5
+.Xr tmpfs 4
filesystem, translating the
.Fl s
size option, if present, into a `-o size=' mount option.
Any
.Fl o
options on the command line are passed through to the
-.Xr tmpfs 5
+.Xr tmpfs 4
mount.
Options specific to
.Xr mdconfig 8
@@ -122,7 +120,7 @@ are ignored.
When
.Ar md-device
does not result in
-.Xr tmpfs 5
+.Xr tmpfs 4
being used, then an
.Xr md 4
device is configured instead.
@@ -151,7 +149,7 @@ it uses the default arguments to all the helper programs.
The following options are available.
Where possible,
the option letter matches the one used by
-.Xr mount_mfs 8
+.Nm mount_mfs
for the same thing.
.Bl -tag -width indent
.It Fl a Ar maxcontig
@@ -406,10 +404,10 @@ Mount a vnode-backed cd9660 file system using automatic device numbering:
The
.Nm
utility, while designed to be compatible with
-.Xr mount_mfs 8 ,
+.Nm mount_mfs ,
can be useful by itself.
Since
-.Xr mount_mfs 8
+.Nm mount_mfs
had some silly defaults, a
.Dq compatibility
mode is provided for the case where bug-to-bug compatibility is desired.
@@ -423,7 +421,7 @@ or
(as returned by
.Xr getprogname 3 ) .
In this mode, the following behavior, as done by
-.Xr mount_mfs 8 ,
+.Nm mount_mfs ,
is duplicated:
.Bl -bullet -offset indent
.It
@@ -437,8 +435,8 @@ was given on the command line.
.El
.Sh SEE ALSO
.Xr md 4 ,
+.Xr tmpfs 4 ,
.Xr fstab 5 ,
-.Xr tmpfs 5 ,
.Xr mdconfig 8 ,
.Xr mount 8 ,
.Xr newfs 8
diff --git a/sbin/mdmfs/mdmfs.c b/sbin/mdmfs/mdmfs.c
index 2e6bb458def3..69149b3fb465 100644
--- a/sbin/mdmfs/mdmfs.c
+++ b/sbin/mdmfs/mdmfs.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2001 Dima Dorfman.
* All rights reserved.
@@ -32,9 +32,6 @@
* the deprecated mount_mfs(8).
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/mdioctl.h>
@@ -107,7 +104,7 @@ main(int argc, char **argv)
bool detach, softdep, autounit, newfs;
const char *mtpoint, *size_arg, *skel, *unitstr;
char *p;
- int ch, idx;
+ int ch, idx, rv;
void *set;
unsigned long ul;
@@ -360,6 +357,13 @@ main(int argc, char **argv)
do_mdconfig_attach(mdconfig_arg, mdtype);
if (newfs)
do_newfs(newfs_arg);
+ if (!softdep) {
+ rv = run(NULL, "%s %s /dev/%s%d", _PATH_TUNEFS,
+ "-n disable", mdname, unit);
+ if (rv)
+ errx(1, "tunefs exited %s %d", run_exitstr(rv),
+ run_exitnumber(rv));
+ }
do_mount_md(mount_arg, mtpoint);
}
diff --git a/sbin/mknod/Makefile b/sbin/mknod/Makefile
index 610d2a4f399a..2182f31ca247 100644
--- a/sbin/mknod/Makefile
+++ b/sbin/mknod/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
PACKAGE=runtime
PROG= mknod
MAN= mknod.8
diff --git a/sbin/mknod/Makefile.depend b/sbin/mknod/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/mknod/Makefile.depend
+++ b/sbin/mknod/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mknod/mknod.8 b/sbin/mknod/mknod.8
index d2992416c4ee..fc562e76f0db 100644
--- a/sbin/mknod/mknod.8
+++ b/sbin/mknod/mknod.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)mknod.8 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD$
-.\"
.Dd October 3, 2016
.Dt MKNOD 8
.Os
@@ -110,7 +107,7 @@ will cause the number to be interpreted as octal.
The
.Nm
utility can be used to recreate deleted device nodes under a
-.Xr devfs 5
+.Xr devfs 4
mount point by invoking it with only a filename as an argument.
Example:
.Pp
@@ -132,7 +129,7 @@ devices.
As of
.Fx 5.0 ,
device nodes are managed by the device file system
-.Xr devfs 5 ,
+.Xr devfs 4 ,
making the
.Nm
utility superfluous.
@@ -143,7 +140,7 @@ nodes cannot be used to access devices.
.Sh SEE ALSO
.Xr mkfifo 1 ,
.Xr mknod 2 ,
-.Xr devfs 5 ,
+.Xr devfs 4 ,
.Xr chown 8
.Sh HISTORY
A
diff --git a/sbin/mknod/mknod.c b/sbin/mknod/mknod.c
index be7c97cf06fb..a9eb65e7a76c 100644
--- a/sbin/mknod/mknod.c
+++ b/sbin/mknod/mknod.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mknod.c 8.1 (Berkeley) 6/5/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/sbin/mksnap_ffs/Makefile b/sbin/mksnap_ffs/Makefile
index a79ae2f73417..cf5079fdfa8e 100644
--- a/sbin/mksnap_ffs/Makefile
+++ b/sbin/mksnap_ffs/Makefile
@@ -1,14 +1,11 @@
-# $FreeBSD$
-
.PATH: ${.CURDIR:H}/mount
-PACKAGE=runtime
+PACKAGE=ufs
PROG= mksnap_ffs
-SRCS= mksnap_ffs.c getmntopts.c
+LIBADD= util
MAN= mksnap_ffs.8
WARNS?= 2
-CFLAGS+=-I${.CURDIR:H}/mount
.if defined(NOSUID)
BINMODE=554
diff --git a/sbin/mksnap_ffs/Makefile.depend b/sbin/mksnap_ffs/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/mksnap_ffs/Makefile.depend
+++ b/sbin/mksnap_ffs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mksnap_ffs/mksnap_ffs.8 b/sbin/mksnap_ffs/mksnap_ffs.8
index 201014522721..f28c15f73ad5 100644
--- a/sbin/mksnap_ffs/mksnap_ffs.8
+++ b/sbin/mksnap_ffs/mksnap_ffs.8
@@ -32,9 +32,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd October 3, 2016
+.Dd May 22, 2023
.Dt MKSNAP_FFS 8
.Os
.Sh NAME
@@ -48,6 +46,19 @@ The
.Nm
utility creates a snapshot named
.Ar snapshot_name .
+This name is a path in the file system to be snapshotted.
+Typically this is under the
+.Pa .snap
+directory in the root of the file system, but it can
+be anywhere in the filesystem being snapshotted.
+Snapshots can be listed using the
+.Xr snapinfo 8
+command.
+.Pp
+After a snapshot is taken it appears as a file.
+The size of the snapshot file is equal to the size of the
+file system from which it was taken.
+It can be moved, renamed or deleted (which removes the snapshot).
.Pp
The group ownership of the file is set to
.Dq Li operator ;
@@ -59,18 +70,25 @@ or members of the
group.
.Sh EXAMPLES
Create a snapshot of
-.Pa /usr/home
+.Pa /home
file system and mount the snapshot elsewhere:
.Bd -literal -offset indent
-mksnap_ffs /usr/home/snapshot
-mdconfig -a -t vnode -o readonly -f /usr/home/snapshot
+mksnap_ffs /home/.snap/snap1
+mdconfig -a -t vnode -o readonly -f /home/.snap/snap1
mount -o ro /dev/md0 /mnt/
.Ed
+.Pp
+Delete a snapshot:
+.Bd -literal -offset indent
+rm /home/.snap/snap1
+.Ed
.Sh SEE ALSO
+.Xr rm 1 ,
.Xr chmod 2 ,
.Xr chown 8 ,
.Xr mdconfig 8 ,
-.Xr mount 8
+.Xr mount 8 ,
+.Xr snapinfo 8
.Sh HISTORY
The
.Nm
diff --git a/sbin/mksnap_ffs/mksnap_ffs.c b/sbin/mksnap_ffs/mksnap_ffs.c
index 0e3586fcb2e2..58939cc69029 100644
--- a/sbin/mksnap_ffs/mksnap_ffs.c
+++ b/sbin/mksnap_ffs/mksnap_ffs.c
@@ -33,8 +33,6 @@
* 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>
@@ -152,7 +150,7 @@ main(int argc, char **argv)
errx(1, "%s: Not a mount point", stfsbuf.f_mntonname);
}
if (cp != stfsbuf.f_mntonname)
- strlcpy(stfsbuf.f_mntonname, cp, sizeof(stfsbuf.f_mntonname));
+ memmove(stfsbuf.f_mntonname, cp, strlen(cp) + 1);
/*
* Having verified access to the directory in which the
diff --git a/sbin/mount/Makefile b/sbin/mount/Makefile
index 34ba498a2a3f..e2a3098813c4 100644
--- a/sbin/mount/Makefile
+++ b/sbin/mount/Makefile
@@ -1,11 +1,7 @@
-# @(#)Makefile 8.6 (Berkeley) 5/8/95
-# $FreeBSD$
-
PACKAGE=runtime
PROG= mount
-SRCS= mount.c mount_fs.c getmntopts.c vfslist.c
+SRCS= mount.c mount_fs.c vfslist.c
MAN= mount.8
-# We do NOT install the getmntopts.3 man page.
LIBADD= util xo
diff --git a/sbin/mount/Makefile.depend b/sbin/mount/Makefile.depend
index 991757ecadc0..b915f0b12d3b 100644
--- a/sbin/mount/Makefile.depend
+++ b/sbin/mount/Makefile.depend
@@ -1,14 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
lib/libutil \
+ lib/libxo/libxo \
.include <dirdeps.mk>
diff --git a/sbin/mount/extern.h b/sbin/mount/extern.h
index 29c6e49412c3..8e9756ace757 100644
--- a/sbin/mount/extern.h
+++ b/sbin/mount/extern.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1997 FreeBSD Inc.
* All rights reserved.
@@ -24,8 +24,6 @@
* 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$
*/
/* vfslist.c */
diff --git a/sbin/mount/getmntopts.3 b/sbin/mount/getmntopts.3
deleted file mode 100644
index b87956d051b7..000000000000
--- a/sbin/mount/getmntopts.3
+++ /dev/null
@@ -1,181 +0,0 @@
-.\" Copyright (c) 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.
-.\"
-.\" @(#)getmntopts.3 8.3 (Berkeley) 3/30/95
-.\" $FreeBSD$
-.\"
-.Dd February 17, 2008
-.Dt GETMNTOPTS 3
-.Os
-.Sh NAME
-.Nm getmntopts
-.Nd scan mount options
-.Sh SYNOPSIS
-.Fd #include \&"mntopts.h"
-.Ft void
-.Fo getmntopts
-.Fa "const char *options" "const struct mntopt *mopts"
-.Fa "int *flagp" "int *altflagp"
-.Fc
-.Sh DESCRIPTION
-The
-.Fn getmntopts
-function takes a comma separated option list and a list
-of valid option names, and computes the bitmask
-corresponding to the requested set of options.
-.Pp
-The string
-.Fa options
-is broken down into a sequence of comma separated tokens.
-Each token is looked up in the table described by
-.Fa mopts
-and the bits in
-the word referenced by either
-.Fa flagp
-or
-.Fa altflagp
-(depending on the
-.Va m_altloc
-field of the option's table entry)
-are updated.
-The flag words are not initialized by
-.Fn getmntopts .
-The table,
-.Fa mopts ,
-has the following format:
-.Bd -literal
-struct mntopt {
- char *m_option; /* option name */
- int m_inverse; /* is this a negative option, e.g., "dev" */
- int m_flag; /* bit to set, e.g., MNT_RDONLY */
- int m_altloc; /* non-zero to use altflagp rather than flagp */
-};
-.Ed
-.Pp
-The members of this structure are:
-.Bl -tag -width m_inverse
-.It Va m_option
-the option name,
-for example
-.Dq Li suid .
-.It Va m_inverse
-tells
-.Fn getmntopts
-that the name has the inverse meaning of the
-bit.
-For example,
-.Dq Li suid
-is the string, whereas the
-mount flag is
-.Dv MNT_NOSUID .
-In this case, the sense of the string and the flag
-are inverted, so the
-.Va m_inverse
-flag should be set.
-.It Va m_flag
-the value of the bit to be set or cleared in
-the flag word when the option is recognized.
-The bit is set when the option is discovered,
-but cleared if the option name was preceded
-by the letters
-.Dq Li no .
-The
-.Va m_inverse
-flag causes these two operations to be reversed.
-.It Va m_altloc
-the bit should be set or cleared in
-.Fa altflagp
-rather than
-.Fa flagp .
-.El
-.Pp
-Each of the user visible
-.Dv MNT_
-flags has a corresponding
-.Dv MOPT_
-macro which defines an appropriate
-.Vt "struct mntopt"
-entry.
-To simplify the program interface and ensure consistency across all
-programs, a general purpose macro,
-.Dv MOPT_STDOPTS ,
-is defined which
-contains an entry for all the generic VFS options.
-In addition, the macros
-.Dv MOPT_FORCE
-and
-.Dv MOPT_UPDATE
-exist to enable the
-.Dv MNT_FORCE
-and
-.Dv MNT_UPDATE
-flags to be set.
-Finally, the table must be terminated by an entry with a
-.Dv NULL
-first element.
-.Sh EXAMPLES
-Most commands will use the standard option set.
-Local file systems which support the
-.Dv MNT_UPDATE
-flag, would also have an
-.Dv MOPT_UPDATE
-entry.
-This can be declared and used as follows:
-.Bd -literal
-#include "mntopts.h"
-
-struct mntopt mopts[] = {
- MOPT_STDOPTS,
- MOPT_UPDATE,
- { NULL }
-};
-
- ...
- mntflags = mntaltflags = 0;
- ...
- getmntopts(options, mopts, &mntflags, &mntaltflags);
- ...
-.Ed
-.Sh DIAGNOSTICS
-If the external integer variable
-.Va getmnt_silent
-is zero, then the
-.Fn getmntopts
-function displays an error message and exits if an
-unrecognized option is encountered.
-Otherwise unrecognized options are silently ignored.
-By default
-.Va getmnt_silent
-is zero.
-.Sh SEE ALSO
-.Xr err 3 ,
-.Xr mount 8
-.Sh HISTORY
-The
-.Fn getmntopts
-function appeared in
-.Bx 4.4 .
diff --git a/sbin/mount/getmntopts.c b/sbin/mount/getmntopts.c
deleted file mode 100644
index fb739c6406ae..000000000000
--- a/sbin/mount/getmntopts.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Copyright (c) 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.
- */
-
-#if 0
-#ifndef lint
-static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "mntopts.h"
-
-int getmnt_silent = 0;
-
-void
-getmntopts(const char *options, const struct mntopt *m0, int *flagp,
- int *altflagp)
-{
- const struct mntopt *m;
- int negative, len;
- char *opt, *optbuf, *p;
- int *thisflagp;
-
- /* Copy option string, since it is about to be torn asunder... */
- if ((optbuf = strdup(options)) == NULL)
- err(1, NULL);
-
- for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
- /* Check for "no" prefix. */
- if (opt[0] == 'n' && opt[1] == 'o') {
- negative = 1;
- opt += 2;
- } else
- negative = 0;
-
- /*
- * for options with assignments in them (ie. quotas)
- * ignore the assignment as it's handled elsewhere
- */
- p = strchr(opt, '=');
- if (p != NULL)
- *++p = '\0';
-
- /* Scan option table. */
- for (m = m0; m->m_option != NULL; ++m) {
- len = strlen(m->m_option);
- if (strncasecmp(opt, m->m_option, len) == 0)
- if (opt[len] == '\0' || opt[len] == '=')
- break;
- }
-
- /* Save flag, or fail if option is not recognized. */
- if (m->m_option) {
- thisflagp = m->m_altloc ? altflagp : flagp;
- if (negative == m->m_inverse)
- *thisflagp |= m->m_flag;
- else
- *thisflagp &= ~m->m_flag;
- } else if (!getmnt_silent) {
- errx(1, "-o %s: option not supported", opt);
- }
- }
-
- free(optbuf);
-}
-
-void
-rmslashes(char *rrpin, char *rrpout)
-{
- char *rrpoutstart;
-
- *rrpout = *rrpin;
- for (rrpoutstart = rrpout; *rrpin != '\0'; *rrpout++ = *rrpin++) {
-
- /* skip all double slashes */
- while (*rrpin == '/' && *(rrpin + 1) == '/')
- rrpin++;
- }
-
- /* remove trailing slash if necessary */
- if (rrpout - rrpoutstart > 1 && *(rrpout - 1) == '/')
- *(rrpout - 1) = '\0';
- else
- *rrpout = '\0';
-}
-
-int
-checkpath(const char *path, char *resolved)
-{
- struct stat sb;
-
- if (realpath(path, resolved) == NULL || stat(resolved, &sb) != 0)
- return (1);
- if (!S_ISDIR(sb.st_mode)) {
- errno = ENOTDIR;
- return (1);
- }
- return (0);
-}
-
-void
-build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
- size_t len)
-{
- int i;
-
- if (*iovlen < 0)
- return;
- i = *iovlen;
- *iov = realloc(*iov, sizeof **iov * (i + 2));
- if (*iov == NULL) {
- *iovlen = -1;
- return;
- }
- (*iov)[i].iov_base = strdup(name);
- (*iov)[i].iov_len = strlen(name) + 1;
- i++;
- (*iov)[i].iov_base = val;
- if (len == (size_t)-1) {
- if (val != NULL)
- len = strlen(val) + 1;
- else
- len = 0;
- }
- (*iov)[i].iov_len = (int)len;
- *iovlen = ++i;
-}
-
-/*
- * This function is needed for compatibility with parameters
- * which used to use the mount_argf() command for the old mount() syscall.
- */
-void
-build_iovec_argf(struct iovec **iov, int *iovlen, const char *name,
- const char *fmt, ...)
-{
- va_list ap;
- char val[255] = { 0 };
-
- va_start(ap, fmt);
- vsnprintf(val, sizeof(val), fmt, ap);
- va_end(ap);
- build_iovec(iov, iovlen, name, strdup(val), (size_t)-1);
-}
-
-/*
- * Free the iovec and reset to NULL with zero length. Useful for calling
- * nmount in a loop.
- */
-void
-free_iovec(struct iovec **iov, int *iovlen)
-{
- int i;
-
- for (i = 0; i < *iovlen; i++)
- free((*iov)[i].iov_base);
- free(*iov);
-}
diff --git a/sbin/mount/mntopts.h b/sbin/mount/mntopts.h
deleted file mode 100644
index 183d6d9e501d..000000000000
--- a/sbin/mount/mntopts.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-3-Clause
- *
- * Copyright (c) 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.
- *
- * @(#)mntopts.h 8.7 (Berkeley) 3/29/95
- * $FreeBSD$
- */
-
-struct mntopt {
- const char *m_option; /* option name */
- int m_inverse; /* if a negative option, e.g. "atime" */
- long long m_flag; /* bit to set, e.g. MNT_RDONLY */
- int m_altloc; /* 1 => set bit in altflags */
-};
-
-/* User-visible MNT_ flags. */
-#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 }
-#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0 }
-#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 }
-#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 }
-#define MOPT_NOSYMFOLLOW { "symfollow", 1, MNT_NOSYMFOLLOW, 0 }
-#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 }
-#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 }
-#define MOPT_UNION { "union", 0, MNT_UNION, 0 }
-#define MOPT_USERQUOTA { "userquota", 0, 0, 0 }
-#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 }
-#define MOPT_NOCLUSTERR { "clusterr", 1, MNT_NOCLUSTERR, 0 }
-#define MOPT_NOCLUSTERW { "clusterw", 1, MNT_NOCLUSTERW, 0 }
-#define MOPT_SUIDDIR { "suiddir", 0, MNT_SUIDDIR, 0 }
-#define MOPT_SNAPSHOT { "snapshot", 0, MNT_SNAPSHOT, 0 }
-#define MOPT_MULTILABEL { "multilabel", 0, MNT_MULTILABEL, 0 }
-#define MOPT_ACLS { "acls", 0, MNT_ACLS, 0 }
-#define MOPT_NFS4ACLS { "nfsv4acls", 0, MNT_NFS4ACLS, 0 }
-#define MOPT_AUTOMOUNTED { "automounted",0, MNT_AUTOMOUNTED, 0 }
-#define MOPT_UNTRUSTED { "untrusted", 0, MNT_UNTRUSTED, 0 }
-
-/* Control flags. */
-#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 }
-#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 }
-#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 }
-#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 }
-#define MOPT_NOCOVER { "cover", 1, MNT_NOCOVER, 0 }
-#define MOPT_EMPTYDIR { "emptydir", 0, MNT_EMPTYDIR, 0 }
-/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */
-#define MOPT_AUTO { "auto", 0, 0, 0 }
-
-/* A handy macro as terminator of MNT_ array. */
-#define MOPT_END { NULL, 0, 0, 0 }
-
-#define MOPT_FSTAB_COMPAT \
- MOPT_RO, \
- MOPT_RW, \
- MOPT_AUTO
-
-/* Standard options which all mounts can understand. */
-#define MOPT_STDOPTS \
- MOPT_USERQUOTA, \
- MOPT_GROUPQUOTA, \
- MOPT_FSTAB_COMPAT, \
- MOPT_NOATIME, \
- MOPT_NOEXEC, \
- MOPT_SUIDDIR, /* must be before MOPT_NOSUID */ \
- MOPT_NOSUID, \
- MOPT_NOSYMFOLLOW, \
- MOPT_RDONLY, \
- MOPT_UNION, \
- MOPT_NOCLUSTERR, \
- MOPT_NOCLUSTERW, \
- MOPT_MULTILABEL, \
- MOPT_ACLS, \
- MOPT_NFS4ACLS, \
- MOPT_AUTOMOUNTED, \
- MOPT_UNTRUSTED, \
- MOPT_NOCOVER, \
- MOPT_EMPTYDIR
-
-void getmntopts(const char *, const struct mntopt *, int *, int *);
-void rmslashes(char *, char *);
-int checkpath(const char *, char resolved_path[]);
-extern int getmnt_silent;
-void build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val, size_t len);
-void build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, const char *fmt, ...);
-void free_iovec(struct iovec **iovec, int *iovlen);
diff --git a/sbin/mount/mount.8 b/sbin/mount/mount.8
index 2a877c04c079..7bfc21ea41d5 100644
--- a/sbin/mount/mount.8
+++ b/sbin/mount/mount.8
@@ -1,3 +1,6 @@
+.\"
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1980, 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -25,10 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)mount.8 8.8 (Berkeley) 6/16/94
-.\" $FreeBSD$
-.\"
-.Dd March 17, 2022
+.Dd July 16, 2025
.Dt MOUNT 8
.Os
.Sh NAME
@@ -40,7 +40,7 @@
.Op Fl adflpruvw
.Op Fl F Ar fstab
.Op Fl o Ar options
-.Op Fl t Oo Cm no Oc Ns Cm Ar type Ns Op Cm , Ns Ar type ...
+.Op Fl t Oo Cm no Oc Ns Ar type Ns Op , Ns Ar type ...
.Nm
.Op Fl -libxo
.Op Fl dfpruvw
@@ -49,7 +49,7 @@
.Op Fl -libxo
.Op Fl dfpruvw
.Op Fl o Ar options
-.Op Fl t Oo Cm no Oc Ns Cm Ar type Ns Op Cm , Ns Ar type ...
+.Op Fl t Oo Cm no Oc Ns Ar type Ns Op , Ns Ar type ...
.Ar special node
.Sh DESCRIPTION
The
@@ -80,7 +80,7 @@ Generate output via
.Xr libxo 3
in a selection of different human and machine readable formats.
See
-.Xr xo_parse_args 3
+.Xr xo_options 7
for details on command line arguments.
.It Fl a
All the file systems described in
@@ -158,6 +158,9 @@ For this reason, the
.Cm async
flag should be used sparingly, and only when some data recovery
mechanism is present.
+.It Cm atime
+Update the file access time when reading from a file.
+This is the default.
.It Cm automounted
This flag indicates that the file system was mounted by
.Xr automountd 8 .
@@ -264,17 +267,17 @@ mounted partition.
.It Cm nosuid
Do not allow set-user-identifier or set-group-identifier bits to take effect.
Note: this option is worthless if a public available suid or sgid
-wrapper like
-.Xr suidperl 1
-is installed on your system.
+wrapper is installed on your system.
It is set automatically when the user does not have super-user privileges.
.It Cm nosymfollow
Do not follow symlinks
on the mounted file system.
.It Cm ro
-The same as
-.Fl r ;
-mount the file system read-only (even the super-user may not write it).
+Mount the filesystem read-only, even the super-user may not write it.
+Equivalent to
+.Fl r .
+.It Cm rw
+Mount the filesystem read-write.
.It Cm snapshot
Take a snapshot of the specified filesystem.
When this option is used, all other options are ignored.
@@ -434,7 +437,7 @@ The same as the
argument to the
.Fl o
option.
-.It Fl t Oo Cm no Oc Ns Cm Ar type Ns Op Cm , Ns Ar type ...
+.It Fl t Oo Cm no Oc Ns Ar type Ns Op , Ns Ar type ...
The argument following the
.Fl t
is used to indicate the file system type.
@@ -549,6 +552,10 @@ for more information.)
.It Pa /etc/fstab
file system table
.El
+.Sh EXAMPLES
+Remount the root filesystem with read-write permissions:
+.Pp
+.Dl mount -uw /
.Sh DIAGNOSTICS
Various, most of them are self-explanatory.
.Pp
@@ -564,15 +571,18 @@ support for a particular file system might be provided either on a static
.Xr setfacl 1 ,
.Xr nmount 2 ,
.Xr acl 3 ,
+.Xr getmntinfo 3 ,
.Xr libxo 3 ,
-.Xr xo_parse_args 3 ,
+.Xr xo_options 7 ,
+.Xr cd9660 4 ,
+.Xr devfs 4 ,
+.Xr ext2fs 4 ,
+.Xr ffs 4 ,
.Xr mac 4 ,
-.Xr cd9660 5 ,
-.Xr devfs 5 ,
-.Xr ext2fs 5 ,
+.Xr procfs 4 ,
+.Xr tarfs 4 ,
+.Xr tmpfs 4 ,
.Xr fstab 5 ,
-.Xr procfs 5 ,
-.Xr tmpfs 5 ,
.Xr automount 8 ,
.Xr fstyp 8 ,
.Xr kldload 8 ,
@@ -583,6 +593,7 @@ support for a particular file system might be provided either on a static
.Xr mount_smbfs 8 ,
.Xr mount_udf 8 ,
.Xr mount_unionfs 8 ,
+.Xr quotacheck 8 ,
.Xr umount 8 ,
.Xr zfs 8 ,
.Xr zpool 8
@@ -615,3 +626,17 @@ only when the file system is mounted via
.Nm .
.Sh BUGS
It is possible for a corrupted file system to cause a crash.
+.Pp
+The
+.Fl p
+option will not list
+.Cm userquota
+or
+.Cm groupquota
+items from
+.Xr fstab 5
+because they are not true mount options and are not information returned by
+.Xr getmntinfo 3 .
+At boot
+.Xr quotacheck 8 ,
+processes these items.
diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c
index 6c986907bcda..496d71b57e4c 100644
--- a/sbin/mount/mount.c
+++ b/sbin/mount/mount.c
@@ -1,4 +1,4 @@
-/*-
+/*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1980, 1989, 1993, 1994
@@ -29,18 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1989, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#if 0
-static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95";
-#endif
-#endif /* not lint */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#define _WANT_MNTOPTNAMES
#include <sys/mount.h>
@@ -48,9 +36,10 @@ __FBSDID("$FreeBSD$");
#include <sys/wait.h>
#include <ctype.h>
-#include <err.h>
+
#include <errno.h>
#include <fstab.h>
+#include <mntopts.h>
#include <paths.h>
#include <pwd.h>
#include <signal.h>
@@ -63,12 +52,12 @@ __FBSDID("$FreeBSD$");
#include <libxo/xo.h>
#include "extern.h"
-#include "mntopts.h"
#include "pathnames.h"
#define EXIT(a) { \
xo_close_container("mount"); \
- xo_finish(); \
+ if (xo_finish() < 0) \
+ xo_err(EXIT_FAILURE, "stdout"); \
exit(a); \
}
@@ -85,10 +74,10 @@ struct cpa {
};
char *catopt(char *, const char *);
-struct statfs *getmntpt(const char *);
int hasopt(const char *, const char *);
int ismounted(struct fstab *, struct statfs *, int);
int isremountable(const char *);
+int allow_file_mount(const char *);
void mangle(char *, struct cpa *);
char *update_options(char *, char *, int);
int mountfs(const char *, const char *, const char *,
@@ -154,7 +143,7 @@ exec_mountprog(const char *name, const char *execname, char *const argv[])
switch (pid = fork()) {
case -1: /* Error. */
xo_warn("fork");
- EXIT(1);
+ EXIT(EXIT_FAILURE);
case 0: /* Child. */
/* Go find an executable. */
execvP(execname, _PATH_SYSPATH, argv);
@@ -164,7 +153,7 @@ exec_mountprog(const char *name, const char *execname, char *const argv[])
xo_warnx("in path: %s", _PATH_SYSPATH);
}
}
- EXIT(1);
+ EXIT(EXIT_FAILURE);
default: /* Parent. */
if (waitpid(pid, &status, 0) < 0) {
xo_warn("waitpid");
@@ -229,7 +218,7 @@ main(int argc, char *argv[])
argc = xo_parse_args(argc, argv);
if (argc < 0)
- exit(1);
+ exit(EXIT_FAILURE);
xo_open_container("mount");
while ((ch = getopt(argc, argv, "adF:fLlno:prt:uvw")) != -1)
@@ -301,7 +290,7 @@ main(int argc, char *argv[])
if ((init_flags & MNT_UPDATE) && (ro == 0))
options = catopt(options, "noro");
- rval = 0;
+ rval = EXIT_SUCCESS;
switch (argc) {
case 0:
if ((mntsize = getmntinfo(&mntbuf,
@@ -332,7 +321,7 @@ main(int argc, char *argv[])
if (mountfs(fs->fs_vfstype, fs->fs_spec,
fs->fs_file, init_flags, options,
fs->fs_mntops) && !failok)
- rval = 1;
+ rval = EXIT_FAILURE;
}
} else if (fstab_style) {
xo_open_list("fstab");
@@ -368,7 +357,7 @@ main(int argc, char *argv[])
if (init_flags & MNT_UPDATE) {
mntfromname = NULL;
have_fstab = 0;
- if ((mntbuf = getmntpt(*argv)) == NULL)
+ if ((mntbuf = getmntpoint(*argv)) == NULL)
xo_errx(1, "not currently mounted %s", *argv);
/*
* Only get the mntflags from fstab if both mntpoint
@@ -453,7 +442,7 @@ main(int argc, char *argv[])
* If the mount was successfully, and done by root, tell mountd the
* good news.
*/
- if (rval == 0 && getuid() == 0)
+ if (rval == EXIT_SUCCESS && getuid() == 0)
restart_mountd();
EXIT(rval);
@@ -503,6 +492,15 @@ isremountable(const char *vfsname)
}
int
+allow_file_mount(const char *vfsname)
+{
+
+ if (strcmp(vfsname, "nullfs") == 0)
+ return (1);
+ return (0);
+}
+
+int
hasopt(const char *mntopts, const char *option)
{
int negative, found;
@@ -548,9 +546,16 @@ mountfs(const char *vfstype, const char *spec, const char *name, int flags,
static struct cpa mnt_argv;
/* resolve the mountpoint with realpath(3) */
- if (checkpath(name, mntpath) != 0) {
- xo_warn("%s", mntpath);
- return (1);
+ if (allow_file_mount(vfstype)) {
+ if (checkpath_allow_file(name, mntpath) != 0) {
+ xo_warn("%s", mntpath);
+ return (1);
+ }
+ } else {
+ if (checkpath(name, mntpath) != 0) {
+ xo_warn("%s", mntpath);
+ return (1);
+ }
}
name = mntpath;
@@ -702,21 +707,6 @@ prmount(struct statfs *sfp)
xo_emit("{D:)}\n");
}
-struct statfs *
-getmntpt(const char *name)
-{
- struct statfs *mntbuf;
- int i, mntsize;
-
- mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
- for (i = mntsize - 1; i >= 0; i--) {
- if (strcmp(mntbuf[i].f_mntfromname, name) == 0 ||
- strcmp(mntbuf[i].f_mntonname, name) == 0)
- return (&mntbuf[i]);
- }
- return (NULL);
-}
-
char *
catopt(char *s0, const char *s1)
{
@@ -892,19 +882,21 @@ usage(void)
{
xo_error("%s\n%s\n%s\n",
-"usage: mount [-adflpruvw] [-F fstab] [-o options] [-t ufs | external_type]",
+"usage: mount [-adflpruvw] [-F fstab] [-o options] [-t [no]type[,type ...]]",
" mount [-dfpruvw] special | node",
-" mount [-dfpruvw] [-o options] [-t ufs | external_type] special node");
- EXIT(1);
+" mount [-dfpruvw] [-o options] [-t [no]type[,type ...]] special node");
+ EXIT(EXIT_FAILURE);
}
void
putfsent(struct statfs *ent)
{
struct fstab *fst;
+ const char *mntfromname;
char *opts, *rw;
int l;
+ mntfromname = ent->f_mntfromname;
opts = NULL;
/* flags2opts() doesn't return the "rw" option. */
if ((ent->f_flags & MNT_RDONLY) != 0)
@@ -915,16 +907,14 @@ putfsent(struct statfs *ent)
opts = flags2opts(ent->f_flags);
opts = catopt(rw, opts);
- if (strncmp(ent->f_mntfromname, "<below>", 7) == 0 ||
- strncmp(ent->f_mntfromname, "<above>", 7) == 0) {
- strlcpy(ent->f_mntfromname,
- (strnstr(ent->f_mntfromname, ":", 8) +1),
- sizeof(ent->f_mntfromname));
+ if (strncmp(mntfromname, "<below>:", 8) == 0 ||
+ strncmp(mntfromname, "<above>:", 8) == 0) {
+ mntfromname += 8;
}
- l = strlen(ent->f_mntfromname);
+ l = strlen(mntfromname);
xo_emit("{:device}{P:/%s}{P:/%s}{P:/%s}",
- ent->f_mntfromname,
+ mntfromname,
l < 8 ? "\t" : "",
l < 16 ? "\t" : "",
l < 24 ? "\t" : " ");
@@ -940,7 +930,7 @@ putfsent(struct statfs *ent)
l < 8 ? "\t" : " ");
free(opts);
- if ((fst = getfsspec(ent->f_mntfromname)))
+ if ((fst = getfsspec(mntfromname)))
xo_emit("{P:\t}{n:dump/%u}{P: }{n:pass/%u}\n",
fst->fs_freq, fst->fs_passno);
else if ((fst = getfsfile(ent->f_mntonname)))
diff --git a/sbin/mount/mount_fs.c b/sbin/mount/mount_fs.c
index 5674e94594bf..30c34ae32f31 100644
--- a/sbin/mount/mount_fs.c
+++ b/sbin/mount/mount_fs.c
@@ -32,33 +32,19 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mount_fs.c 8.6 (Berkeley) 4/26/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/mount.h>
#include <err.h>
#include <getopt.h>
#include <libgen.h>
+#include <mntopts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
-#include "mntopts.h"
static struct mntopt mopts[] = {
MOPT_STDOPTS,
diff --git a/sbin/mount/pathnames.h b/sbin/mount/pathnames.h
index 7dfb3f1a30e0..169d5384cc7b 100644
--- a/sbin/mount/pathnames.h
+++ b/sbin/mount/pathnames.h
@@ -27,9 +27,6 @@
* 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.
- *
- * @(#)pathnames.h 8.2 (Berkeley) 3/27/94
- * $FreeBSD$
*/
#define _PATH_MOUNTDPID "/var/run/mountd.pid"
diff --git a/sbin/mount/vfslist.c b/sbin/mount/vfslist.c
index e45aaec5fc09..ea6086651483 100644
--- a/sbin/mount/vfslist.c
+++ b/sbin/mount/vfslist.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)vfslist.c 8.1 (Berkeley) 5/8/95";
-#endif
-#endif /* not lint */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <err.h>
#include <stdlib.h>
#include <string.h>
diff --git a/sbin/mount_cd9660/Makefile b/sbin/mount_cd9660/Makefile
index 5660af8b39a4..9fa8e7436169 100644
--- a/sbin/mount_cd9660/Makefile
+++ b/sbin/mount_cd9660/Makefile
@@ -1,19 +1,10 @@
-# @(#)Makefile 8.3 (Berkeley) 3/27/94
-# $FreeBSD$
-
PACKAGE=runtime
PROG= mount_cd9660
-SRCS= mount_cd9660.c getmntopts.c
MAN= mount_cd9660.8
-LIBADD= kiconv
-
-MOUNT= ${.CURDIR:H}/mount
-CFLAGS+= -I${MOUNT}
+LIBADD= kiconv util
# Needs to be dynamically linked for optional dlopen() access to
# userland libiconv
NO_SHARED?= NO
-.PATH: ${MOUNT}
-
.include <bsd.prog.mk>
diff --git a/sbin/mount_cd9660/Makefile.depend b/sbin/mount_cd9660/Makefile.depend
index f2cf917f0e4c..912b8a359ac5 100644
--- a/sbin/mount_cd9660/Makefile.depend
+++ b/sbin/mount_cd9660/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
diff --git a/sbin/mount_cd9660/mount_cd9660.8 b/sbin/mount_cd9660/mount_cd9660.8
index fd0b74d7f2bb..2c6af7500277 100644
--- a/sbin/mount_cd9660/mount_cd9660.8
+++ b/sbin/mount_cd9660/mount_cd9660.8
@@ -29,10 +29,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)mount_cd9660.8 8.3 (Berkeley) 3/27/94
-.\" $FreeBSD$
-.\"
-.Dd August 11, 2018
+.Dd December 6, 2024
.Dt MOUNT_CD9660 8
.Os
.Sh NAME
@@ -42,8 +39,12 @@
.Nm
.Op Fl begjrv
.Op Fl C Ar charset
+.Op Fl G Ar gid
+.Op Fl m Ar mask
+.Op Fl M Ar mask
.Op Fl o Ar options
.Op Fl s Ar startsector
+.Op Fl U Ar uid
.Ar special node
.Sh DESCRIPTION
The
@@ -69,6 +70,38 @@ Do not strip version numbers on files.
only the last one will be listed.)
In either case, files may be opened without explicitly stating a
version number.
+.It Fl G Ar group
+Set the group of the files in the file system to
+.Ar group .
+The default gid on volumes without extended attributes or Rockridge extensions
+is zero.
+.It Fl U Ar user
+Set the owner of the files in the file system to
+.Ar user .
+The default uid on volumes without extended attributes or Rockridge extensions
+is zero.
+.It Fl m Ar mask
+Specify the maximum file permissions for files
+in the file system.
+For example, a
+.Ar mask
+of
+.Li 544
+limits the owner to
+read and execute permissions for files and
+others to only read permission.
+See
+.Xr chmod 1
+for more information about octal file modes.
+The default
+.Ar mask
+is 7777.
+The default permissions on volumes without extended attributes or Rockridge
+extensions is 555.
+.It Fl M Ar mask
+Specify the maximum file permissions for directories
+in the file system.
+See the previous option's description for details.
.It Fl j
Do not use any Joliet extensions included in the file system.
.It Fl o
@@ -138,7 +171,7 @@ The following command can be used to mount a Kodak Photo-CD:
.Xr cdcontrol 1 ,
.Xr mount 2 ,
.Xr unmount 2 ,
-.Xr cd9660 5 ,
+.Xr cd9660 4 ,
.Xr fstab 5 ,
.Xr mdconfig 8 ,
.Xr mount 8
diff --git a/sbin/mount_cd9660/mount_cd9660.c b/sbin/mount_cd9660/mount_cd9660.c
index f322ac73a439..3eddbefb9a03 100644
--- a/sbin/mount_cd9660/mount_cd9660.c
+++ b/sbin/mount_cd9660/mount_cd9660.c
@@ -32,24 +32,8 @@
* 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.
- *
- * @(#)mount_cd9660.c 8.7 (Berkeley) 5/1/95
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-/*
-static char sccsid[] = "@(#)mount_cd9660.c 8.7 (Berkeley) 5/1/95";
-*/
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/cdio.h>
#include <sys/file.h>
#include <sys/param.h>
@@ -60,22 +44,27 @@ static const char rcsid[] =
#include <arpa/inet.h>
+#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <grp.h>
+#include <mntopts.h>
+#include <pwd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
-#include "mntopts.h"
-
static struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
MOPT_END
};
+static gid_t a_gid(const char *);
+static uid_t a_uid(const char *);
+static mode_t a_mask(const char *);
static int get_ssector(const char *dev);
static int set_charset(struct iovec **, int *iovlen, const char *);
void usage(void);
@@ -96,7 +85,7 @@ main(int argc, char **argv)
mntflags = verbose = 0;
ssector = -1;
- while ((ch = getopt(argc, argv, "begjo:rs:vC:")) != -1)
+ while ((ch = getopt(argc, argv, "begG:jm:M:o:rs:U:vC:")) != -1)
switch (ch) {
case 'b':
build_iovec(&iov, &iovlen, "brokenjoliet", NULL, (size_t)-1);
@@ -107,6 +96,15 @@ main(int argc, char **argv)
case 'g':
build_iovec(&iov, &iovlen, "gens", NULL, (size_t)-1);
break;
+ case 'G':
+ build_iovec_argf(&iov, &iovlen, "gid", "%d", a_gid(optarg));
+ break;
+ case 'm':
+ build_iovec_argf(&iov, &iovlen, "mask", "%u", a_mask(optarg));
+ break;
+ case 'M':
+ build_iovec_argf(&iov, &iovlen, "dirmask", "%u", a_mask(optarg));
+ break;
case 'j':
build_iovec(&iov, &iovlen, "nojoliet", NULL, (size_t)-1);
break;
@@ -126,6 +124,9 @@ main(int argc, char **argv)
case 's':
ssector = atoi(optarg);
break;
+ case 'U':
+ build_iovec_argf(&iov, &iovlen, "uid", "%d", a_uid(optarg));
+ break;
case 'v':
verbose++;
break;
@@ -189,8 +190,8 @@ void
usage(void)
{
(void)fprintf(stderr,
-"usage: mount_cd9660 [-begjrv] [-C charset] [-o options] [-s startsector]\n"
-" special node\n");
+"usage: mount_cd9660 [-begjrv] [-C charset] [-G gid] [-m mask] [-M mask]\n"
+" [-o options] [-U uid] [-s startsector] special node\n");
exit(EX_USAGE);
}
@@ -270,3 +271,58 @@ set_charset(struct iovec **iov, int *iovlen, const char *localcs)
return (0);
}
+
+static gid_t
+a_gid(const char *s)
+{
+ struct group *gr;
+ const char *gname;
+ gid_t gid;
+
+ if ((gr = getgrnam(s)) != NULL)
+ gid = gr->gr_gid;
+ else {
+ for (gname = s; *s && isdigit(*s); ++s);
+ if (!*s)
+ gid = atoi(gname);
+ else
+ errx(EX_NOUSER, "unknown group id: %s", gname);
+ }
+ return (gid);
+}
+
+static uid_t
+a_uid(const char *s)
+{
+ struct passwd *pw;
+ const char *uname;
+ uid_t uid;
+
+ if ((pw = getpwnam(s)) != NULL)
+ uid = pw->pw_uid;
+ else {
+ for (uname = s; *s && isdigit(*s); ++s);
+ if (!*s)
+ uid = atoi(uname);
+ else
+ errx(EX_NOUSER, "unknown user id: %s", uname);
+ }
+ return (uid);
+}
+
+static mode_t
+a_mask(const char *s)
+{
+ int done, rv;
+ char *ep;
+
+ done = 0;
+ rv = -1;
+ if (*s >= '0' && *s <= '7') {
+ done = 1;
+ rv = strtol(optarg, &ep, 8);
+ }
+ if (!done || rv < 0 || *ep)
+ errx(EX_USAGE, "invalid file mode: %s", s);
+ return (rv);
+}
diff --git a/sbin/mount_fusefs/Makefile b/sbin/mount_fusefs/Makefile
index 4003e4fb35f6..a237ba99eb6b 100644
--- a/sbin/mount_fusefs/Makefile
+++ b/sbin/mount_fusefs/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.if defined(DEBUG)
DEBUG_FLAGS+= -D_DEBUG -g
.endif
@@ -22,12 +20,7 @@ DEBUG_FLAGS+= -DFUSE4BSD_VERSION="\"${F4BVERS}\""
PACKAGE=runtime
PROG= mount_fusefs
-SRCS= mount_fusefs.c getmntopts.c
-MAN8= mount_fusefs.8
-
-MOUNT= ${.CURDIR:H}/mount
-CFLAGS+= -I${MOUNT}
-
-.PATH: ${MOUNT}
+MAN= mount_fusefs.8
+LIBADD= util
.include <bsd.prog.mk>
diff --git a/sbin/mount_fusefs/Makefile.depend b/sbin/mount_fusefs/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/mount_fusefs/Makefile.depend
+++ b/sbin/mount_fusefs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mount_fusefs/mount_fusefs.8 b/sbin/mount_fusefs/mount_fusefs.8
index 9740d0ed59ff..44f7e029dec6 100644
--- a/sbin/mount_fusefs/mount_fusefs.8
+++ b/sbin/mount_fusefs/mount_fusefs.8
@@ -32,8 +32,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd October 9, 2021
.Dt MOUNT_FUSEFS 8
.Os
@@ -110,7 +108,7 @@ Prohibit the
.Cm allow_other
mount flag.
Intended for use in scripts and the
-.Xr sudoers 5
+.Xr sudoers 5 Pq Pa ports/security/sudo
file.
.It Fl S , Ic --safe
Run in safe mode (i.e., reject invoking a filesystem daemon).
@@ -253,7 +251,7 @@ beyond the
.Va vfs.usermount
sysctl).
The primary tool for such purposes is
-.Xr sudo 8 .
+.Xr sudo 8 Pq Pa ports/security/sudo .
However, given that
.Nm
is capable of invoking an arbitrary program, one must be careful when doing this.
@@ -275,7 +273,7 @@ ignores the environment variable
and always behaves as described.
.Pp
In general, to be as scripting /
-.Xr sudoers 5
+.Xr sudoers 5 Pq Pa ports/security/sudo
friendly as possible, no information has a fixed
position in the command line, but once a given piece of information is
provided, subsequent arguments/options cannot override it (with the
@@ -355,7 +353,7 @@ does not call any external utility and also provides a hacky
.Sh SEE ALSO
.Xr fstat 1 ,
.Xr mount 8 ,
-.Xr sudo 8 ,
+.Xr sudo 8 Pq Pa ports/security/sudo ,
.Xr umount 8
.Sh HISTORY
.Nm
diff --git a/sbin/mount_fusefs/mount_fusefs.c b/sbin/mount_fusefs/mount_fusefs.c
index 9cb5de66d2dd..2d65494421ef 100644
--- a/sbin/mount_fusefs/mount_fusefs.c
+++ b/sbin/mount_fusefs/mount_fusefs.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2005 Jean-Sebastien Pedron
* Copyright (c) 2005 Csaba Henk
@@ -33,9 +33,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/uio.h>
@@ -52,11 +49,10 @@ __FBSDID("$FreeBSD$");
#include <signal.h>
#include <getopt.h>
#include <limits.h>
+#include <mntopts.h>
#include <osreldate.h>
#include <paths.h>
-#include "mntopts.h"
-
#ifndef FUSE4BSD_VERSION
#define FUSE4BSD_VERSION "0.3.9-pre1"
#endif
diff --git a/sbin/mount_msdosfs/Makefile b/sbin/mount_msdosfs/Makefile
index e4c984484eda..50f07f175001 100644
--- a/sbin/mount_msdosfs/Makefile
+++ b/sbin/mount_msdosfs/Makefile
@@ -1,20 +1,10 @@
-#
-# $FreeBSD$
-#
-
PACKAGE=runtime
PROG= mount_msdosfs
-SRCS= mount_msdosfs.c getmntopts.c
MAN= mount_msdosfs.8
-LIBADD= kiconv
-
-MOUNT= ${.CURDIR:H}/mount
-CFLAGS+= -I${MOUNT}
+LIBADD= kiconv util
# Needs to be dynamically linked for optional dlopen() access to
# userland libiconv
NO_SHARED?= NO
-.PATH: ${MOUNT}
-
.include <bsd.prog.mk>
diff --git a/sbin/mount_msdosfs/Makefile.depend b/sbin/mount_msdosfs/Makefile.depend
index cdb18932a6c2..631a12a29245 100644
--- a/sbin/mount_msdosfs/Makefile.depend
+++ b/sbin/mount_msdosfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mount_msdosfs/mount_msdosfs.8 b/sbin/mount_msdosfs/mount_msdosfs.8
index ee9c6cfc225a..4ae3e6960122 100644
--- a/sbin/mount_msdosfs/mount_msdosfs.8
+++ b/sbin/mount_msdosfs/mount_msdosfs.8
@@ -28,14 +28,12 @@
.\" (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 May 28, 2017
.Dt MOUNT_MSDOSFS 8
.Os
.Sh NAME
.Nm mount_msdosfs
-.Nd mount an MS-DOS file system
+.Nd mount an MS-DOS (FAT) file system
.Sh SYNOPSIS
.Nm
.Op Fl 9ls
@@ -181,8 +179,8 @@ To mount a Japanese MS-DOS file system located in
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
+.Xr msdosfs 4 ,
.Xr fstab 5 ,
-.Xr msdosfs 5 ,
.Xr mount 8
.Pp
List of Localized MS Operating Systems:
diff --git a/sbin/mount_msdosfs/mount_msdosfs.c b/sbin/mount_msdosfs/mount_msdosfs.c
index 36be6a161ecf..36e1c524922d 100644
--- a/sbin/mount_msdosfs/mount_msdosfs.c
+++ b/sbin/mount_msdosfs/mount_msdosfs.c
@@ -32,11 +32,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
@@ -49,6 +44,7 @@ static const char rcsid[] =
#include <errno.h>
#include <grp.h>
#include <locale.h>
+#include <mntopts.h>
#include <pwd.h>
#include <stdio.h>
/* must be after stdio to declare fparseln */
@@ -58,8 +54,6 @@ static const char rcsid[] =
#include <sysexits.h>
#include <unistd.h>
-#include "mntopts.h"
-
static gid_t a_gid(char *);
static uid_t a_uid(char *);
static mode_t a_mask(char *);
diff --git a/sbin/mount_nfs/Makefile b/sbin/mount_nfs/Makefile
index a896edef898f..fb425106dd81 100644
--- a/sbin/mount_nfs/Makefile
+++ b/sbin/mount_nfs/Makefile
@@ -1,16 +1,12 @@
-# @(#)Makefile 8.2 (Berkeley) 3/27/94
-#
-# $FreeBSD$
-
-PACKAGE=runtime
+PACKAGE=nfs
PROG= mount_nfs
-SRCS= mount_nfs.c getmntopts.c mounttab.c
+SRCS= mount_nfs.c mounttab.c
MAN= mount_nfs.8
+LIBADD= util
-MOUNT= ${.CURDIR:H}/mount
UMNTALL= ${SRCTOP}/usr.sbin/rpc.umntall
-CFLAGS+= -DNFS -I${MOUNT} -I${UMNTALL}
+CFLAGS+= -DNFS -I${UMNTALL}
-.PATH: ${MOUNT} ${UMNTALL}
+.PATH: ${UMNTALL}
.include <bsd.prog.mk>
diff --git a/sbin/mount_nfs/Makefile.depend b/sbin/mount_nfs/Makefile.depend
index faed4b4cc2aa..732a025c9552 100644
--- a/sbin/mount_nfs/Makefile.depend
+++ b/sbin/mount_nfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/rpc \
diff --git a/sbin/mount_nfs/mount_nfs.8 b/sbin/mount_nfs/mount_nfs.8
index 88c9b11e9392..4ae4b6dbd46b 100644
--- a/sbin/mount_nfs/mount_nfs.8
+++ b/sbin/mount_nfs/mount_nfs.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)mount_nfs.8 8.3 (Berkeley) 3/29/95
-.\" $FreeBSD$
-.\"
-.Dd July 2, 2022
+.Dd November 29, 2024
.Dt MOUNT_NFS 8
.Os
.Sh NAME
@@ -166,7 +163,7 @@ It allows the mount to be performed by
and avoids problems with
cached credentials for the system operations expiring.
The
-.Dq "service-prinicpal-name"
+.Dq "service-principal-name"
should be specified without instance or domain and is typically
.Dq "host" ,
.Dq "nfs"
@@ -188,6 +185,10 @@ Same as not specifying
Make the mount interruptible, which implies that file system calls that
are delayed due to an unresponsive server will fail with EINTR when a
termination signal is posted for the process.
+To avoid leaving file locks in an indeterminate state on the NFS
+server, it is recommended that the
+.Cm nolockd
+option be used with this option.
.It Cm maxgroups Ns = Ns Aq Ar value
Set the maximum size of the group list for the credentials to the
specified value.
@@ -195,6 +196,16 @@ This should be used for mounts on old servers that cannot handle a
group list size of 16, as specified in RFC 1057.
Try 8, if users in a lot of groups cannot get response from the mount
point.
+.It Cm mountport Ns = Ns Aq Ar value
+Specify the port number to be used to communicate with
+.Xr mountd 8
+on the NFS server.
+This option allows an NFSv2 or NFSv3 mount to be done without
+the need to run the
+.Xr rpcbind 8
+service.
+This option is meaningless for an NFSv4 mount, since NFSv4
+does not use the Mount protocol.
.It Cm mntudp
Force the mount protocol to use UDP transport, even for TCP NFS mounts.
(Necessary for some old
@@ -227,6 +238,9 @@ This option will result in more IP port#s being used.
This option requires the
.Cm nfsv4
option.
+Note that for NFS servers such as AmazonEFS, where each new TCP
+connection can connect to a different cluster that maintains lock
+state separately, this option cannot be used.
.It Cm nfsv2
Use the NFS Version 2 protocol (the default is to try version 3 first
then version 2).
@@ -242,6 +256,9 @@ supported by the NFS Version 4 server will be used.
See the
.Cm minorversion
option.
+Make sure that all your NFS Version 4 clients have unique
+values in
+.Pa /etc/hostid .
.It Cm minorversion Ns = Ns Aq Ar value
Use the specified minor version for a NFS Version 4 mount,
overriding the default.
@@ -314,22 +331,23 @@ Do
.Em not
forward
.Xr fcntl 2
-locks over the wire via the NLM protocol for NFSv3 mounts.
+locks over the wire via the NLM protocol for NFSv3 mounts
+or via the NFSv4 protocol for NFSv4 mounts.
All locks will be local and not seen by the server
-and likewise not seen by other NFS clients for NFSv3 mounts.
+and likewise not seen by other NFS clients for NFSv3 or NFSv4 mounts.
This removes the need to run the
.Xr rpcbind 8
service and the
.Xr rpc.statd 8
and
.Xr rpc.lockd 8
-servers on the client.
+servers on the client for NFSv3 mounts.
Note that this option will only be honored when performing the
initial mount, it will be silently ignored if used while updating
the mount options.
-Also, note that NFSv4 mounts do not use these daemons and handle locks over the
-wire in the NFSv4 protocol.
-As such, this option is meaningless for NFSv4 mounts.
+Also, note that NFSv4 mounts do not use these daemons.
+The NFSv4 protocol handles locks,
+unless this option is specified.
.It Cm noncontigwr
This mount option allows the NFS client to
combine non-contiguous byte ranges being written
@@ -433,6 +451,21 @@ A soft mount, which implies that file system calls will fail
after
.Ar retrycnt
round trip timeout intervals.
+.It Cm syskrb5
+This option specifies that a KerberosV NFSv4 minor version 1 or 2 mount
+uses AUTH_SYS for system operations.
+Using this option avoids the need for a KerberosV mount to have a
+host-based principal entry in the default keytab file
+(no
+.Cm gssname
+option) or a requirement for the user doing the mount to have a
+valid KerberosV ticket granting ticket (TGT) when the mount is done.
+This option is intended to be used with the
+.Cm sec Ns = Ns krb5
+and
+.Cm tls
+options and can only be used for
+NFSv4 mounts with minor version 1 or 2.
.It Cm tcp
Use TCP transport.
This is the default option, as it provides for increased reliability on both
@@ -458,7 +491,7 @@ Alias for
.Cm timeout .
.It Cm tls
This option specifies that the connection to the server must use TLS
-per RFC NNNN.
+per RFC 9289.
TLS is only supported for TCP connections and the
.Xr rpc.tlsclntd 8
daemon must be running for an NFS over TCP connection to use TLS.
@@ -521,6 +554,26 @@ options should only be used as a last ditch effort at improving performance
when mounting servers that do not support TCP mounts.
.El
.El
+.Sh IMPLEMENTATION NOTES
+When neither the
+.Cm rsize
+nor
+.Cm wsize
+options are specified, the I/O size will be set to the largest value
+supported by both the NFS client and server.
+The largest value supported by the NFS client is defined by
+the tunable
+.Cd vfs.maxbcachebuf
+which can be set to a power of two up to
+.Cd kern.maxphys .
+.Pp
+The
+.Xr nfsstat 1
+command with the
+.Ic -m
+command line option will show what
+.Nm
+option settings are actually in use for the mount.
.Sh COMPATIBILITY
The following command line flags are equivalent to
.Fl o
@@ -590,6 +643,7 @@ Same as
.It Fl t
Same as
.Fl o Cm retransmit Ns = Ns Aq Ar value
+(deprecated)
.It Fl w
Same as
.Fl o Cm wsize Ns = Ns Aq Ar value
@@ -604,7 +658,7 @@ named options are equivalent to other
.Fl o
named options and are supported for compatibility with other
operating systems (e.g., Linux, Solaris, and OSX) to ease usage of
-.Xr autofs 5
+.Xr autofs 4
support.
.Bl -tag -width indent
.It Fl o Cm vers Ns = Ns 2
@@ -617,26 +671,6 @@ Same as
Same as
.Fl o Cm nfsv4
.El
-.Sh IMPLEMENTATION NOTES
-When neither the
-.Cm rsize
-nor
-.Cm wsize
-options are specified, the I/O size will be set to the largest value
-supported by both the NFS client and server.
-The largest value supported by the NFS client is defined by
-the tunable
-.Cd vfs.maxbcachebuf
-which can be set to a power of two up to
-.Cd kern.maxphys .
-.Pp
-The
-.Xr nfsstat 1
-command with the
-.Ic -m
-command line option will show what
-.Nm
-option settings are actually in use for the mount.
.Sh SEE ALSO
.Xr nfsstat 1 ,
.Xr nmount 2 ,
@@ -648,6 +682,7 @@ option settings are actually in use for the mount.
.Xr mount 8 ,
.Xr nfsd 8 ,
.Xr nfsiod 8 ,
+.Xr rpcbind 8 ,
.Xr rpc.tlsclntd 8 ,
.Xr showmount 8
.Sh HISTORY
@@ -656,14 +691,25 @@ A version of the
utility appeared in
.Bx 4.4 .
.Sh BUGS
-Since nfsv4 performs open/lock operations that have their ordering strictly
+Since NFSv4 performs open/lock operations that have their ordering strictly
enforced by the server, the options
.Cm intr
and
.Cm soft
cannot be safely used.
-For NFSv4 minor version 1 or 2 mounts, these options may
-also result
-in hung mount points, due to corruption of session slots.
+For NFSv4 minor version 1 or 2 mounts, the ordering is done
+via session slots and the NFSv4 client now handles broken session slots
+fairly well.
+As such, if the
+.Cm nolockd
+option is used along with
+.Cm intr
+and/or
+.Cm soft ,
+an NFSv4 minor version 1 or 2 mount
+should work fairly well, although still not completely correctly.
+For NFSv4 minor version 0 mounts,
.Cm hard
-nfsv4 mounts are strongly recommended.
+mounts without the
+.Cm intr
+mount option is strongly recommended.
diff --git a/sbin/mount_nfs/mount_nfs.c b/sbin/mount_nfs/mount_nfs.c
index 284b34323885..55adb01fc1da 100644
--- a/sbin/mount_nfs/mount_nfs.c
+++ b/sbin/mount_nfs/mount_nfs.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)mount_nfs.c 8.11 (Berkeley) 5/4/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/module.h>
@@ -72,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <mntopts.h>
#include <netdb.h>
#include <stdbool.h>
#include <stdio.h>
@@ -81,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <sysexits.h>
#include <unistd.h>
-#include "mntopts.h"
#include "mounttab.h"
/* Table for af,sotype -> netid conversions. */
@@ -122,6 +108,7 @@ static u_char *fh = NULL;
static int fhsize = 0;
static int secflavor = -1;
static int got_principal = 0;
+static in_port_t mntproto_port = 0;
static enum mountmode {
ANY,
@@ -374,6 +361,13 @@ main(int argc, char *argv[])
softintr = true;
} else if (strcmp(opt, "intr") == 0) {
softintr = true;
+ } else if (strcmp(opt, "mountport") == 0) {
+ num = strtol(val, &p, 10);
+ if (*p || num <= 0 || num > IPPORT_MAX)
+ errx(1, "illegal port num -- "
+ "%s", val);
+ mntproto_port = num;
+ pass_flag_to_nmount=0;
}
if (pass_flag_to_nmount) {
build_iovec(&iov, &iovlen, opt,
@@ -593,6 +587,7 @@ getnfsargs(char **specp, char **hostpp, struct iovec **iov, int *iovlen)
char *hostp, *delimp, *errstr, *spec;
size_t len;
static char nam[MNAMELEN + 1], pname[MAXHOSTNAMELEN + 5];
+ bool resolved;
spec = *specp;
if (*spec == '[' && (delimp = strchr(spec + 1, ']')) != NULL &&
@@ -649,30 +644,7 @@ getnfsargs(char **specp, char **hostpp, struct iovec **iov, int *iovlen)
else if (nfsproto == IPPROTO_UDP)
hints.ai_socktype = SOCK_DGRAM;
- if (getaddrinfo(hostp, portspec, &hints, &ai_nfs) != 0) {
- hints.ai_flags = AI_CANONNAME;
- if ((ecode = getaddrinfo(hostp, portspec, &hints, &ai_nfs))
- != 0) {
- if (portspec == NULL)
- errx(1, "%s: %s", hostp, gai_strerror(ecode));
- else
- errx(1, "%s:%s: %s", hostp, portspec,
- gai_strerror(ecode));
- return (0);
- }
-
- /*
- * For a Kerberized nfs mount where the "principal"
- * argument has not been set, add it here.
- */
- if (got_principal == 0 && secflavor != AUTH_SYS &&
- ai_nfs->ai_canonname != NULL) {
- snprintf(pname, sizeof (pname), "nfs@%s",
- ai_nfs->ai_canonname);
- build_iovec(iov, iovlen, "principal", pname,
- strlen(pname) + 1);
- }
- }
+ resolved = (getaddrinfo(hostp, portspec, &hints, &ai_nfs) == 0);
if ((opflags & (BGRNDNOW | ISBGRND)) == BGRNDNOW) {
warnx("Mount %s:%s, backgrounding",
@@ -684,6 +656,37 @@ getnfsargs(char **specp, char **hostpp, struct iovec **iov, int *iovlen)
ret = TRYRET_LOCALERR;
for (;;) {
+ if (!resolved) {
+ hints.ai_flags = AI_CANONNAME;
+ if ((ecode = getaddrinfo(hostp, portspec, &hints,
+ &ai_nfs)) != 0) {
+ if (portspec == NULL)
+ warnx("%s: %s", hostp,
+ gai_strerror(ecode));
+ else
+ warnx("%s:%s: %s", hostp, portspec,
+ gai_strerror(ecode));
+ if (ecode == EAI_AGAIN &&
+ (opflags & (BGRNDNOW | BGRND)))
+ goto retry;
+ else
+ exit(1);
+ }
+ resolved = true;
+ /*
+ * For a Kerberized nfs mount where the
+ * "principal" argument has not been set, add
+ * it here.
+ */
+ if (got_principal == 0 && secflavor != AUTH_SYS &&
+ ai_nfs->ai_canonname != NULL) {
+ snprintf(pname, sizeof (pname), "nfs@%s",
+ ai_nfs->ai_canonname);
+ build_iovec(iov, iovlen, "principal", pname,
+ strlen(pname) + 1);
+ }
+ }
+
/*
* Try each entry returned by getaddrinfo(). Note the
* occurrence of remote errors by setting `remoteerr'.
@@ -711,7 +714,7 @@ getnfsargs(char **specp, char **hostpp, struct iovec **iov, int *iovlen)
/* Exit if all errors were local. */
if (!remoteerr)
exit(1);
-
+retry:
/*
* If retrycnt == 0, we are to keep retrying forever.
* Otherwise decrement it, and exit if it hits zero.
@@ -914,11 +917,47 @@ tryagain:
return (TRYRET_SUCCESS);
}
+ /*
+ * malloc() and copy the address, so that it can be used for
+ * nfsargs below.
+ */
+ addrlen = nfs_nb.len;
+ addr = malloc(addrlen);
+ if (addr == NULL)
+ err(1, "malloc");
+ bcopy(nfs_nb.buf, addr, addrlen);
+
/* Send the MOUNTPROC_MNT RPC to get the root filehandle. */
try.tv_sec = 10;
try.tv_usec = 0;
- clp = clnt_tp_create(hostp, MOUNTPROG, mntvers, nconf_mnt);
+ if (mntproto_port != 0) {
+ struct sockaddr *sad;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+
+ sad = (struct sockaddr *)nfs_nb.buf;
+ switch (sad->sa_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)nfs_nb.buf;
+ sin->sin_port = htons(mntproto_port);
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)nfs_nb.buf;
+ sin6->sin6_port = htons(mntproto_port);
+ break;
+ default:
+ snprintf(errbuf, sizeof(errbuf),
+ "Mnt port bad addr family %d\n", sad->sa_family);
+ return (TRYRET_LOCALERR);
+ }
+ clp = clnt_tli_create(RPC_ANYFD, nconf_mnt, &nfs_nb, MOUNTPROG,
+ mntvers, 0, 0);
+ } else {
+ /* Get the Mount protocol port# via rpcbind. */
+ clp = clnt_tp_create(hostp, MOUNTPROG, mntvers, nconf_mnt);
+ }
if (clp == NULL) {
+ free(addr);
snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt,
hostp, spec, clnt_spcreateerror("RPCMNT: clnt_create"));
return (returncode(rpc_createerr.cf_stat,
@@ -928,10 +967,10 @@ tryagain:
nfhret.auth = secflavor;
nfhret.vers = mntvers;
clntstat = clnt_call(clp, MOUNTPROC_MNT, (xdrproc_t)xdr_dir, spec,
- (xdrproc_t)xdr_fh, &nfhret,
- try);
+ (xdrproc_t)xdr_fh, &nfhret, try);
auth_destroy(clp->cl_auth);
if (clntstat != RPC_SUCCESS) {
+ free(addr);
if (clntstat == RPC_PROGVERSMISMATCH && trymntmode == ANY) {
clnt_destroy(clp);
trymntmode = V2;
@@ -946,6 +985,7 @@ tryagain:
clnt_destroy(clp);
if (nfhret.stat != 0) {
+ free(addr);
snprintf(errbuf, sizeof errbuf, "[%s] %s:%s: %s", netid_mnt,
hostp, spec, strerror(nfhret.stat));
return (TRYRET_REMOTEERR);
@@ -955,13 +995,10 @@ tryagain:
* Store the filehandle and server address in nfsargsp, making
* sure to copy any locally allocated structures.
*/
- addrlen = nfs_nb.len;
- addr = malloc(addrlen);
fhsize = nfhret.fhsize;
fh = malloc(fhsize);
- if (addr == NULL || fh == NULL)
+ if (fh == NULL)
err(1, "malloc");
- bcopy(nfs_nb.buf, addr, addrlen);
bcopy(nfhret.nfh, fh, fhsize);
build_iovec(iov, iovlen, "addr", addr, addrlen);
diff --git a/sbin/mount_nullfs/Makefile b/sbin/mount_nullfs/Makefile
index 43580cfdb82f..1844aa14b24f 100644
--- a/sbin/mount_nullfs/Makefile
+++ b/sbin/mount_nullfs/Makefile
@@ -1,14 +1,6 @@
-# @(#)Makefile 8.3 (Berkeley) 3/27/94
-# $FreeBSD$
-
PACKAGE=runtime
PROG= mount_nullfs
-SRCS= mount_nullfs.c getmntopts.c
MAN= mount_nullfs.8
-
-MOUNT= ${.CURDIR:H}/mount
-CFLAGS+=-I${MOUNT}
-
-.PATH: ${MOUNT}
+LIBADD= util
.include <bsd.prog.mk>
diff --git a/sbin/mount_nullfs/Makefile.depend b/sbin/mount_nullfs/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/mount_nullfs/Makefile.depend
+++ b/sbin/mount_nullfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mount_nullfs/mount_nullfs.8 b/sbin/mount_nullfs/mount_nullfs.8
index 756b13a7ffdf..b3cf57fd9dea 100644
--- a/sbin/mount_nullfs/mount_nullfs.8
+++ b/sbin/mount_nullfs/mount_nullfs.8
@@ -30,10 +30,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)mount_null.8 8.6 (Berkeley) 5/1/95
-.\" $FreeBSD$
-.\"
-.Dd May 6, 2022
+.Dd March 24, 2024
.Dt MOUNT_NULLFS 8
.Os
.Sh NAME
@@ -48,7 +45,8 @@
The
.Nm
utility creates a
-null layer, duplicating a sub-tree of the file system
+.Xr nullfs 4
+layer, duplicating a sub-tree of the file system
name space under another part of the global file system namespace.
This allows existing files and directories to be accessed
using a different pathname.
@@ -64,6 +62,17 @@ but in other respects it is indistinguishable from the original.
.Pp
The
.Nm
+utility supports mounting both directories and single files.
+Both
+.Ar target
+and
+.Ar mount_point
+must be the same type.
+Mounting directories to files or files to
+directories is not supported.
+.Pp
+The
+.Nm
file system differs from a traditional
loopback file system in two respects: it is implemented using
a stackable layers techniques, and its
@@ -81,15 +90,47 @@ See the
.Xr mount 8
man page for possible options and their meanings.
Additionally the following option is supported:
-.Bl -tag -width indent
+.Bl -tag -width nounixbypass
.It Cm nocache
Disable metadata caching in the null layer.
Some lower-layer file systems may force this option.
Depending on the access pattern,
this may result in increased lock contention.
+.It Cm cache
+Force enable metadata caching.
+.It Cm nounixbypass
+Disable bypassing
+.Xr unix 4
+socket files used for
+.Xr bind 2
+and
+.Xr connect 2 ,
+to the lower (mounted-from) filesystem layer.
+.Pp
+The effect is that lower and upper (bypassed) unix sockets
+are separate.
+.It Cm unixbypass
+Enable the bypass of unix socket file to lower filesystem layer.
+This is default.
+.Pp
+The effect is that
+.Xr bind 2
+and
+.Xr connect 2
+operations on a unix socket done from either the upper (nullfs) or lower
+layer path are performed on same unix socket.
+For instance, if a server
+.Xr bind 2
+is done on a socket in the lower layer, then
+.Xr connect 2
+on the socket file accessed via the nullfs mount, connects to the server.
.El
.El
.Pp
+The
+.Dv vfs.nullfs.cache_vnodes
+sysctl specifies global default for mount-specific cache/nocache option.
+.Pp
The null layer has two purposes.
First, it serves as a demonstration of layering by providing a layer
which does nothing.
@@ -242,6 +283,7 @@ is that vnode arguments must be manually mapped.
.\"
.\"
.Sh SEE ALSO
+.Xr nullfs 4 ,
.Xr mount 8
.Pp
UCLA Technical Report CSD-910056,
diff --git a/sbin/mount_nullfs/mount_nullfs.c b/sbin/mount_nullfs/mount_nullfs.c
index 77ec0991ea9b..fc04961e6247 100644
--- a/sbin/mount_nullfs/mount_nullfs.c
+++ b/sbin/mount_nullfs/mount_nullfs.c
@@ -32,35 +32,29 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mount_null.c 8.6 (Berkeley) 4/26/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/mount.h>
+#include <sys/stat.h>
#include <sys/uio.h>
#include <err.h>
+#include <mntopts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
-#include "mntopts.h"
-
static void usage(void) __dead2;
+static int
+stat_realpath(const char *path, char *resolved, struct stat *sbp)
+{
+ if (realpath(path, resolved) == NULL || stat(resolved, sbp) != 0)
+ return (1);
+ return (0);
+}
+
int
main(int argc, char *argv[])
{
@@ -71,6 +65,8 @@ main(int argc, char *argv[])
char errmsg[255];
int ch, iovlen;
char nullfs[] = "nullfs";
+ struct stat target_stat;
+ struct stat mountpoint_stat;
iov = NULL;
iovlen = 0;
@@ -98,10 +94,18 @@ main(int argc, char *argv[])
usage();
/* resolve target and mountpoint with realpath(3) */
- if (checkpath(argv[0], target) != 0)
+ if (stat_realpath(argv[0], target, &target_stat) != 0)
err(EX_USAGE, "%s", target);
- if (checkpath(argv[1], mountpoint) != 0)
+ if (stat_realpath(argv[1], mountpoint, &mountpoint_stat) != 0)
err(EX_USAGE, "%s", mountpoint);
+ if (!S_ISDIR(target_stat.st_mode) && !S_ISREG(target_stat.st_mode))
+ errx(EX_USAGE, "%s: must be either a file or directory",
+ target);
+ if ((target_stat.st_mode & S_IFMT) !=
+ (mountpoint_stat.st_mode & S_IFMT))
+ errx(EX_USAGE,
+ "%s: must be same type as %s (file or directory)",
+ mountpoint, target);
build_iovec(&iov, &iovlen, "fstype", nullfs, (size_t)-1);
build_iovec(&iov, &iovlen, "fspath", mountpoint, (size_t)-1);
diff --git a/sbin/mount_udf/Makefile b/sbin/mount_udf/Makefile
index 903ec7690ea4..6506f6ba3985 100644
--- a/sbin/mount_udf/Makefile
+++ b/sbin/mount_udf/Makefile
@@ -1,14 +1,7 @@
-# $FreeBSD$
-
PACKAGE=runtime
PROG= mount_udf
-SRCS= mount_udf.c getmntopts.c
MAN= mount_udf.8
-LIBADD= kiconv
-
-MOUNT= ${.CURDIR:H}/mount
-CFLAGS+= -I${MOUNT} -I${SRCTOP}/sys
-.PATH: ${MOUNT}
+LIBADD= kiconv util
# Needs to be dynamically linked for optional dlopen() access to
# userland libiconv
diff --git a/sbin/mount_udf/Makefile.depend b/sbin/mount_udf/Makefile.depend
index 9258f1c2123f..6de9b208e915 100644
--- a/sbin/mount_udf/Makefile.depend
+++ b/sbin/mount_udf/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mount_udf/mount_udf.8 b/sbin/mount_udf/mount_udf.8
index fb39419aea48..505582746550 100644
--- a/sbin/mount_udf/mount_udf.8
+++ b/sbin/mount_udf/mount_udf.8
@@ -24,8 +24,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd March 23, 2002
.Dt MOUNT_UDF 8
.Os
diff --git a/sbin/mount_udf/mount_udf.c b/sbin/mount_udf/mount_udf.c
index 3f612cbc2fab..0425c6a1378c 100644
--- a/sbin/mount_udf/mount_udf.c
+++ b/sbin/mount_udf/mount_udf.c
@@ -33,8 +33,6 @@
* 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$
*/
/*
@@ -55,14 +53,13 @@
#include <err.h>
#include <errno.h>
+#include <mntopts.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
-#include "mntopts.h"
-
static struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_UPDATE,
diff --git a/sbin/mount_unionfs/Makefile b/sbin/mount_unionfs/Makefile
index 7e7136094995..35e7e8fa75b7 100644
--- a/sbin/mount_unionfs/Makefile
+++ b/sbin/mount_unionfs/Makefile
@@ -1,14 +1,6 @@
-# @(#)Makefile 8.3 (Berkeley) 3/27/94
-# $FreeBSD$
-
PACKAGE=runtime
PROG= mount_unionfs
-SRCS= mount_unionfs.c getmntopts.c
MAN= mount_unionfs.8
-
-MOUNT= ${.CURDIR:H}/mount
-CFLAGS+=-I${MOUNT}
-
-.PATH: ${MOUNT}
+LIBADD= util
.include <bsd.prog.mk>
diff --git a/sbin/mount_unionfs/Makefile.depend b/sbin/mount_unionfs/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/mount_unionfs/Makefile.depend
+++ b/sbin/mount_unionfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/mount_unionfs/mount_unionfs.8 b/sbin/mount_unionfs/mount_unionfs.8
index d77fa3fa476e..5469fef4ad35 100644
--- a/sbin/mount_unionfs/mount_unionfs.8
+++ b/sbin/mount_unionfs/mount_unionfs.8
@@ -28,9 +28,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)mount_union.8 8.6 (Berkeley) 3/27/94
-.\" $FreeBSD$
-.\"
.Dd October 3, 2016
.Dt MOUNT_UNIONFS 8
.Os
@@ -353,11 +350,7 @@ wrote about the changes in this manual page.
.Sh BUGS
THIS FILE SYSTEM TYPE IS NOT YET FULLY SUPPORTED (READ: IT DOESN'T WORK)
AND USING IT MAY, IN FACT, DESTROY DATA ON YOUR SYSTEM.
-USE AT YOUR
-OWN RISK.
-BEWARE OF DOG.
-SLIPPERY WHEN WET.
-BATTERIES NOT INCLUDED.
+USE AT YOUR OWN RISK.
.Pp
This code also needs an owner in order to be less dangerous - serious
hackers can apply by sending mail to
diff --git a/sbin/mount_unionfs/mount_unionfs.c b/sbin/mount_unionfs/mount_unionfs.c
index 9aafaf13d81f..d207e5581745 100644
--- a/sbin/mount_unionfs/mount_unionfs.c
+++ b/sbin/mount_unionfs/mount_unionfs.c
@@ -35,27 +35,13 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)mount_union.c 8.5 (Berkeley) 3/27/94";
-#else
-static const char rcsid[] =
- "$FreeBSD$";
-#endif
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/uio.h>
#include <sys/errno.h>
#include <err.h>
+#include <mntopts.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -64,8 +50,6 @@ static const char rcsid[] =
#include <grp.h>
#include <pwd.h>
-#include "mntopts.h"
-
static int
subdir(const char *p, const char *dir)
{
diff --git a/sbin/natd/Makefile b/sbin/natd/Makefile
index aef193b3f1d0..b8d54c780bfa 100644
--- a/sbin/natd/Makefile
+++ b/sbin/natd/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= natd
PROG = natd
SRCS = natd.c icmp.c
diff --git a/sbin/natd/Makefile.depend b/sbin/natd/Makefile.depend
index ed80e66dfc4b..8b9910a02d31 100644
--- a/sbin/natd/Makefile.depend
+++ b/sbin/natd/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
diff --git a/sbin/natd/README b/sbin/natd/README
index d2e8a9ae6709..12299b8e75ad 100644
--- a/sbin/natd/README
+++ b/sbin/natd/README
@@ -1,4 +1,3 @@
-# $FreeBSD$
A Network Address Translation Daemon for FreeBSD
diff --git a/sbin/natd/icmp.c b/sbin/natd/icmp.c
index f85457ac4773..0c7210b6dfa8 100644
--- a/sbin/natd/icmp.c
+++ b/sbin/natd/icmp.c
@@ -8,8 +8,6 @@
* You may copy, modify and distribute this software (icmp.c) freely.
*
* Ari Suutari <suutari@iki.fi>
- *
- * $FreeBSD$
*/
#include <stdlib.h>
diff --git a/sbin/natd/natd.8 b/sbin/natd/natd.8
index a09d632c7e69..8beff2e66b6a 100644
--- a/sbin/natd/natd.8
+++ b/sbin/natd/natd.8
@@ -1,5 +1,4 @@
-.\" $FreeBSD$
-.Dd October 5, 2016
+.Dd December 6, 2024
.Dt NATD 8
.Os
.Sh NAME
@@ -15,6 +14,7 @@
.Op Fl deny_incoming | d
.Op Fl use_sockets | s
.Op Fl same_ports | m
+.Op Fl udp_eim
.Op Fl verbose | v
.Op Fl dynamic
.Op Fl in_port | i Ar port
@@ -115,6 +115,26 @@ With this option, protocols such as RPC will have a better chance
of working.
If it is not possible to maintain the port number, it will be silently
changed as per normal.
+.It Fl udp_eim
+When enabled, UDP packets use endpoint-independent mapping (EIM) from RFC 4787
+("full cone" NAT of RFC 3489).
+All packets from the same internal address:port are mapped to the same NAT
+address:port, regardless of their destination address:port.
+If filtering rules allow, and if
+.Em deny_incoming
+is disabled, any other external address:port can
+also send to the internal address:port through its mapped NAT address:port.
+This is more compatible with applications, and can reduce the need for port
+forwarding, but less scalable as each NAT address:port can only be
+concurrently used by at most one internal address:port.
+.Pp
+When disabled, UDP packets use endpoint-dependent mapping (EDM) ("symmetric"
+NAT).
+Each connection from a particular internal address:port to different
+external addresses:ports is mapped to a random and unpredictable NAT
+address:port.
+Two appplications behind EDM NATs can only connect to each other
+by port forwarding on the NAT, or tunnelling through an in-between server.
.It Fl verbose | v
Do not call
.Xr daemon 3
diff --git a/sbin/natd/natd.c b/sbin/natd/natd.c
index 402c430dfdfd..6a62495dd064 100644
--- a/sbin/natd/natd.c
+++ b/sbin/natd/natd.c
@@ -11,8 +11,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#define SYSLOG_NAMES
#include <sys/types.h>
@@ -226,7 +224,7 @@ int main (int argc, char** argv)
*/
if (mip->inOutPort) {
- mip->divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ mip->divertInOut = socket(PF_DIVERT, SOCK_RAW, 0);
if (mip->divertInOut == -1)
Quit ("Unable to create divert socket.");
if (mip->divertInOut > fdMax)
@@ -249,14 +247,14 @@ int main (int argc, char** argv)
}
else {
- mip->divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ mip->divertIn = socket(PF_DIVERT, SOCK_RAW, 0);
if (mip->divertIn == -1)
Quit ("Unable to create incoming divert socket.");
if (mip->divertIn > fdMax)
fdMax = mip->divertIn;
- mip->divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ mip->divertOut = socket(PF_DIVERT, SOCK_RAW, 0);
if (mip->divertOut == -1)
Quit ("Unable to create outgoing divert socket.");
if (mip->divertOut > fdMax)
@@ -317,7 +315,7 @@ int main (int argc, char** argv)
}
if (globalPort) {
- divertGlobal = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ divertGlobal = socket(PF_DIVERT, SOCK_RAW, 0);
if (divertGlobal == -1)
Quit ("Unable to create divert socket.");
if (divertGlobal > fdMax)
@@ -1140,6 +1138,14 @@ static struct OptionInfo optionTable[] = {
"same_ports",
"m" },
+ { LibAliasOption,
+ PKT_ALIAS_UDP_EIM,
+ YesNo,
+ "[yes|no]",
+ "UDP traffic uses endpoint-independent mapping (\"full cone\" NAT)",
+ "udp_eim",
+ NULL },
+
{ Verbose,
0,
YesNo,
diff --git a/sbin/natd/natd.h b/sbin/natd/natd.h
index 32bffd81a745..3139984e3493 100644
--- a/sbin/natd/natd.h
+++ b/sbin/natd/natd.h
@@ -8,8 +8,6 @@
* You may copy, modify and distribute this software (natd.h) freely.
*
* Ari Suutari <suutari@iki.fi>
- *
- * $FreeBSD$
*/
#define PIDFILE "/var/run/natd.pid"
diff --git a/sbin/natd/samples/natd.cf.sample b/sbin/natd/samples/natd.cf.sample
index d4dcd714bd92..24d38e1095a7 100644
--- a/sbin/natd/samples/natd.cf.sample
+++ b/sbin/natd/samples/natd.cf.sample
@@ -1,5 +1,4 @@
#
-# $FreeBSD$
#
#
# Configuration file for natd.
diff --git a/sbin/newfs/Makefile b/sbin/newfs/Makefile
index 9e3ea13b6e5c..1138e819055f 100644
--- a/sbin/newfs/Makefile
+++ b/sbin/newfs/Makefile
@@ -1,8 +1,6 @@
-# @(#)Makefile 8.2 (Berkeley) 3/27/94
-# $FreeBSD$
-
.PATH: ${SRCTOP}/sys/geom
+PACKAGE= ufs
PROG= newfs
LIBADD= ufs util
SRCS= newfs.c mkfs.c geom_bsd_enc.c
diff --git a/sbin/newfs/Makefile.depend b/sbin/newfs/Makefile.depend
index 51f2384d1c84..2e61386bc0cc 100644
--- a/sbin/newfs/Makefile.depend
+++ b/sbin/newfs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c
index a6c4ee60c2d5..3715ef58ad0f 100644
--- a/sbin/newfs/mkfs.c
+++ b/sbin/newfs/mkfs.c
@@ -38,15 +38,7 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#define IN_RTLD /* So we pickup the P_OSREL defines */
+#define _WANT_P_OSREL
#include <sys/param.h>
#include <sys/disklabel.h>
#include <sys/file.h>
@@ -76,14 +68,27 @@ __FBSDID("$FreeBSD$");
#define UMASK 0755
#define POWEROF2(num) (((num) & ((num) - 1)) == 0)
+/*
+ * The definition of "struct cg" used to contain an extra field at the end
+ * to represent the variable-length data that followed the fixed structure.
+ * This had the effect of artificially limiting the number of blocks that
+ * newfs would put in a CG, since newfs thought that the fixed-size header
+ * was bigger than it really was. When we started validating that the CG
+ * header data actually fit into one fs block, the placeholder field caused
+ * a problem because it caused struct cg to be a different size depending on
+ * platform. The placeholder field was later removed, but this caused a
+ * backward compatibility problem with older binaries that still thought
+ * struct cg was larger, and a new file system could fail validation if
+ * viewed by the older binaries. To avoid this compatibility problem, we
+ * now artificially reduce the amount of space that the variable-length data
+ * can use such that new file systems will pass validation by older binaries.
+ */
+#define CGSIZEFUDGE 8
+
static struct csum *fscs;
#define sblock disk.d_fs
#define acg disk.d_cg
-union dinode {
- struct ufs1_dinode dp1;
- struct ufs2_dinode dp2;
-};
#define DIP(dp, field) \
((sblock.fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
@@ -332,6 +337,7 @@ restart:
* can put into each cylinder group. If this is too big, we reduce
* the density until it fits.
*/
+retry:
maxinum = (((int64_t)(1)) << 32) - INOPB(&sblock);
minfragsperinode = 1 + fssize / maxinum;
if (density == 0) {
@@ -368,7 +374,8 @@ restart:
sblock.fs_fpg = minfpg;
sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
INOPB(&sblock));
- if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
+ CGSIZEFUDGE)
break;
density -= sblock.fs_fsize;
}
@@ -387,9 +394,11 @@ restart:
if (Oflag > 1 || (Oflag == 1 && sblock.fs_ipg <= 0x7fff)) {
if (sblock.fs_size / sblock.fs_fpg < MINCYLGRPS)
break;
- if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
+ if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize -
+ CGSIZEFUDGE)
continue;
- if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
+ if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize -
+ CGSIZEFUDGE)
break;
}
sblock.fs_fpg -= sblock.fs_frag;
@@ -636,23 +645,26 @@ restart:
* Read the last sector of the boot block, replace the last
* 20 bytes with the recovery information, then write it back.
* The recovery information only works for UFS2 filesystems.
+ * For UFS1, zero out the area to ensure that an old UFS2
+ * recovery block is not accidentally found.
*/
- if (sblock.fs_magic == FS_UFS2_MAGIC) {
- if ((fsrbuf = malloc(realsectorsize)) == NULL || bread(&disk,
- part_ofs + (SBLOCK_UFS2 - realsectorsize) / disk.d_bsize,
- fsrbuf, realsectorsize) == -1)
- err(1, "can't read recovery area: %s", disk.d_error);
- fsr =
- (struct fsrecovery *)&fsrbuf[realsectorsize - sizeof *fsr];
+ if ((fsrbuf = malloc(realsectorsize)) == NULL || bread(&disk,
+ part_ofs + (SBLOCK_UFS2 - realsectorsize) / disk.d_bsize,
+ fsrbuf, realsectorsize) == -1)
+ err(1, "can't read recovery area: %s", disk.d_error);
+ fsr = (struct fsrecovery *)&fsrbuf[realsectorsize - sizeof *fsr];
+ if (sblock.fs_magic != FS_UFS2_MAGIC) {
+ memset(fsr, 0, sizeof *fsr);
+ } else {
fsr->fsr_magic = sblock.fs_magic;
fsr->fsr_fpg = sblock.fs_fpg;
fsr->fsr_fsbtodb = sblock.fs_fsbtodb;
fsr->fsr_sblkno = sblock.fs_sblkno;
fsr->fsr_ncg = sblock.fs_ncg;
- wtfs((SBLOCK_UFS2 - realsectorsize) / disk.d_bsize,
- realsectorsize, fsrbuf);
- free(fsrbuf);
}
+ wtfs((SBLOCK_UFS2 - realsectorsize) / disk.d_bsize,
+ realsectorsize, fsrbuf);
+ free(fsrbuf);
/*
* Update information about this partition in pack
* label, to that it may be updated on disk.
@@ -663,6 +675,21 @@ restart:
pp->p_frag = sblock.fs_frag;
pp->p_cpg = sblock.fs_fpg;
}
+ /*
+ * This should NOT happen. If it does complain loudly and
+ * take evasive action.
+ */
+ if ((int32_t)CGSIZE(&sblock) > sblock.fs_bsize) {
+ printf("INTERNAL ERROR: ipg %d, fpg %d, contigsumsize %d, ",
+ sblock.fs_ipg, sblock.fs_fpg, sblock.fs_contigsumsize);
+ printf("old_cpg %d, size_cg %zu, CGSIZE %zu\n",
+ sblock.fs_old_cpg, sizeof(struct cg), CGSIZE(&sblock));
+ printf("Please file a FreeBSD bug report and include this "
+ "output\n");
+ maxblkspercg = fragstoblks(&sblock, sblock.fs_fpg) - 1;
+ density = 0;
+ goto retry;
+ }
}
/*
@@ -702,7 +729,7 @@ initcg(int cylno, time_t utime)
acg.cg_ndblk = dmax - cbase;
if (sblock.fs_contigsumsize > 0)
acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
- start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
+ start = sizeof(acg);
if (Oflag == 2) {
acg.cg_iusedoff = start;
} else {
@@ -730,7 +757,8 @@ initcg(int cylno, time_t utime)
howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
}
if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) {
- printf("Panic: cylinder group too big\n");
+ printf("Panic: cylinder group too big by %d bytes\n",
+ acg.cg_nextfreeoff - (unsigned)sblock.fs_cgsize);
exit(37);
}
acg.cg_cs.cs_nifree += sblock.fs_ipg;
@@ -912,8 +940,9 @@ fsinit(time_t utime)
alloc(sblock.fs_fsize, node.dp1.di_mode);
node.dp1.di_blocks =
btodb(fragroundup(&sblock, node.dp1.di_size));
- wtfs(fsbtodb(&sblock, node.dp1.di_db[0]),
- sblock.fs_fsize, iobuf);
+ node.dp1.di_dirdepth = 1;
+ wtfs(fsbtodb(&sblock, node.dp1.di_db[0]),
+ sblock.fs_fsize, iobuf);
iput(&node, UFS_ROOTINO + 1);
}
} else {
@@ -948,8 +977,9 @@ fsinit(time_t utime)
alloc(sblock.fs_fsize, node.dp2.di_mode);
node.dp2.di_blocks =
btodb(fragroundup(&sblock, node.dp2.di_size));
- wtfs(fsbtodb(&sblock, node.dp2.di_db[0]),
- sblock.fs_fsize, iobuf);
+ node.dp2.di_dirdepth = 1;
+ wtfs(fsbtodb(&sblock, node.dp2.di_db[0]),
+ sblock.fs_fsize, iobuf);
iput(&node, UFS_ROOTINO + 1);
}
}
@@ -1188,7 +1218,7 @@ ilog2(int val)
static u_int32_t
newfs_random(void)
{
- static int nextnum = 1;
+ static u_int32_t nextnum = 1;
if (Rflag)
return (nextnum++);
diff --git a/sbin/newfs/newfs.8 b/sbin/newfs/newfs.8
index 5213e4109363..16bca26f7cd8 100644
--- a/sbin/newfs/newfs.8
+++ b/sbin/newfs/newfs.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)newfs.8 8.6 (Berkeley) 5/3/95
-.\" $FreeBSD$
-.\"
-.Dd April 17, 2021
+.Dd January 23, 2025
.Dt NEWFS 8
.Os
.Sh NAME
@@ -101,6 +98,10 @@ The default format is UFS2.
For backward compatibility.
.It Fl U
Enable soft updates on the new file system.
+Soft updates are enabled by default for UFS2 format file systems.
+Use
+.Xr tunefs 8
+to disable soft updates if they are not wanted.
.It Fl a Ar maxcontig
Specify the maximum number of contiguous blocks that will be
laid out before forcing a rotational delay.
@@ -169,6 +170,41 @@ This flag is implemented by running the
.Xr tunefs 8
utility found in the user's
.Dv $PATH .
+.Pp
+Enabling journaling reduces the time spent by
+.Xr fsck_ffs 8
+cleaning up a filesystem after a crash to a few seconds from minutes to hours.
+Without journaling, the time to recover after a crash is a function
+of the number of files in the filesystem and the size of the filesystem.
+With journaling, the time to recover after a crash is a function of the
+amount of activity in the filesystem in the minute before the crash.
+Journaled recovery time is usually only a few seconds and never
+exceeds a minute.
+.Pp
+The drawback to using journaling is that the writes to its log adds
+an extra write load to the media containing the filesystem.
+Thus a write-intensive workload will have reduced throughput on a
+filesystem running with journaling.
+.Pp
+Like all journaling filesystems, the journal recovery will only fix
+issues known to the journal.
+Specifically if a media error occurs,
+the journal will not know about it and hence will not fix it.
+Thus when using journaling, it is still necessary to run a full fsck
+every few months or after a filesystem panic to check for and fix
+any errors brought on by media failure.
+A full fsck can be done by running a background fsck on a live
+filesystem or by running with the
+.Fl f
+flag on an unmounted filesystem.
+When running
+.Xr fsck_ffs 8
+in background on a live filesystem the filesystem performance
+will be about half of normal during the time that the background
+.Xr fsck_ffs 8
+is running.
+Running a full fsck on a UFS filesystem is the equivalent of
+running a scrub on a ZFS filesystem.
.It Fl k Ar held-for-metadata-blocks
Set the amount of space to be held for metadata blocks in each cylinder group.
When set, the file system preference routines will try to save
@@ -314,18 +350,18 @@ than the historical defaults
This large fragment size may lead to much wasted space
on file systems that contain many small files.
.Sh SEE ALSO
-.Xr fdformat 1 ,
+.Xr ffs 4 ,
.Xr geom 4 ,
.Xr disktab 5 ,
.Xr fs 5 ,
.Xr camcontrol 8 ,
.Xr dump 8 ,
.Xr dumpfs 8 ,
+.Xr fdformat 8 ,
.Xr fsck 8 ,
.Xr gjournal 8 ,
.Xr gpart 8 ,
.Xr growfs 8 ,
-.Xr gvinum 8 ,
.Xr makefs 8 ,
.Xr mount 8 ,
.Xr newfs_msdos 8 ,
diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c
index a2d97131d3a7..418319d1cd3a 100644
--- a/sbin/newfs/newfs.c
+++ b/sbin/newfs/newfs.c
@@ -38,20 +38,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* newfs: friendly front end to mkfs
*/
@@ -119,12 +105,11 @@ struct uufsd disk; /* libufs disk structure */
static char device[MAXPATHLEN];
static u_char bootarea[BBSIZE];
static int is_file; /* work on a file, not a device */
-static char *dkname;
static char *disktype;
static void getfssize(intmax_t *, const char *p, intmax_t, intmax_t);
static struct disklabel *getdisklabel(void);
-static void usage(void);
+static void usage(void) __dead2;
static int expand_number_int(const char *buf, int *num);
ufs2_daddr_t part_ofs; /* partition offset in blocks, used with files */
@@ -137,7 +122,8 @@ main(int argc, char *argv[])
struct stat st;
char *cp, *special;
intmax_t reserved;
- int ch, i, rval;
+ int ch, rval;
+ size_t i;
char part_name; /* partition name, default to full disk */
part_name = 'c';
@@ -153,9 +139,10 @@ main(int argc, char *argv[])
break;
case 'L':
volumelabel = optarg;
- i = -1;
- while (isalnum(volumelabel[++i]) ||
- volumelabel[i] == '_' || volumelabel[i] == '-');
+ for (i = 0; isalnum(volumelabel[i]) ||
+ volumelabel[i] == '_' || volumelabel[i] == '-';
+ i++)
+ continue;
if (volumelabel[i] != '\0') {
errx(1, "bad volume label. Valid characters "
"are alphanumerics, dashes, and underscores.");
@@ -340,9 +327,7 @@ main(int argc, char *argv[])
if (fstat(disk.d_fd, &st) < 0)
err(1, "%s", special);
if ((st.st_mode & S_IFMT) != S_IFCHR) {
- warn("%s: not a character-special device", special);
is_file = 1; /* assume it is a file */
- dkname = special;
if (sectorsize == 0)
sectorsize = 512;
mediasize = st.st_size;
@@ -356,6 +341,11 @@ main(int argc, char *argv[])
}
pp = NULL;
lp = getdisklabel();
+ /*
+ * set filesystem size from file size when a bsdlabel isn't present
+ */
+ if (lp == NULL && is_file)
+ fssize = mediasize / sectorsize;
if (lp != NULL) {
if (!is_file) /* already set for files */
part_name = special[strlen(special) - 1];
@@ -395,6 +385,9 @@ main(int argc, char *argv[])
fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
opt = FS_OPTSPACE;
}
+ /* Use soft updates by default for UFS2 and above */
+ if (Oflag > 1)
+ Uflag = 1;
realsectorsize = sectorsize;
if (sectorsize != DEV_BSIZE) { /* XXX */
int secperblk = sectorsize / DEV_BSIZE;
@@ -442,7 +435,7 @@ getdisklabel(void)
bootarea + (0 /* labeloffset */ +
1 /* labelsoffset */ * sectorsize),
&lab, MAXPARTITIONS))
- errx(1, "no valid label found");
+ return (NULL);
lp = &lab;
return &lab;
diff --git a/sbin/newfs/newfs.h b/sbin/newfs/newfs.h
index cebb1d999462..538c1718810e 100644
--- a/sbin/newfs/newfs.h
+++ b/sbin/newfs/newfs.h
@@ -36,8 +36,6 @@
* 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 <libufs.h>
diff --git a/sbin/newfs/ref.test b/sbin/newfs/ref.test
index 1967e247d4e5..194b22188920 100644
--- a/sbin/newfs/ref.test
+++ b/sbin/newfs/ref.test
@@ -1,4 +1,3 @@
-# $FreeBSD$
00c08266df6b0c79d2673515c182216a
c00458f223a9119190591e8b8679bf97
7d5b3c75244898dbb07a4cd20860c8a1
diff --git a/sbin/newfs/runtest00.sh b/sbin/newfs/runtest00.sh
index ea51dee8dbda..5e8e772e44f5 100644
--- a/sbin/newfs/runtest00.sh
+++ b/sbin/newfs/runtest00.sh
@@ -1,5 +1,4 @@
#!/bin/sh
-# $FreeBSD$
set -e
diff --git a/sbin/newfs/runtest01.sh b/sbin/newfs/runtest01.sh
index 6fe91cb86963..1ae254d78d1e 100644
--- a/sbin/newfs/runtest01.sh
+++ b/sbin/newfs/runtest01.sh
@@ -1,5 +1,4 @@
#!/bin/sh
-# $FreeBSD$
set -e
diff --git a/sbin/newfs_msdos/Makefile b/sbin/newfs_msdos/Makefile
index 0123f4dd7a8a..bd5b3486b6b6 100644
--- a/sbin/newfs_msdos/Makefile
+++ b/sbin/newfs_msdos/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=runtime
@@ -11,7 +9,6 @@ SRCS= newfs_msdos.c mkfs_msdos.c
.if ${MACHINE_CPUARCH} == "arm"
WARNS?= 3
.endif
-CSTD= c11
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/sbin/newfs_msdos/Makefile.depend b/sbin/newfs_msdos/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/newfs_msdos/Makefile.depend
+++ b/sbin/newfs_msdos/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/newfs_msdos/mkfs_msdos.c b/sbin/newfs_msdos/mkfs_msdos.c
index 13a804c82625..dcc2bb982efc 100644
--- a/sbin/newfs_msdos/mkfs_msdos.c
+++ b/sbin/newfs_msdos/mkfs_msdos.c
@@ -25,11 +25,6 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#ifdef MAKEFS
/* In the makefs case we only want struct disklabel */
@@ -254,7 +249,7 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
ssize_t n;
time_t now;
u_int fat, bss, rds, cls, dir, lsn, x, x1, x2;
- u_int extra_res, alignment, saved_x, attempts=0;
+ u_int extra_res, alignment, alignto, saved_x, attempts=0;
bool set_res, set_spf, set_spc;
int fd, fd1, rv;
struct msdos_options o = *op;
@@ -417,8 +412,12 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
}
bpb.bpbFATs = o.num_FAT;
}
- if (o.directory_entries)
- bpb.bpbRootDirEnts = o.directory_entries;
+ if (o.directory_entries) {
+ bpb.bpbRootDirEnts = roundup(o.directory_entries,
+ bpb.bpbBytesPerSec / sizeof(struct de));
+ if (bpb.bpbBytesPerSec == 0 || o.directory_entries >= MAXU16)
+ bpb.bpbRootDirEnts = MAXU16;
+ }
if (o.media_descriptor_set) {
if (o.media_descriptor < 0xf0) {
warnx("illegal media descriptor (%#x)", o.media_descriptor);
@@ -569,14 +568,17 @@ mkfs_msdos(const char *fname, const char *dtype, const struct msdos_options *op)
x1 += (bpb.bpbBigFATsecs - 1) * bpb.bpbFATs;
}
if (set_res) {
- /* attempt to align root directory */
- alignment = (bpb.bpbResSectors + bpb.bpbBigFATsecs * bpb.bpbFATs) %
- bpb.bpbSecPerClust;
- if (o.align)
- extra_res += bpb.bpbSecPerClust - alignment;
+ alignto = bpb.bpbSecPerClust;
+ if (alignto > 1) {
+ /* align data clusters */
+ alignment = (bpb.bpbResSectors + bpb.bpbBigFATsecs * bpb.bpbFATs + rds) %
+ alignto;
+ if (alignment != 0)
+ extra_res += alignto - alignment;
+ }
}
attempts++;
- } while (o.align && alignment != 0 && attempts < 2);
+ } while (alignment != 0 && attempts < 2);
if (o.align && alignment != 0)
warnx("warning: Alignment failed.");
diff --git a/sbin/newfs_msdos/mkfs_msdos.h b/sbin/newfs_msdos/mkfs_msdos.h
index 7e0c6622c8b7..6e5bad0da8f0 100644
--- a/sbin/newfs_msdos/mkfs_msdos.h
+++ b/sbin/newfs_msdos/mkfs_msdos.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $NetBSD: mkfs_msdos.h,v 1.3 2015/10/16 17:38:17 christos Exp $ */
/*-
diff --git a/sbin/newfs_msdos/newfs_msdos.8 b/sbin/newfs_msdos/newfs_msdos.8
index 0cdd3848bcd6..03dfbfced51f 100644
--- a/sbin/newfs_msdos/newfs_msdos.8
+++ b/sbin/newfs_msdos/newfs_msdos.8
@@ -23,9 +23,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd June 14, 2018
+.Dd June 6, 2024
.Dt NEWFS_MSDOS 8
.Os
.Sh NAME
@@ -93,7 +91,11 @@ A suffix s, k, m, g (lower or upper case)
appended to the offset specifies that the
number is in sectors, kilobytes, megabytes or gigabytes, respectively.
.It Fl A
-Attempt to cluster align root directory, useful for SD card.
+Attempt to cluster align the data area, useful for flash based storage.
+This option is enabled by default, unless a number of reserved sectors
+is specified using the
+.Fl r
+option.
.It Fl B Ar boot
Get bootstrap from file.
.It Fl C Ar create-size
@@ -136,7 +138,7 @@ File system block size (bytes per cluster).
This should resolve to an
acceptable number of sectors per cluster (see below).
.It Fl c Ar cluster-size
-Sectors per cluster.
+Sectors per cluster, also called allocation size.
Acceptable values are powers of 2 in the range
1 through 128.
If the block or cluster size are not specified, the code
@@ -169,6 +171,10 @@ is 2.
Number of hidden sectors.
.It Fl r Ar reserved
Number of reserved sectors.
+If the
+.Fl r
+option is not used, the number of reserved sectors is set to a value that
+aligns the start of the data area to a multiple of the cluster size.
.It Fl s Ar total
File system size.
.It Fl u Ar track-size
@@ -226,6 +232,12 @@ Create a file system, using default parameters, on
newfs_msdos /dev/ada0s1
.Ed
.Pp
+Create a FAT32 filesystem with a 32K allocation size on
+.Pa /dev/mmcsd0s1 :
+.Bd -literal -offset indent
+newfs_msdos -F 32 -A -c 64 /dev/mmcsd0s1
+.Ed
+.Pp
Create a standard 1.44M file system, with volume label
.Ar foo ,
on
@@ -240,6 +252,7 @@ Create a 30MB image file, with the FAT partition starting
newfs_msdos -C 30M -@63s ./somefile
.Ed
.Sh SEE ALSO
+.Xr msdosfs 4 ,
.Xr gpart 8 ,
.Xr newfs 8
.Sh HISTORY
diff --git a/sbin/newfs_msdos/newfs_msdos.c b/sbin/newfs_msdos/newfs_msdos.c
index bac250e7dd05..312a862d9113 100644
--- a/sbin/newfs_msdos/newfs_msdos.c
+++ b/sbin/newfs_msdos/newfs_msdos.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
@@ -27,11 +27,6 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/stat.h>
#include <err.h>
@@ -51,7 +46,7 @@ static const char rcsid[] =
static u_int argtou(const char *, u_int, u_int, const char *);
static off_t argtooff(const char *, const char *);
-static void usage(void);
+static void usage(void) __dead2;
static time_t
get_tstamp(const char *b)
diff --git a/sbin/nfsiod/Makefile b/sbin/nfsiod/Makefile
index 912dd19e25cb..974c7de3362b 100644
--- a/sbin/nfsiod/Makefile
+++ b/sbin/nfsiod/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
PROG= nfsiod
MAN= nfsiod.8
diff --git a/sbin/nfsiod/Makefile.depend b/sbin/nfsiod/Makefile.depend
index cae7e645ef6a..93249906da4f 100644
--- a/sbin/nfsiod/Makefile.depend
+++ b/sbin/nfsiod/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
lib/${CSU_DIR} \
lib/libc \
diff --git a/sbin/nfsiod/nfsiod.8 b/sbin/nfsiod/nfsiod.8
index 826b5f18e303..7abe5a832bbf 100644
--- a/sbin/nfsiod/nfsiod.8
+++ b/sbin/nfsiod/nfsiod.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" From: @(#)nfsiod.8 8.2 (Berkeley) 2/22/94
-.\" $FreeBSD$
-.\"
.Dd December 26, 2009
.Dt NFSIOD 8
.Os
diff --git a/sbin/nfsiod/nfsiod.c b/sbin/nfsiod/nfsiod.c
index b518d94d384c..c34671a8c551 100644
--- a/sbin/nfsiod/nfsiod.c
+++ b/sbin/nfsiod/nfsiod.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif
-
-#ifndef lint
-static char sccsid[] = "@(#)nfsiod.c 8.4 (Berkeley) 5/3/95";
-#endif
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/syslog.h>
#include <sys/wait.h>
diff --git a/sbin/nos-tun/Makefile b/sbin/nos-tun/Makefile
index 9f1024f41e8e..bef6878b7f25 100644
--- a/sbin/nos-tun/Makefile
+++ b/sbin/nos-tun/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PROG= nos-tun
MAN= nos-tun.8
WARNS?= 3
diff --git a/sbin/nos-tun/Makefile.depend b/sbin/nos-tun/Makefile.depend
index d5ed563ecfc8..344a5d0e9310 100644
--- a/sbin/nos-tun/Makefile.depend
+++ b/sbin/nos-tun/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
diff --git a/sbin/nos-tun/nos-tun.8 b/sbin/nos-tun/nos-tun.8
index ca235d7c5d8d..f5e2352254a3 100644
--- a/sbin/nos-tun/nos-tun.8
+++ b/sbin/nos-tun/nos-tun.8
@@ -6,8 +6,6 @@
.\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
.\" ----------------------------------------------------------------------------
.\"
-.\" $FreeBSD$
-.\"
.Dd October 5, 2016
.Dt NOS-TUN 8
.Os
diff --git a/sbin/nos-tun/nos-tun.c b/sbin/nos-tun/nos-tun.c
index 76e11bae75c4..ca0e33b2509a 100644
--- a/sbin/nos-tun/nos-tun.c
+++ b/sbin/nos-tun/nos-tun.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1996, Nickolay Dudorov
* All rights reserved.
@@ -57,11 +57,6 @@
*
*/
-#ifndef lint
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
@@ -89,7 +84,7 @@ static struct ifreq ifrq;
int net; /* socket descriptor */
int tun; /* tunnel descriptor */
-static void usage(void);
+static void usage(void) __dead2;
static int
Set_address(char *addr, struct sockaddr_in *sin)
@@ -146,7 +141,7 @@ tun_open(char *dev_name, struct sockaddr *ouraddr, char *theiraddr)
* when tunN have no addresses, so - log and ignore it.
*
*/
- if (ioctl(s, SIOCDIFADDR, &ifra) < 0) {
+ if (ioctl(s, SIOCDIFADDR, &ifrq) < 0) {
syslog(LOG_ERR,"SIOCDIFADDR - %m");
}
@@ -225,10 +220,8 @@ Finish(int signum)
/*
* Delete addresses for interface
*/
- bzero(&ifra.ifra_addr, sizeof(ifra.ifra_addr));
- bzero(&ifra.ifra_broadaddr, sizeof(ifra.ifra_addr));
- bzero(&ifra.ifra_mask, sizeof(ifra.ifra_addr));
- if (ioctl(s, SIOCDIFADDR, &ifra) < 0) {
+ bzero(&ifrq.ifr_addr, sizeof(ifrq.ifr_addr));
+ if (ioctl(s, SIOCDIFADDR, &ifrq) < 0) {
syslog(LOG_ERR,"can't delete interface's addresses - %m");
}
closing_fds:
diff --git a/sbin/nvmecontrol/Makefile b/sbin/nvmecontrol/Makefile
index b5ceb350ed0d..cf9c23548e36 100644
--- a/sbin/nvmecontrol/Makefile
+++ b/sbin/nvmecontrol/Makefile
@@ -1,18 +1,36 @@
-# $FreeBSD$
-
.include <src.opts.mk>
-PACKAGE=runtime
+PACKAGE=nvme-tools
PROG= nvmecontrol
-SRCS= comnd.c nvmecontrol.c
-SRCS+= devlist.c firmware.c format.c identify.c logpage.c ns.c nsid.c
-SRCS+= perftest.c power.c reset.c resv.c sanitize.c
+SRCS+= comnd.c
+SRCS+= connect.c
+SRCS+= devlist.c
+SRCS+= disconnect.c
+SRCS+= discover.c
+SRCS+= fabrics.c
+SRCS+= firmware.c
+SRCS+= format.c
+SRCS+= identify.c
+SRCS+= identify_ext.c
+SRCS+= logpage.c
+SRCS+= nc_util.c
+SRCS+= ns.c
+SRCS+= nsid.c
+SRCS+= nvme_util.c
+SRCS+= nvmecontrol.c
SRCS+= passthru.c
-SRCS+= identify_ext.c nvme_util.c nc_util.c
+SRCS+= perftest.c
+SRCS+= power.c
+SRCS+= reconnect.c
+SRCS+= reset.c
+SRCS+= resv.c
+SRCS+= sanitize.c
SRCS+= selftest.c
+SRCS+= telemetry.c
+CFLAGS+= -I${SRCTOP}/lib/libnvmf
MAN= nvmecontrol.8
LDFLAGS+= -rdynamic
-LIBADD+= util
+LIBADD+= nvmf sbuf util
SUBDIR= modules
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/sbin/nvmecontrol/Makefile.depend b/sbin/nvmecontrol/Makefile.depend
index 6cfaab1c3644..4eaed14a78cc 100644
--- a/sbin/nvmecontrol/Makefile.depend
+++ b/sbin/nvmecontrol/Makefile.depend
@@ -1,13 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libnvmf \
+ lib/libutil \
.include <dirdeps.mk>
diff --git a/sbin/nvmecontrol/comnd.c b/sbin/nvmecontrol/comnd.c
index 0c53c54b9818..112857f58943 100644
--- a/sbin/nvmecontrol/comnd.c
+++ b/sbin/nvmecontrol/comnd.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Netflix, Inc
*
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
diff --git a/sbin/nvmecontrol/comnd.h b/sbin/nvmecontrol/comnd.h
index 91c97d4a873f..a1765233d2b2 100644
--- a/sbin/nvmecontrol/comnd.h
+++ b/sbin/nvmecontrol/comnd.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Netflix, Inc
*
@@ -23,8 +23,6 @@
* 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 COMND_H
diff --git a/sbin/nvmecontrol/connect.c b/sbin/nvmecontrol/connect.c
new file mode 100644
index 000000000000..3d6d12bf2c48
--- /dev/null
+++ b/sbin/nvmecontrol/connect.c
@@ -0,0 +1,313 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023-2024 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <sys/socket.h>
+#include <err.h>
+#include <libnvmf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "comnd.h"
+#include "fabrics.h"
+
+/*
+ * Settings that are currently hardcoded but could be exposed to the
+ * user via additional command line options:
+ *
+ * - ADMIN queue entries
+ * - MaxR2T
+ */
+
+static struct options {
+ const char *transport;
+ const char *address;
+ const char *cntlid;
+ const char *subnqn;
+ const char *hostnqn;
+ uint32_t kato;
+ uint32_t reconnect_delay;
+ uint32_t controller_loss_timeout;
+ uint16_t num_io_queues;
+ uint16_t queue_size;
+ bool data_digests;
+ bool flow_control;
+ bool header_digests;
+} opt = {
+ .transport = "tcp",
+ .address = NULL,
+ .cntlid = "dynamic",
+ .subnqn = NULL,
+ .hostnqn = NULL,
+ .kato = NVMF_KATO_DEFAULT / 1000,
+ .reconnect_delay = NVMF_DEFAULT_RECONNECT_DELAY,
+ .controller_loss_timeout = NVMF_DEFAULT_CONTROLLER_LOSS,
+ .num_io_queues = 1,
+ .queue_size = 0,
+ .data_digests = false,
+ .flow_control = false,
+ .header_digests = false,
+};
+
+static void
+tcp_association_params(struct nvmf_association_params *params)
+{
+ params->tcp.pda = 0;
+ params->tcp.header_digests = opt.header_digests;
+ params->tcp.data_digests = opt.data_digests;
+ /* XXX */
+ params->tcp.maxr2t = 1;
+}
+
+static int
+connect_nvm_controller(enum nvmf_trtype trtype, int adrfam, const char *address,
+ const char *port, uint16_t cntlid, const char *subnqn,
+ const struct nvme_discovery_log_entry *dle)
+{
+ struct nvme_controller_data cdata;
+ struct nvme_discovery_log_entry dle_thunk;
+ struct nvmf_association_params aparams;
+ struct nvmf_qpair *admin, **io;
+ const char *hostnqn;
+ int error;
+
+ memset(&aparams, 0, sizeof(aparams));
+ aparams.sq_flow_control = opt.flow_control;
+ switch (trtype) {
+ case NVMF_TRTYPE_TCP:
+ tcp_association_params(&aparams);
+ break;
+ default:
+ warnx("Unsupported transport %s", nvmf_transport_type(trtype));
+ return (EX_UNAVAILABLE);
+ }
+
+ hostnqn = opt.hostnqn;
+ if (hostnqn == NULL)
+ hostnqn = nvmf_default_hostnqn();
+ io = calloc(opt.num_io_queues, sizeof(*io));
+ error = connect_nvm_queues(&aparams, trtype, adrfam, address, port,
+ cntlid, subnqn, hostnqn, opt.kato * 1000, &admin, io,
+ opt.num_io_queues, opt.queue_size, &cdata);
+ if (error != 0) {
+ free(io);
+ return (error);
+ }
+
+ if (dle == NULL) {
+ error = nvmf_init_dle_from_admin_qp(admin, &cdata, &dle_thunk);
+ if (error != 0) {
+ warnc(error, "Failed to generate handoff parameters");
+ disconnect_nvm_queues(admin, io, opt.num_io_queues);
+ free(io);
+ return (EX_IOERR);
+ }
+ dle = &dle_thunk;
+ }
+
+ error = nvmf_handoff_host(dle, hostnqn, admin, opt.num_io_queues, io,
+ &cdata, opt.reconnect_delay, opt.controller_loss_timeout);
+ if (error != 0) {
+ warnc(error, "Failed to handoff queues to kernel");
+ free(io);
+ return (EX_IOERR);
+ }
+ free(io);
+ return (0);
+}
+
+static void
+connect_discovery_entry(struct nvme_discovery_log_entry *entry)
+{
+ int adrfam;
+
+ switch (entry->trtype) {
+ case NVMF_TRTYPE_TCP:
+ switch (entry->adrfam) {
+ case NVMF_ADRFAM_IPV4:
+ adrfam = AF_INET;
+ break;
+ case NVMF_ADRFAM_IPV6:
+ adrfam = AF_INET6;
+ break;
+ default:
+ warnx("Skipping unsupported address family for %s",
+ entry->subnqn);
+ return;
+ }
+ switch (entry->tsas.tcp.sectype) {
+ case NVME_TCP_SECURITY_NONE:
+ break;
+ default:
+ warnx("Skipping unsupported TCP security type for %s",
+ entry->subnqn);
+ return;
+ }
+ break;
+ default:
+ warnx("Skipping unsupported transport %s for %s",
+ nvmf_transport_type(entry->trtype), entry->subnqn);
+ return;
+ }
+
+ /*
+ * XXX: Track portids and avoid duplicate connections for a
+ * given (subnqn,portid)?
+ */
+
+ /* XXX: Should this make use of entry->aqsz in some way? */
+ connect_nvm_controller(entry->trtype, adrfam, entry->traddr,
+ entry->trsvcid, entry->cntlid, entry->subnqn, entry);
+}
+
+static void
+connect_discovery_log_page(struct nvmf_qpair *qp)
+{
+ struct nvme_discovery_log *log;
+ int error;
+
+ error = nvmf_host_fetch_discovery_log_page(qp, &log);
+ if (error != 0)
+ errc(EX_IOERR, error, "Failed to fetch discovery log page");
+
+ for (u_int i = 0; i < log->numrec; i++)
+ connect_discovery_entry(&log->entries[i]);
+ free(log);
+}
+
+static void
+discover_controllers(enum nvmf_trtype trtype, const char *address,
+ const char *port)
+{
+ struct nvmf_qpair *qp;
+
+ qp = connect_discovery_adminq(trtype, address, port, opt.hostnqn);
+
+ connect_discovery_log_page(qp);
+
+ nvmf_free_qpair(qp);
+}
+
+static void
+connect_fn(const struct cmd *f, int argc, char *argv[])
+{
+ enum nvmf_trtype trtype;
+ const char *address, *port;
+ char *tofree;
+ u_long cntlid;
+ int error;
+
+ if (arg_parse(argc, argv, f))
+ return;
+
+ if (opt.num_io_queues <= 0)
+ errx(EX_USAGE, "Invalid number of I/O queues");
+
+ if (strcasecmp(opt.transport, "tcp") == 0) {
+ trtype = NVMF_TRTYPE_TCP;
+ } else
+ errx(EX_USAGE, "Unsupported or invalid transport");
+
+ nvmf_parse_address(opt.address, &address, &port, &tofree);
+ if (port == NULL)
+ errx(EX_USAGE, "Explicit port required");
+
+ cntlid = nvmf_parse_cntlid(opt.cntlid);
+
+ error = connect_nvm_controller(trtype, AF_UNSPEC, address, port, cntlid,
+ opt.subnqn, NULL);
+ if (error != 0)
+ exit(error);
+
+ free(tofree);
+}
+
+static void
+connect_all_fn(const struct cmd *f, int argc, char *argv[])
+{
+ enum nvmf_trtype trtype;
+ const char *address, *port;
+ char *tofree;
+
+ if (arg_parse(argc, argv, f))
+ return;
+
+ if (opt.num_io_queues <= 0)
+ errx(EX_USAGE, "Invalid number of I/O queues");
+
+ if (strcasecmp(opt.transport, "tcp") == 0) {
+ trtype = NVMF_TRTYPE_TCP;
+ } else
+ errx(EX_USAGE, "Unsupported or invalid transport");
+
+ nvmf_parse_address(opt.address, &address, &port, &tofree);
+ discover_controllers(trtype, address, port);
+
+ free(tofree);
+}
+
+static const struct opts connect_opts[] = {
+#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
+ OPT("transport", 't', arg_string, opt, transport,
+ "Transport type"),
+ OPT("cntlid", 'c', arg_string, opt, cntlid,
+ "Controller ID"),
+ OPT("nr-io-queues", 'i', arg_uint16, opt, num_io_queues,
+ "Number of I/O queues"),
+ OPT("queue-size", 'Q', arg_uint16, opt, queue_size,
+ "Number of entries in each I/O queue"),
+ OPT("keep-alive-tmo", 'k', arg_uint32, opt, kato,
+ "Keep Alive timeout (in seconds)"),
+ OPT("reconnect-delay", 'r', arg_uint32, opt, reconnect_delay,
+ "Delay between reconnect attempts after connection loss "
+ "(in seconds)"),
+ OPT("ctrl-loss-tmo", 'l', arg_uint32, opt, controller_loss_timeout,
+ "Controller loss timeout after connection loss (in seconds)"),
+ OPT("hostnqn", 'q', arg_string, opt, hostnqn,
+ "Host NQN"),
+ OPT("flow_control", 'F', arg_none, opt, flow_control,
+ "Request SQ flow control"),
+ OPT("hdr_digests", 'g', arg_none, opt, header_digests,
+ "Enable TCP PDU header digests"),
+ OPT("data_digests", 'G', arg_none, opt, data_digests,
+ "Enable TCP PDU data digests"),
+ { NULL, 0, arg_none, NULL, NULL }
+};
+#undef OPT
+
+static const struct args connect_args[] = {
+ { arg_string, &opt.address, "address" },
+ { arg_string, &opt.subnqn, "SubNQN" },
+ { arg_none, NULL, NULL },
+};
+
+static const struct args connect_all_args[] = {
+ { arg_string, &opt.address, "address" },
+ { arg_none, NULL, NULL },
+};
+
+static struct cmd connect_cmd = {
+ .name = "connect",
+ .fn = connect_fn,
+ .descr = "Connect to a fabrics controller",
+ .ctx_size = sizeof(opt),
+ .opts = connect_opts,
+ .args = connect_args,
+};
+
+static struct cmd connect_all_cmd = {
+ .name = "connect-all",
+ .fn = connect_all_fn,
+ .descr = "Discover and connect to fabrics controllers",
+ .ctx_size = sizeof(opt),
+ .opts = connect_opts,
+ .args = connect_all_args,
+};
+
+CMD_COMMAND(connect_cmd);
+CMD_COMMAND(connect_all_cmd);
diff --git a/sbin/nvmecontrol/devlist.c b/sbin/nvmecontrol/devlist.c
index 35dd1b47a811..7bf6bc6f097c 100644
--- a/sbin/nvmecontrol/devlist.c
+++ b/sbin/nvmecontrol/devlist.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
@@ -26,20 +26,23 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
+#include <sys/nv.h>
+#include <sys/time.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <stdbool.h>
+#include <libnvmf.h>
+#include <libutil.h>
#include <paths.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
+#include <time.h>
#include <unistd.h>
#include "nvmecontrol.h"
@@ -51,10 +54,27 @@ __FBSDID("$FreeBSD$");
static cmd_fn_t devlist;
+static struct options {
+ bool human;
+} opt = {
+ .human = false,
+};
+
+static const struct opts devlist_opts[] = {
+#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
+ OPT("human", 'h', arg_none, opt, human,
+ "Show human readable disk size"),
+ { NULL, 0, arg_none, NULL, NULL }
+};
+#undef OPT
+
static struct cmd devlist_cmd = {
.name = "devlist",
.fn = devlist,
- .descr = "List NVMe controllers and namespaces"
+ .descr = "List NVMe controllers and namespaces",
+ .ctx_size = sizeof(opt),
+ .opts = devlist_opts,
+ .args = NULL,
};
CMD_COMMAND(devlist_cmd);
@@ -66,23 +86,151 @@ ns_get_sector_size(struct nvme_namespace_data *nsdata)
{
uint8_t flbas_fmt, lbads;
- flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
- NVME_NS_DATA_FLBAS_FORMAT_MASK;
- lbads = (nsdata->lbaf[flbas_fmt] >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
- NVME_NS_DATA_LBAF_LBADS_MASK;
+ flbas_fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, nsdata->flbas);
+ lbads = NVMEV(NVME_NS_DATA_LBAF_LBADS, nsdata->lbaf[flbas_fmt]);
return (1 << lbads);
}
static void
-devlist(const struct cmd *f, int argc, char *argv[])
+scan_namespace(int fd, int ctrlr, uint32_t nsid)
{
- struct nvme_controller_data cdata;
- struct nvme_namespace_data nsdata;
+ struct nvme_namespace_data nsdata;
char name[64];
+ uint8_t buf[7];
+ uint64_t size;
+
+ if (read_namespace_data(fd, nsid, &nsdata) != 0)
+ return;
+ if (nsdata.nsze == 0)
+ return;
+ snprintf(name, sizeof(name), "%s%d%s%d", NVME_CTRLR_PREFIX, ctrlr,
+ NVME_NS_PREFIX, nsid);
+ size = nsdata.nsze * (uint64_t)ns_get_sector_size(&nsdata);
+ if (opt.human) {
+ humanize_number(buf, sizeof(buf), size, "B",
+ HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+ printf(" %10s (%s)\n", name, buf);
+ } else {
+ printf(" %10s (%juMB)\n", name, (uintmax_t)size / 1024 / 1024);
+ }
+}
+
+static bool
+print_controller_info(const char *name, int fd)
+{
+ static struct timespec now;
+ struct nvme_controller_data cdata;
+ struct timespec last_disconnect, delta;
uint8_t mn[64];
- uint32_t i;
- int ctrlr, fd, found, ret;
+ nvlist_t *nvl;
+ const nvlist_t *nvl_ts;
+ bool connected;
+
+ /*
+ * If the controller doesn't support connection status, assume
+ * it is connected.
+ */
+ if (nvmf_connection_status(fd, &nvl) != 0) {
+ connected = true;
+ nvl = NULL;
+ } else {
+ connected = nvlist_get_bool(nvl, "connected");
+ }
+
+ if (connected) {
+ if (read_controller_data(fd, &cdata) != 0) {
+ nvlist_destroy(nvl);
+ return (false);
+ }
+ } else {
+ if (ioctl(fd, NVME_GET_CONTROLLER_DATA, &cdata) == -1) {
+ nvlist_destroy(nvl);
+ return (false);
+ }
+ }
+
+ nvme_strvis(mn, cdata.mn, sizeof(mn), NVME_MODEL_NUMBER_LENGTH);
+ printf("%6s: %s", name, mn);
+ if (connected) {
+ const struct nvme_discovery_log_entry *dle;
+ size_t len;
+
+ nvlist_destroy(nvl);
+ if (nvmf_reconnect_params(fd, &nvl) == 0) {
+ dle = nvlist_get_binary(nvl, "dle", &len);
+ if (len == sizeof(*dle)) {
+ printf(" (connected via %s %.*s:%.*s)",
+ nvmf_transport_type(dle->trtype),
+ (int)sizeof(dle->traddr), dle->traddr,
+ (int)sizeof(dle->trsvcid), dle->trsvcid);
+ }
+ } else {
+ nvl = NULL;
+ }
+ } else {
+ if (now.tv_sec == 0)
+ clock_gettime(CLOCK_REALTIME, &now);
+
+ nvl_ts = nvlist_get_nvlist(nvl, "last_disconnect");
+ last_disconnect.tv_sec = nvlist_get_number(nvl_ts, "tv_sec");
+ last_disconnect.tv_nsec = nvlist_get_number(nvl_ts, "tv_nsec");
+ timespecsub(&now, &last_disconnect, &delta);
+ printf(" (disconnected for %ju seconds)",
+ (uintmax_t)delta.tv_sec);
+ }
+ printf("\n");
+ nvlist_destroy(nvl);
+ return (connected);
+}
+
+static bool
+scan_controller(int ctrlr)
+{
+ struct nvme_ns_list nslist;
+ char name[64];
+ uint32_t nsid;
+ int fd, ret;
+
+ snprintf(name, sizeof(name), "%s%d", NVME_CTRLR_PREFIX, ctrlr);
+
+ ret = open_dev(name, &fd, 0, 0);
+
+ if (ret == EACCES) {
+ warnx("could not open "_PATH_DEV"%s\n", name);
+ return (false);
+ } else if (ret != 0)
+ return (false);
+
+ if (!print_controller_info(name, fd)) {
+ close(fd);
+ return (true);
+ }
+
+ nsid = 0;
+ for (;;) {
+ if (read_active_namespaces(fd, nsid, &nslist) != 0)
+ break;
+ for (u_int i = 0; i < nitems(nslist.ns); i++) {
+ nsid = nslist.ns[i];
+ if (nsid == 0) {
+ break;
+ }
+
+ scan_namespace(fd, ctrlr, nsid);
+ }
+ if (nsid == 0 || nsid >= NVME_GLOBAL_NAMESPACE_TAG - 1)
+ break;
+ }
+
+ close(fd);
+ return (true);
+}
+
+static void
+devlist(const struct cmd *f, int argc, char *argv[])
+{
+ int ctrlr, found;
if (arg_parse(argc, argv, f))
return;
@@ -92,37 +240,8 @@ devlist(const struct cmd *f, int argc, char *argv[])
while (ctrlr < NVME_MAX_UNIT) {
ctrlr++;
- sprintf(name, "%s%d", NVME_CTRLR_PREFIX, ctrlr);
-
- ret = open_dev(name, &fd, 0, 0);
-
- if (ret == EACCES) {
- warnx("could not open "_PATH_DEV"%s\n", name);
- continue;
- } else if (ret != 0)
- continue;
-
- found++;
- if (read_controller_data(fd, &cdata))
- continue;
- nvme_strvis(mn, cdata.mn, sizeof(mn), NVME_MODEL_NUMBER_LENGTH);
- printf("%6s: %s\n", name, mn);
-
- for (i = 0; i < cdata.nn; i++) {
- if (read_namespace_data(fd, i + 1, &nsdata))
- continue;
- if (nsdata.nsze == 0)
- continue;
- sprintf(name, "%s%d%s%d", NVME_CTRLR_PREFIX, ctrlr,
- NVME_NS_PREFIX, i + 1);
- printf(" %10s (%lldMB)\n",
- name,
- nsdata.nsze *
- (long long)ns_get_sector_size(&nsdata) /
- 1024 / 1024);
- }
-
- close(fd);
+ if (scan_controller(ctrlr))
+ found++;
}
if (found == 0) {
diff --git a/sbin/nvmecontrol/disconnect.c b/sbin/nvmecontrol/disconnect.c
new file mode 100644
index 000000000000..b1b6af6271e8
--- /dev/null
+++ b/sbin/nvmecontrol/disconnect.c
@@ -0,0 +1,82 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023-2024 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <err.h>
+#include <libnvmf.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "nvmecontrol.h"
+
+static struct options {
+ const char *dev;
+} opt = {
+ .dev = NULL
+};
+
+static const struct args args[] = {
+ { arg_string, &opt.dev, "controller-id|namespace-id|SubNQN" },
+ { arg_none, NULL, NULL },
+};
+
+static void
+disconnect(const struct cmd *f, int argc, char *argv[])
+{
+ int error, fd;
+ char *path;
+
+ if (arg_parse(argc, argv, f))
+ return;
+ if (nvmf_nqn_valid(opt.dev)) {
+ error = nvmf_disconnect_host(opt.dev);
+ if (error != 0)
+ errc(EX_IOERR, error, "failed to disconnect from %s",
+ opt.dev);
+ } else {
+ open_dev(opt.dev, &fd, 1, 1);
+ get_nsid(fd, &path, NULL);
+ close(fd);
+
+ error = nvmf_disconnect_host(path);
+ if (error != 0)
+ errc(EX_IOERR, error, "failed to disconnect from %s",
+ path);
+ }
+
+ exit(0);
+}
+
+static void
+disconnect_all(const struct cmd *f __unused, int argc __unused,
+ char *argv[] __unused)
+{
+ int error;
+
+ error = nvmf_disconnect_all();
+ if (error != 0)
+ errc(EX_IOERR, error,
+ "failed to disconnect from remote controllers");
+
+ exit(0);
+}
+
+static struct cmd disconnect_cmd = {
+ .name = "disconnect",
+ .fn = disconnect,
+ .descr = "Disconnect from a fabrics controller",
+ .args = args,
+};
+
+static struct cmd disconnect_all_cmd = {
+ .name = "disconnect-all",
+ .fn = disconnect_all,
+ .descr = "Disconnect from all fabrics controllers",
+};
+
+CMD_COMMAND(disconnect_cmd);
+CMD_COMMAND(disconnect_all_cmd);
diff --git a/sbin/nvmecontrol/discover.c b/sbin/nvmecontrol/discover.c
new file mode 100644
index 000000000000..c782ebeb7452
--- /dev/null
+++ b/sbin/nvmecontrol/discover.c
@@ -0,0 +1,300 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023-2024 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <err.h>
+#include <libnvmf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include "comnd.h"
+#include "fabrics.h"
+#include "nvmecontrol_ext.h"
+
+static struct options {
+ const char *transport;
+ const char *address;
+ const char *hostnqn;
+ bool verbose;
+} opt = {
+ .transport = "tcp",
+ .address = NULL,
+ .hostnqn = NULL,
+ .verbose = false,
+};
+
+static void
+identify_controller(struct nvmf_qpair *qp)
+{
+ struct nvme_controller_data cdata;
+ int error;
+
+ error = nvmf_host_identify_controller(qp, &cdata);
+ if (error != 0)
+ errc(EX_IOERR, error, "Failed to fetch controller data");
+ nvme_print_controller(&cdata);
+}
+
+static const char *
+nvmf_address_family(uint8_t adrfam)
+{
+ static char buf[8];
+
+ switch (adrfam) {
+ case NVMF_ADRFAM_IPV4:
+ return ("AF_INET");
+ case NVMF_ADRFAM_IPV6:
+ return ("AF_INET6");
+ case NVMF_ADRFAM_IB:
+ return ("InfiniBand");
+ case NVMF_ADRFAM_FC:
+ return ("Fibre Channel");
+ case NVMF_ADRFAM_INTRA_HOST:
+ return ("Intra-host");
+ default:
+ snprintf(buf, sizeof(buf), "0x%02x\n", adrfam);
+ return (buf);
+ }
+}
+
+static const char *
+nvmf_subsystem_type(uint8_t subtype)
+{
+ static char buf[8];
+
+ switch (subtype) {
+ case NVMF_SUBTYPE_DISCOVERY:
+ return ("Discovery");
+ case NVMF_SUBTYPE_NVME:
+ return ("NVMe");
+ default:
+ snprintf(buf, sizeof(buf), "0x%02x\n", subtype);
+ return (buf);
+ }
+}
+
+static const char *
+nvmf_secure_channel(uint8_t treq)
+{
+ switch (treq & 0x03) {
+ case NVMF_TREQ_SECURE_CHANNEL_NOT_SPECIFIED:
+ return ("Not specified");
+ case NVMF_TREQ_SECURE_CHANNEL_REQUIRED:
+ return ("Required");
+ case NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED:
+ return ("Not required");
+ default:
+ return ("0x03");
+ }
+}
+
+static const char *
+nvmf_controller_id(uint16_t cntlid)
+{
+ static char buf[8];
+
+ switch (cntlid) {
+ case NVMF_CNTLID_DYNAMIC:
+ return ("Dynamic");
+ case NVMF_CNTLID_STATIC_ANY:
+ return ("Static");
+ default:
+ snprintf(buf, sizeof(buf), "%u", cntlid);
+ return (buf);
+ }
+}
+
+static const char *
+nvmf_rdma_service_type(uint8_t qptype)
+{
+ static char buf[8];
+
+ switch (qptype) {
+ case NVMF_RDMA_QPTYPE_RELIABLE_CONNECTED:
+ return ("Reliable connected");
+ case NVMF_RDMA_QPTYPE_RELIABLE_DATAGRAM:
+ return ("Reliable datagram");
+ default:
+ snprintf(buf, sizeof(buf), "0x%02x\n", qptype);
+ return (buf);
+ }
+}
+
+static const char *
+nvmf_rdma_provider_type(uint8_t prtype)
+{
+ static char buf[8];
+
+ switch (prtype) {
+ case NVMF_RDMA_PRTYPE_NONE:
+ return ("None");
+ case NVMF_RDMA_PRTYPE_IB:
+ return ("InfiniBand");
+ case NVMF_RDMA_PRTYPE_ROCE:
+ return ("RoCE (v1)");
+ case NVMF_RDMA_PRTYPE_ROCE2:
+ return ("RoCE (v2)");
+ case NVMF_RDMA_PRTYPE_IWARP:
+ return ("iWARP");
+ default:
+ snprintf(buf, sizeof(buf), "0x%02x\n", prtype);
+ return (buf);
+ }
+}
+
+static const char *
+nvmf_rdma_cms(uint8_t cms)
+{
+ static char buf[8];
+
+ switch (cms) {
+ case NVMF_RDMA_CMS_RDMA_CM:
+ return ("RDMA_IP_CM");
+ default:
+ snprintf(buf, sizeof(buf), "0x%02x\n", cms);
+ return (buf);
+ }
+}
+
+static const char *
+nvmf_tcp_security_type(uint8_t sectype)
+{
+ static char buf[8];
+
+ switch (sectype) {
+ case NVME_TCP_SECURITY_NONE:
+ return ("None");
+ case NVME_TCP_SECURITY_TLS_1_2:
+ return ("TLS 1.2");
+ case NVME_TCP_SECURITY_TLS_1_3:
+ return ("TLS 1.3");
+ default:
+ snprintf(buf, sizeof(buf), "0x%02x\n", sectype);
+ return (buf);
+ }
+}
+
+static void
+print_discovery_entry(u_int i, struct nvme_discovery_log_entry *entry)
+{
+ printf("Entry %02d\n", i + 1);
+ printf("========\n");
+ printf(" Transport type: %s\n",
+ nvmf_transport_type(entry->trtype));
+ printf(" Address family: %s\n",
+ nvmf_address_family(entry->adrfam));
+ printf(" Subsystem type: %s\n",
+ nvmf_subsystem_type(entry->subtype));
+ printf(" SQ flow control: %s\n",
+ (entry->treq & (1 << 2)) == 0 ? "required" : "optional");
+ printf(" Secure Channel: %s\n", nvmf_secure_channel(entry->treq));
+ printf(" Port ID: %u\n", entry->portid);
+ printf(" Controller ID: %s\n",
+ nvmf_controller_id(entry->cntlid));
+ printf(" Max Admin SQ Size: %u\n", entry->aqsz);
+ printf(" Sub NQN: %s\n", entry->subnqn);
+ printf(" Transport address: %s\n", entry->traddr);
+ printf(" Service identifier: %s\n", entry->trsvcid);
+ switch (entry->trtype) {
+ case NVMF_TRTYPE_RDMA:
+ printf(" RDMA Service Type: %s\n",
+ nvmf_rdma_service_type(entry->tsas.rdma.rdma_qptype));
+ printf(" RDMA Provider Type: %s\n",
+ nvmf_rdma_provider_type(entry->tsas.rdma.rdma_prtype));
+ printf(" RDMA CMS: %s\n",
+ nvmf_rdma_cms(entry->tsas.rdma.rdma_cms));
+ printf(" Partition key: %u\n",
+ entry->tsas.rdma.rdma_pkey);
+ break;
+ case NVMF_TRTYPE_TCP:
+ printf(" Security Type: %s\n",
+ nvmf_tcp_security_type(entry->tsas.tcp.sectype));
+ break;
+ }
+}
+
+static void
+dump_discovery_log_page(struct nvmf_qpair *qp)
+{
+ struct nvme_discovery_log *log;
+ int error;
+
+ error = nvmf_host_fetch_discovery_log_page(qp, &log);
+ if (error != 0)
+ errc(EX_IOERR, error, "Failed to fetch discovery log page");
+
+ printf("Discovery\n");
+ printf("=========\n");
+ if (log->numrec == 0) {
+ printf("No entries found\n");
+ } else {
+ for (u_int i = 0; i < log->numrec; i++)
+ print_discovery_entry(i, &log->entries[i]);
+ }
+ free(log);
+}
+
+static void
+discover(const struct cmd *f, int argc, char *argv[])
+{
+ enum nvmf_trtype trtype;
+ struct nvmf_qpair *qp;
+ const char *address, *port;
+ char *tofree;
+
+ if (arg_parse(argc, argv, f))
+ return;
+
+ if (strcasecmp(opt.transport, "tcp") == 0) {
+ trtype = NVMF_TRTYPE_TCP;
+ } else
+ errx(EX_USAGE, "Unsupported or invalid transport");
+
+ nvmf_parse_address(opt.address, &address, &port, &tofree);
+ qp = connect_discovery_adminq(trtype, address, port, opt.hostnqn);
+ free(tofree);
+
+ /* Use Identify to fetch controller data */
+ if (opt.verbose) {
+ identify_controller(qp);
+ printf("\n");
+ }
+
+ /* Fetch Log pages */
+ dump_discovery_log_page(qp);
+
+ nvmf_free_qpair(qp);
+}
+
+static const struct opts discover_opts[] = {
+#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
+ OPT("transport", 't', arg_string, opt, transport,
+ "Transport type"),
+ OPT("hostnqn", 'q', arg_string, opt, hostnqn,
+ "Host NQN"),
+ OPT("verbose", 'v', arg_none, opt, verbose,
+ "Display the discovery controller's controller data"),
+ { NULL, 0, arg_none, NULL, NULL }
+};
+#undef OPT
+
+static const struct args discover_args[] = {
+ { arg_string, &opt.address, "address" },
+ { arg_none, NULL, NULL },
+};
+
+static struct cmd discover_cmd = {
+ .name = "discover",
+ .fn = discover,
+ .descr = "List discovery log pages from a fabrics controller",
+ .ctx_size = sizeof(opt),
+ .opts = discover_opts,
+ .args = discover_args,
+};
+
+CMD_COMMAND(discover_cmd);
diff --git a/sbin/nvmecontrol/fabrics.c b/sbin/nvmecontrol/fabrics.c
new file mode 100644
index 000000000000..5fdbf68127d4
--- /dev/null
+++ b/sbin/nvmecontrol/fabrics.c
@@ -0,0 +1,559 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023-2024 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <err.h>
+#include <libnvmf.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "fabrics.h"
+
+/*
+ * Subroutines shared by several Fabrics commands.
+ */
+static char nqn[NVMF_NQN_MAX_LEN];
+static uint8_t hostid[16];
+static bool hostid_initted = false;
+
+static bool
+init_hostid(void)
+{
+ int error;
+
+ if (hostid_initted)
+ return (true);
+
+ error = nvmf_hostid_from_hostuuid(hostid);
+ if (error != 0) {
+ warnc(error, "Failed to generate hostid");
+ return (false);
+ }
+ error = nvmf_nqn_from_hostuuid(nqn);
+ if (error != 0) {
+ warnc(error, "Failed to generate host NQN");
+ return (false);
+ }
+
+ hostid_initted = true;
+ return (true);
+}
+
+const char *
+nvmf_default_hostnqn(void)
+{
+ if (!init_hostid())
+ exit(EX_IOERR);
+ return (nqn);
+}
+
+void
+nvmf_parse_address(const char *in_address, const char **address,
+ const char **port, char **tofree)
+{
+ char *cp;
+
+ /*
+ * Accepts the following address formats:
+ *
+ * [IPv6 address]:port
+ * IPv4 address:port
+ * hostname:port
+ * [IPv6 address]
+ * IPv6 address
+ * IPv4 address
+ * hostname
+ */
+ if (in_address[0] == '[') {
+ /* IPv6 address in square brackets. */
+ cp = strchr(in_address + 1, ']');
+ if (cp == NULL || cp == in_address + 1)
+ errx(EX_USAGE, "Invalid address %s", in_address);
+ *tofree = strndup(in_address + 1, cp - (in_address + 1));
+ *address = *tofree;
+
+ /* Skip over ']' */
+ cp++;
+ switch (*cp) {
+ case '\0':
+ *port = NULL;
+ return;
+ case ':':
+ if (cp[1] != '\0') {
+ *port = cp + 1;
+ return;
+ }
+ /* FALLTHROUGH */
+ default:
+ errx(EX_USAGE, "Invalid address %s", in_address);
+ }
+ }
+
+ /* Look for the first colon. */
+ cp = strchr(in_address, ':');
+ if (cp == NULL) {
+ *address = in_address;
+ *port = NULL;
+ *tofree = NULL;
+ return;
+ }
+
+ /* If there is another colon, assume this is an IPv6 address. */
+ if (strchr(cp + 1, ':') != NULL) {
+ *address = in_address;
+ *port = NULL;
+ *tofree = NULL;
+ return;
+ }
+
+ /* Both strings on either side of the colon must be non-empty. */
+ if (cp == in_address || cp[1] == '\0')
+ errx(EX_USAGE, "Invalid address %s", in_address);
+
+ *tofree = strndup(in_address, cp - in_address);
+ *address = *tofree;
+
+ /* Skip over ':' */
+ *port = cp + 1;
+}
+
+uint16_t
+nvmf_parse_cntlid(const char *cntlid)
+{
+ u_long value;
+
+ if (strcasecmp(cntlid, "dynamic") == 0)
+ return (NVMF_CNTLID_DYNAMIC);
+ else if (strcasecmp(cntlid, "static") == 0)
+ return (NVMF_CNTLID_STATIC_ANY);
+ else {
+ value = strtoul(cntlid, NULL, 0);
+
+ if (value > NVMF_CNTLID_STATIC_MAX)
+ errx(EX_USAGE, "Invalid controller ID");
+
+ return (value);
+ }
+}
+
+static bool
+tcp_qpair_params(struct nvmf_qpair_params *params, int adrfam,
+ const char *address, const char *port, struct addrinfo **aip,
+ struct addrinfo **listp)
+{
+ struct addrinfo hints, *ai, *list;
+ int error, s;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = adrfam;
+ hints.ai_protocol = IPPROTO_TCP;
+ error = getaddrinfo(address, port, &hints, &list);
+ if (error != 0) {
+ warnx("%s", gai_strerror(error));
+ return (false);
+ }
+
+ for (ai = list; ai != NULL; ai = ai->ai_next) {
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s == -1)
+ continue;
+
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) != 0) {
+ close(s);
+ continue;
+ }
+
+ params->tcp.fd = s;
+ if (listp != NULL) {
+ *aip = ai;
+ *listp = list;
+ } else
+ freeaddrinfo(list);
+ return (true);
+ }
+ warn("Failed to connect to controller at %s:%s", address, port);
+ freeaddrinfo(list);
+ return (false);
+}
+
+static bool
+tcp_qpair_params_ai(struct nvmf_qpair_params *params, struct addrinfo *ai)
+{
+ int s;
+
+ s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (s == -1)
+ return (false);
+
+ if (connect(s, ai->ai_addr, ai->ai_addrlen) != 0) {
+ close(s);
+ return (false);
+ }
+
+ params->tcp.fd = s;
+ return (true);
+}
+
+static void
+tcp_discovery_association_params(struct nvmf_association_params *params)
+{
+ params->tcp.pda = 0;
+ params->tcp.header_digests = false;
+ params->tcp.data_digests = false;
+ params->tcp.maxr2t = 1;
+}
+
+struct nvmf_qpair *
+connect_discovery_adminq(enum nvmf_trtype trtype, const char *address,
+ const char *port, const char *hostnqn)
+{
+ struct nvmf_association_params aparams;
+ struct nvmf_qpair_params qparams;
+ struct nvmf_association *na;
+ struct nvmf_qpair *qp;
+ uint64_t cap, cc, csts;
+ int error, timo;
+
+ memset(&aparams, 0, sizeof(aparams));
+ aparams.sq_flow_control = false;
+ switch (trtype) {
+ case NVMF_TRTYPE_TCP:
+ /* 7.4.9.3 Default port for discovery */
+ if (port == NULL)
+ port = "8009";
+ tcp_discovery_association_params(&aparams);
+ break;
+ default:
+ errx(EX_UNAVAILABLE, "Unsupported transport %s",
+ nvmf_transport_type(trtype));
+ }
+
+ if (!init_hostid())
+ exit(EX_IOERR);
+ if (hostnqn != NULL) {
+ if (!nvmf_nqn_valid(hostnqn))
+ errx(EX_USAGE, "Invalid HostNQN %s", hostnqn);
+ } else
+ hostnqn = nqn;
+
+ na = nvmf_allocate_association(trtype, false, &aparams);
+ if (na == NULL)
+ err(EX_IOERR, "Failed to create discovery association");
+ memset(&qparams, 0, sizeof(qparams));
+ qparams.admin = true;
+ if (!tcp_qpair_params(&qparams, AF_UNSPEC, address, port, NULL, NULL))
+ exit(EX_NOHOST);
+ qp = nvmf_connect(na, &qparams, 0, NVME_MIN_ADMIN_ENTRIES, hostid,
+ NVMF_CNTLID_DYNAMIC, NVMF_DISCOVERY_NQN, hostnqn, 0);
+ if (qp == NULL)
+ errx(EX_IOERR, "Failed to connect to discovery controller: %s",
+ nvmf_association_error(na));
+ nvmf_free_association(na);
+
+ /* Fetch Controller Capabilities Property */
+ error = nvmf_read_property(qp, NVMF_PROP_CAP, 8, &cap);
+ if (error != 0)
+ errc(EX_IOERR, error, "Failed to fetch CAP");
+
+ /* Set Controller Configuration Property (CC.EN=1) */
+ error = nvmf_read_property(qp, NVMF_PROP_CC, 4, &cc);
+ if (error != 0)
+ errc(EX_IOERR, error, "Failed to fetch CC");
+
+ /* Clear known fields preserving any reserved fields. */
+ cc &= ~(NVMEM(NVME_CC_REG_SHN) | NVMEM(NVME_CC_REG_AMS) |
+ NVMEM(NVME_CC_REG_MPS) | NVMEM(NVME_CC_REG_CSS));
+
+ /* Leave AMS, MPS, and CSS as 0. */
+
+ cc |= NVMEF(NVME_CC_REG_EN, 1);
+
+ error = nvmf_write_property(qp, NVMF_PROP_CC, 4, cc);
+ if (error != 0)
+ errc(EX_IOERR, error, "Failed to set CC");
+
+ /* Wait for CSTS.RDY in Controller Status */
+ timo = NVME_CAP_LO_TO(cap);
+ for (;;) {
+ error = nvmf_read_property(qp, NVMF_PROP_CSTS, 4, &csts);
+ if (error != 0)
+ errc(EX_IOERR, error, "Failed to fetch CSTS");
+
+ if (NVMEV(NVME_CSTS_REG_RDY, csts) != 0)
+ break;
+
+ if (timo == 0)
+ errx(EX_IOERR, "Controller failed to become ready");
+ timo--;
+ usleep(500 * 1000);
+ }
+
+ return (qp);
+}
+
+/*
+ * XXX: Should this accept the admin queue size as a parameter rather
+ * than always using NVMF_MIN_ADMIN_MAX_SQ_SIZE?
+ */
+static int
+connect_nvm_adminq(struct nvmf_association *na,
+ const struct nvmf_qpair_params *params, struct nvmf_qpair **qpp,
+ uint16_t cntlid, const char *subnqn, const char *hostnqn, uint32_t kato,
+ uint16_t *mqes)
+{
+ struct nvmf_qpair *qp;
+ uint64_t cap, cc, csts;
+ u_int mps, mpsmin, mpsmax;
+ int error, timo;
+
+ qp = nvmf_connect(na, params, 0, NVMF_MIN_ADMIN_MAX_SQ_SIZE, hostid,
+ cntlid, subnqn, hostnqn, kato);
+ if (qp == NULL) {
+ warnx("Failed to connect to NVM controller %s: %s", subnqn,
+ nvmf_association_error(na));
+ return (EX_IOERR);
+ }
+
+ /* Fetch Controller Capabilities Property */
+ error = nvmf_read_property(qp, NVMF_PROP_CAP, 8, &cap);
+ if (error != 0) {
+ warnc(error, "Failed to fetch CAP");
+ nvmf_free_qpair(qp);
+ return (EX_IOERR);
+ }
+
+ /* Require the NVM command set. */
+ if (NVME_CAP_HI_CSS_NVM(cap >> 32) == 0) {
+ warnx("Controller %s does not support the NVM command set",
+ subnqn);
+ nvmf_free_qpair(qp);
+ return (EX_UNAVAILABLE);
+ }
+
+ *mqes = NVME_CAP_LO_MQES(cap);
+
+ /* Prefer native host page size if it fits. */
+ mpsmin = NVMEV(NVME_CAP_HI_REG_MPSMIN, cap >> 32);
+ mpsmax = NVMEV(NVME_CAP_HI_REG_MPSMAX, cap >> 32);
+ mps = ffs(getpagesize()) - 1;
+ if (mps < mpsmin + NVME_MPS_SHIFT)
+ mps = mpsmin;
+ else if (mps > mpsmax + NVME_MPS_SHIFT)
+ mps = mpsmax;
+ else
+ mps -= NVME_MPS_SHIFT;
+
+ /* Configure controller. */
+ error = nvmf_read_property(qp, NVMF_PROP_CC, 4, &cc);
+ if (error != 0) {
+ warnc(error, "Failed to fetch CC");
+ nvmf_free_qpair(qp);
+ return (EX_IOERR);
+ }
+
+ /* Clear known fields preserving any reserved fields. */
+ cc &= ~(NVMEM(NVME_CC_REG_IOCQES) | NVMEM(NVME_CC_REG_IOSQES) |
+ NVMEM(NVME_CC_REG_SHN) | NVMEM(NVME_CC_REG_AMS) |
+ NVMEM(NVME_CC_REG_MPS) | NVMEM(NVME_CC_REG_CSS));
+
+ cc |= NVMEF(NVME_CC_REG_IOCQES, 4); /* CQE entry size == 16 */
+ cc |= NVMEF(NVME_CC_REG_IOSQES, 6); /* SEQ entry size == 64 */
+ cc |= NVMEF(NVME_CC_REG_AMS, 0); /* AMS 0 (Round-robin) */
+ cc |= NVMEF(NVME_CC_REG_MPS, mps);
+ cc |= NVMEF(NVME_CC_REG_CSS, 0); /* NVM command set */
+ cc |= NVMEF(NVME_CC_REG_EN, 1); /* EN = 1 */
+
+ error = nvmf_write_property(qp, NVMF_PROP_CC, 4, cc);
+ if (error != 0) {
+ warnc(error, "Failed to set CC");
+ nvmf_free_qpair(qp);
+ return (EX_IOERR);
+ }
+
+ /* Wait for CSTS.RDY in Controller Status */
+ timo = NVME_CAP_LO_TO(cap);
+ for (;;) {
+ error = nvmf_read_property(qp, NVMF_PROP_CSTS, 4, &csts);
+ if (error != 0) {
+ warnc(error, "Failed to fetch CSTS");
+ nvmf_free_qpair(qp);
+ return (EX_IOERR);
+ }
+
+ if (NVMEV(NVME_CSTS_REG_RDY, csts) != 0)
+ break;
+
+ if (timo == 0) {
+ warnx("Controller failed to become ready");
+ nvmf_free_qpair(qp);
+ return (EX_IOERR);
+ }
+ timo--;
+ usleep(500 * 1000);
+ }
+
+ *qpp = qp;
+ return (0);
+}
+
+static void
+shutdown_controller(struct nvmf_qpair *qp)
+{
+ uint64_t cc;
+ int error;
+
+ error = nvmf_read_property(qp, NVMF_PROP_CC, 4, &cc);
+ if (error != 0) {
+ warnc(error, "Failed to fetch CC");
+ goto out;
+ }
+
+ cc |= NVMEF(NVME_CC_REG_SHN, NVME_SHN_NORMAL);
+
+ error = nvmf_write_property(qp, NVMF_PROP_CC, 4, cc);
+ if (error != 0) {
+ warnc(error, "Failed to set CC to trigger shutdown");
+ goto out;
+ }
+
+out:
+ nvmf_free_qpair(qp);
+}
+
+/* Returns a value from <sysexits.h> */
+int
+connect_nvm_queues(const struct nvmf_association_params *aparams,
+ enum nvmf_trtype trtype, int adrfam, const char *address,
+ const char *port, uint16_t cntlid, const char *subnqn, const char *hostnqn,
+ uint32_t kato, struct nvmf_qpair **admin, struct nvmf_qpair **io,
+ u_int num_io_queues, u_int queue_size, struct nvme_controller_data *cdata)
+{
+ struct nvmf_qpair_params qparams;
+ struct nvmf_association *na;
+ struct addrinfo *ai, *list;
+ u_int queues;
+ int error;
+ uint16_t mqes;
+
+ switch (trtype) {
+ case NVMF_TRTYPE_TCP:
+ break;
+ default:
+ warnx("Unsupported transport %s", nvmf_transport_type(trtype));
+ return (EX_UNAVAILABLE);
+ }
+
+ if (!init_hostid())
+ return (EX_IOERR);
+ if (hostnqn == NULL || !nvmf_nqn_valid(hostnqn)) {
+ warnx("Invalid HostNQN %s", hostnqn);
+ return (EX_USAGE);
+ }
+
+ /* Association. */
+ na = nvmf_allocate_association(trtype, false, aparams);
+ if (na == NULL) {
+ warn("Failed to create association for %s", subnqn);
+ return (EX_IOERR);
+ }
+
+ /* Admin queue. */
+ memset(&qparams, 0, sizeof(qparams));
+ qparams.admin = true;
+ if (!tcp_qpair_params(&qparams, adrfam, address, port, &ai, &list)) {
+ nvmf_free_association(na);
+ return (EX_NOHOST);
+ }
+ error = connect_nvm_adminq(na, &qparams, admin, cntlid, subnqn, hostnqn,
+ kato, &mqes);
+ if (error != 0) {
+ nvmf_free_association(na);
+ freeaddrinfo(list);
+ return (error);
+ }
+
+ /* Validate I/O queue size. */
+ memset(io, 0, sizeof(*io) * num_io_queues);
+ if (queue_size == 0)
+ queue_size = (u_int)mqes + 1;
+ else if (queue_size > (u_int)mqes + 1) {
+ warnx("I/O queue size exceeds controller maximum (%u)",
+ mqes + 1);
+ error = EX_USAGE;
+ goto out;
+ }
+
+ /* Fetch controller data. */
+ error = nvmf_host_identify_controller(*admin, cdata);
+ if (error != 0) {
+ warnc(error, "Failed to fetch controller data for %s", subnqn);
+ error = EX_IOERR;
+ goto out;
+ }
+
+ nvmf_update_assocation(na, cdata);
+
+ error = nvmf_host_request_queues(*admin, num_io_queues, &queues);
+ if (error != 0) {
+ warnc(error, "Failed to request I/O queues");
+ error = EX_IOERR;
+ goto out;
+ }
+ if (queues < num_io_queues) {
+ warnx("Controller enabled fewer I/O queues (%u) than requested (%u)",
+ queues, num_io_queues);
+ error = EX_PROTOCOL;
+ goto out;
+ }
+
+ /* I/O queues. */
+ for (u_int i = 0; i < num_io_queues; i++) {
+ memset(&qparams, 0, sizeof(qparams));
+ qparams.admin = false;
+ if (!tcp_qpair_params_ai(&qparams, ai)) {
+ warn("Failed to connect to controller at %s:%s",
+ address, port);
+ error = EX_NOHOST;
+ goto out;
+ }
+ io[i] = nvmf_connect(na, &qparams, i + 1, queue_size, hostid,
+ nvmf_cntlid(*admin), subnqn, hostnqn, 0);
+ if (io[i] == NULL) {
+ warnx("Failed to create I/O queue: %s",
+ nvmf_association_error(na));
+ error = EX_IOERR;
+ goto out;
+ }
+ }
+ nvmf_free_association(na);
+ freeaddrinfo(list);
+ return (0);
+
+out:
+ disconnect_nvm_queues(*admin, io, num_io_queues);
+ nvmf_free_association(na);
+ freeaddrinfo(list);
+ return (error);
+}
+
+void
+disconnect_nvm_queues(struct nvmf_qpair *admin, struct nvmf_qpair **io,
+ u_int num_io_queues)
+{
+ for (u_int i = 0; i < num_io_queues; i++) {
+ if (io[i] == NULL)
+ break;
+ nvmf_free_qpair(io[i]);
+ }
+ shutdown_controller(admin);
+}
diff --git a/sbin/nvmecontrol/fabrics.h b/sbin/nvmecontrol/fabrics.h
new file mode 100644
index 000000000000..1f43fc53bb8f
--- /dev/null
+++ b/sbin/nvmecontrol/fabrics.h
@@ -0,0 +1,50 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023-2024 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#ifndef __FABRICS_H__
+#define __FABRICS_H__
+
+/*
+ * Splits 'in_address' into separate 'address' and 'port' strings. If
+ * a separate buffer for the address was allocated, 'tofree' is set to
+ * the allocated buffer, otherwise 'tofree' is set to NULL.
+ */
+void nvmf_parse_address(const char *in_address, const char **address,
+ const char **port, char **tofree);
+
+uint16_t nvmf_parse_cntlid(const char *cntlid);
+
+const char *nvmf_default_hostnqn(void);
+
+int nvmf_init_dle_from_address(enum nvmf_trtype trtype, const char *address,
+ const char *port, uint16_t cntlid, const char *subnqn,
+ struct nvme_discovery_log_entry *dle);
+
+/* Connect to a discovery controller and return the Admin qpair. */
+struct nvmf_qpair *connect_discovery_adminq(enum nvmf_trtype trtype,
+ const char *address, const char *port, const char *hostnqn);
+
+/*
+ * Connect to an NVM controller establishing an Admin qpair and one or
+ * more I/O qpairs. The controller's controller data is returned in
+ * *cdata on success. Returns a non-zero value from <sysexits.h> on
+ * failure.
+ */
+int connect_nvm_queues(const struct nvmf_association_params *aparams,
+ enum nvmf_trtype trtype, int adrfam, const char *address,
+ const char *port, uint16_t cntlid, const char *subnqn, const char *hostnqn,
+ uint32_t kato, struct nvmf_qpair **admin, struct nvmf_qpair **io,
+ u_int num_io_queues, u_int queue_size, struct nvme_controller_data *cdata);
+
+/*
+ * Disconnect from an NVM controller disconnecting all queues and
+ * shutting down the controller.
+ */
+void disconnect_nvm_queues(struct nvmf_qpair *admin, struct nvmf_qpair **io,
+ u_int num_io_queues);
+
+#endif /* !__FABRICS_H__ */
diff --git a/sbin/nvmecontrol/firmware.c b/sbin/nvmecontrol/firmware.c
index e6ebc9b70321..c1c26c310627 100644
--- a/sbin/nvmecontrol/firmware.c
+++ b/sbin/nvmecontrol/firmware.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2013 EMC Corp.
* All rights reserved.
@@ -29,9 +29,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
#include <sys/stat.h>
@@ -105,9 +102,10 @@ slot_has_valid_firmware(int fd, int slot)
int has_fw = false;
read_logpage(fd, NVME_LOG_FIRMWARE_SLOT,
- NVME_GLOBAL_NAMESPACE_TAG, 0, 0, 0, &fw, sizeof(fw));
+ NVME_GLOBAL_NAMESPACE_TAG, 0, 0, 0, 0, 0, 0, 0,
+ &fw, sizeof(fw));
- if (fw.revision[slot-1] != 0LLU)
+ if (fw.revision[slot-1][0] != '\0')
has_fw = true;
return (has_fw);
@@ -280,21 +278,18 @@ firmware(const struct cmd *f, int argc, char *argv[])
if (read_controller_data(fd, &cdata))
errx(EX_IOERR, "Identify request failed");
- oacs_fw = (cdata.oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) &
- NVME_CTRLR_DATA_OACS_FIRMWARE_MASK;
+ oacs_fw = NVMEV(NVME_CTRLR_DATA_OACS_FIRMWARE, cdata.oacs);
if (oacs_fw == 0)
errx(EX_UNAVAILABLE,
"controller does not support firmware activate/download");
- fw_slot1_ro = (cdata.frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) &
- NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK;
+ fw_slot1_ro = NVMEV(NVME_CTRLR_DATA_FRMW_SLOT1_RO, cdata.frmw);
if (opt.fw_img && opt.slot == 1 && fw_slot1_ro)
errx(EX_UNAVAILABLE, "slot %d is marked as read only", opt.slot);
- fw_num_slots = (cdata.frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) &
- NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK;
+ fw_num_slots = NVMEV(NVME_CTRLR_DATA_FRMW_NUM_SLOTS, cdata.frmw);
if (opt.slot > fw_num_slots)
errx(EX_UNAVAILABLE,
diff --git a/sbin/nvmecontrol/format.c b/sbin/nvmecontrol/format.c
index a9ab80562032..16699605ea8c 100644
--- a/sbin/nvmecontrol/format.c
+++ b/sbin/nvmecontrol/format.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2018-2019 Alexander Motin <mav@FreeBSD.org>
*
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -76,7 +73,7 @@ static struct options {
static const struct opts format_opts[] = {
#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
OPT("crypto", 'C', arg_none, opt, Cflag,
- "Crptographic erase"),
+ "Cryptographic erase"),
OPT("erase", 'E', arg_none, opt, Eflag,
"User data erase"),
OPT("lbaf", 'f', arg_uint32, opt, lbaf,
@@ -162,38 +159,33 @@ format(const struct cmd *f, int argc, char *argv[])
/* Check that controller can execute this command. */
if (read_controller_data(fd, &cd))
errx(EX_IOERR, "Identify request failed");
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_FORMAT_SHIFT) &
- NVME_CTRLR_DATA_OACS_FORMAT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_FORMAT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support format");
- if (((cd.fna >> NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_SHIFT) &
- NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_MASK) == 0 && ses == SES_CRYPTO)
+ if (NVMEV(NVME_CTRLR_DATA_FNA_CRYPTO_ERASE, cd.fna) == 0 &&
+ ses == SES_CRYPTO)
errx(EX_UNAVAILABLE, "controller does not support cryptographic erase");
if (nsid != NVME_GLOBAL_NAMESPACE_TAG) {
- if (((cd.fna >> NVME_CTRLR_DATA_FNA_FORMAT_ALL_SHIFT) &
- NVME_CTRLR_DATA_FNA_FORMAT_ALL_MASK) && ses == SES_NONE)
+ if (NVMEV(NVME_CTRLR_DATA_FNA_FORMAT_ALL, cd.fna) &&
+ ses == SES_NONE)
errx(EX_UNAVAILABLE, "controller does not support per-NS format");
- if (((cd.fna >> NVME_CTRLR_DATA_FNA_ERASE_ALL_SHIFT) &
- NVME_CTRLR_DATA_FNA_ERASE_ALL_MASK) && ses != SES_NONE)
+ if (NVMEV(NVME_CTRLR_DATA_FNA_ERASE_ALL, cd.fna) &&
+ ses != SES_NONE)
errx(EX_UNAVAILABLE, "controller does not support per-NS erase");
/* Try to keep previous namespace parameters. */
if (read_namespace_data(fd, nsid, &nsd))
errx(EX_IOERR, "Identify request failed");
if (lbaf < 0)
- lbaf = (nsd.flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT)
- & NVME_NS_DATA_FLBAS_FORMAT_MASK;
+ lbaf = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, nsd.flbas);
if (lbaf > nsd.nlbaf)
errx(EX_USAGE, "LBA format is out of range");
if (ms < 0)
- ms = (nsd.flbas >> NVME_NS_DATA_FLBAS_EXTENDED_SHIFT)
- & NVME_NS_DATA_FLBAS_EXTENDED_MASK;
+ ms = NVMEV(NVME_NS_DATA_FLBAS_EXTENDED, nsd.flbas);
if (pi < 0)
- pi = (nsd.dps >> NVME_NS_DATA_DPS_MD_START_SHIFT)
- & NVME_NS_DATA_DPS_MD_START_MASK;
+ pi = NVMEV(NVME_NS_DATA_DPS_MD_START, nsd.dps);
if (pil < 0)
- pil = (nsd.dps >> NVME_NS_DATA_DPS_PIT_SHIFT)
- & NVME_NS_DATA_DPS_PIT_MASK;
+ pil = NVMEV(NVME_NS_DATA_DPS_PIT, nsd.dps);
} else {
/* We have no previous parameters, so default to zeroes. */
diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c
index 0d4d8003e5d2..98a3141bf9ad 100644
--- a/sbin/nvmecontrol/identify.c
+++ b/sbin/nvmecontrol/identify.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
@@ -27,9 +27,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <ctype.h>
@@ -69,11 +66,9 @@ print_namespace(struct nvme_namespace_data *nsdata)
uint8_t thin_prov, ptype;
uint8_t flbas_fmt, t;
- thin_prov = (nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_THIN_PROV_SHIFT) &
- NVME_NS_DATA_NSFEAT_THIN_PROV_MASK;
+ thin_prov = NVMEV(NVME_NS_DATA_NSFEAT_THIN_PROV, nsdata->nsfeat);
- flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
- NVME_NS_DATA_FLBAS_FORMAT_MASK;
+ flbas_fmt = NVMEV(NVME_NS_DATA_FLBAS_FORMAT, nsdata->flbas);
printf("Size: %lld blocks\n",
(long long)nsdata->nsze);
@@ -85,83 +80,77 @@ print_namespace(struct nvme_namespace_data *nsdata)
thin_prov ? "Supported" : "Not Supported");
printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1);
printf("Current LBA Format: LBA Format #%02d", flbas_fmt);
- if (nsdata->lbaf[flbas_fmt] >> NVME_NS_DATA_LBAF_MS_SHIFT & NVME_NS_DATA_LBAF_MS_MASK)
- printf(" %s metadata\n", nsdata->flbas >> NVME_NS_DATA_FLBAS_EXTENDED_SHIFT &
- NVME_NS_DATA_FLBAS_EXTENDED_MASK ? "Extended" : "Separate");
+ if (NVMEV(NVME_NS_DATA_LBAF_MS, nsdata->lbaf[flbas_fmt]) != 0)
+ printf(" %s metadata\n",
+ NVMEV(NVME_NS_DATA_FLBAS_EXTENDED, nsdata->flbas) != 0 ?
+ "Extended" : "Separate");
else
printf("\n");
printf("Metadata Capabilities\n");
printf(" Extended: %s\n",
- nsdata->mc >> NVME_NS_DATA_MC_EXTENDED_SHIFT & NVME_NS_DATA_MC_EXTENDED_MASK ? "Supported" : "Not Supported");
+ NVMEV(NVME_NS_DATA_MC_EXTENDED, nsdata->mc) != 0 ? "Supported" :
+ "Not Supported");
printf(" Separate: %s\n",
- nsdata->mc >> NVME_NS_DATA_MC_POINTER_SHIFT & NVME_NS_DATA_MC_POINTER_MASK ? "Supported" : "Not Supported");
+ NVMEV(NVME_NS_DATA_MC_POINTER, nsdata->mc) != 0 ? "Supported" :
+ "Not Supported");
printf("Data Protection Caps: %s%s%s%s%s%s\n",
(nsdata->dpc == 0) ? "Not Supported" : "",
- ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_END_SHIFT) &
- NVME_NS_DATA_DPC_MD_END_MASK) ? "Last Bytes, " : "",
- ((nsdata->dpc >> NVME_NS_DATA_DPC_MD_START_SHIFT) &
- NVME_NS_DATA_DPC_MD_START_MASK) ? "First Bytes, " : "",
- ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT3_SHIFT) &
- NVME_NS_DATA_DPC_PIT3_MASK) ? "Type 3, " : "",
- ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT2_SHIFT) &
- NVME_NS_DATA_DPC_PIT2_MASK) ? "Type 2, " : "",
- ((nsdata->dpc >> NVME_NS_DATA_DPC_PIT1_SHIFT) &
- NVME_NS_DATA_DPC_PIT1_MASK) ? "Type 1" : "");
+ NVMEV(NVME_NS_DATA_DPC_MD_END, nsdata->dpc) != 0 ? "Last Bytes, " :
+ "",
+ NVMEV(NVME_NS_DATA_DPC_MD_START, nsdata->dpc) != 0 ?
+ "First Bytes, " : "",
+ NVMEV(NVME_NS_DATA_DPC_PIT3, nsdata->dpc) != 0 ? "Type 3, " : "",
+ NVMEV(NVME_NS_DATA_DPC_PIT2, nsdata->dpc) != 0 ? "Type 2, " : "",
+ NVMEV(NVME_NS_DATA_DPC_PIT1, nsdata->dpc) != 0 ? "Type 1" : "");
printf("Data Protection Settings: ");
- ptype = (nsdata->dps >> NVME_NS_DATA_DPS_PIT_SHIFT) &
- NVME_NS_DATA_DPS_PIT_MASK;
- if (ptype) {
+ ptype = NVMEV(NVME_NS_DATA_DPS_PIT, nsdata->dps);
+ if (ptype != 0) {
printf("Type %d, %s Bytes\n", ptype,
- ((nsdata->dps >> NVME_NS_DATA_DPS_MD_START_SHIFT) &
- NVME_NS_DATA_DPS_MD_START_MASK) ? "First" : "Last");
+ NVMEV(NVME_NS_DATA_DPS_MD_START, nsdata->dps) != 0 ?
+ "First" : "Last");
} else {
printf("Not Enabled\n");
}
printf("Multi-Path I/O Capabilities: %s%s\n",
(nsdata->nmic == 0) ? "Not Supported" : "",
- ((nsdata->nmic >> NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) &
- NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK) ? "May be shared" : "");
+ NVMEV(NVME_NS_DATA_NMIC_MAY_BE_SHARED, nsdata->nmic) != 0 ?
+ "May be shared" : "");
printf("Reservation Capabilities: %s%s%s%s%s%s%s%s%s\n",
(nsdata->rescap == 0) ? "Not Supported" : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_IEKEY13_SHIFT) &
- NVME_NS_DATA_RESCAP_IEKEY13_MASK) ? "IEKEY13, " : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_AR_SHIFT) &
- NVME_NS_DATA_RESCAP_EX_AC_AR_MASK) ? "EX_AC_AR, " : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_AR_SHIFT) &
- NVME_NS_DATA_RESCAP_WR_EX_AR_MASK) ? "WR_EX_AR, " : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_RO_SHIFT) &
- NVME_NS_DATA_RESCAP_EX_AC_RO_MASK) ? "EX_AC_RO, " : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_RO_SHIFT) &
- NVME_NS_DATA_RESCAP_WR_EX_RO_MASK) ? "WR_EX_RO, " : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_EX_AC_SHIFT) &
- NVME_NS_DATA_RESCAP_EX_AC_MASK) ? "EX_AC, " : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_WR_EX_SHIFT) &
- NVME_NS_DATA_RESCAP_WR_EX_MASK) ? "WR_EX, " : "",
- ((nsdata->rescap >> NVME_NS_DATA_RESCAP_PTPL_SHIFT) &
- NVME_NS_DATA_RESCAP_PTPL_MASK) ? "PTPL" : "");
+ NVMEV(NVME_NS_DATA_RESCAP_IEKEY13, nsdata->rescap) != 0 ?
+ "IEKEY13, " : "",
+ NVMEV(NVME_NS_DATA_RESCAP_EX_AC_AR, nsdata->rescap) != 0 ?
+ "EX_AC_AR, " : "",
+ NVMEV(NVME_NS_DATA_RESCAP_WR_EX_AR, nsdata->rescap) != 0 ?
+ "WR_EX_AR, " : "",
+ NVMEV(NVME_NS_DATA_RESCAP_EX_AC_RO, nsdata->rescap) != 0 ?
+ "EX_AC_RO, " : "",
+ NVMEV(NVME_NS_DATA_RESCAP_WR_EX_RO, nsdata->rescap) != 0 ?
+ "WR_EX_RO, " : "",
+ NVMEV(NVME_NS_DATA_RESCAP_EX_AC, nsdata->rescap) != 0 ?
+ "EX_AC, " : "",
+ NVMEV(NVME_NS_DATA_RESCAP_WR_EX, nsdata->rescap) != 0 ?
+ "WR_EX, " : "",
+ NVMEV(NVME_NS_DATA_RESCAP_PTPL, nsdata->rescap) != 0 ? "PTPL" : "");
printf("Format Progress Indicator: ");
- if ((nsdata->fpi >> NVME_NS_DATA_FPI_SUPP_SHIFT) &
- NVME_NS_DATA_FPI_SUPP_MASK) {
+ if (NVMEV(NVME_NS_DATA_FPI_SUPP, nsdata->fpi) != 0) {
printf("%u%% remains\n",
- (nsdata->fpi >> NVME_NS_DATA_FPI_PERC_SHIFT) &
- NVME_NS_DATA_FPI_PERC_MASK);
+ NVMEV(NVME_NS_DATA_FPI_PERC, nsdata->fpi));
} else
printf("Not Supported\n");
- t = (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_READ_SHIFT) &
- NVME_NS_DATA_DLFEAT_READ_MASK;
+ t = NVMEV(NVME_NS_DATA_DLFEAT_READ, nsdata->dlfeat);
printf("Deallocate Logical Block: Read %s%s%s\n",
(t == NVME_NS_DATA_DLFEAT_READ_NR) ? "Not Reported" :
(t == NVME_NS_DATA_DLFEAT_READ_00) ? "00h" :
(t == NVME_NS_DATA_DLFEAT_READ_FF) ? "FFh" : "Unknown",
- (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_DWZ_SHIFT) &
- NVME_NS_DATA_DLFEAT_DWZ_MASK ? ", Write Zero" : "",
- (nsdata->dlfeat >> NVME_NS_DATA_DLFEAT_GCRC_SHIFT) &
- NVME_NS_DATA_DLFEAT_GCRC_MASK ? ", Guard CRC" : "");
+ NVMEV(NVME_NS_DATA_DLFEAT_DWZ, nsdata->dlfeat) != 0 ?
+ ", Write Zero" : "",
+ NVMEV(NVME_NS_DATA_DLFEAT_GCRC, nsdata->dlfeat) != 0 ?
+ ", Guard CRC" : "");
printf("Optimal I/O Boundary: %u blocks\n", nsdata->noiob);
printf("NVM Capacity: %s bytes\n",
uint128_to_str(to128(nsdata->nvmcap), cbuf, sizeof(cbuf)));
- if ((nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_NPVALID_SHIFT) &
- NVME_NS_DATA_NSFEAT_NPVALID_MASK) {
+ if (NVMEV(NVME_NS_DATA_NSFEAT_NPVALID, nsdata->nsfeat) != 0) {
printf("Preferred Write Granularity: %u blocks\n",
nsdata->npwg + 1);
printf("Preferred Write Alignment: %u blocks\n",
@@ -183,14 +172,11 @@ print_namespace(struct nvme_namespace_data *nsdata)
printf("\n");
for (i = 0; i <= nsdata->nlbaf; i++) {
lbaf = nsdata->lbaf[i];
- lbads = (lbaf >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
- NVME_NS_DATA_LBAF_LBADS_MASK;
+ lbads = NVMEV(NVME_NS_DATA_LBAF_LBADS, lbaf);
if (lbads == 0)
continue;
- ms = (lbaf >> NVME_NS_DATA_LBAF_MS_SHIFT) &
- NVME_NS_DATA_LBAF_MS_MASK;
- rp = (lbaf >> NVME_NS_DATA_LBAF_RP_SHIFT) &
- NVME_NS_DATA_LBAF_RP_MASK;
+ ms = NVMEV(NVME_NS_DATA_LBAF_MS, lbaf);
+ rp = NVMEV(NVME_NS_DATA_LBAF_RP, lbaf);
printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d"
" Performance: %s\n",
i, 1 << lbads, ms, (rp == 0) ? "Best" :
@@ -281,7 +267,7 @@ identify(const struct cmd *f, int argc, char *argv[])
static const struct opts identify_opts[] = {
#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
OPT("hex", 'x', arg_none, opt, hex,
- "Print identiy information in hex"),
+ "Print identity information in hex"),
OPT("verbose", 'v', arg_none, opt, verbose,
"More verbosity: print entire identify table"),
OPT("nsid", 'n', arg_uint32, opt, nsid,
diff --git a/sbin/nvmecontrol/identify_ext.c b/sbin/nvmecontrol/identify_ext.c
index 50b8901b799e..95ca4b5187d4 100644
--- a/sbin/nvmecontrol/identify_ext.c
+++ b/sbin/nvmecontrol/identify_ext.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
@@ -27,9 +27,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <ctype.h>
@@ -59,41 +56,27 @@ nvme_print_controller(struct nvme_controller_data *cdata)
uint8_t fwug;
oncs = cdata->oncs;
- compare = (oncs >> NVME_CTRLR_DATA_ONCS_COMPARE_SHIFT) &
- NVME_CTRLR_DATA_ONCS_COMPARE_MASK;
- write_unc = (oncs >> NVME_CTRLR_DATA_ONCS_WRITE_UNC_SHIFT) &
- NVME_CTRLR_DATA_ONCS_WRITE_UNC_MASK;
- dsm = (oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) &
- NVME_CTRLR_DATA_ONCS_DSM_MASK;
+ compare = NVMEV(NVME_CTRLR_DATA_ONCS_COMPARE, oncs);
+ write_unc = NVMEV(NVME_CTRLR_DATA_ONCS_WRITE_UNC, oncs);
+ dsm = NVMEV(NVME_CTRLR_DATA_ONCS_DSM, oncs);
oacs = cdata->oacs;
- security = (oacs >> NVME_CTRLR_DATA_OACS_SECURITY_SHIFT) &
- NVME_CTRLR_DATA_OACS_SECURITY_MASK;
- fmt = (oacs >> NVME_CTRLR_DATA_OACS_FORMAT_SHIFT) &
- NVME_CTRLR_DATA_OACS_FORMAT_MASK;
- fw = (oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) &
- NVME_CTRLR_DATA_OACS_FIRMWARE_MASK;
- nsmgmt = (oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK;
+ security = NVMEV(NVME_CTRLR_DATA_OACS_SECURITY, oacs);
+ fmt = NVMEV(NVME_CTRLR_DATA_OACS_FORMAT, oacs);
+ fw = NVMEV(NVME_CTRLR_DATA_OACS_FIRMWARE, oacs);
+ nsmgmt = NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, oacs);
- fw_num_slots = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) &
- NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK;
- fw_slot1_ro = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) &
- NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK;
+ fw_num_slots = NVMEV(NVME_CTRLR_DATA_FRMW_NUM_SLOTS, cdata->frmw);
+ fw_slot1_ro = NVMEV(NVME_CTRLR_DATA_FRMW_SLOT1_RO, cdata->frmw);
fwug = cdata->fwug;
- ns_smart = (cdata->lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) &
- NVME_CTRLR_DATA_LPA_NS_SMART_MASK;
+ ns_smart = NVMEV(NVME_CTRLR_DATA_LPA_NS_SMART, cdata->lpa);
- sqes_min = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MIN_SHIFT) &
- NVME_CTRLR_DATA_SQES_MIN_MASK;
- sqes_max = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MAX_SHIFT) &
- NVME_CTRLR_DATA_SQES_MAX_MASK;
+ sqes_min = NVMEV(NVME_CTRLR_DATA_SQES_MIN, cdata->sqes);
+ sqes_max = NVMEV(NVME_CTRLR_DATA_SQES_MAX, cdata->sqes);
- cqes_min = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MIN_SHIFT) &
- NVME_CTRLR_DATA_CQES_MIN_MASK;
- cqes_max = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MAX_SHIFT) &
- NVME_CTRLR_DATA_CQES_MAX_MASK;
+ cqes_min = NVMEV(NVME_CTRLR_DATA_CQES_MIN, cdata->cqes);
+ cqes_max = NVMEV(NVME_CTRLR_DATA_CQES_MAX, cdata->cqes);
printf("Controller Capabilities/Features\n");
printf("================================\n");
@@ -107,17 +90,17 @@ nvme_print_controller(struct nvme_controller_data *cdata)
printf("Firmware Version: %s\n", str);
printf("Recommended Arb Burst: %d\n", cdata->rab);
printf("IEEE OUI Identifier: %02x %02x %02x\n",
- cdata->ieee[0], cdata->ieee[1], cdata->ieee[2]);
+ cdata->ieee[2], cdata->ieee[1], cdata->ieee[0]);
printf("Multi-Path I/O Capabilities: %s%s%s%s%s\n",
(cdata->mic == 0) ? "Not Supported" : "",
- ((cdata->mic >> NVME_CTRLR_DATA_MIC_ANAR_SHIFT) &
- NVME_CTRLR_DATA_MIC_SRIOVVF_MASK) ? "Asymmetric, " : "",
- ((cdata->mic >> NVME_CTRLR_DATA_MIC_SRIOVVF_SHIFT) &
- NVME_CTRLR_DATA_MIC_SRIOVVF_MASK) ? "SR-IOV VF, " : "",
- ((cdata->mic >> NVME_CTRLR_DATA_MIC_MCTRLRS_SHIFT) &
- NVME_CTRLR_DATA_MIC_MCTRLRS_MASK) ? "Multiple controllers, " : "",
- ((cdata->mic >> NVME_CTRLR_DATA_MIC_MPORTS_SHIFT) &
- NVME_CTRLR_DATA_MIC_MPORTS_MASK) ? "Multiple ports" : "");
+ NVMEV(NVME_CTRLR_DATA_MIC_ANAR, cdata->mic) != 0 ?
+ "Asymmetric, " : "",
+ NVMEV(NVME_CTRLR_DATA_MIC_SRIOVVF, cdata->mic) != 0 ?
+ "SR-IOV VF, " : "",
+ NVMEV(NVME_CTRLR_DATA_MIC_MCTRLRS, cdata->mic) != 0 ?
+ "Multiple controllers, " : "",
+ NVMEV(NVME_CTRLR_DATA_MIC_MPORTS, cdata->mic) != 0 ?
+ "Multiple ports" : "");
/* TODO: Use CAP.MPSMIN to determine true memory page size. */
printf("Max Data Transfer Size: ");
if (cdata->mdts == 0)
@@ -125,24 +108,19 @@ nvme_print_controller(struct nvme_controller_data *cdata)
else
printf("%ld bytes\n", PAGE_SIZE * (1L << cdata->mdts));
printf("Sanitize Crypto Erase: %s\n",
- ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_CES_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_CES_MASK) ?
- "Supported" : "Not Supported");
+ NVMEV(NVME_CTRLR_DATA_SANICAP_CES, cdata->sanicap) != 0 ?
+ "Supported" : "Not Supported");
printf("Sanitize Block Erase: %s\n",
- ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_BES_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_BES_MASK) ?
- "Supported" : "Not Supported");
+ NVMEV(NVME_CTRLR_DATA_SANICAP_BES, cdata->sanicap) != 0 ?
+ "Supported" : "Not Supported");
printf("Sanitize Overwrite: %s\n",
- ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_OWS_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_OWS_MASK) ?
- "Supported" : "Not Supported");
+ NVMEV(NVME_CTRLR_DATA_SANICAP_OWS, cdata->sanicap) != 0 ?
+ "Supported" : "Not Supported");
printf("Sanitize NDI: %s\n",
- ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_NDI_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_NDI_MASK) ?
- "Supported" : "Not Supported");
+ NVMEV(NVME_CTRLR_DATA_SANICAP_NDI, cdata->sanicap) != 0 ?
+ "Supported" : "Not Supported");
printf("Sanitize NODMMAS: ");
- switch (((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_NODMMAS_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_NODMMAS_MASK)) {
+ switch (NVMEV(NVME_CTRLR_DATA_SANICAP_NODMMAS, cdata->sanicap)) {
case NVME_CTRLR_DATA_SANICAP_NODMMAS_UNDEF:
printf("Undefined\n");
break;
@@ -160,6 +138,36 @@ nvme_print_controller(struct nvme_controller_data *cdata)
printf("Version: %d.%d.%d\n",
(cdata->ver >> 16) & 0xffff, (cdata->ver >> 8) & 0xff,
cdata->ver & 0xff);
+ printf("Traffic Based Keep Alive: %sSupported\n",
+ NVMEV(NVME_CTRLR_DATA_CTRATT_TBKAS, cdata->ctratt) ? "" : "Not ");
+ printf("Controller Type: ");
+ switch (cdata->cntrltype) {
+ case 0:
+ printf("Not Reported\n");
+ break;
+ case 1:
+ printf("I/O Controller\n");
+ break;
+ case 2:
+ printf("Discovery Controller\n");
+ break;
+ case 3:
+ printf("Administrative Controller\n");
+ break;
+ default:
+ printf("%d (Reserved)\n", cdata->cntrltype);
+ break;
+ }
+ printf("Keep Alive Timer ");
+ if (cdata->kas == 0)
+ printf("Not Supported\n");
+ else
+ printf("%u ms granularity\n", cdata->kas * 100);
+ printf("Maximum Outstanding Commands ");
+ if (cdata->maxcmd == 0)
+ printf("Not Specified\n");
+ else
+ printf("%u\n", cdata->maxcmd);
printf("\n");
printf("Admin Command Set Attributes\n");
@@ -173,47 +181,33 @@ nvme_print_controller(struct nvme_controller_data *cdata)
printf("Namespace Management: %s\n",
nsmgmt ? "Supported" : "Not Supported");
printf("Device Self-test: %sSupported\n",
- ((oacs >> NVME_CTRLR_DATA_OACS_SELFTEST_SHIFT) &
- NVME_CTRLR_DATA_OACS_SELFTEST_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_OACS_SELFTEST, oacs) != 0 ? "" : "Not ");
printf("Directives: %sSupported\n",
- ((oacs >> NVME_CTRLR_DATA_OACS_DIRECTIVES_SHIFT) &
- NVME_CTRLR_DATA_OACS_DIRECTIVES_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_OACS_DIRECTIVES, oacs) != 0 ? "" : "Not ");
printf("NVMe-MI Send/Receive: %sSupported\n",
- ((oacs >> NVME_CTRLR_DATA_OACS_NVMEMI_SHIFT) &
- NVME_CTRLR_DATA_OACS_NVMEMI_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_OACS_NVMEMI, oacs) != 0 ? "" : "Not ");
printf("Virtualization Management: %sSupported\n",
- ((oacs >> NVME_CTRLR_DATA_OACS_VM_SHIFT) &
- NVME_CTRLR_DATA_OACS_VM_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_OACS_VM, oacs) != 0 ? "" : "Not ");
printf("Doorbell Buffer Config: %sSupported\n",
- ((oacs >> NVME_CTRLR_DATA_OACS_DBBUFFER_SHIFT) &
- NVME_CTRLR_DATA_OACS_DBBUFFER_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_OACS_DBBUFFER, oacs) != 0 ? "" : "Not ");
printf("Get LBA Status: %sSupported\n",
- ((oacs >> NVME_CTRLR_DATA_OACS_GETLBA_SHIFT) &
- NVME_CTRLR_DATA_OACS_GETLBA_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_OACS_GETLBA, oacs) != 0 ? "" : "Not ");
printf("Sanitize: ");
if (cdata->sanicap != 0) {
printf("%s%s%s\n",
- ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_CES_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_CES_MASK) ? "crypto, " : "",
- ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_BES_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_BES_MASK) ? "block, " : "",
- ((cdata->sanicap >> NVME_CTRLR_DATA_SANICAP_OWS_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_OWS_MASK) ? "overwrite" : "");
+ NVMEV(NVME_CTRLR_DATA_SANICAP_CES, cdata->sanicap) != 0 ?
+ "crypto, " : "",
+ NVMEV(NVME_CTRLR_DATA_SANICAP_BES, cdata->sanicap) != 0 ?
+ "block, " : "",
+ NVMEV(NVME_CTRLR_DATA_SANICAP_OWS, cdata->sanicap) != 0 ?
+ "overwrite" : "");
} else {
printf("Not Supported\n");
}
printf("Abort Command Limit: %d\n", cdata->acl+1);
printf("Async Event Request Limit: %d\n", cdata->aerl+1);
- printf("Number of Firmware Slots: ");
- if (fw != 0)
- printf("%d\n", fw_num_slots);
- else
- printf("N/A\n");
- printf("Firmware Slot 1 Read-Only: ");
- if (fw != 0)
- printf("%s\n", fw_slot1_ro ? "Yes" : "No");
- else
- printf("N/A\n");
+ printf("Number of Firmware Slots: %d\n", fw_num_slots);
+ printf("Firmware Slot 1 Read-Only: %s\n", fw_slot1_ro ? "Yes" : "No");
printf("Per-Namespace SMART Log: %s\n",
ns_smart ? "Yes" : "No");
printf("Error Log Page Entries: %d\n", cdata->elpe+1);
@@ -255,39 +249,54 @@ nvme_print_controller(struct nvme_controller_data *cdata)
printf("Dataset Management Command: %s\n",
dsm ? "Supported" : "Not Supported");
printf("Write Zeroes Command: %sSupported\n",
- ((oncs >> NVME_CTRLR_DATA_ONCS_WRZERO_SHIFT) &
- NVME_CTRLR_DATA_ONCS_WRZERO_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_ONCS_WRZERO, oncs) != 0 ? "" : "Not ");
printf("Save Features: %sSupported\n",
- ((oncs >> NVME_CTRLR_DATA_ONCS_SAVEFEAT_SHIFT) &
- NVME_CTRLR_DATA_ONCS_SAVEFEAT_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_ONCS_SAVEFEAT, oncs) != 0 ? "" : "Not ");
printf("Reservations: %sSupported\n",
- ((oncs >> NVME_CTRLR_DATA_ONCS_RESERV_SHIFT) &
- NVME_CTRLR_DATA_ONCS_RESERV_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_ONCS_RESERV, oncs) != 0 ? "" : "Not ");
printf("Timestamp feature: %sSupported\n",
- ((oncs >> NVME_CTRLR_DATA_ONCS_TIMESTAMP_SHIFT) &
- NVME_CTRLR_DATA_ONCS_TIMESTAMP_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_ONCS_TIMESTAMP, oncs) != 0 ? "" : "Not ");
printf("Verify feature: %sSupported\n",
- ((oncs >> NVME_CTRLR_DATA_ONCS_VERIFY_SHIFT) &
- NVME_CTRLR_DATA_ONCS_VERIFY_MASK) ? "" : "Not ");
+ NVMEV(NVME_CTRLR_DATA_ONCS_VERIFY, oncs) != 0 ? "" : "Not ");
printf("Fused Operation Support: %s%s\n",
(cdata->fuses == 0) ? "Not Supported" : "",
- ((cdata->fuses >> NVME_CTRLR_DATA_FUSES_CNW_SHIFT) &
- NVME_CTRLR_DATA_FUSES_CNW_MASK) ? "Compare and Write" : "");
+ NVMEV(NVME_CTRLR_DATA_FUSES_CNW, cdata->fuses) != 0 ?
+ "Compare and Write" : "");
printf("Format NVM Attributes: %s%s Erase, %s Format\n",
- ((cdata->fna >> NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_SHIFT) &
- NVME_CTRLR_DATA_FNA_CRYPTO_ERASE_MASK) ? "Crypto Erase, " : "",
- ((cdata->fna >> NVME_CTRLR_DATA_FNA_ERASE_ALL_SHIFT) &
- NVME_CTRLR_DATA_FNA_ERASE_ALL_MASK) ? "All-NVM" : "Per-NS",
- ((cdata->fna >> NVME_CTRLR_DATA_FNA_FORMAT_ALL_SHIFT) &
- NVME_CTRLR_DATA_FNA_FORMAT_ALL_MASK) ? "All-NVM" : "Per-NS");
- t = (cdata->vwc >> NVME_CTRLR_DATA_VWC_ALL_SHIFT) &
- NVME_CTRLR_DATA_VWC_ALL_MASK;
+ NVMEV(NVME_CTRLR_DATA_FNA_CRYPTO_ERASE, cdata->fna) != 0 ?
+ "Crypto Erase, " : "",
+ NVMEV(NVME_CTRLR_DATA_FNA_ERASE_ALL, cdata->fna) != 0 ?
+ "All-NVM" : "Per-NS",
+ NVMEV(NVME_CTRLR_DATA_FNA_FORMAT_ALL, cdata->fna) != 0 ?
+ "All-NVM" : "Per-NS");
+ t = NVMEV(NVME_CTRLR_DATA_VWC_ALL, cdata->vwc);
printf("Volatile Write Cache: %s%s\n",
- ((cdata->vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) &
- NVME_CTRLR_DATA_VWC_PRESENT_MASK) ? "Present" : "Not Present",
+ NVMEV(NVME_CTRLR_DATA_VWC_PRESENT, cdata->vwc) != 0 ?
+ "Present" : "Not Present",
(t == NVME_CTRLR_DATA_VWC_ALL_NO) ? ", no flush all" :
(t == NVME_CTRLR_DATA_VWC_ALL_YES) ? ", flush all" : "");
if (cdata->ver >= 0x010201)
printf("\nNVM Subsystem Name: %.256s\n", cdata->subnqn);
+
+ if (cdata->ioccsz != 0) {
+ printf("\n");
+ printf("Fabrics Attributes\n");
+ printf("==================\n");
+ printf("I/O Command Capsule Size: %d bytes\n",
+ cdata->ioccsz * 16);
+ printf("I/O Response Capsule Size: %d bytes\n",
+ cdata->iorcsz * 16);
+ printf("In Capsule Data Offset: %d bytes\n",
+ cdata->icdoff * 16);
+ printf("Controller Model: %s\n",
+ (cdata->fcatt & 1) == 0 ? "Dynamic" : "Static");
+ printf("Max SGL Descriptors: ");
+ if (cdata->msdbd == 0)
+ printf("Unlimited\n");
+ else
+ printf("%d\n", cdata->msdbd);
+ printf("Disconnect of I/O Queues: %sSupported\n",
+ (cdata->ofcs & 1) == 1 ? "" : "Not ");
+ }
}
diff --git a/sbin/nvmecontrol/logpage.c b/sbin/nvmecontrol/logpage.c
index f7a6ef311a40..023adf8f2d6a 100644
--- a/sbin/nvmecontrol/logpage.c
+++ b/sbin/nvmecontrol/logpage.c
@@ -1,11 +1,12 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2013 EMC Corp.
* All rights reserved.
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
+ * Copyright (C) 2016-2023 Warner Losh <imp@FreeBSD.org>
* Copyright (C) 2018-2019 Alexander Motin <mav@FreeBSD.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -30,9 +31,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -192,11 +190,11 @@ get_log_buffer(uint32_t size)
void
read_logpage(int fd, uint8_t log_page, uint32_t nsid, uint8_t lsp,
- uint16_t lsi, uint8_t rae, void *payload, uint32_t payload_size)
+ uint16_t lsi, uint8_t rae, uint64_t lpo, uint8_t csi, uint8_t ot,
+ uint16_t uuid_index, void *payload, uint32_t payload_size)
{
struct nvme_pt_command pt;
- struct nvme_error_information_entry *err_entry;
- u_int i, err_pages, numd;
+ u_int numd;
numd = payload_size / sizeof(uint32_t) - 1;
memset(&pt, 0, sizeof(pt));
@@ -210,9 +208,12 @@ read_logpage(int fd, uint8_t log_page, uint32_t nsid, uint8_t lsp,
pt.cmd.cdw11 = htole32(
((uint32_t)lsi << 16) | /* LSI */
(numd >> 16)); /* NUMDU */
- pt.cmd.cdw12 = 0; /* LPOL */
- pt.cmd.cdw13 = 0; /* LPOU */
- pt.cmd.cdw14 = 0; /* UUID Index */
+ pt.cmd.cdw12 = htole32(lpo & 0xffffffff); /* LPOL */
+ pt.cmd.cdw13 = htole32(lpo >> 32); /* LPOU */
+ pt.cmd.cdw14 = htole32(
+ (csi << 24) | /* CSI */
+ (ot << 23) | /* OT */
+ uuid_index); /* UUID Index */
pt.buf = payload;
pt.len = payload_size;
pt.is_read = 1;
@@ -220,49 +221,6 @@ read_logpage(int fd, uint8_t log_page, uint32_t nsid, uint8_t lsp,
if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
err(EX_IOERR, "get log page request failed");
- /* Convert data to host endian */
- switch (log_page) {
- case NVME_LOG_ERROR:
- err_entry = (struct nvme_error_information_entry *)payload;
- err_pages = payload_size / sizeof(struct nvme_error_information_entry);
- for (i = 0; i < err_pages; i++)
- nvme_error_information_entry_swapbytes(err_entry++);
- break;
- case NVME_LOG_HEALTH_INFORMATION:
- nvme_health_information_page_swapbytes(
- (struct nvme_health_information_page *)payload);
- break;
- case NVME_LOG_FIRMWARE_SLOT:
- nvme_firmware_page_swapbytes(
- (struct nvme_firmware_page *)payload);
- break;
- case NVME_LOG_CHANGED_NAMESPACE:
- nvme_ns_list_swapbytes((struct nvme_ns_list *)payload);
- break;
- case NVME_LOG_DEVICE_SELF_TEST:
- nvme_device_self_test_swapbytes(
- (struct nvme_device_self_test_page *)payload);
- break;
- case NVME_LOG_COMMAND_EFFECT:
- nvme_command_effects_page_swapbytes(
- (struct nvme_command_effects_page *)payload);
- break;
- case NVME_LOG_RES_NOTIFICATION:
- nvme_res_notification_page_swapbytes(
- (struct nvme_res_notification_page *)payload);
- break;
- case NVME_LOG_SANITIZE_STATUS:
- nvme_sanitize_status_page_swapbytes(
- (struct nvme_sanitize_status_page *)payload);
- break;
- case INTEL_LOG_TEMP_STATS:
- intel_log_temp_stats_swapbytes(
- (struct intel_log_temp_stats *)payload);
- break;
- default:
- break;
- }
-
if (nvme_completion_is_error(&pt.cpl))
errx(EX_IOERR, "get log page request returned error");
}
@@ -278,17 +236,17 @@ print_log_error(const struct nvme_controller_data *cdata __unused, void *buf, ui
printf("Error Information Log\n");
printf("=====================\n");
- if (entry->error_count == 0) {
+ if (letoh(entry->error_count) == 0) {
printf("No error entries found\n");
return;
}
- nentries = size/sizeof(struct nvme_error_information_entry);
+ nentries = size / sizeof(struct nvme_error_information_entry);
for (i = 0; i < nentries; i++, entry++) {
- if (entry->error_count == 0)
+ if (letoh(entry->error_count) == 0)
break;
- status = entry->status;
+ status = letoh(entry->status);
p = NVME_STATUS_GET_P(status);
sc = NVME_STATUS_GET_SC(status);
@@ -298,9 +256,9 @@ print_log_error(const struct nvme_controller_data *cdata __unused, void *buf, ui
printf("Entry %02d\n", i + 1);
printf("=========\n");
- printf(" Error count: %ju\n", entry->error_count);
- printf(" Submission queue ID: %u\n", entry->sqid);
- printf(" Command ID: %u\n", entry->cid);
+ printf(" Error count: %ju\n", letoh(entry->error_count));
+ printf(" Submission queue ID: %u\n", letoh(entry->sqid));
+ printf(" Command ID: %u\n", letoh(entry->cid));
/* TODO: Export nvme_status_string structures from kernel? */
printf(" Status:\n");
printf(" Phase tag: %d\n", p);
@@ -308,22 +266,27 @@ print_log_error(const struct nvme_controller_data *cdata __unused, void *buf, ui
printf(" Status code type: %d\n", sct);
printf(" More: %d\n", m);
printf(" DNR: %d\n", dnr);
- printf(" Error location: %u\n", entry->error_location);
- printf(" LBA: %ju\n", entry->lba);
- printf(" Namespace ID: %u\n", entry->nsid);
- printf(" Vendor specific info: %u\n", entry->vendor_specific);
- printf(" Transport type: %u\n", entry->trtype);
- printf(" Command specific info:%ju\n", entry->csi);
- printf(" Transport specific: %u\n", entry->ttsi);
+ printf(" Error location: %u\n", letoh(entry->error_location));
+ printf(" LBA: %ju\n", letoh(entry->lba));
+ printf(" Namespace ID: %u\n", letoh(entry->nsid));
+ printf(" Vendor specific info: %u\n", letoh(entry->vendor_specific));
+ printf(" Transport type: %u\n", letoh(entry->trtype));
+ printf(" Command specific info:%ju\n", letoh(entry->csi));
+ printf(" Transport specific: %u\n", letoh(entry->ttsi));
}
}
void
-print_temp(uint16_t t)
+print_temp_K(uint16_t t)
{
printf("%u K, %2.2f C, %3.2f F\n", t, (float)t - 273.15, (float)t * 9 / 5 - 459.67);
}
+void
+print_temp_C(uint16_t t)
+{
+ printf("%2.2f K, %u C, %3.2f F\n", (float)t + 273.15, t, (float)t * 9 / 5 + 32);
+}
static void
print_log_health(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused)
@@ -333,7 +296,7 @@ print_log_health(const struct nvme_controller_data *cdata __unused, void *buf, u
uint8_t warning;
int i;
- warning = health->critical_warning;
+ warning = letoh(health->critical_warning);
printf("SMART/Health Information Log\n");
printf("============================\n");
@@ -350,13 +313,13 @@ print_log_health(const struct nvme_controller_data *cdata __unused, void *buf, u
printf(" Volatile memory backup: %d\n",
!!(warning & NVME_CRIT_WARN_ST_VOLATILE_MEMORY_BACKUP));
printf("Temperature: ");
- print_temp(health->temperature);
+ print_temp_K(letoh(health->temperature));
printf("Available spare: %u\n",
- health->available_spare);
+ letoh(health->available_spare));
printf("Available spare threshold: %u\n",
- health->available_spare_threshold);
+ letoh(health->available_spare_threshold));
printf("Percentage used: %u\n",
- health->percentage_used);
+ letoh(health->percentage_used));
printf("Data units (512,000 byte) read: %s\n",
uint128_to_str(to128(health->data_units_read), cbuf, sizeof(cbuf)));
@@ -379,18 +342,18 @@ print_log_health(const struct nvme_controller_data *cdata __unused, void *buf, u
printf("No. error info log entries: %s\n",
uint128_to_str(to128(health->num_error_info_log_entries), cbuf, sizeof(cbuf)));
- printf("Warning Temp Composite Time: %d\n", health->warning_temp_time);
- printf("Error Temp Composite Time: %d\n", health->error_temp_time);
+ printf("Warning Temp Composite Time: %d\n", letoh(health->warning_temp_time));
+ printf("Error Temp Composite Time: %d\n", letoh(health->error_temp_time));
for (i = 0; i < 8; i++) {
- if (health->temp_sensor[i] == 0)
+ if (letoh(health->temp_sensor[i]) == 0)
continue;
printf("Temperature Sensor %d: ", i + 1);
- print_temp(health->temp_sensor[i]);
+ print_temp_K(letoh(health->temp_sensor[i]));
}
- printf("Temperature 1 Transition Count: %d\n", health->tmt1tc);
- printf("Temperature 2 Transition Count: %d\n", health->tmt2tc);
- printf("Total Time For Temperature 1: %d\n", health->ttftmt1);
- printf("Total Time For Temperature 2: %d\n", health->ttftmt2);
+ printf("Temperature 1 Transition Count: %d\n", letoh(health->tmt1tc));
+ printf("Temperature 2 Transition Count: %d\n", letoh(health->tmt2tc));
+ printf("Total Time For Temperature 1: %d\n", letoh(health->ttftmt1));
+ printf("Total Time For Temperature 2: %d\n", letoh(health->ttftmt2));
}
static void
@@ -403,13 +366,10 @@ print_log_firmware(const struct nvme_controller_data *cdata, void *buf, uint32_t
uint16_t oacs_fw;
uint8_t fw_num_slots;
- afi_slot = fw->afi >> NVME_FIRMWARE_PAGE_AFI_SLOT_SHIFT;
- afi_slot &= NVME_FIRMWARE_PAGE_AFI_SLOT_MASK;
+ afi_slot = NVMEV(NVME_FIRMWARE_PAGE_AFI_SLOT, fw->afi);
- oacs_fw = (cdata->oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) &
- NVME_CTRLR_DATA_OACS_FIRMWARE_MASK;
- fw_num_slots = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) &
- NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK;
+ oacs_fw = NVMEV(NVME_CTRLR_DATA_OACS_FIRMWARE, cdata->oacs);
+ fw_num_slots = NVMEV(NVME_CTRLR_DATA_FRMW_NUM_SLOTS, cdata->frmw);
printf("Firmware Slot Log\n");
printf("=================\n");
@@ -426,15 +386,10 @@ print_log_firmware(const struct nvme_controller_data *cdata, void *buf, uint32_t
else
status = "Inactive";
- if (fw->revision[i] == 0LLU)
+ if (fw->revision[i][0] == '\0')
printf("Empty\n");
else
- if (isprint(*(char *)&fw->revision[i]))
- printf("[%s] %.8s\n", status,
- (char *)&fw->revision[i]);
- else
- printf("[%s] %016jx\n", status,
- fw->revision[i]);
+ printf("[%s] %.8s\n", status, fw->revision[i]);
}
}
@@ -449,8 +404,8 @@ print_log_ns(const struct nvme_controller_data *cdata __unused, void *buf,
printf("Changed Namespace List\n");
printf("======================\n");
- for (i = 0; i < nitems(nsl->ns) && nsl->ns[i] != 0; i++) {
- printf("%08x\n", nsl->ns[i]);
+ for (i = 0; i < nitems(nsl->ns) && letoh(nsl->ns[i]) != 0; i++) {
+ printf("%08x\n", letoh(nsl->ns[i]));
}
}
@@ -468,42 +423,28 @@ print_log_command_effects(const struct nvme_controller_data *cdata __unused,
printf(" Command\tLBCC\tNCC\tNIC\tCCC\tCSE\tUUID\n");
for (i = 0; i < 255; i++) {
- s = ce->acs[i];
- if (((s >> NVME_CE_PAGE_CSUP_SHIFT) &
- NVME_CE_PAGE_CSUP_MASK) == 0)
+ s = letoh(ce->acs[i]);
+ if (NVMEV(NVME_CE_PAGE_CSUP, s) == 0)
continue;
printf("Admin\t%02x\t%s\t%s\t%s\t%s\t%u\t%s\n", i,
- ((s >> NVME_CE_PAGE_LBCC_SHIFT) &
- NVME_CE_PAGE_LBCC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_NCC_SHIFT) &
- NVME_CE_PAGE_NCC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_NIC_SHIFT) &
- NVME_CE_PAGE_NIC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_CCC_SHIFT) &
- NVME_CE_PAGE_CCC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_CSE_SHIFT) &
- NVME_CE_PAGE_CSE_MASK),
- ((s >> NVME_CE_PAGE_UUID_SHIFT) &
- NVME_CE_PAGE_UUID_MASK) ? "Yes" : "No");
+ NVMEV(NVME_CE_PAGE_LBCC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_NCC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_NIC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_CCC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_CSE, s),
+ NVMEV(NVME_CE_PAGE_UUID, s) != 0 ? "Yes" : "No");
}
for (i = 0; i < 255; i++) {
- s = ce->iocs[i];
- if (((s >> NVME_CE_PAGE_CSUP_SHIFT) &
- NVME_CE_PAGE_CSUP_MASK) == 0)
+ s = letoh(ce->iocs[i]);
+ if (NVMEV(NVME_CE_PAGE_CSUP, s) == 0)
continue;
printf("I/O\t%02x\t%s\t%s\t%s\t%s\t%u\t%s\n", i,
- ((s >> NVME_CE_PAGE_LBCC_SHIFT) &
- NVME_CE_PAGE_LBCC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_NCC_SHIFT) &
- NVME_CE_PAGE_NCC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_NIC_SHIFT) &
- NVME_CE_PAGE_NIC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_CCC_SHIFT) &
- NVME_CE_PAGE_CCC_MASK) ? "Yes" : "No",
- ((s >> NVME_CE_PAGE_CSE_SHIFT) &
- NVME_CE_PAGE_CSE_MASK),
- ((s >> NVME_CE_PAGE_UUID_SHIFT) &
- NVME_CE_PAGE_UUID_MASK) ? "Yes" : "No");
+ NVMEV(NVME_CE_PAGE_LBCC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_NCC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_NIC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_CCC, s) != 0 ? "Yes" : "No",
+ NVMEV(NVME_CE_PAGE_CSE, s),
+ NVMEV(NVME_CE_PAGE_UUID, s) != 0 ? "Yes" : "No");
}
}
@@ -517,9 +458,10 @@ print_log_res_notification(const struct nvme_controller_data *cdata __unused,
printf("Reservation Notification\n");
printf("========================\n");
- printf("Log Page Count: %ju\n", rn->log_page_count);
+ printf("Log Page Count: %ju\n",
+ (uintmax_t)letoh(rn->log_page_count));
printf("Log Page Type: ");
- switch (rn->log_page_type) {
+ switch (letoh(rn->log_page_type)) {
case 0:
printf("Empty Log Page\n");
break;
@@ -533,11 +475,11 @@ print_log_res_notification(const struct nvme_controller_data *cdata __unused,
printf("Reservation Preempted\n");
break;
default:
- printf("Unknown %x\n", rn->log_page_type);
+ printf("Unknown %x\n", letoh(rn->log_page_type));
break;
};
- printf("Number of Available Log Pages: %d\n", rn->available_log_pages);
- printf("Namespace ID: 0x%x\n", rn->nsid);
+ printf("Number of Available Log Pages: %d\n", letoh(rn->available_log_pages));
+ printf("Namespace ID: 0x%x\n", letoh(rn->nsid));
}
static void
@@ -546,16 +488,18 @@ print_log_sanitize_status(const struct nvme_controller_data *cdata __unused,
{
struct nvme_sanitize_status_page *ss;
u_int p;
+ uint16_t sprog, sstat;
ss = (struct nvme_sanitize_status_page *)buf;
printf("Sanitize Status\n");
printf("===============\n");
+ sprog = letoh(ss->sprog);
printf("Sanitize Progress: %u%% (%u/65535)\n",
- (ss->sprog * 100 + 32768) / 65536, ss->sprog);
+ (sprog * 100 + 32768) / 65536, sprog);
printf("Sanitize Status: ");
- switch ((ss->sstat >> NVME_SS_PAGE_SSTAT_STATUS_SHIFT) &
- NVME_SS_PAGE_SSTAT_STATUS_MASK) {
+ sstat = letoh(ss->sstat);
+ switch (NVMEV(NVME_SS_PAGE_SSTAT_STATUS, sstat)) {
case NVME_SS_PAGE_SSTAT_STATUS_NEVER:
printf("Never sanitized");
break;
@@ -572,24 +516,22 @@ print_log_sanitize_status(const struct nvme_controller_data *cdata __unused,
printf("Completed with deallocation");
break;
default:
- printf("Unknown");
+ printf("Unknown 0x%x", sstat);
break;
}
- p = (ss->sstat >> NVME_SS_PAGE_SSTAT_PASSES_SHIFT) &
- NVME_SS_PAGE_SSTAT_PASSES_MASK;
+ p = NVMEV(NVME_SS_PAGE_SSTAT_PASSES, sstat);
if (p > 0)
printf(", %d passes", p);
- if ((ss->sstat >> NVME_SS_PAGE_SSTAT_GDE_SHIFT) &
- NVME_SS_PAGE_SSTAT_GDE_MASK)
+ if (NVMEV(NVME_SS_PAGE_SSTAT_GDE, sstat) != 0)
printf(", Global Data Erased");
printf("\n");
- printf("Sanitize Command Dword 10: 0x%x\n", ss->scdw10);
- printf("Time For Overwrite: %u sec\n", ss->etfo);
- printf("Time For Block Erase: %u sec\n", ss->etfbe);
- printf("Time For Crypto Erase: %u sec\n", ss->etfce);
- printf("Time For Overwrite No-Deallocate: %u sec\n", ss->etfownd);
- printf("Time For Block Erase No-Deallocate: %u sec\n", ss->etfbewnd);
- printf("Time For Crypto Erase No-Deallocate: %u sec\n", ss->etfcewnd);
+ printf("Sanitize Command Dword 10: 0x%x\n", letoh(ss->scdw10));
+ printf("Time For Overwrite: %u sec\n", letoh(ss->etfo));
+ printf("Time For Block Erase: %u sec\n", letoh(ss->etfbe));
+ printf("Time For Crypto Erase: %u sec\n", letoh(ss->etfce));
+ printf("Time For Overwrite No-Deallocate: %u sec\n", letoh(ss->etfownd));
+ printf("Time For Block Erase No-Deallocate: %u sec\n", letoh(ss->etfbewnd));
+ printf("Time For Crypto Erase No-Deallocate: %u sec\n", letoh(ss->etfcewnd));
}
static const char *
@@ -613,13 +555,14 @@ print_log_self_test_status(const struct nvme_controller_data *cdata __unused,
{
struct nvme_device_self_test_page *dst;
uint32_t r;
+ uint16_t vs;
dst = buf;
printf("Device Self-test Status\n");
printf("=======================\n");
printf("Current Operation: ");
- switch (dst->curr_operation) {
+ switch (letoh(dst->curr_operation)) {
case 0x0:
printf("No device self-test operation in progress\n");
break;
@@ -633,19 +576,20 @@ print_log_self_test_status(const struct nvme_controller_data *cdata __unused,
printf("Vendor specific\n");
break;
default:
- printf("Reserved (0x%x)\n", dst->curr_operation);
+ printf("Reserved (0x%x)\n", letoh(dst->curr_operation));
}
- if (dst->curr_operation != 0)
- printf("Current Completion: %u%%\n", dst->curr_compl & 0x7f);
+ if (letoh(dst->curr_operation) != 0)
+ printf("Current Completion: %u%%\n", letoh(dst->curr_compl) & 0x7f);
printf("Results\n");
for (r = 0; r < 20; r++) {
uint64_t failing_lba;
- uint8_t code, res;
+ uint8_t code, res, status;
- code = (dst->result[r].status >> 4) & 0xf;
- res = dst->result[r].status & 0xf;
+ status = letoh(dst->result[r].status);
+ code = (status >> 4) & 0xf;
+ res = status & 0xf;
if (res == 0xf)
continue;
@@ -670,21 +614,24 @@ print_log_self_test_status(const struct nvme_controller_data *cdata __unused,
printf(" Reserved status 0x%x", res);
if (res == 7)
- printf(" starting in segment %u", dst->result[r].segment_num);
+ printf(" starting in segment %u",
+ letoh(dst->result[r].segment_num));
#define BIT(b) (1 << (b))
- if (dst->result[r].valid_diag_info & BIT(0))
- printf(" NSID=0x%x", dst->result[r].nsid);
- if (dst->result[r].valid_diag_info & BIT(1)) {
+ if (letoh(dst->result[r].valid_diag_info) & BIT(0))
+ printf(" NSID=0x%x", letoh(dst->result[r].nsid));
+ if (letoh(dst->result[r].valid_diag_info) & BIT(1)) {
memcpy(&failing_lba, dst->result[r].failing_lba,
sizeof(failing_lba));
- printf(" FLBA=0x%jx", failing_lba);
+ printf(" FLBA=0x%jx", (uintmax_t)letoh(failing_lba));
}
- if (dst->result[r].valid_diag_info & BIT(2))
- printf(" SCT=0x%x", dst->result[r].status_code_type);
- if (dst->result[r].valid_diag_info & BIT(3))
- printf(" SC=0x%x", dst->result[r].status_code);
+ if (letoh(dst->result[r].valid_diag_info) & BIT(2))
+ printf(" SCT=0x%x", letoh(dst->result[r].status_code_type));
+ if (letoh(dst->result[r].valid_diag_info) & BIT(3))
+ printf(" SC=0x%x", letoh(dst->result[r].status_code));
#undef BIT
+ memcpy(&vs, dst->result[r].vendor_specific, sizeof(vs));
+ printf(" VENDOR_SPECIFIC=0x%x", letoh(vs));
printf("\n");
}
}
@@ -802,11 +749,10 @@ logpage(const struct cmd *f, int argc, char *argv[])
if (read_controller_data(fd, &cdata))
errx(EX_IOERR, "Identify request failed");
- ns_smart = (cdata.lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) &
- NVME_CTRLR_DATA_LPA_NS_SMART_MASK;
+ ns_smart = NVMEV(NVME_CTRLR_DATA_LPA_NS_SMART, cdata.lpa);
/*
- * The log page attribtues indicate whether or not the controller
+ * The log page attributes indicate whether or not the controller
* supports the SMART/Health information log page on a per
* namespace basis.
*/
@@ -852,7 +798,8 @@ logpage(const struct cmd *f, int argc, char *argv[])
/* Read the log page */
buf = get_log_buffer(size);
- read_logpage(fd, opt.page, nsid, opt.lsp, opt.lsi, opt.rae, buf, size);
+ read_logpage(fd, opt.page, nsid, opt.lsp, opt.lsi, opt.rae,
+ 0, 0, 0, 0, buf, size);
print_fn(&cdata, buf, size);
close(fd);
diff --git a/sbin/nvmecontrol/modules/Makefile b/sbin/nvmecontrol/modules/Makefile
index e615eaffb8c9..f3c3572acb34 100644
--- a/sbin/nvmecontrol/modules/Makefile
+++ b/sbin/nvmecontrol/modules/Makefile
@@ -1,5 +1,6 @@
-# $FreeBSD$
-
-SUBDIR= intel wdc
+SUBDIR= intel
+SUBDIR+=micron
+SUBDIR+=samsung
+SUBDIR+=wdc
.include <bsd.subdir.mk>
diff --git a/sbin/nvmecontrol/modules/Makefile.inc b/sbin/nvmecontrol/modules/Makefile.inc
index bdc25f711a67..030b488e44e0 100644
--- a/sbin/nvmecontrol/modules/Makefile.inc
+++ b/sbin/nvmecontrol/modules/Makefile.inc
@@ -1,10 +1,7 @@
-# $FreeBSD$
-
-PACKAGE=runtime
+PACKAGE=nvme-tools
NVMECONTROLDIR= ${SRCTOP}/sbin/nvmecontrol
MK_INSTALLLIB= no
-MK_PROFILE= no
CFLAGS+= -I${NVMECONTROLDIR}
diff --git a/sbin/nvmecontrol/modules/intel/Makefile b/sbin/nvmecontrol/modules/intel/Makefile
index f2ba4f97aa3a..9e4eafa0feec 100644
--- a/sbin/nvmecontrol/modules/intel/Makefile
+++ b/sbin/nvmecontrol/modules/intel/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
LIB= intel
SRCS= intel.c
diff --git a/sbin/nvmecontrol/modules/intel/intel.c b/sbin/nvmecontrol/modules/intel/intel.c
index 8e3ed9e06cb9..6ffe2c4c1563 100644
--- a/sbin/nvmecontrol/modules/intel/intel.c
+++ b/sbin/nvmecontrol/modules/intel/intel.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2013 EMC Corp.
* All rights reserved.
@@ -29,9 +29,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -64,18 +61,21 @@ print_intel_temp_stats(const struct nvme_controller_data *cdata __unused, void *
printf("=====================\n");
printf("Current: ");
- print_temp(temp->current);
- printf("Overtemp Last Flags %#jx\n", (uintmax_t)temp->overtemp_flag_last);
- printf("Overtemp Lifetime Flags %#jx\n", (uintmax_t)temp->overtemp_flag_life);
+ print_temp_C(letoh(temp->current));
+ printf("Overtemp Last Flags %#jx\n",
+ (uintmax_t)letoh(temp->overtemp_flag_last));
+ printf("Overtemp Lifetime Flags %#jx\n",
+ (uintmax_t)letoh(temp->overtemp_flag_life));
printf("Max Temperature ");
- print_temp(temp->max_temp);
+ print_temp_C(letoh(temp->max_temp));
printf("Min Temperature ");
- print_temp(temp->min_temp);
+ print_temp_C(letoh(temp->min_temp));
printf("Max Operating Temperature ");
- print_temp(temp->max_oper_temp);
+ print_temp_C(letoh(temp->max_oper_temp));
printf("Min Operating Temperature ");
- print_temp(temp->min_oper_temp);
- printf("Estimated Temperature Offset: %ju C/K\n", (uintmax_t)temp->est_offset);
+ print_temp_C(letoh(temp->min_oper_temp));
+ printf("Estimated Temperature Offset: %ju C/K\n",
+ (uintmax_t)letoh(temp->est_offset));
}
/*
@@ -118,6 +118,8 @@ print_intel_write_lat_log(const struct nvme_controller_data *cdata __unused, voi
/*
* Table 19. 5.4 SMART Attributes. Others also implement this and some extra data not documented.
+ * Note: different models implement the same key values to mean different things. To fix that,
+ * we'd need to index this to a vendor/device values.
*/
void
print_intel_add_smart(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused)
@@ -138,11 +140,15 @@ print_intel_add_smart(const struct nvme_controller_data *cdata __unused, void *b
{ 0xe2, "Timed: Media Wear" },
{ 0xe3, "Timed: Host Read %" },
{ 0xe4, "Timed: Elapsed Time" },
+ { 0xe7, "Lifetime Temperature" },
+ { 0xe8, "Power" },
{ 0xea, "Thermal Throttle Status" },
{ 0xf0, "Retry Buffer Overflows" },
{ 0xf3, "PLL Lock Loss Count" },
{ 0xf4, "NAND Bytes Written" },
{ 0xf5, "Host Bytes Written" },
+ { 0xf9, "NAND GiB Written" },
+ { 0xfa, "NAND GiB Read" },
};
printf("Additional SMART Data Log\n");
@@ -170,17 +176,37 @@ print_intel_add_smart(const struct nvme_controller_data *cdata __unused, void *b
case 0xe2:
printf("%-32s: %3d %.3f%%\n", name, normalized, raw / 1024.0);
break;
+ case 0xe7:
+ printf("%-32s: %3d %#jx max: %dK min: %dK cur: %dK\n", name, normalized,
+ (uintmax_t)raw, le16dec(walker+5), le16dec(walker+7), le16dec(walker+9));
+ break;
+ case 0xe8:
+ printf("%-32s: %3d %#jx max: %dW min: %dW cur: %dW\n", name, normalized,
+ (uintmax_t)raw, le16dec(walker+5), le16dec(walker+7), le16dec(walker+9));
+ break;
case 0xea:
printf("%-32s: %3d %d%% %d times\n", name, normalized, walker[5], le32dec(walker+6));
break;
default:
- printf("%-32s: %3d %ju\n", name, normalized, (uintmax_t)raw);
+ printf("%-32s: %3d %ju %#jx\n", name, normalized, (uintmax_t)raw, (uintmax_t)raw);
break;
}
walker += 12;
}
}
+static void
+print_intel_drive_marketing_name(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused)
+{
+ const char *p = buf;
+
+ printf("Intel Drive Marketing Name Log\n");
+ printf("=======================\n");
+ printf("%.*s\n", 29, p);
+}
+
+#define INTEL_LOG_DRIVE_MARKETING_NAME 0xdd
+
NVME_LOGPAGE(intel_temp,
INTEL_LOG_TEMP_STATS, "intel", "Temperature Stats",
print_intel_temp_stats, sizeof(struct intel_log_temp_stats));
@@ -190,6 +216,9 @@ NVME_LOGPAGE(intel_rlat,
NVME_LOGPAGE(intel_wlat,
INTEL_LOG_WRITE_LAT_LOG, "intel", "Write Latencies",
print_intel_write_lat_log, DEFAULT_SIZE);
-NVME_LOGPAGE(intel_smart,
+NVME_LOGPAGE(intel_smart, /* Note: Samsung and Micron also use this */
INTEL_LOG_ADD_SMART, "intel", "Extra Health/SMART Data",
print_intel_add_smart, DEFAULT_SIZE);
+NVME_LOGPAGE(intel_dmn,
+ INTEL_LOG_DRIVE_MARKETING_NAME, "intel", "Drive Marketing Name Log",
+ print_intel_drive_marketing_name, DEFAULT_SIZE);
diff --git a/sbin/nvmecontrol/modules/micron/Makefile b/sbin/nvmecontrol/modules/micron/Makefile
new file mode 100644
index 000000000000..3cefd455f711
--- /dev/null
+++ b/sbin/nvmecontrol/modules/micron/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+LIB= micron
+SRCS= micron.c
+
+.include <bsd.lib.mk>
diff --git a/sbin/nvmecontrol/modules/micron/micron.c b/sbin/nvmecontrol/modules/micron/micron.c
new file mode 100644
index 000000000000..2d4731e7da47
--- /dev/null
+++ b/sbin/nvmecontrol/modules/micron/micron.c
@@ -0,0 +1,129 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2022 Wanpeng Qian <wanpengqian@gmail.com>
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ioccom.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/endian.h>
+
+#include "nvmecontrol.h"
+
+static void
+print_micron_unique_smart(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused)
+{
+ uint8_t *walker = buf;
+ uint8_t *end = walker + 150;
+ const char *name;
+ uint64_t raw;
+ uint8_t normalized;
+
+ static struct kv_name kv[] =
+ {
+ { 0xf9, "NAND Writes 1GiB" },
+ { 0xfa, "NAND Reads 1GiB" },
+ { 0xea, "Thermal Throttle Status" },
+ { 0xe7, "Temperature" },
+ { 0xe8, "Power Consumption" },
+ { 0xaf, "Power Loss Protection" },
+ };
+
+ printf("Vendor Unique SMART Information\n");
+ printf("=========================\n");
+ /*
+ * walker[0] = Key
+ * walker[1,2] = reserved
+ * walker[3] = Normalized Value
+ * walker[4] = reserved
+ * walker[5..10] = Little Endian Raw value
+ * (or other represenations)
+ * walker[11] = reserved
+ */
+ while (walker < end) {
+ name = kv_lookup(kv, nitems(kv), *walker);
+ normalized = walker[3];
+ raw = le48dec(walker + 5);
+ switch (*walker){
+ case 0:
+ break;
+ case 0xf9:
+ /* FALLTHOUGH */
+ case 0xfa:
+ printf("%2X %-24s: %ju GiB\n", *walker, name, (uintmax_t)raw);
+ break;
+ case 0xea:
+ printf("%2X %-24s:", *walker, name);
+ if (*(walker + 5) == 0)
+ printf(" inactive\n");
+ if (*(walker + 5) == 1)
+ printf(" active, total throttling time %u mins\n", le32dec(walker + 6));
+ break;
+ case 0xe7:
+ printf("%2X %-24s: max ", *walker, name);
+ print_temp_C(le16dec(walker + 5));
+ printf(" : min ");
+ print_temp_C(le16dec(walker + 7));
+ printf(" : cur ");
+ print_temp_C(le16dec(walker + 9));
+ break;
+ case 0xe8:
+ printf("%2X %-24s: max %u W, min %u W, ave %u W\n",
+ *walker, name, le16dec(walker + 5), le16dec(walker + 7), le16dec(walker + 9));
+ break;
+ case 0xaf:
+ printf("%2X %-24s:", *walker, name);
+ if (normalized == 100)
+ printf(" success");
+ if (normalized == 0)
+ printf(" failed");
+ printf(" %3d\n", normalized);
+ break;
+ default:
+ printf("%2X %-24s: %3d %ju\n",
+ *walker, name, normalized, (uintmax_t)raw);
+ break;
+ }
+ walker += 12;
+ }
+}
+
+#define MICRON_LOG_UNIQUE_SMART 0xca
+
+NVME_LOGPAGE(micron_smart,
+ MICRON_LOG_UNIQUE_SMART, "micron", "Vendor Unique SMART Information",
+ print_micron_unique_smart, DEFAULT_SIZE);
diff --git a/sbin/nvmecontrol/modules/samsung/Makefile b/sbin/nvmecontrol/modules/samsung/Makefile
new file mode 100644
index 000000000000..750dd07cbeb4
--- /dev/null
+++ b/sbin/nvmecontrol/modules/samsung/Makefile
@@ -0,0 +1,4 @@
+LIB= samsung
+SRCS= samsung.c
+
+.include <bsd.lib.mk>
diff --git a/sbin/nvmecontrol/modules/samsung/samsung.c b/sbin/nvmecontrol/modules/samsung/samsung.c
new file mode 100644
index 000000000000..82e7af8ecd33
--- /dev/null
+++ b/sbin/nvmecontrol/modules/samsung/samsung.c
@@ -0,0 +1,162 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2022 Wanpeng Qian <wanpengqian@gmail.org>
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/ioccom.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/endian.h>
+
+#include "nvmecontrol.h"
+
+struct samsung_log_extended_smart
+{
+ uint8_t kv[256];/* Key-Value pair */
+ uint32_t lwaf; /* Lifetime Write Amplification */
+ uint32_t thwaf; /* Trailing Hour Write Amplification Factor */
+ uint64_t luw[2]; /* Lifetime User Writes */
+ uint64_t lnw[2]; /* Lifetime NAND Writes */
+ uint64_t lur[2]; /* Lifetime User Reads */
+ uint32_t lrbc; /* Lifetime Retired Block Count */
+ uint16_t ct; /* Current Temperature */
+ uint16_t ch; /* Capacitor Health */
+ uint32_t luurb; /* Lifetime Unused Reserved Block */
+ uint64_t rrc; /* Read Reclaim Count */
+ uint64_t lueccc; /* Lifetime Uncorrectable ECC count */
+ uint32_t lurb; /* Lifetime Used Reserved Block */
+ uint64_t poh[2]; /* Power on Hours */
+ uint64_t npoc[2];/* Normal Power Off Count */
+ uint64_t spoc[2];/* Sudden Power Off Count */
+ uint32_t pi; /* Performance Indicator */
+} __packed;
+
+static void
+print_samsung_extended_smart(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused)
+{
+ struct samsung_log_extended_smart *temp = buf;
+ char cbuf[UINT128_DIG + 1];
+ uint8_t *walker = buf;
+ uint8_t *end = walker + 150;
+ const char *name;
+ uint64_t raw;
+ uint8_t normalized;
+
+ static struct kv_name kv[] =
+ {
+ { 0xab, "Lifetime Program Fail Count" },
+ { 0xac, "Lifetime Erase Fail Count" },
+ { 0xad, "Lifetime Wear Leveling Count" },
+ { 0xb8, "Lifetime End to End Error Count" },
+ { 0xc7, "Lifetime CRC Error Count" },
+ { 0xe2, "Media Wear %" },
+ { 0xe3, "Host Read %" },
+ { 0xe4, "Workload Timer" },
+ { 0xea, "Lifetime Thermal Throttle Status" },
+ { 0xf4, "Lifetime Phy Pages Written Count" },
+ { 0xf5, "Lifetime Data Units Written" },
+ };
+
+ printf("Extended SMART Information\n");
+ printf("=========================\n");
+ /*
+ * walker[0] = Key
+ * walker[1,2] = reserved
+ * walker[3] = Normalized Value
+ * walker[4] = reserved
+ * walker[5..10] = Little Endian Raw value
+ * (or other represenations)
+ * walker[11] = reserved
+ */
+ while (walker < end) {
+ name = kv_lookup(kv, nitems(kv), *walker);
+ normalized = walker[3];
+ raw = le48dec(walker + 5);
+ switch (*walker){
+ case 0:
+ break;
+ case 0xad:
+ printf("%2X %-41s: %3d min: %u max: %u ave: %u\n",
+ le16dec(walker), name, normalized,
+ le16dec(walker + 5), le16dec(walker + 7), le16dec(walker + 9));
+ break;
+ case 0xe2:
+ printf("%2X %-41s: %3d %.3f%%\n",
+ le16dec(walker), name, normalized,
+ raw / 1024.0);
+ break;
+ case 0xea:
+ printf("%2X %-41s: %3d %d%% %d times\n",
+ le16dec(walker), name, normalized,
+ walker[5], le32dec(walker+6));
+ break;
+ default:
+ printf("%2X %-41s: %3d %ju\n",
+ le16dec(walker), name, normalized,
+ (uintmax_t)raw);
+ break;
+ }
+ walker += 12;
+ }
+
+ printf(" Lifetime Write Amplification Factor : %u\n", le32dec(&temp->lwaf));
+ printf(" Trailing Hour Write Amplification Factor : %u\n", le32dec(&temp->thwaf));
+ printf(" Lifetime User Writes : %s\n",
+ uint128_to_str(to128(temp->luw), cbuf, sizeof(cbuf)));
+ printf(" Lifetime NAND Writes : %s\n",
+ uint128_to_str(to128(temp->lnw), cbuf, sizeof(cbuf)));
+ printf(" Lifetime User Reads : %s\n",
+ uint128_to_str(to128(temp->lur), cbuf, sizeof(cbuf)));
+ printf(" Lifetime Retired Block Count : %u\n", le32dec(&temp->lrbc));
+ printf(" Current Temperature : ");
+ print_temp_K(le16dec(&temp->ct));
+ printf(" Capacitor Health : %u\n", le16dec(&temp->ch));
+ printf(" Reserved Erase Block Count : %u\n", le32dec(&temp->luurb));
+ printf(" Read Reclaim Count : %ju\n", (uintmax_t) le64dec(&temp->rrc));
+ printf(" Lifetime Uncorrectable ECC Count : %ju\n", (uintmax_t) le64dec(&temp->lueccc));
+ printf(" Reallocated Block Count : %u\n", le32dec(&temp->lurb));
+ printf(" Power on Hours : %s\n",
+ uint128_to_str(to128(temp->poh), cbuf, sizeof(cbuf)));
+ printf(" Normal Power Off Count : %s\n",
+ uint128_to_str(to128(temp->npoc), cbuf, sizeof(cbuf)));
+ printf(" Sudden Power Off Count : %s\n",
+ uint128_to_str(to128(temp->spoc), cbuf, sizeof(cbuf)));
+ printf(" Performance Indicator : %u\n", le32dec(&temp->pi));
+}
+
+#define SAMSUNG_LOG_EXTEND_SMART 0xca
+
+NVME_LOGPAGE(samsung_extended_smart,
+ SAMSUNG_LOG_EXTEND_SMART, "samsung", "Extended SMART Information",
+ print_samsung_extended_smart, DEFAULT_SIZE);
diff --git a/sbin/nvmecontrol/modules/wdc/Makefile b/sbin/nvmecontrol/modules/wdc/Makefile
index 40c77254fbea..8f8185d5f7ad 100644
--- a/sbin/nvmecontrol/modules/wdc/Makefile
+++ b/sbin/nvmecontrol/modules/wdc/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
LIB= wdc
SRCS= wdc.c
diff --git a/sbin/nvmecontrol/modules/wdc/wdc.c b/sbin/nvmecontrol/modules/wdc/wdc.c
index 050458a8812f..55758dc7e037 100644
--- a/sbin/nvmecontrol/modules/wdc/wdc.c
+++ b/sbin/nvmecontrol/modules/wdc/wdc.c
@@ -23,9 +23,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
#include <sys/endian.h>
@@ -268,7 +265,7 @@ static void
wdc_get_dui_log_size(int fd, uint32_t opcode, uint8_t data_area,
uint64_t *log_size, int len_off)
{
- uint8_t *hdr;
+ uint8_t *hdr, *tofree;
uint8_t max_sections;
int i, j;
uint16_t hdr_ver;
@@ -277,7 +274,7 @@ wdc_get_dui_log_size(int fd, uint32_t opcode, uint8_t data_area,
dui_size = 0;
len = 1024;
- hdr = (uint8_t*)malloc(len);
+ tofree = hdr = (uint8_t*)malloc(len);
if (hdr == NULL)
errx(EX_OSERR, "Can't get buffer to read header");
wdc_get_data_dui(fd, opcode, len, 0, hdr, len);
@@ -315,7 +312,7 @@ wdc_get_dui_log_size(int fd, uint32_t opcode, uint8_t data_area,
errx(EX_PROTOCOL, "ERROR : No valid header ");
*log_size = dui_size;
- free(hdr);
+ free(tofree);
}
static void
@@ -591,7 +588,7 @@ print_hgst_info_background_scan(void *buf, uint16_t subtype __unused, uint8_t re
return;
}
if (code != 0) {
- printf("Expceted code 0, found code %#x\n", code);
+ printf("Expected code 0, found code %#x\n", code);
return;
}
pom = le32dec(walker);
@@ -783,7 +780,6 @@ static void
print_hgst_info_log(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused)
{
uint8_t *walker, *end, *subpage;
- int pages;
uint16_t len;
uint8_t subtype, res;
@@ -791,8 +787,7 @@ print_hgst_info_log(const struct nvme_controller_data *cdata __unused, void *buf
printf("===================\n");
walker = buf;
- pages = *walker++;
- walker++;
+ walker += 2; /* Page count */
len = le16dec(walker);
walker += 2;
end = walker + len; /* Length is exclusive of this header */
diff --git a/sbin/nvmecontrol/nc_util.c b/sbin/nvmecontrol/nc_util.c
index e2ad59b2fd23..6b02ac0098ec 100644
--- a/sbin/nvmecontrol/nc_util.c
+++ b/sbin/nvmecontrol/nc_util.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2017 Netflix, Inc.
*
@@ -26,8 +26,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/endian.h>
#include "nvmecontrol.h"
diff --git a/sbin/nvmecontrol/ns.c b/sbin/nvmecontrol/ns.c
index 5c537e920dc3..c538338eb6c3 100644
--- a/sbin/nvmecontrol/ns.c
+++ b/sbin/nvmecontrol/ns.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2017 Netflix, Inc.
* Copyright (C) 2018-2019 Alexander Motin <mav@FreeBSD.org>
@@ -26,9 +26,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -336,7 +333,7 @@ static struct identify_options {
static const struct opts identify_opts[] = {
OPT("hex", 'x', arg_none, identify_opt, hex,
- "Print identiy information in hex"),
+ "Print identity information in hex"),
OPT("verbose", 'v', arg_none, identify_opt, verbose,
"More verbosity: print entire identify table"),
OPT("nsid", 'n', arg_uint32, identify_opt, nsid,
@@ -419,8 +416,7 @@ nsactive(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
memset(&pt, 0, sizeof(pt));
@@ -465,8 +461,7 @@ nsallocated(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
memset(&pt, 0, sizeof(pt));
@@ -511,8 +506,7 @@ nscontrollers(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
memset(&pt, 0, sizeof(pt));
@@ -537,7 +531,7 @@ nscontrollers(const struct cmd *f, int argc, char *argv[])
/*
* NS MGMT Command specific status values:
* 0xa = Invalid Format
- * 0x15 = Namespace Insuffience capacity
+ * 0x15 = Namespace Insufficient capacity
* 0x16 = Namespace ID unavailable (number namespaces exceeded)
* 0xb = Thin Provisioning Not supported
*/
@@ -573,34 +567,46 @@ nscreate(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
- /* Allow namespaces sharing if Multi-Path I/O is supported. */
- if (create_opt.nmic == NONE) {
- create_opt.nmic = cd.mic ? (NVME_NS_DATA_NMIC_MAY_BE_SHARED_MASK <<
- NVME_NS_DATA_NMIC_MAY_BE_SHARED_SHIFT) : 0;
- }
-
memset(&nsdata, 0, sizeof(nsdata));
nsdata.nsze = create_opt.nsze;
nsdata.ncap = create_opt.cap;
- if (create_opt.flbas == NONE)
- nsdata.flbas = ((create_opt.lbaf & NVME_NS_DATA_FLBAS_FORMAT_MASK)
- << NVME_NS_DATA_FLBAS_FORMAT_SHIFT) |
- ((create_opt.mset & NVME_NS_DATA_FLBAS_EXTENDED_MASK)
- << NVME_NS_DATA_FLBAS_EXTENDED_SHIFT);
- else
+ if (create_opt.flbas != NONE) {
nsdata.flbas = create_opt.flbas;
- if (create_opt.dps == NONE)
- nsdata.dps = ((create_opt.pi & NVME_NS_DATA_DPS_MD_START_MASK)
- << NVME_NS_DATA_DPS_MD_START_SHIFT) |
- ((create_opt.pil & NVME_NS_DATA_DPS_PIT_MASK)
- << NVME_NS_DATA_DPS_PIT_SHIFT);
- else
+ } else {
+ /* Default to the first format, whatever it is. */
+ nsdata.flbas = 0;
+ if (create_opt.lbaf != NONE) {
+ nsdata.flbas |= NVMEF(NVME_NS_DATA_FLBAS_FORMAT,
+ create_opt.lbaf);
+ }
+ if (create_opt.mset != NONE) {
+ nsdata.flbas |= NVMEF(NVME_NS_DATA_FLBAS_EXTENDED,
+ create_opt.mset);
+ }
+ }
+ if (create_opt.dps != NONE) {
nsdata.dps = create_opt.dps;
- nsdata.nmic = create_opt.nmic;
+ } else {
+ /* Default to protection disabled. */
+ nsdata.dps = 0;
+ if (create_opt.pi != NONE) {
+ nsdata.dps |= NVMEF(NVME_NS_DATA_DPS_MD_START,
+ create_opt.pi);
+ }
+ if (create_opt.pil != NONE) {
+ nsdata.dps |= NVMEF(NVME_NS_DATA_DPS_PIT,
+ create_opt.pil);
+ }
+ }
+ if (create_opt.nmic != NONE) {
+ nsdata.nmic = create_opt.nmic;
+ } else {
+ /* Allow namespaces sharing if Multi-Path I/O is supported. */
+ nsdata.nmic = NVMEF(NVME_NS_DATA_NMIC_MAY_BE_SHARED, !!cd.mic);
+ }
nvme_namespace_data_swapbytes(&nsdata);
memset(&pt, 0, sizeof(pt));
@@ -614,8 +620,7 @@ nscreate(const struct cmd *f, int argc, char *argv[])
if (nvme_completion_is_error(&pt.cpl)) {
errx(EX_IOERR, "namespace creation failed: %s",
- get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) &
- NVME_STATUS_SC_MASK));
+ get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status)));
}
printf("namespace %d created\n", pt.cpl.cdw0);
exit(0);
@@ -641,7 +646,7 @@ nsdelete(const struct cmd *f, int argc, char *argv[])
open_dev(path, &fd, 1, 1);
} else if (delete_opt.nsid == NONE - 1) {
close(fd);
- fprintf(stderr, "No NSID specified");
+ fprintf(stderr, "No NSID specified\n");
arg_help(argc, argv, f);
}
if (delete_opt.nsid != NONE - 1)
@@ -651,8 +656,7 @@ nsdelete(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
memset(&pt, 0, sizeof(pt));
@@ -668,8 +672,7 @@ nsdelete(const struct cmd *f, int argc, char *argv[])
if (nvme_completion_is_error(&pt.cpl)) {
errx(EX_IOERR, "namespace deletion failed: %s",
- get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) &
- NVME_STATUS_SC_MASK));
+ get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status)));
}
printf("namespace %d deleted\n", nsid);
exit(0);
@@ -709,7 +712,7 @@ nsattach(const struct cmd *f, int argc, char *argv[])
open_dev(path, &fd, 1, 1);
} else if (attach_opt.nsid == NONE) {
close(fd);
- fprintf(stderr, "No NSID specified");
+ fprintf(stderr, "No NSID specified\n");
arg_help(argc, argv, f);
}
if (attach_opt.nsid != NONE)
@@ -718,8 +721,7 @@ nsattach(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
if (attach_opt.ctrlrid == NONE) {
@@ -755,8 +757,7 @@ nsattach(const struct cmd *f, int argc, char *argv[])
if (nvme_completion_is_error(&pt.cpl)) {
errx(EX_IOERR, "namespace attach failed: %s",
- get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) &
- NVME_STATUS_SC_MASK));
+ get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status)));
}
printf("namespace %d attached\n", nsid);
exit(0);
@@ -781,7 +782,7 @@ nsdetach(const struct cmd *f, int argc, char *argv[])
open_dev(path, &fd, 1, 1);
} else if (detach_opt.nsid == NONE) {
close(fd);
- fprintf(stderr, "No NSID specified");
+ fprintf(stderr, "No NSID specified\n");
arg_help(argc, argv, f);
}
if (detach_opt.nsid != NONE)
@@ -790,8 +791,7 @@ nsdetach(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
if (detach_opt.ctrlrid == NONE) {
@@ -834,8 +834,7 @@ nsdetach(const struct cmd *f, int argc, char *argv[])
if (nvme_completion_is_error(&pt.cpl)) {
errx(EX_IOERR, "namespace detach failed: %s",
- get_res_str((pt.cpl.status >> NVME_STATUS_SC_SHIFT) &
- NVME_STATUS_SC_MASK));
+ get_res_str(NVMEV(NVME_STATUS_SC, pt.cpl.status)));
}
printf("namespace %d detached\n", nsid);
exit(0);
@@ -860,7 +859,7 @@ nsattached(const struct cmd *f, int argc, char *argv[])
open_dev(path, &fd, 1, 1);
} else if (attached_opt.nsid == NONE) {
close(fd);
- fprintf(stderr, "No NSID specified");
+ fprintf(stderr, "No NSID specified\n");
arg_help(argc, argv, f);
}
if (attached_opt.nsid != NONE)
@@ -869,8 +868,7 @@ nsattached(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
memset(&pt, 0, sizeof(pt));
@@ -914,7 +912,7 @@ nsidentify(const struct cmd *f, int argc, char *argv[])
open_dev(path, &fd, 1, 1);
} else if (identify_opt.nsid == NONE) {
close(fd);
- fprintf(stderr, "No NSID specified");
+ fprintf(stderr, "No NSID specified\n");
arg_help(argc, argv, f);
}
if (identify_opt.nsid != NONE)
@@ -923,8 +921,7 @@ nsidentify(const struct cmd *f, int argc, char *argv[])
errx(EX_IOERR, "Identify request failed");
/* Check that controller can execute this command. */
- if (((cd.oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
- NVME_CTRLR_DATA_OACS_NSMGMT_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_NSMGMT, cd.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support namespace management");
memset(&pt, 0, sizeof(pt));
diff --git a/sbin/nvmecontrol/nsid.c b/sbin/nvmecontrol/nsid.c
index 34671901b49c..c49cec246737 100644
--- a/sbin/nvmecontrol/nsid.c
+++ b/sbin/nvmecontrol/nsid.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Alexander Motin <mav@FreeBSD.org>
*
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <stdio.h>
diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8
index 7d70e1762f73..dc757bcf90c3 100644
--- a/sbin/nvmecontrol/nvmecontrol.8
+++ b/sbin/nvmecontrol/nvmecontrol.8
@@ -33,9 +33,7 @@
.\"
.\" Author: Jim Harris <jimharris@FreeBSD.org>
.\"
-.\" $FreeBSD$
-.\"
-.Dd December 19, 2020
+.Dd July 9, 2025
.Dt NVMECONTROL 8
.Os
.Sh NAME
@@ -44,6 +42,7 @@
.Sh SYNOPSIS
.Nm
.Ic devlist
+.Op Fl h
.Nm
.Ic identify
.Op Fl v
@@ -128,10 +127,10 @@
.Aq Ar namespace-id
.Nm
.Ic resv register
+.Op Fl i
.Op Fl c Ar crkey
.Aq Fl k Ar nrkey
.Aq Fl r Ar rrega
-.Op Fl i Ar iekey
.Op Fl p Ar cptpl
.Aq Ar namespace-id
.Nm
@@ -156,7 +155,7 @@
.Ic format
.Op Fl f Ar fmt
.Op Fl m Ar mset
-.Op Fl o Ar pi
+.Op Fl p Ar pi
.Op Fl l Ar pil
.Op Fl E
.Op Fl C
@@ -206,9 +205,69 @@
.Ic io-passthru
.Op args
.Aq Ar namespace-id
+.Nm
+.Ic discover
+.Op Fl v
+.Op Fl t Ar transport
+.Op Fl q Ar HostNQN
+.Nm
+.Ic connect
+.Op Fl FGg
+.Op Fl c Ar cntl-id
+.Op Fl i Ar queues
+.Op Fl k Ar seconds
+.Op Fl l Ar seconds
+.Op Fl r Ar seconds
+.Op Fl t Ar transport
+.Op Fl q Ar HostNQN
+.Op Fl Q Ar entries
+.Aq Ar address
+.Aq Ar SubNQN
+.Nm
+.Ic connect-all
+.Op Fl FGg
+.Op Fl i Ar queues
+.Op Fl k Ar seconds
+.Op Fl l Ar seconds
+.Op Fl r Ar seconds
+.Op Fl t Ar transport
+.Op Fl q Ar HostNQN
+.Op Fl Q Ar entries
+.Aq Ar address
+.Nm
+.Ic disconnect
+.Aq Ar device-id | Ar namespace-id | Ar SubNQN
+.Nm
+.Ic reconnect
+.Aq Ar device-id
+.Nm
+.Ic reconnect
+.Op Fl FGg
+.Op Fl i Ar queues
+.Op Fl k Ar seconds
+.Op Fl l Ar seconds
+.Op Fl r Ar seconds
+.Op Fl t Ar transport
+.Op Fl q Ar HostNQN
+.Op Fl Q Ar entries
+.Aq Ar device-id
+.Aq Ar address
+.Nm
+.Ic telemetry-log
+.Fl O Ar output-file
+.Op Fl d Ar data-area
+.Aq Ar device-id
.Sh DESCRIPTION
-NVM Express (NVMe) is a storage protocol standard, for SSDs and other
-high-speed storage devices over PCI Express.
+NVM Express (NVMe) is a storage protocol standard for SSDs and other
+high-speed storage devices over PCI Express as well as remote storage
+devices accessed via a network fabric.
+.Ss devlist
+List all NVMe controllers and namespaces along with their device nodes.
+With the
+.Fl h
+argument, use unit suffixes: Byte, Kibibyte, Mebibyte, Gibibyte, Tebibyte
+and Pebibyte (based on powers of 1024) when showing the disk space.
+By default, uses Mebibyte.
.Ss identify
The identify commands reports information from the drive's
.Dv IDENTIFY_CONTROLLER
@@ -244,7 +303,8 @@ data associated with that drive.
.El
.Ss logpage
The logpage command knows how to print log pages of various types.
-It also knows about vendor specific log pages from hgst/wdc and intel.
+It also knows about vendor specific log pages from HGST/WDC, Samsung,
+Micron and Intel.
Note that some vendors use the same log page numbers for different data.
.Pp
.Bl -tag -compact -width "Page 0x00"
@@ -269,11 +329,15 @@ Advanced SMART information (WDC/HGST)
.It Dv Page 0xc1
Read latency stats (Intel)
.It Dv Page 0xc2
-Wite latency stats (Intel)
+Write latency stats (Intel)
.It Dv Page 0xc5
Temperature stats (Intel)
.It Dv Page 0xca
Advanced SMART information (Intel)
+.It Dv Page 0xca
+Extended SMART information (Samsung)
+.It Dv Page 0xca
+Vendor Unique SMART information (Micron)
.El
.Pp
Specifying
@@ -294,6 +358,47 @@ will set Retain Asynchronous Event.
Various namespace management commands.
If namespace management is supported by device, allow list, create and delete
namespaces, list, attach and detach controllers to namespaces.
+Each NVM device consists of one or more NVM subsystems.
+Each NVM subsystem has one or more NVM ports.
+Each NVM port is attached to one or more NVM controllers (though typically 1).
+Each NVM controller is attached to one or more namespaces.
+.Pp
+After a namespace is created, it is considered
+.Dq allocated .
+All namespaces that have not been created are unallocated.
+An allocated namespace may be active or inactive.
+An active namespace is attached to the controller and may be interacted with.
+A namespace can move from active to inactive when detached.
+An allocated namespace may be deleted to become unallocated.
+For more details on the nuances of NVM namespaces, please see section 2
+.Em Theory of Operation
+and section 3
+.Em NVM Express Architecture
+of the latest NVM standard.
+.Ss ns active
+Provide a list of active namespace identifiers for the givne NVM controller.
+.Ss ns allocated
+Provide a list of allocated namespace identifiers for the givne NVM controller.
+.Ss ns attach
+Attach an nsid to a controller.
+The primary controller is used if one is not specified.
+.Ss ns attached
+Provide a list of controllers attached to a nsid.
+If only a nvme controller argument is provided, a nsid must also be specified.
+.Ss ns controllers
+Provide a list of all controllers in the NVM subsystem.
+.Ss ns create
+Creates a new namespace.
+.Ss ns delete
+Delete a namespace.
+It must be currently inactive.
+.Ss ns detach
+Detach a namespace from a controller.
+The namespace will become inaccessible, but its contents will remain if it is
+.Em activated
+again.
+.Ss ns identify
+Print detailed information about the namespace.
.Ss nsid
Reports the namespace id and controller device associated with the
.Aq Ar namespace-id
@@ -393,24 +498,62 @@ Use Extended Data Structure.
.Ss format
Format either specified namespace, or all namespaces of specified controller,
using specified parameters:
+.Bl -tag -width 8n
+.It Fl f Ar fmt
+The index
.Ar fmt
-LBA Format,
+of the parameters to use.
+LBA Format #, as specified in the identification of the namespace using
+.Dq nvmecontrol identify
+command with a namespace specified maps this index into these parameters.
+.It Fl m Ar mset
+Metadata Setting.
.Ar mset
-Metadata Settings,
-.Ar pi
-Protection Information,
-.Ar pil
+.Bl -tag -compact -width 6n
+.It Dv 0
+do not transfer metadata with LBA information
+.It Dv 1
+Transfer the metadata as part of the extended LBA information.
+.El
+.It Fl p Ar pi
+Protection Information.
+.Bl -tag -compact -width 6n
+.It Dv 0
+Protection Information not enabled.
+.It Dv 1
+Type 1 information protection enabled.
+.It Dv 2
+Type 2 information protection enabled.
+.It Dv 3
+Type 3 information protection enabled.
+.El
+.It Fl l Ar pil
Protection Information Location.
+.Bl -tag -compact -width 6n
+.It Dv 0
+Transfer the protection metadata as the last N bytes of the transfer.
+.It Dv 1
+Transfer the protection metadata as the first N bytes of the transfer.
+.El
+.It Fl E
+Enables User Data Erase during format.
+All users data is erased and subsequent reads are indeterminate.
+The drive may implement this as a cryptographic erase or it may
+physically erase the underlying media.
+.It Fl C
+Enables Cryptographic Erase during format.
+All user data is erased cryptographically by deleting the encryption key,
+rendering it unintelligible.
+.El
+.Pp
When formatting specific namespace, existing values are used as defaults.
When formatting all namespaces, all parameters should be specified.
Some controllers may not support formatting or erasing specific or all
namespaces.
-Option
-.Fl E
-enables User Data Erase during format.
-Option
-.Fl C
-enables Cryptographic Erase during format.
+The
+.Xr nvme 4
+driver does not currently support metadata and protection information
+transfers.
.Ss sanitize
Sanitize NVM subsystem of specified controller,
using specified parameters:
@@ -441,6 +584,16 @@ A failed sanitize operation can only be exited if it was
run in the unrestricted completion mode, as provided by the
.Fl U
argument.
+.It 1, 2, 3, 4
+nvme-cli compatible
+.Fl a
+values for
+.Dq exitfailure ,
+.Dq block ,
+.Dq overwrite ,
+and
+.Dq crypto
+respectively.
.El
.It Fl c Ar passes
The number of passes when performing an
@@ -579,6 +732,7 @@ Show all the command values on stdout.
.It Fl w -write
Command writes data to the device.
.El
+.Pp
Send arbitrary commands to the device.
Can be used to extract vendor specific logs.
Transfers to/from the device possible, but limited to
@@ -588,6 +742,140 @@ Commands either read data or write it, but not both.
Commands needing metadata are not supported by the
.Xr nvme 4
drive.
+.Ss discover
+List the remote controllers advertised by a remote Discovery Controller:
+.Bl -tag -width 6n
+.It Fl t Ar transport
+Transport to use.
+The default is
+.Ar tcp .
+.It Fl q Ar HostNQN
+NVMe Qualified Name to use for this host.
+By default an NQN is auto-generated from the current host's UUID.
+.It Fl v
+Display the
+.Dv IDENTIFY_CONTROLLER
+data for the Discovery Controller.
+.El
+.Ss connect
+Establish an association with the I/O controller named
+.Ar SubNQN
+at
+.Ar address .
+The address must include a port.
+.Pp
+An admin queue pair and one or more I/O queue pairs are created and handed
+off to the kernel to create a new controller device.
+.Bl -tag -width 6n
+.It Fl c Ar cntl-id
+Remote controller ID to request:
+.Bl -tag
+.It dynamic
+Request a dynamic controller ID for controllers using the dynamic
+controller model.
+This is the default.
+.It static
+Request a dynamic controller ID for controllers using the static
+controller model.
+.It Ar number
+Request a specific controller ID for controllers using the static
+controller model.
+.El
+.It Fl F
+Request submission queue flow control.
+By default submission queue flow control is disabled unless the remote
+controller requires it.
+.It Fl g
+Enable TCP PDU header digests.
+.It Fl G
+Enable TCP PDU data digests.
+.It Fl i Ar queues
+Number of I/O queue pairs to create.
+The default is 1.
+.It Fl k Ar seconds
+Keep Alive timer duration in seconds.
+The default is 120.
+.It Fl l Ar seconds
+Controller Loss timer duration in seconds.
+The default is 600.
+.Pp
+This timer starts when an association is lost with a remote I/O controller
+and is cancelled when a new association is established.
+If the timer expires, the controller device is deleted.
+A setting of zero disables this timer.
+.It Fl r Ar seconds
+Reconnect timer duration in seconds.
+The default is 10.
+.Pp
+When an association is lost with a remote I/O controller,
+the controller device will request reconnection via periodic
+.Xr devctl 4
+notifications until either a new association is established or the controller
+device is deleted.
+This timer sets the interval between each
+.Xr devctl 4
+notification.
+Note that the first notification is triggered immediately after an association
+is lost.
+A setting of zero disables this timer.
+.It Fl t Ar transport
+Transport to use.
+The default is
+.Ar tcp .
+.It Fl q Ar HostNQN
+NVMe Qualified Name to use for this host.
+By default an NQN is auto-generated from the current host's UUID.
+.It Fl Q Ar entries
+Number of entries in each I/O queue.
+By default the maximum queue size reported by the MQES field
+of the remote host's CAP property is used.
+.El
+.Ss connect-all
+Query the Discovery Controller at
+.Ar address
+and establish an association for each advertised I/O controller.
+The
+.Fl t
+flag determines the transport used for the initial association with
+the Discovery Controller and defaults to
+.Ar tcp .
+All other flags are used to control properties of each I/O assocation as
+described above for the
+.Cm connect
+command.
+.Ss disconnect
+Delete the controller device associated with a remote I/O controller
+including any active association and open queues.
+.Ss reconnect
+Reestablish an association for the remote I/O controller associated with
+.Ar device-id .
+If an
+.Ar address
+is not provided,
+the resolved address and settings from the previous association are used
+to establish a new association.
+If an
+.Ar address
+is provided,
+the supplied address and command line flags are used to establish a new
+association.
+In this case,
+the address must include a port and
+the flags have the same meaning for the new association as described above
+for the
+.Cm connect
+command.
+.Ss telemetry-log
+Extract the telemetry log associated with
+.Ar device-id ,
+using the specified parameters:
+.Bl -tag -width 6n
+.It Fl O Ar output-file
+Output file for the data.
+This parameter is mandatory.
+.It Fl d Ar data-area
+The data area is either 1, 2 or 3.
+.El
.Sh DEVICE NAMES
Where
.Aq Ar namespace-id
@@ -599,13 +887,13 @@ or
.Pa nvdZ .
The leading
.Pa /dev/
-is omitted.
+may be omitted.
Where
.Aq Ar device-id
is required, you can use either the
.Pa nvmeX
device, or the disk device such as
-.Pa nda Z
+.Pa ndaZ
or
.Pa nvdZ .
For commands that take an optional
@@ -617,6 +905,37 @@ A
of
.Dq 0
means query the drive itself.
+.Sh FABRICS TRANSPORTS
+The following NVM Express over Fabrics transports are supported for
+accessing remote controllers:
+.Bl -tag
+.It tcp
+TCP transport
+.El
+.Sh NETWORK ADDRESSES
+Network addresses for remote controllers can use one of the following formats:
+.Bl -bullet
+.It
+.Bq Ar IPv6 address
+.Ns : Ns Ar port
+.It
+.Ar IPv4 address
+.Ns : Ns Ar port
+.It
+.Ar hostname Ns : Ns Ar port
+.It
+.Bq Ar IPv6 address
+.It
+.Ar IPv6 address
+.It
+.Ar IPv4 address
+.It
+.Ar hostname
+.El
+.Pp
+If a
+.Ar port
+is not provided, a default value is used if possible.
.Sh EXAMPLES
.Dl nvmecontrol devlist
.Pp
@@ -713,6 +1032,27 @@ device.
The corresponding
.Pa nvmeXnsY
device is used automatically.
+.Pp
+.Dl nvmecontrol format -f 2 -m 0 -p 0 -l 0 -C nvme2
+.Pp
+Format all the name spaces on nvme2 using parameters from
+.Dq LBA Format #2
+with no metadata or protection data using cryptographic erase.
+If the
+.Dq nvmecontrol identify -n 1 nvme2
+command ended with
+.Pp
+.Bd -literal
+LBA Format #00: Data Size: 512 Metadata Size: 0 Performance: Good
+LBA Format #01: Data Size: 512 Metadata Size: 8 Performance: Good
+LBA Format #02: Data Size: 4096 Metadata Size: 0 Performance: Good
+LBA Format #03: Data Size: 4096 Metadata Size: 8 Performance: Good
+LBA Format #04: Data Size: 4096 Metadata Size: 64 Performance: Good
+.Ed
+.Pp
+then this would give a 4k data format for at least namespace 1, with no
+metadata.
+.Pp
.Sh DYNAMIC LOADING
The directories
.Pa /lib/nvmecontrol
diff --git a/sbin/nvmecontrol/nvmecontrol.c b/sbin/nvmecontrol/nvmecontrol.c
index 68a2ecb9b0b8..b38fb8038fc3 100644
--- a/sbin/nvmecontrol/nvmecontrol.c
+++ b/sbin/nvmecontrol/nvmecontrol.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
#include <sys/stat.h>
@@ -146,11 +143,38 @@ read_namespace_data(int fd, uint32_t nsid, struct nvme_namespace_data *nsdata)
}
int
+read_active_namespaces(int fd, uint32_t nsid, struct nvme_ns_list *nslist)
+{
+ struct nvme_pt_command pt;
+
+ memset(&pt, 0, sizeof(pt));
+ pt.cmd.opc = NVME_OPC_IDENTIFY;
+ pt.cmd.nsid = htole32(nsid);
+ pt.cmd.cdw10 = htole32(2);
+ pt.buf = nslist;
+ pt.len = sizeof(*nslist);
+ pt.is_read = 1;
+
+ if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
+ return (errno);
+
+ /* Convert data to host endian */
+ nvme_ns_list_swapbytes(nslist);
+
+ if (nvme_completion_is_error(&pt.cpl))
+ return (EIO);
+ return (0);
+}
+
+int
open_dev(const char *str, int *fd, int write, int exit_on_error)
{
- char full_path[64];
+ char full_path[MAXPATHLEN];
- snprintf(full_path, sizeof(full_path), _PATH_DEV"%s", str);
+ if (str[0] == '/') /* Full path */
+ strlcpy(full_path, str, sizeof(full_path));
+ else /* Add /dev/ */
+ snprintf(full_path, sizeof(full_path), _PATH_DEV"%s", str);
*fd = open(full_path, write ? O_RDWR : O_RDONLY);
if (*fd < 0) {
if (exit_on_error) {
diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h
index c1daaf6730d3..968e9c20160e 100644
--- a/sbin/nvmecontrol/nvmecontrol.h
+++ b/sbin/nvmecontrol/nvmecontrol.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 __NVMECONTROL_H__
@@ -62,6 +60,17 @@ struct kv_name {
const char *name;
};
+/*
+ * Generically convert little endian to host endian, based on the type of the thing
+ * being converted. Use the proposed name for future changes to endian.h.
+ */
+#define letoh(x) \
+ _Generic(x, \
+ uint8_t: (x), \
+ uint16_t: le16toh(x), \
+ uint32_t: le32toh(x), \
+ uint64_t: le64toh(x))
+
const char *kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key);
void logpage_register(struct logpage_function *p);
@@ -72,31 +81,45 @@ int open_dev(const char *str, int *fd, int write, int exit_on_error);
void get_nsid(int fd, char **ctrlr_str, uint32_t *nsid);
int read_controller_data(int fd, struct nvme_controller_data *cdata);
int read_namespace_data(int fd, uint32_t nsid, struct nvme_namespace_data *nsdata);
+int read_active_namespaces(int fd, uint32_t nsid, struct nvme_ns_list *nslist);
void print_hex(void *data, uint32_t length);
void print_namespace(struct nvme_namespace_data *nsdata);
void read_logpage(int fd, uint8_t log_page, uint32_t nsid, uint8_t lsp,
- uint16_t lsi, uint8_t rae, void *payload, uint32_t payload_size);
-void print_temp(uint16_t t);
+ uint16_t lsi, uint8_t rae, uint64_t lpo, uint8_t csi, uint8_t ot,
+ uint16_t uuid_index, void *payload, uint32_t payload_size);
+void print_temp_C(uint16_t t);
+void print_temp_K(uint16_t t);
void print_intel_add_smart(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused);
/* Utility Routines */
/*
- * 128-bit integer augments to standard values. On i386 this
- * doesn't exist, so we use 64-bit values. So, on 32-bit i386,
- * you'll get truncated values until someone implement 128bit
- * ints in sofware.
+ * C23 supports 128-bit integers via _BitInt(128). clang 16 and gcc 13 support
+ * this. Older compilers will support 128-bit ints on 64-bit
+ * platforms. Otherwise we truncate this to 64-bit on 32-bit systems with older
+ * compilers. We also check for > C18 instead of >= C23 because clang 17 was
+ * released before the __STDC_VERSION__ was defined.
*/
#define UINT128_DIG 39
-#ifdef __i386__
-typedef uint64_t uint128_t;
-#else
+#if __STDC_VERSION__ >= 202311L
+typedef unsigned _BitInt(128) uint128_t;
+#elif defined(__SIZEOF_INT128__)
typedef __uint128_t uint128_t;
+#else
+typedef uint64_t uint128_t;
#endif
static __inline uint128_t
to128(void *p)
{
- return *(uint128_t *)p;
+#if __STDC_VERSION__ >= 202311L || defined(__SIZEOF_INT128__)
+ uint64_t lo, hi;
+
+ lo = le64dec(p);
+ hi = le64dec((const char *)p + 8);
+ return ((uint128_t)hi << 64 | lo);
+#else
+ return (le64dec(p));
+#endif
}
uint64_t le48dec(const void *pp);
diff --git a/sbin/nvmecontrol/nvmecontrol_ext.h b/sbin/nvmecontrol/nvmecontrol_ext.h
index d60fcd4d8a2c..97c3095e6d20 100644
--- a/sbin/nvmecontrol/nvmecontrol_ext.h
+++ b/sbin/nvmecontrol/nvmecontrol_ext.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2018 Netflix, Inc.
*
@@ -23,8 +23,6 @@
* 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$
*/
void nvme_print_controller(struct nvme_controller_data *cdata);
diff --git a/sbin/nvmecontrol/passthru.c b/sbin/nvmecontrol/passthru.c
index 0b24d7b1ea1f..cf38e185a582 100644
--- a/sbin/nvmecontrol/passthru.c
+++ b/sbin/nvmecontrol/passthru.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019-2021 Netflix, Inc
*
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -123,7 +120,7 @@ static struct opts opts[] = {
ARG("data-len", 'l', arg_uint32, opt, data_len,
"Length of data for I/O (bytes)"),
ARG("metadata-len", 'm', arg_uint32, opt, metadata_len,
- "Length of metadata segment (bytes) (igored)"),
+ "Length of metadata segment (bytes) (ignored)"),
ARG("flags", 'f', arg_uint8, opt, flags,
"NVMe command flags"),
ARG("input-file", 'i', arg_path, opt, ifn,
diff --git a/sbin/nvmecontrol/perftest.c b/sbin/nvmecontrol/perftest.c
index 0223bf3b5d51..59439d3ed2a9 100644
--- a/sbin/nvmecontrol/perftest.c
+++ b/sbin/nvmecontrol/perftest.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
diff --git a/sbin/nvmecontrol/power.c b/sbin/nvmecontrol/power.c
index 47ebc9c8c153..b26570da0c52 100644
--- a/sbin/nvmecontrol/power.c
+++ b/sbin/nvmecontrol/power.c
@@ -23,9 +23,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -65,14 +62,10 @@ power_list_one(int i, struct nvme_power_state *nps)
int mpower, apower, ipower;
uint8_t mps, nops, aps, apw;
- mps = (nps->mps_nops >> NVME_PWR_ST_MPS_SHIFT) &
- NVME_PWR_ST_MPS_MASK;
- nops = (nps->mps_nops >> NVME_PWR_ST_NOPS_SHIFT) &
- NVME_PWR_ST_NOPS_MASK;
- apw = (nps->apw_aps >> NVME_PWR_ST_APW_SHIFT) &
- NVME_PWR_ST_APW_MASK;
- aps = (nps->apw_aps >> NVME_PWR_ST_APS_SHIFT) &
- NVME_PWR_ST_APS_MASK;
+ mps = NVMEV(NVME_PWR_ST_MPS, nps->mps_nops);
+ nops = NVMEV(NVME_PWR_ST_NOPS, nps->mps_nops);
+ apw = NVMEV(NVME_PWR_ST_APW, nps->apw_aps);
+ aps = NVMEV(NVME_PWR_ST_APS, nps->apw_aps);
mpower = nps->mp;
if (mps == 0)
@@ -97,7 +90,7 @@ power_list(struct nvme_controller_data *cdata)
int i;
printf("\nPower States Supported: %d\n\n", cdata->npss + 1);
- printf(" # Max pwr Enter Lat Exit Lat RT RL WT WL Idle Pwr Act Pwr Workloadd\n");
+ printf(" # Max pwr Enter Lat Exit Lat RT RL WT WL Idle Pwr Act Pwr Workload\n");
printf("-- -------- --------- --------- -- -- -- -- -------- -------- --\n");
for (i = 0; i <= cdata->npss; i++)
power_list_one(i, &cdata->power_state[i]);
@@ -137,7 +130,8 @@ power_show(int fd)
if (nvme_completion_is_error(&pt.cpl))
errx(EX_IOERR, "set feature power mgmt request returned error");
- printf("Current Power Mode is %d\n", pt.cpl.cdw0);
+ printf("Current Power State is %d\n", pt.cpl.cdw0 & 0x1F);
+ printf("Current Workload Hint is %d\n", pt.cpl.cdw0 >> 5);
}
static void
@@ -189,7 +183,7 @@ static const struct opts power_opts[] = {
OPT("power", 'p', arg_uint32, opt, power,
"Set the power state"),
OPT("workload", 'w', arg_uint32, opt, workload,
- "Set the workload"),
+ "Set the workload hint"),
{ NULL, 0, arg_none, NULL, NULL }
};
#undef OPT
diff --git a/sbin/nvmecontrol/reconnect.c b/sbin/nvmecontrol/reconnect.c
new file mode 100644
index 000000000000..06af40624177
--- /dev/null
+++ b/sbin/nvmecontrol/reconnect.c
@@ -0,0 +1,333 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023-2024 Chelsio Communications, Inc.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ */
+
+#include <sys/dnv.h>
+#include <sys/nv.h>
+#include <sys/socket.h>
+#include <err.h>
+#include <libnvmf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "nvmecontrol.h"
+#include "fabrics.h"
+
+/*
+ * See comment about other possible settings in connect.c.
+ */
+
+static struct options {
+ const char *dev;
+ const char *transport;
+ const char *hostnqn;
+ uint32_t kato;
+ uint32_t reconnect_delay;
+ uint32_t controller_loss_timeout;
+ uint16_t num_io_queues;
+ uint16_t queue_size;
+ bool data_digests;
+ bool flow_control;
+ bool header_digests;
+} opt = {
+ .dev = NULL,
+ .transport = "tcp",
+ .hostnqn = NULL,
+ .kato = NVMF_KATO_DEFAULT / 1000,
+ .reconnect_delay = NVMF_DEFAULT_RECONNECT_DELAY,
+ .controller_loss_timeout = NVMF_DEFAULT_CONTROLLER_LOSS,
+ .num_io_queues = 1,
+ .queue_size = 0,
+ .data_digests = false,
+ .flow_control = false,
+ .header_digests = false,
+};
+
+static void
+tcp_association_params(struct nvmf_association_params *params,
+ bool header_digests, bool data_digests)
+{
+ params->tcp.pda = 0;
+ params->tcp.header_digests = header_digests;
+ params->tcp.data_digests = data_digests;
+ /* XXX */
+ params->tcp.maxr2t = 1;
+}
+
+static int
+reconnect_nvm_controller(int fd, const struct nvmf_association_params *aparams,
+ enum nvmf_trtype trtype, int adrfam, const char *address, const char *port,
+ uint16_t cntlid, const char *subnqn, const char *hostnqn, uint32_t kato,
+ uint32_t reconnect_delay, uint32_t controller_loss_timeout,
+ u_int num_io_queues, u_int queue_size,
+ const struct nvme_discovery_log_entry *dle)
+{
+ struct nvme_controller_data cdata;
+ struct nvme_discovery_log_entry dle_thunk;
+ struct nvmf_qpair *admin, **io;
+ int error;
+
+ io = calloc(num_io_queues, sizeof(*io));
+ error = connect_nvm_queues(aparams, trtype, adrfam, address, port,
+ cntlid, subnqn, hostnqn, kato, &admin, io, num_io_queues,
+ queue_size, &cdata);
+ if (error != 0) {
+ free(io);
+ return (error);
+ }
+
+ if (dle == NULL) {
+ error = nvmf_init_dle_from_admin_qp(admin, &cdata, &dle_thunk);
+ if (error != 0) {
+ warnc(error, "Failed to generate handoff parameters");
+ disconnect_nvm_queues(admin, io, num_io_queues);
+ free(io);
+ return (EX_IOERR);
+ }
+ dle = &dle_thunk;
+ }
+
+ error = nvmf_reconnect_host(fd, dle, hostnqn, admin, num_io_queues, io,
+ &cdata, reconnect_delay, controller_loss_timeout);
+ if (error != 0) {
+ warnc(error, "Failed to handoff queues to kernel");
+ free(io);
+ return (EX_IOERR);
+ }
+ free(io);
+ return (0);
+}
+
+static int
+reconnect_by_address(int fd, const nvlist_t *rparams, const char *addr)
+{
+ const struct nvme_discovery_log_entry *dle;
+ struct nvmf_association_params aparams;
+ enum nvmf_trtype trtype;
+ const char *address, *hostnqn, *port;
+ char *subnqn, *tofree;
+ int error;
+
+ memset(&aparams, 0, sizeof(aparams));
+ aparams.sq_flow_control = opt.flow_control;
+ if (strcasecmp(opt.transport, "tcp") == 0) {
+ trtype = NVMF_TRTYPE_TCP;
+ tcp_association_params(&aparams, opt.header_digests,
+ opt.data_digests);
+ } else {
+ warnx("Unsupported or invalid transport");
+ return (EX_USAGE);
+ }
+
+ nvmf_parse_address(addr, &address, &port, &tofree);
+ if (port == NULL) {
+ free(tofree);
+ warnx("Explicit port required");
+ return (EX_USAGE);
+ }
+
+ dle = nvlist_get_binary(rparams, "dle", NULL);
+
+ hostnqn = opt.hostnqn;
+ if (hostnqn == NULL)
+ hostnqn = nvmf_default_hostnqn();
+
+ /* Ensure subnqn is a terminated C string. */
+ subnqn = strndup(dle->subnqn, sizeof(dle->subnqn));
+
+ error = reconnect_nvm_controller(fd, &aparams, trtype, AF_UNSPEC,
+ address, port, le16toh(dle->cntlid), subnqn, hostnqn,
+ opt.kato * 1000, opt.reconnect_delay, opt.controller_loss_timeout,
+ opt.num_io_queues, opt.queue_size, NULL);
+ free(subnqn);
+ free(tofree);
+ return (error);
+}
+
+static int
+reconnect_by_params(int fd, const nvlist_t *rparams)
+{
+ struct nvmf_association_params aparams;
+ const struct nvme_discovery_log_entry *dle;
+ char *address, *port, *subnqn;
+ int adrfam, error;
+
+ dle = nvlist_get_binary(rparams, "dle", NULL);
+
+ memset(&aparams, 0, sizeof(aparams));
+ aparams.sq_flow_control = nvlist_get_bool(rparams, "sq_flow_control");
+ switch (dle->trtype) {
+ case NVMF_TRTYPE_TCP:
+ switch (dle->adrfam) {
+ case NVMF_ADRFAM_IPV4:
+ adrfam = AF_INET;
+ break;
+ case NVMF_ADRFAM_IPV6:
+ adrfam = AF_INET6;
+ break;
+ default:
+ warnx("Unsupported address family");
+ return (EX_UNAVAILABLE);
+ }
+ switch (dle->tsas.tcp.sectype) {
+ case NVME_TCP_SECURITY_NONE:
+ break;
+ default:
+ warnx("Unsupported TCP security type");
+ return (EX_UNAVAILABLE);
+ }
+ break;
+
+ tcp_association_params(&aparams,
+ nvlist_get_bool(rparams, "header_digests"),
+ nvlist_get_bool(rparams, "data_digests"));
+ break;
+ default:
+ warnx("Unsupported transport %s",
+ nvmf_transport_type(dle->trtype));
+ return (EX_UNAVAILABLE);
+ }
+
+ /* Ensure address, port, and subnqn is a terminated C string. */
+ address = strndup(dle->traddr, sizeof(dle->traddr));
+ port = strndup(dle->trsvcid, sizeof(dle->trsvcid));
+ subnqn = strndup(dle->subnqn, sizeof(dle->subnqn));
+
+ error = reconnect_nvm_controller(fd, &aparams, dle->trtype, adrfam,
+ address, port, le16toh(dle->cntlid), dle->subnqn,
+ nvlist_get_string(rparams, "hostnqn"),
+ dnvlist_get_number(rparams, "kato", 0),
+ dnvlist_get_number(rparams, "reconnect_delay", 0),
+ dnvlist_get_number(rparams, "controller_loss_timeout", 0),
+ nvlist_get_number(rparams, "num_io_queues"),
+ nvlist_get_number(rparams, "io_qsize"), dle);
+ free(subnqn);
+ free(port);
+ free(address);
+ return (error);
+}
+
+static int
+fetch_and_validate_rparams(int fd, nvlist_t **rparamsp)
+{
+ const struct nvme_discovery_log_entry *dle;
+ nvlist_t *rparams;
+ size_t len;
+ int error;
+
+ error = nvmf_reconnect_params(fd, &rparams);
+ if (error != 0) {
+ warnc(error, "Failed to fetch reconnect parameters");
+ return (EX_IOERR);
+ }
+
+ if (!nvlist_exists_binary(rparams, "dle") ||
+ !nvlist_exists_string(rparams, "hostnqn") ||
+ !nvlist_exists_number(rparams, "num_io_queues") ||
+ !nvlist_exists_number(rparams, "io_qsize") ||
+ !nvlist_exists_bool(rparams, "sq_flow_control")) {
+ nvlist_destroy(rparams);
+ warnx("Missing required reconnect parameters");
+ return (EX_IOERR);
+ }
+
+ dle = nvlist_get_binary(rparams, "dle", &len);
+ if (len != sizeof(*dle)) {
+ nvlist_destroy(rparams);
+ warnx("Discovery Log entry reconnect parameter is wrong size");
+ return (EX_IOERR);
+ }
+
+ switch (dle->trtype) {
+ case NVMF_TRTYPE_TCP:
+ if (!nvlist_exists_bool(rparams, "header_digests") ||
+ !nvlist_exists_bool(rparams, "data_digests")) {
+ nvlist_destroy(rparams);
+ warnx("Missing required reconnect parameters");
+ return (EX_IOERR);
+ }
+ break;
+ default:
+ nvlist_destroy(rparams);
+ warnx("Unsupported transport %s",
+ nvmf_transport_type(dle->trtype));
+ return (EX_UNAVAILABLE);
+ }
+
+ *rparamsp = rparams;
+ return (0);
+}
+
+static void
+reconnect_fn(const struct cmd *f, int argc, char *argv[])
+{
+ nvlist_t *rparams;
+ int error, fd;
+
+ if (arg_parse(argc, argv, f))
+ return;
+
+ open_dev(opt.dev, &fd, 1, 1);
+ error = fetch_and_validate_rparams(fd, &rparams);
+ if (error != 0)
+ exit(error);
+
+ /* Check for optional address. */
+ if (optind < argc)
+ error = reconnect_by_address(fd, rparams, argv[optind]);
+ else
+ error = reconnect_by_params(fd, rparams);
+ if (error != 0)
+ exit(error);
+
+ nvlist_destroy(rparams);
+ close(fd);
+}
+
+static const struct opts reconnect_opts[] = {
+#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
+ OPT("transport", 't', arg_string, opt, transport,
+ "Transport type"),
+ OPT("nr-io-queues", 'i', arg_uint16, opt, num_io_queues,
+ "Number of I/O queues"),
+ OPT("queue-size", 'Q', arg_uint16, opt, queue_size,
+ "Number of entries in each I/O queue"),
+ OPT("keep-alive-tmo", 'k', arg_uint32, opt, kato,
+ "Keep Alive timeout (in seconds)"),
+ OPT("reconnect-delay", 'r', arg_uint32, opt, reconnect_delay,
+ "Delay between reconnect attempts after connection loss "
+ "(in seconds)"),
+ OPT("ctrl-loss-tmo", 'l', arg_uint32, opt, controller_loss_timeout,
+ "Controller loss timeout after connection loss (in seconds)"),
+ OPT("hostnqn", 'q', arg_string, opt, hostnqn,
+ "Host NQN"),
+ OPT("flow_control", 'F', arg_none, opt, flow_control,
+ "Request SQ flow control"),
+ OPT("hdr_digests", 'g', arg_none, opt, header_digests,
+ "Enable TCP PDU header digests"),
+ OPT("data_digests", 'G', arg_none, opt, data_digests,
+ "Enable TCP PDU data digests"),
+ { NULL, 0, arg_none, NULL, NULL }
+};
+#undef OPT
+
+static const struct args reconnect_args[] = {
+ { arg_string, &opt.dev, "controller-id" },
+ { arg_none, NULL, NULL },
+};
+
+static struct cmd reconnect_cmd = {
+ .name = "reconnect",
+ .fn = reconnect_fn,
+ .descr = "Reconnect to a fabrics controller",
+ .ctx_size = sizeof(opt),
+ .opts = reconnect_opts,
+ .args = reconnect_args,
+};
+
+CMD_COMMAND(reconnect_cmd);
diff --git a/sbin/nvmecontrol/reset.c b/sbin/nvmecontrol/reset.c
index f5ab7265c98b..267413c975f8 100644
--- a/sbin/nvmecontrol/reset.c
+++ b/sbin/nvmecontrol/reset.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2012-2013 Intel Corporation
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
diff --git a/sbin/nvmecontrol/resv.c b/sbin/nvmecontrol/resv.c
index adb3b64c9ec3..d607b0b015e6 100644
--- a/sbin/nvmecontrol/resv.c
+++ b/sbin/nvmecontrol/resv.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Alexander Motin <mav@FreeBSD.org>
*
@@ -25,9 +25,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -255,6 +252,7 @@ resvacquire(const struct cmd *f, int argc, char *argv[])
memset(&pt, 0, sizeof(pt));
pt.cmd.opc = NVME_OPC_RESERVATION_ACQUIRE;
+ pt.cmd.nsid = htole32(nsid);
pt.cmd.cdw10 = htole32((acquire_opt.racqa & 7) |
(acquire_opt.rtype << 8));
pt.buf = &data;
@@ -293,6 +291,7 @@ resvregister(const struct cmd *f, int argc, char *argv[])
memset(&pt, 0, sizeof(pt));
pt.cmd.opc = NVME_OPC_RESERVATION_REGISTER;
+ pt.cmd.nsid = htole32(nsid);
pt.cmd.cdw10 = htole32((register_opt.rrega & 7) |
(register_opt.iekey << 3) | (register_opt.cptpl << 30));
pt.buf = &data;
@@ -330,6 +329,7 @@ resvrelease(const struct cmd *f, int argc, char *argv[])
memset(&pt, 0, sizeof(pt));
pt.cmd.opc = NVME_OPC_RESERVATION_RELEASE;
+ pt.cmd.nsid = htole32(nsid);
pt.cmd.cdw10 = htole32((release_opt.rrela & 7) |
(release_opt.rtype << 8));
pt.buf = &data;
@@ -369,6 +369,7 @@ resvreport(const struct cmd *f, int argc, char *argv[])
bzero(data, sizeof(data));
memset(&pt, 0, sizeof(pt));
pt.cmd.opc = NVME_OPC_RESERVATION_REPORT;
+ pt.cmd.nsid = htole32(nsid);
pt.cmd.cdw10 = htole32(sizeof(data) / 4 - 1);
pt.cmd.cdw11 = htole32(report_opt.eds); /* EDS */
pt.buf = &data;
diff --git a/sbin/nvmecontrol/sanitize.c b/sbin/nvmecontrol/sanitize.c
index d5f649959d70..e720c6d43497 100644
--- a/sbin/nvmecontrol/sanitize.c
+++ b/sbin/nvmecontrol/sanitize.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Alexander Motin <mav@FreeBSD.org>
*
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -133,8 +130,11 @@ sanitize(const struct cmd *f, int argc, char *argv[])
sanact = 3;
else if (strcmp(opt.sanact, "crypto") == 0)
sanact = 4;
+ else if ((sanact = (int)strtol(opt.sanact, NULL, 10) != 0)
+ && (sanact >= 1 && sanact <= 4))
+ ; /* compat with nvme sanitize -a number */
else {
- fprintf(stderr, "Incorrect Sanitize Action value\n");
+ fprintf(stderr, "Incorrect Sanitize Action value: %s\n", opt.sanact);
arg_help(argc, argv, f);
}
}
@@ -157,14 +157,11 @@ sanitize(const struct cmd *f, int argc, char *argv[])
/* Check that controller can execute this command. */
if (read_controller_data(fd, &cd))
errx(EX_IOERR, "Identify request failed");
- if (((cd.sanicap >> NVME_CTRLR_DATA_SANICAP_BES_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_BES_MASK) == 0 && sanact == 2)
+ if (NVMEV(NVME_CTRLR_DATA_SANICAP_BES, cd.sanicap) == 0 && sanact == 2)
errx(EX_UNAVAILABLE, "controller does not support Block Erase");
- if (((cd.sanicap >> NVME_CTRLR_DATA_SANICAP_OWS_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_OWS_MASK) == 0 && sanact == 3)
+ if (NVMEV(NVME_CTRLR_DATA_SANICAP_OWS, cd.sanicap) == 0 && sanact == 3)
errx(EX_UNAVAILABLE, "controller does not support Overwrite");
- if (((cd.sanicap >> NVME_CTRLR_DATA_SANICAP_CES_SHIFT) &
- NVME_CTRLR_DATA_SANICAP_CES_MASK) == 0 && sanact == 4)
+ if (NVMEV(NVME_CTRLR_DATA_SANICAP_CES, cd.sanicap) == 0 && sanact == 4)
errx(EX_UNAVAILABLE, "controller does not support Crypto Erase");
/*
@@ -188,9 +185,9 @@ sanitize(const struct cmd *f, int argc, char *argv[])
wait:
read_logpage(fd, NVME_LOG_SANITIZE_STATUS,
- NVME_GLOBAL_NAMESPACE_TAG, 0, 0, 0, &ss, sizeof(ss));
- switch ((ss.sstat >> NVME_SS_PAGE_SSTAT_STATUS_SHIFT) &
- NVME_SS_PAGE_SSTAT_STATUS_MASK) {
+ NVME_GLOBAL_NAMESPACE_TAG, 0, 0, 0,
+ 0, 0, 0, 0, &ss, sizeof(ss));
+ switch (NVMEV(NVME_SS_PAGE_SSTAT_STATUS, ss.sstat)) {
case NVME_SS_PAGE_SSTAT_STATUS_NEVER:
printf("Never sanitized");
break;
diff --git a/sbin/nvmecontrol/selftest.c b/sbin/nvmecontrol/selftest.c
index 17945248f8e3..6a4da902999e 100644
--- a/sbin/nvmecontrol/selftest.c
+++ b/sbin/nvmecontrol/selftest.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2020 Chuck Tuffli
*
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioccom.h>
@@ -102,8 +99,7 @@ selftest(const struct cmd *f, int argc, char *argv[])
if (read_controller_data(fd, &cdata))
errx(EX_IOERR, "Identify request failed");
- if (((cdata.oacs >> NVME_CTRLR_DATA_OACS_SELFTEST_SHIFT) &
- NVME_CTRLR_DATA_OACS_SELFTEST_MASK) == 0)
+ if (NVMEV(NVME_CTRLR_DATA_OACS_SELFTEST, cdata.oacs) == 0)
errx(EX_UNAVAILABLE, "controller does not support self-test");
selftest_op(fd, nsid, opt.stc);
diff --git a/sbin/nvmecontrol/telemetry.c b/sbin/nvmecontrol/telemetry.c
new file mode 100644
index 000000000000..72c304229a80
--- /dev/null
+++ b/sbin/nvmecontrol/telemetry.c
@@ -0,0 +1,182 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2024 Netflix, 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.
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/ioccom.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <sys/endian.h>
+
+#include "nvmecontrol.h"
+
+/* Tables for command line parsing */
+
+static cmd_fn_t telemetry_log;
+
+#define NONE 0xffffffffu
+static struct options {
+ const char *outfn;
+ const char *dev;
+ uint8_t da;
+} opt = {
+ .outfn = NULL,
+ .dev = NULL,
+ .da = 3,
+};
+
+static const struct opts telemetry_log_opts[] = {
+#define OPT(l, s, t, opt, addr, desc) { l, s, t, &opt.addr, desc }
+ OPT("output-file", 'O', arg_string, opt, outfn,
+ "output file for telemetry data"),
+ OPT("data-area", 'd', arg_uint8, opt, da,
+ "output file for telemetry data"),
+ { NULL, 0, arg_none, NULL, NULL }
+};
+#undef OPT
+
+static const struct args telemetry_log_args[] = {
+ { arg_string, &opt.dev, "<controller id|namespace id>" },
+ { arg_none, NULL, NULL },
+};
+
+static struct cmd telemetry_log_cmd = {
+ .name = "telemetry-log",
+ .fn = telemetry_log,
+ .descr = "Retrieves telemetry log pages from drive",
+ .ctx_size = sizeof(opt),
+ .opts = telemetry_log_opts,
+ .args = telemetry_log_args,
+};
+
+CMD_COMMAND(telemetry_log_cmd);
+
+/* End of tables for command line parsing */
+
+/*
+ * Note: Even though this is a logpage, it's variable size and tricky
+ * to get with some weird options, so it's its own command.
+ */
+
+static void
+telemetry_log(const struct cmd *f, int argc, char *argv[])
+{
+ int fd, fdout;
+ char *path;
+ uint32_t nsid;
+ ssize_t size;
+ uint64_t off;
+ ssize_t chunk;
+ struct nvme_controller_data cdata;
+ bool can_telemetry;
+ struct nvme_telemetry_log_page tlp, buf;
+
+ if (arg_parse(argc, argv, f))
+ return;
+ if (opt.da < 1 || opt.da > 3)
+ errx(EX_USAGE, "Data area %d is not in the range 1-3\n", opt.da);
+ if (opt.outfn == NULL)
+ errx(EX_USAGE, "No output file specified");
+
+ open_dev(opt.dev, &fd, 0, 1);
+ get_nsid(fd, &path, &nsid);
+ if (nsid == 0) {
+ nsid = NVME_GLOBAL_NAMESPACE_TAG;
+ } else {
+ close(fd);
+ open_dev(path, &fd, 0, 1);
+ }
+ free(path);
+
+ if (read_controller_data(fd, &cdata))
+ errx(EX_IOERR, "Identify request failed");
+
+ can_telemetry = NVMEV(NVME_CTRLR_DATA_LPA_TELEMETRY, cdata.lpa);
+ if (!can_telemetry)
+ errx(EX_UNAVAILABLE, "Drive does not support telemetry");
+ if (nsid != NVME_GLOBAL_NAMESPACE_TAG)
+ errx(EX_UNAVAILABLE, "Cannot operate on namespace");
+
+ fdout = open(opt.outfn, O_WRONLY | O_CREAT, 0664);
+ if (fdout == -1)
+ err(EX_IOERR, "Can't create %s", opt.outfn);
+
+ /* Read the log page */
+ size = sizeof(tlp);
+ off = 0;
+ read_logpage(fd, NVME_LOG_TELEMETRY_HOST_INITIATED, nsid, 0, 0, 0,
+ off, 0, 0, 0, &tlp, size);
+ switch(opt.da) {
+ case 1:
+ size = letoh(tlp.da1_last);
+ break;
+ case 2:
+ size = letoh(tlp.da2_last);
+ break;
+ case 3:
+ size = letoh(tlp.da3_last);
+ break;
+ default:
+ errx(EX_USAGE, "Impossible data area %d", opt.da);
+ }
+ size = (size + 1) * 512; /* The count of additional pages */
+ chunk = 4096;
+
+ printf("Extracting %llu bytes\n", (unsigned long long)size);
+ do {
+ if (chunk > size)
+ chunk = size;
+ read_logpage(fd, NVME_LOG_TELEMETRY_HOST_INITIATED, nsid, 0, 0, 0,
+ off, 0, 0, 0, &buf, chunk);
+ if (off == 0) {
+ /*
+ * Sanity check to make sure that the generation number
+ * didn't change between the two reads.
+ */
+ if (tlp.hi_gen != buf.hi_gen)
+ warnx(
+ "Generation number changed from %d to %d",
+ tlp.hi_gen, buf.hi_gen);
+ }
+ if (write(fdout, &buf, chunk) != chunk)
+ err(EX_IOERR, "Error writing %s", opt.outfn);
+ off += chunk;
+ size -= chunk;
+ } while (size > 0);
+
+ close(fdout);
+ close(fd);
+ exit(0);
+}
diff --git a/sbin/nvmecontrol/tests/Makefile b/sbin/nvmecontrol/tests/Makefile
index 0a2ad0c7e39e..5754dbd743b8 100644
--- a/sbin/nvmecontrol/tests/Makefile
+++ b/sbin/nvmecontrol/tests/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= tests
ATF_TESTS_SH+= basic
diff --git a/sbin/nvmecontrol/tests/Makefile.depend b/sbin/nvmecontrol/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/sbin/nvmecontrol/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/nvmecontrol/tests/basic.sh b/sbin/nvmecontrol/tests/basic.sh
index 4a3a8ed73c5c..83b74721c66b 100755
--- a/sbin/nvmecontrol/tests/basic.sh
+++ b/sbin/nvmecontrol/tests/basic.sh
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2020 David A. Bright
#
@@ -23,7 +23,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
# A basic test for nvmecontrol. This isn't a thorough or complete test
@@ -95,11 +94,11 @@ admin_passthru_head()
admin_passthru_body()
{
if [ -c "${TEST_DEV_PATH}" ] ; then
- atf_check -o not-empty -e empty nvmecontrol admin-passthru --opcode=06 --data-len=4096 --cdw10=1 -r 0 ${TEST_DEV}
+ atf_check -o not-empty -e empty nvmecontrol admin-passthru --opcode=06 --data-len=4096 --cdw10=1 -r ${TEST_DEV}
else
- atf_check -s not-exit:0 -o empty -e not-empty nvmecontrol admin-passthru --opcode=06 --data-len=4096 --cdw10=1 -r 0 ${TEST_DEV}
+ atf_check -s not-exit:0 -o empty -e not-empty nvmecontrol admin-passthru --opcode=06 --data-len=4096 --cdw10=1 -r ${TEST_DEV}
fi
- atf_check -s not-exit:0 -o ignore -e match:"${INV_OPT_MSG}" nvmecontrol admin-passthru ${INV_OPT} --opcode=06 --data-len=4096 --cdw10=1 -r 0 ${TEST_DEV}
+ atf_check -s not-exit:0 -o ignore -e match:"${INV_OPT_MSG}" nvmecontrol admin-passthru ${INV_OPT} --opcode=06 --data-len=4096 --cdw10=1 -r ${TEST_DEV}
}
atf_test_case devlist
@@ -143,11 +142,11 @@ io_passthru_head()
io_passthru_body()
{
if [ -c "${TEST_DEV_PATH}" ] ; then
- atf_check -o not-empty -e empty nvmecontrol io-passthru --opcode=02 --data-len=4096 --cdw10=0 --cdw11=0 --cdw12=0x70000 -r 0 nvme0 ${TEST_DEV}
+ atf_check -o not-empty -e empty nvmecontrol io-passthru --opcode=02 --data-len=4096 --cdw10=0 --cdw11=0 --cdw12=0x70000 -r nvme0 ${TEST_DEV}
else
- atf_check -s not-exit:0 -o empty -e not-empty nvmecontrol io-passthru --opcode=02 --data-len=4096 --cdw10=0 --cdw11=0 --cdw12=0x70000 -r 0 nvme0 ${TEST_DEV}
+ atf_check -s not-exit:0 -o empty -e not-empty nvmecontrol io-passthru --opcode=02 --data-len=4096 --cdw10=0 --cdw11=0 --cdw12=0x70000 -r nvme0 ${TEST_DEV}
fi
- atf_check -s not-exit:0 -o ignore -e match:"${INV_OPT_MSG}" nvmecontrol io-passthru ${INV_OPT} --opcode=02 --data-len=4096 --cdw10=0 --cdw11=0 --cdw12=0x70000 -r 0 nvme0 ${TEST_DEV}
+ atf_check -s not-exit:0 -o ignore -e match:"${INV_OPT_MSG}" nvmecontrol io-passthru ${INV_OPT} --opcode=02 --data-len=4096 --cdw10=0 --cdw11=0 --cdw12=0x70000 -r nvme0 ${TEST_DEV}
}
atf_test_case logpage
diff --git a/sbin/pfctl/Makefile b/sbin/pfctl/Makefile
index 49bdfb9e3733..08ca9a7af81b 100644
--- a/sbin/pfctl/Makefile
+++ b/sbin/pfctl/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=pf
diff --git a/sbin/pfctl/Makefile.depend b/sbin/pfctl/Makefile.depend
index dc2c63d06b09..bc09f07d0227 100644
--- a/sbin/pfctl/Makefile.depend
+++ b/sbin/pfctl/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
@@ -10,6 +8,8 @@ DIRDEPS = \
lib/libc \
lib/libcompiler_rt \
lib/libmd \
+ lib/libnv \
+ lib/libpfctl \
lib/msun \
usr.bin/yacc.host \
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 506716bca689..0f7702fc4630 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -30,8 +30,6 @@
*/
%{
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#define PFIOC_USE_LATEST
#include <sys/types.h>
@@ -91,9 +89,13 @@ static struct file {
TAILQ_ENTRY(file) entry;
FILE *stream;
char *name;
+ size_t ungetpos;
+ size_t ungetsize;
+ u_char *ungetbuf;
+ int eof_reached;
int lineno;
int errors;
-} *file;
+} *file, *topfile;
struct file *pushfile(const char *, int);
int popfile(void);
int check_file_secrecy(int, const char *);
@@ -102,8 +104,9 @@ int yylex(void);
int yyerror(const char *, ...);
int kw_cmp(const void *, const void *);
int lookup(char *);
+int igetc(void);
int lgetc(int);
-int lungetc(int);
+void lungetc(int);
int findeol(void);
static TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
@@ -163,8 +166,8 @@ struct node_gid {
};
struct node_icmp {
- u_int8_t code;
- u_int8_t type;
+ uint16_t code;
+ uint16_t type;
u_int8_t proto;
struct node_icmp *next;
struct node_icmp *tail;
@@ -174,7 +177,8 @@ enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
- PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, };
+ PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY,
+ PF_STATE_OPT_PFLOW, PF_STATE_OPT_ALLOW_RELATED };
enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
@@ -223,17 +227,53 @@ struct node_qassign {
char *pqname;
};
+struct range {
+ int a;
+ int b;
+ int t;
+};
+
+static struct pool_opts {
+ int marker;
+#define POM_TYPE 0x01
+#define POM_STICKYADDRESS 0x02
+#define POM_ENDPI 0x04
+#define POM_IPV6NH 0x08
+ u_int8_t opts;
+ int type;
+ int staticport;
+ struct pf_poolhashkey *key;
+ struct pf_mape_portset mape;
+} pool_opts;
+
+struct redirspec {
+ struct node_host *host;
+ struct range rport;
+ struct pool_opts pool_opts;
+ sa_family_t af;
+ bool binat;
+};
+
static struct filter_opts {
int marker;
-#define FOM_FLAGS 0x01
-#define FOM_ICMP 0x02
-#define FOM_TOS 0x04
-#define FOM_KEEP 0x08
-#define FOM_SRCTRACK 0x10
+#define FOM_FLAGS 0x0001
+#define FOM_ICMP 0x0002
+#define FOM_TOS 0x0004
+#define FOM_KEEP 0x0008
+#define FOM_SRCTRACK 0x0010
+#define FOM_MINTTL 0x0020
+#define FOM_MAXMSS 0x0040
+#define FOM_AFTO 0x0080
+#define FOM_SETTOS 0x0100
+#define FOM_SCRUB_TCP 0x0200
#define FOM_SETPRIO 0x0400
+#define FOM_ONCE 0x1000
#define FOM_PRIO 0x2000
+#define FOM_SETDELAY 0x4000
+#define FOM_FRAGCACHE 0x8000 /* does not exist in OpenBSD */
struct node_uid *uid;
struct node_gid *gid;
+ struct node_if *rcv;
struct {
u_int8_t b1;
u_int8_t b2;
@@ -266,6 +306,19 @@ static struct filter_opts {
struct node_host *addr;
u_int16_t port;
} divert;
+ struct redirspec *nat;
+ struct redirspec *rdr;
+ /* new-style scrub opts */
+ int nodf;
+ int minttl;
+ int settos;
+ int randomid;
+ int max_mss;
+ struct {
+ uint32_t limit;
+ uint32_t seconds;
+ } pktrate;
+ int max_pkt_size;
} filter_opts;
static struct antispoof_opts {
@@ -277,10 +330,6 @@ static struct antispoof_opts {
static struct scrub_opts {
int marker;
-#define SOM_MINTTL 0x01
-#define SOM_MAXMSS 0x02
-#define SOM_FRAGCACHE 0x04
-#define SOM_SETTOS 0x08
int nodf;
int minttl;
int maxmss;
@@ -313,35 +362,24 @@ static struct table_opts {
struct node_tinithead init_nodes;
} table_opts;
-static struct pool_opts {
- int marker;
-#define POM_TYPE 0x01
-#define POM_STICKYADDRESS 0x02
- u_int8_t opts;
- int type;
- int staticport;
- struct pf_poolhashkey *key;
- struct pf_mape_portset mape;
-
-} pool_opts;
-
static struct codel_opts codel_opts;
static struct node_hfsc_opts hfsc_opts;
static struct node_fairq_opts fairq_opts;
static struct node_state_opt *keep_state_defaults = NULL;
static struct pfctl_watermarks syncookie_opts;
+int validate_range(uint8_t, uint16_t, uint16_t);
int disallow_table(struct node_host *, const char *);
int disallow_urpf_failed(struct node_host *, const char *);
int disallow_alias(struct node_host *, const char *);
-int rule_consistent(struct pfctl_rule *, int);
-int filter_consistent(struct pfctl_rule *, int);
+int rule_consistent(struct pfctl_rule *);
+int filter_consistent(struct pfctl_rule *);
int nat_consistent(struct pfctl_rule *);
int rdr_consistent(struct pfctl_rule *);
-int process_tabledef(char *, struct table_opts *);
+int process_tabledef(char *, struct table_opts *, int);
void expand_label_str(char *, size_t, const char *, const char *);
void expand_label_if(const char *, char *, size_t, const char *);
-void expand_label_addr(const char *, char *, size_t, u_int8_t,
+void expand_label_addr(const char *, char *, size_t, sa_family_t,
struct pf_rule_addr *);
void expand_label_port(const char *, char *, size_t,
struct pf_rule_addr *);
@@ -351,12 +389,21 @@ void expand_label_nr(const char *, char *, size_t,
void expand_eth_rule(struct pfctl_eth_rule *,
struct node_if *, struct node_etherproto *,
struct node_mac *, struct node_mac *,
- struct node_host *, struct node_host *, const char *);
-void expand_rule(struct pfctl_rule *, struct node_if *,
- struct node_host *, struct node_proto *, struct node_os *,
- struct node_host *, struct node_port *, struct node_host *,
- struct node_port *, struct node_uid *, struct node_gid *,
- struct node_icmp *, const char *);
+ struct node_host *, struct node_host *, const char *,
+ const char *);
+int apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *, struct redirspec *);
+int apply_nat_ports(struct pfctl_pool *, struct redirspec *);
+int apply_redirspec(struct pfctl_pool *, struct redirspec *);
+int check_binat_redirspec(struct node_host *, struct pfctl_rule *, sa_family_t);
+void add_binat_rdr_rule(struct pfctl_rule *, struct redirspec *,
+ struct node_host *, struct pfctl_rule *, struct redirspec **,
+ struct node_host **);
+void expand_rule(struct pfctl_rule *, bool, struct node_if *,
+ struct redirspec *, struct redirspec *, struct redirspec *,
+ struct node_proto *, struct node_os *, struct node_host *,
+ struct node_port *, struct node_host *, struct node_port *,
+ struct node_uid *, struct node_gid *, struct node_if *,
+ struct node_icmp *);
int expand_altq(struct pf_altq *, struct node_if *,
struct node_queue *, struct node_queue_bw bwspec,
struct node_queue_opt *);
@@ -368,19 +415,24 @@ int expand_skip_interface(struct node_if *);
int check_rulestate(int);
int getservice(char *);
int rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
+int eth_rule_label(struct pfctl_eth_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
int rt_tableid_max(void);
void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
void mv_eth_rules(struct pfctl_eth_ruleset *, struct pfctl_eth_ruleset *);
+void mv_tables(struct pfctl *, struct pfr_ktablehead *,
+ struct pfctl_anchor *, struct pfctl_anchor *);
void decide_address_family(struct node_host *, sa_family_t *);
void remove_invalid_hosts(struct node_host **, sa_family_t *);
int invalid_redirect(struct node_host *, sa_family_t);
u_int16_t parseicmpspec(char *, sa_family_t);
int kw_casecmp(const void *, const void *);
int map_tos(char *string, int *);
+int filteropts_to_rule(struct pfctl_rule *, struct filter_opts *);
struct node_mac* node_mac_from_string(const char *);
struct node_mac* node_mac_from_string_masklen(const char *, int);
struct node_mac* node_mac_from_string_mask(const char *, const char *);
+static bool pfctl_setup_anchor(struct pfctl_rule *, struct pfctl *, char *);
static TAILQ_HEAD(loadanchorshead, loadanchors)
loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
@@ -404,11 +456,7 @@ typedef struct {
u_int16_t w;
u_int16_t w2;
} b;
- struct range {
- int a;
- int b;
- int t;
- } range;
+ struct range range;
struct node_if *interface;
struct node_proto *proto;
struct node_etherproto *etherproto;
@@ -432,17 +480,12 @@ typedef struct {
struct {
struct node_mac *mac;
} etheraddr;
+ char *bridge_to;
struct {
- struct node_host *host;
+ struct redirspec *redirspec;
u_int8_t rt;
- u_int8_t pool_opts;
- sa_family_t af;
- struct pf_poolhashkey *key;
} route;
- struct redirection {
- struct node_host *host;
- struct range rport;
- } *redirection;
+ struct redirspec *redirspec;
struct {
int action;
struct node_state_opt *options;
@@ -490,26 +533,27 @@ int parseport(char *, struct range *r, int);
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
-%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
+%token REASSEMBLE ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
%token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
-%token ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3
+%token ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3 MATCHES
%token ETHER
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET
%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
%token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL
%token DNPIPE DNQUEUE RIDENTIFIER
-%token LOAD RULESET_OPTIMIZATION PRIO
-%token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
-%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY
+%token LOAD RULESET_OPTIMIZATION PRIO ONCE
+%token STICKYADDRESS ENDPI MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
+%token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW ALLOW_RELATED
%token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
-%token DIVERTTO DIVERTREPLY
+%token DIVERTTO DIVERTREPLY BRIDGE_TO RECEIVEDON NE LE GE AFTO NATTO RDRTO
+%token BINATTO MAXPKTRATE MAXPKTSIZE IPV6NH
%token <v.string> STRING
%token <v.number> NUMBER
%token <v.i> PORTBINARY
%type <v.interface> interface if_list if_item_not if_item
%type <v.number> number icmptype icmp6type uid gid
-%type <v.number> tos not yesno
+%type <v.number> tos not yesno optnodf
%type <v.probability> probability
%type <v.i> no dir af fragcache optimizer syncookie_val
%type <v.i> sourcetrack flush unaryop statelock
@@ -527,14 +571,15 @@ int parseport(char *, struct range *r, int);
%type <v.fromto> fromto l3fromto
%type <v.peer> ipportspec from to
%type <v.host> ipspec toipspec xhost host dynaddr host_list
-%type <v.host> redir_host_list redirspec
-%type <v.host> route_host route_host_list routespec
+%type <v.host> redir_host redir_host_list routespec
+%type <v.host> route_host route_host_list
%type <v.os> os xos os_list
%type <v.port> portspec port_list port_item
%type <v.uid> uids uid_list uid_item
%type <v.gid> gids gid_list gid_item
%type <v.route> route
-%type <v.redirection> redirection redirpool
+%type <v.redirspec> no_port_redirspec port_redirspec route_redirspec
+%type <v.redirspec> binat_redirspec nat_redirspec
%type <v.string> label stringall tag anchorname
%type <v.string> string varstring numberstring
%type <v.keep_state> keep
@@ -563,6 +608,7 @@ int parseport(char *, struct range *r, int);
%type <v.etherproto> etherproto etherproto_list etherproto_item
%type <v.etherfromto> etherfromto
%type <v.etheraddr> etherfrom etherto
+%type <v.bridge_to> bridge
%type <v.mac> xmac mac mac_list macspec
%%
@@ -628,7 +674,16 @@ optimizer : string {
}
;
-option : SET OPTIMIZATION STRING {
+optnodf : /* empty */ { $$ = 0; }
+ | NODF { $$ = 1; }
+ ;
+
+option : SET REASSEMBLE yesno optnodf {
+ if (check_rulestate(PFCTL_STATE_OPTION))
+ YYERROR;
+ pfctl_set_reassembly(pf, $3, $4);
+ }
+ | SET OPTIMIZATION STRING {
if (check_rulestate(PFCTL_STATE_OPTION)) {
free($3);
YYERROR;
@@ -667,10 +722,7 @@ option : SET OPTIMIZATION STRING {
yyerror("hostid must be non-zero");
YYERROR;
}
- if (pfctl_set_hostid(pf, $3) != 0) {
- yyerror("error setting hostid %08x", $3);
- YYERROR;
- }
+ pfctl_set_hostid(pf, $3);
}
| SET BLOCKPOLICY DROP {
if (pf->opts & PF_OPT_VERBOSE)
@@ -741,7 +793,7 @@ option : SET OPTIMIZATION STRING {
free($3);
YYERROR;
}
- if (pfctl_set_debug(pf, $3) != 0) {
+ if (pfctl_do_set_debug(pf, $3) != 0) {
yyerror("error setting debuglevel %s", $3);
free($3);
YYERROR;
@@ -862,6 +914,8 @@ varset : STRING '=' varstring {
if (isspace((unsigned char)*s)) {
yyerror("macro name cannot contain "
"whitespace");
+ free($1);
+ free($3);
YYERROR;
}
}
@@ -872,14 +926,36 @@ varset : STRING '=' varstring {
}
;
-anchorname : STRING { $$ = $1; }
+anchorname : STRING {
+ if ($1[0] == '\0') {
+ free($1);
+ yyerror("anchor name must not be empty");
+ YYERROR;
+ }
+ if (strlen(pf->anchor->path) + 1 +
+ strlen($1) >= PATH_MAX) {
+ free($1);
+ yyerror("anchor name is longer than %u",
+ PATH_MAX - 1);
+ YYERROR;
+ }
+ if ($1[0] == '_' || strstr($1, "/_") != NULL) {
+ free($1);
+ yyerror("anchor names beginning with '_' "
+ "are reserved for internal use");
+ YYERROR;
+ }
+ $$ = $1;
+ }
| /* empty */ { $$ = NULL; }
;
pfa_anchorlist : /* empty */
| pfa_anchorlist '\n'
+ | pfa_anchorlist tabledef '\n'
| pfa_anchorlist pfrule '\n'
| pfa_anchorlist anchorrule '\n'
+ | pfa_anchorlist include '\n'
;
pfa_anchor : '{'
@@ -888,14 +964,21 @@ pfa_anchor : '{'
struct pfctl_ruleset *rs;
/* stepping into a brace anchor */
+ if (pf->asd >= PFCTL_ANCHOR_STACK_DEPTH)
+ errx(1, "pfa_anchor: anchors too deep");
pf->asd++;
pf->bn++;
- /* create a holding ruleset in the root */
+ /*
+ * Anchor contents are parsed before the anchor rule
+ * production completes, so we don't know the real
+ * location yet. Create a holding ruleset in the root;
+ * contents will be moved afterwards.
+ */
snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
rs = pf_find_or_create_ruleset(ta);
if (rs == NULL)
- err(1, "pfa_anchor: pf_find_or_create_ruleset");
+ err(1, "pfa_anchor: pf_find_or_create_ruleset (%s)", ta);
pf->astack[pf->asd] = rs->anchor;
pf->anchor = rs->anchor;
} '\n' pfa_anchorlist '}'
@@ -919,75 +1002,14 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
YYERROR;
}
- if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) {
- free($2);
- yyerror("anchor names beginning with '_' "
- "are reserved for internal use");
+ pfctl_init_rule(&r);
+ if (! pfctl_setup_anchor(&r, pf, $2))
YYERROR;
- }
- memset(&r, 0, sizeof(r));
- if (pf->astack[pf->asd + 1]) {
- /* move inline rules into relative location */
- pfctl_anchor_setup(&r,
- &pf->astack[pf->asd]->ruleset,
- $2 ? $2 : pf->alast->name);
-
- if (r.anchor == NULL)
- err(1, "anchorrule: unable to "
- "create ruleset");
-
- if (pf->alast != r.anchor) {
- if (r.anchor->match) {
- yyerror("inline anchor '%s' "
- "already exists",
- r.anchor->name);
- YYERROR;
- }
- mv_rules(&pf->alast->ruleset,
- &r.anchor->ruleset);
- }
- pf_remove_if_empty_ruleset(&pf->alast->ruleset);
- pf->alast = r.anchor;
- } else {
- if (!$2) {
- yyerror("anchors without explicit "
- "rules must specify a name");
- YYERROR;
- }
- }
r.direction = $3;
r.quick = $4.quick;
r.af = $6;
- r.prob = $9.prob;
- r.rtableid = $9.rtableid;
- r.ridentifier = $9.ridentifier;
- if ($9.tag)
- if (strlcpy(r.tagname, $9.tag,
- PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- YYERROR;
- }
- if ($9.match_tag)
- if (strlcpy(r.match_tagname, $9.match_tag,
- PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- YYERROR;
- }
- r.match_tag_not = $9.match_tag_not;
- if (rule_label(&r, $9.label))
- YYERROR;
- for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
- free($9.label[i]);
- r.flags = $9.flags.b1;
- r.flagset = $9.flags.b2;
- if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
- yyerror("flags always false");
- YYERROR;
- }
if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
for (proto = $7; proto != NULL &&
proto->proto != IPPROTO_TCP;
@@ -1005,7 +1027,8 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
}
}
- r.tos = $9.tos;
+ if (filteropts_to_rule(&r, &$9))
+ YYERROR;
if ($9.keep.action) {
yyerror("cannot specify state handling "
@@ -1013,33 +1036,12 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
YYERROR;
}
- if ($9.match_tag)
- if (strlcpy(r.match_tagname, $9.match_tag,
- PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- YYERROR;
- }
- r.match_tag_not = $9.match_tag_not;
- if ($9.marker & FOM_PRIO) {
- if ($9.prio == 0)
- r.prio = PF_PRIO_ZERO;
- else
- r.prio = $9.prio;
- }
- if ($9.marker & FOM_SETPRIO) {
- r.set_prio[0] = $9.set_prio[0];
- r.set_prio[1] = $9.set_prio[1];
- r.scrub_flags |= PFSTATE_SETPRIO;
- }
-
decide_address_family($8.src.host, &r.af);
decide_address_family($8.dst.host, &r.af);
- expand_rule(&r, $5, NULL, $7, $8.src_os,
- $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
- $9.uid, $9.gid, $9.icmpspec,
- pf->astack[pf->asd + 1] ? pf->alast->name : $2);
+ expand_rule(&r, false, $5, NULL, NULL, NULL,
+ $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host,
+ $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec);
free($2);
pf->astack[pf->asd + 1] = NULL;
}
@@ -1051,7 +1053,10 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
YYERROR;
}
- memset(&r, 0, sizeof(r));
+ pfctl_init_rule(&r);
+ if (! pfctl_setup_anchor(&r, pf, $2))
+ YYERROR;
+
r.action = PF_NAT;
r.af = $4;
r.rtableid = $7;
@@ -1059,9 +1064,9 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
decide_address_family($6.src.host, &r.af);
decide_address_family($6.dst.host, &r.af);
- expand_rule(&r, $3, NULL, $5, $6.src_os,
- $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0, $2);
+ expand_rule(&r, false, $3, NULL, NULL, NULL,
+ $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host,
+ $6.dst.port, 0, 0, 0, 0);
free($2);
}
| RDRANCHOR string interface af proto fromto rtable {
@@ -1072,7 +1077,10 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
YYERROR;
}
- memset(&r, 0, sizeof(r));
+ pfctl_init_rule(&r);
+ if (! pfctl_setup_anchor(&r, pf, $2))
+ YYERROR;
+
r.action = PF_RDR;
r.af = $4;
r.rtableid = $7;
@@ -1101,9 +1109,9 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
r.dst.port_op = $6.dst.port->op;
}
- expand_rule(&r, $3, NULL, $5, $6.src_os,
- $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
- 0, 0, 0, $2);
+ expand_rule(&r, false, $3, NULL, NULL, NULL,
+ $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host,
+ $6.dst.port, 0, 0, 0, 0);
free($2);
}
| BINATANCHOR string interface af proto fromto rtable {
@@ -1114,7 +1122,10 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
YYERROR;
}
- memset(&r, 0, sizeof(r));
+ pfctl_init_rule(&r);
+ if (! pfctl_setup_anchor(&r, pf, $2))
+ YYERROR;
+
r.action = PF_BINAT;
r.af = $4;
r.rtableid = $7;
@@ -1138,19 +1149,16 @@ anchorrule : ANCHOR anchorname dir quick interface af proto fromto
decide_address_family($6.src.host, &r.af);
decide_address_family($6.dst.host, &r.af);
- pfctl_append_rule(pf, &r, $2);
+ pfctl_append_rule(pf, &r);
free($2);
}
;
-loadrule : LOAD ANCHOR string FROM string {
+loadrule : LOAD ANCHOR anchorname FROM string {
struct loadanchors *loadanchor;
- if (strlen(pf->anchor->name) + 1 +
- strlen($3) >= MAXPATHLEN) {
- yyerror("anchorname %s too long, max %u\n",
- $3, MAXPATHLEN - 1);
- free($3);
+ if ($3 == NULL) {
+ yyerror("anchor name is missing");
YYERROR;
}
loadanchor = calloc(1, sizeof(struct loadanchors));
@@ -1161,7 +1169,7 @@ loadrule : LOAD ANCHOR string FROM string {
err(1, "loadrule: malloc");
if (pf->anchor->name[0])
snprintf(loadanchor->anchorname, MAXPATHLEN,
- "%s/%s", pf->anchor->name, $3);
+ "%s/%s", pf->anchor->path, $3);
else
strlcpy(loadanchor->anchorname, $3, MAXPATHLEN);
if ((loadanchor->filename = strdup($5)) == NULL)
@@ -1183,7 +1191,7 @@ scrubaction : no SCRUB {
}
;
-etherrule : ETHER action dir quick interface etherproto etherfromto l3fromto etherfilter_opts
+etherrule : ETHER action dir quick interface bridge etherproto etherfromto l3fromto etherfilter_opts
{
struct pfctl_eth_rule r;
@@ -1195,23 +1203,28 @@ etherrule : ETHER action dir quick interface etherproto etherfromto l3fromto eth
r.action = $2.b1;
r.direction = $3;
r.quick = $4.quick;
- if ($9.tag != NULL)
- memcpy(&r.tagname, $9.tag, sizeof(r.tagname));
- if ($9.match_tag)
- if (strlcpy(r.match_tagname, $9.match_tag,
+ if ($10.tag != NULL)
+ strlcpy(r.tagname, $10.tag, sizeof(r.tagname));
+ if ($10.match_tag)
+ if (strlcpy(r.match_tagname, $10.match_tag,
PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
yyerror("tag too long, max %u chars",
PF_TAG_NAME_SIZE - 1);
YYERROR;
}
- r.match_tag_not = $9.match_tag_not;
- if ($9.queues.qname != NULL)
- memcpy(&r.qname, $9.queues.qname, sizeof(r.qname));
- r.dnpipe = $9.dnpipe;
- r.dnflags = $9.free_flags;
+ r.match_tag_not = $10.match_tag_not;
+ if ($10.queues.qname != NULL)
+ strlcpy(r.qname, $10.queues.qname, sizeof(r.qname));
+ r.dnpipe = $10.dnpipe;
+ r.dnflags = $10.free_flags;
+ if (eth_rule_label(&r, $10.label))
+ YYERROR;
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
+ free($10.label[i]);
+ r.ridentifier = $10.ridentifier;
- expand_eth_rule(&r, $5, $6, $7.src, $7.dst,
- $8.src.host, $8.dst.host, "");
+ expand_eth_rule(&r, $5, $7, $8.src, $8.dst,
+ $9.src.host, $9.dst.host, $6, "");
}
;
@@ -1227,6 +1240,8 @@ etherpfa_anchor : '{'
struct pfctl_eth_ruleset *rs;
/* steping into a brace anchor */
+ if (pf->asd >= PFCTL_ANCHOR_STACK_DEPTH)
+ errx(1, "pfa_anchor: anchors too deep");
pf->asd++;
pf->bn++;
@@ -1264,7 +1279,14 @@ etheranchorrule : ETHER ANCHOR anchorname dir quick interface etherproto etherfr
memset(&r, 0, sizeof(r));
if (pf->eastack[pf->asd + 1]) {
- /* move inline rules into relative location */
+ if ($3 && strchr($3, '/') != NULL) {
+ free($3);
+ yyerror("anchor paths containing '/' "
+ "cannot be used for inline anchors.");
+ YYERROR;
+ }
+
+ /* Move inline rules into relative location. */
pfctl_eth_anchor_setup(pf, &r,
&pf->eastack[pf->asd]->ruleset,
$3 ? $3 : pf->ealast->name);
@@ -1296,7 +1318,7 @@ etheranchorrule : ETHER ANCHOR anchorname dir quick interface etherproto etherfr
r.quick = $5.quick;
expand_eth_rule(&r, $6, $7, $8.src, $8.dst,
- $9.src.host, $9.dst.host,
+ $9.src.host, $9.dst.host, NULL,
pf->eastack[pf->asd + 1] ? pf->ealast->name : $3);
free($3);
@@ -1325,6 +1347,16 @@ etherfilter_opt : etherqname {
}
filter_opts.queues = $1;
}
+ | RIDENTIFIER number {
+ filter_opts.ridentifier = $2;
+ }
+ | label {
+ if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
+ yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
+ YYERROR;
+ }
+ filter_opts.label[filter_opts.labelcount++] = $1;
+ }
| TAG string {
filter_opts.tag = $2;
}
@@ -1342,6 +1374,14 @@ etherfilter_opt : etherqname {
}
;
+bridge : /* empty */ {
+ $$ = NULL;
+ }
+ | BRIDGE_TO STRING {
+ $$ = strdup($2);
+ }
+ ;
+
scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
{
struct pfctl_rule r;
@@ -1349,7 +1389,7 @@ scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
if (check_rulestate(PFCTL_STATE_SCRUB))
YYERROR;
- memset(&r, 0, sizeof(r));
+ pfctl_init_rule(&r);
r.action = $1.b1;
r.direction = $2;
@@ -1378,7 +1418,7 @@ scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
r.min_ttl = $8.minttl;
if ($8.maxmss)
r.max_mss = $8.maxmss;
- if ($8.marker & SOM_SETTOS) {
+ if ($8.marker & FOM_SETTOS) {
r.rule_flag |= PFRULE_SET_TOS;
r.set_tos = $8.settos;
}
@@ -1394,9 +1434,9 @@ scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
r.match_tag_not = $8.match_tag_not;
r.rtableid = $8.rtableid;
- expand_rule(&r, $4, NULL, $6, $7.src_os,
- $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
- NULL, NULL, NULL, "");
+ expand_rule(&r, false, $4, NULL, NULL, NULL,
+ $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host,
+ $7.dst.port, NULL, NULL, NULL, NULL);
}
;
@@ -1413,7 +1453,7 @@ scrub_opts : {
}
;
-scrub_opts_l : scrub_opts_l scrub_opt
+scrub_opts_l : scrub_opts_l comma scrub_opt
| scrub_opt
;
@@ -1425,7 +1465,7 @@ scrub_opt : NODF {
scrub_opts.nodf = 1;
}
| MINTTL NUMBER {
- if (scrub_opts.marker & SOM_MINTTL) {
+ if (scrub_opts.marker & FOM_MINTTL) {
yyerror("min-ttl cannot be respecified");
YYERROR;
}
@@ -1433,11 +1473,11 @@ scrub_opt : NODF {
yyerror("illegal min-ttl value %d", $2);
YYERROR;
}
- scrub_opts.marker |= SOM_MINTTL;
+ scrub_opts.marker |= FOM_MINTTL;
scrub_opts.minttl = $2;
}
| MAXMSS NUMBER {
- if (scrub_opts.marker & SOM_MAXMSS) {
+ if (scrub_opts.marker & FOM_MAXMSS) {
yyerror("max-mss cannot be respecified");
YYERROR;
}
@@ -1445,23 +1485,23 @@ scrub_opt : NODF {
yyerror("illegal max-mss value %d", $2);
YYERROR;
}
- scrub_opts.marker |= SOM_MAXMSS;
+ scrub_opts.marker |= FOM_MAXMSS;
scrub_opts.maxmss = $2;
}
| SETTOS tos {
- if (scrub_opts.marker & SOM_SETTOS) {
+ if (scrub_opts.marker & FOM_SETTOS) {
yyerror("set-tos cannot be respecified");
YYERROR;
}
- scrub_opts.marker |= SOM_SETTOS;
+ scrub_opts.marker |= FOM_SETTOS;
scrub_opts.settos = $2;
}
| fragcache {
- if (scrub_opts.marker & SOM_FRAGCACHE) {
+ if (scrub_opts.marker & FOM_FRAGCACHE) {
yyerror("fragcache cannot be respecified");
YYERROR;
}
- scrub_opts.marker |= SOM_FRAGCACHE;
+ scrub_opts.marker |= FOM_FRAGCACHE;
scrub_opts.fragcache = $1;
}
| REASSEMBLE STRING {
@@ -1498,9 +1538,8 @@ scrub_opt : NODF {
}
;
-fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
- | FRAGMENT FRAGCROP { $$ = 0; }
- | FRAGMENT FRAGDROP { $$ = 0; }
+fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
+ | FRAGMENT NO REASSEMBLE { $$ = PFRULE_FRAGMENT_NOREASS; }
;
antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
@@ -1512,7 +1551,7 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
YYERROR;
for (i = $3; i; i = i->next) {
- bzero(&r, sizeof(r));
+ pfctl_init_rule(&r);
r.action = PF_DROP;
r.direction = PF_IN;
@@ -1560,9 +1599,9 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
}
if (h != NULL)
- expand_rule(&r, j, NULL, NULL, NULL, h,
- NULL, NULL, NULL, NULL, NULL,
- NULL, "");
+ expand_rule(&r, false, j, NULL, NULL,
+ NULL, NULL, NULL, h, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL);
if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
bzero(&r, sizeof(r));
@@ -1582,9 +1621,10 @@ antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
else
h = ifa_lookup(i->ifname, 0);
if (h != NULL)
- expand_rule(&r, NULL, NULL,
- NULL, NULL, h, NULL, NULL,
- NULL, NULL, NULL, NULL, "");
+ expand_rule(&r, false, NULL,
+ NULL, NULL, NULL, NULL,
+ NULL, h, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL);
} else
free(hh);
}
@@ -1663,7 +1703,7 @@ tabledef : TABLE '<' STRING '>' table_opts {
YYERROR;
}
if (pf->loadopt & PFCTL_FLAG_TABLE)
- if (process_tabledef($3, &$5)) {
+ if (process_tabledef($3, &$5, pf->opts)) {
free($3);
YYERROR;
}
@@ -2296,7 +2336,7 @@ pfrule : action dir logquick interface route af proto fromto
if (check_rulestate(PFCTL_STATE_FILTER))
YYERROR;
- memset(&r, 0, sizeof(r));
+ pfctl_init_rule(&r);
r.action = $1.b1;
switch ($1.b2) {
@@ -2319,48 +2359,11 @@ pfrule : action dir logquick interface route af proto fromto
r.log = $3.log;
r.logif = $3.logif;
r.quick = $3.quick;
- r.prob = $9.prob;
- r.rtableid = $9.rtableid;
-
- if ($9.marker & FOM_PRIO) {
- if ($9.prio == 0)
- r.prio = PF_PRIO_ZERO;
- else
- r.prio = $9.prio;
- }
- if ($9.marker & FOM_SETPRIO) {
- r.set_prio[0] = $9.set_prio[0];
- r.set_prio[1] = $9.set_prio[1];
- r.scrub_flags |= PFSTATE_SETPRIO;
- }
-
r.af = $6;
- if ($9.tag)
- if (strlcpy(r.tagname, $9.tag,
- PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- YYERROR;
- }
- if ($9.match_tag)
- if (strlcpy(r.match_tagname, $9.match_tag,
- PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
- yyerror("tag too long, max %u chars",
- PF_TAG_NAME_SIZE - 1);
- YYERROR;
- }
- r.match_tag_not = $9.match_tag_not;
- if (rule_label(&r, $9.label))
- YYERROR;
- for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
- free($9.label[i]);
- r.ridentifier = $9.ridentifier;
- r.flags = $9.flags.b1;
- r.flagset = $9.flags.b2;
- if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
- yyerror("flags always false");
+
+ if (filteropts_to_rule(&r, &$9))
YYERROR;
- }
+
if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
for (proto = $7; proto != NULL &&
proto->proto != IPPROTO_TCP;
@@ -2376,18 +2379,8 @@ pfrule : action dir logquick interface route af proto fromto
"apply to tcp");
YYERROR;
}
-#if 0
- if (($9.flags.b1 & parse_flags("S")) == 0 &&
- $8.src_os) {
- yyerror("OS fingerprinting requires "
- "the SYN TCP flag (flags S/SA)");
- YYERROR;
- }
-#endif
}
- r.tos = $9.tos;
- r.keep_state = $9.keep.action;
o = $9.keep.options;
/* 'keep state' by default on pass rules. */
@@ -2538,6 +2531,22 @@ pfrule : action dir logquick interface route af proto fromto
}
r.rule_flag |= PFRULE_STATESLOPPY;
break;
+ case PF_STATE_OPT_PFLOW:
+ if (r.rule_flag & PFRULE_PFLOW) {
+ yyerror("state pflow option: "
+ "multiple definitions");
+ YYERROR;
+ }
+ r.rule_flag |= PFRULE_PFLOW;
+ break;
+ case PF_STATE_OPT_ALLOW_RELATED:
+ if (r.rule_flag & PFRULE_ALLOW_RELATED) {
+ yyerror("state allow-related option: "
+ "multiple definitions");
+ YYERROR;
+ }
+ r.rule_flag |= PFRULE_ALLOW_RELATED;
+ break;
case PF_STATE_OPT_TIMEOUT:
if (o->data.timeout.number ==
PFTM_ADAPTIVE_START ||
@@ -2605,10 +2614,6 @@ pfrule : action dir logquick interface route af proto fromto
if (r.keep_state && !statelock)
r.rule_flag |= default_statelock;
- if ($9.fragment)
- r.rule_flag |= PFRULE_FRAGMENT;
- r.allow_opts = $9.allowopts;
-
decide_address_family($8.src.host, &r.af);
decide_address_family($8.dst.host, &r.af);
@@ -2619,62 +2624,18 @@ pfrule : action dir logquick interface route af proto fromto
YYERROR;
}
r.rt = $5.rt;
- r.rpool.opts = $5.pool_opts;
- if ($5.key != NULL)
- memcpy(&r.rpool.key, $5.key,
- sizeof(struct pf_poolhashkey));
- }
- if (r.rt) {
- decide_address_family($5.host, &r.af);
- remove_invalid_hosts(&$5.host, &r.af);
- if ($5.host == NULL) {
- yyerror("no routing address with "
- "matching address family found.");
- YYERROR;
- }
- if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
- PF_POOL_NONE && ($5.host->next != NULL ||
- $5.host->addr.type == PF_ADDR_TABLE ||
- DYNIF_MULTIADDR($5.host->addr)))
- r.rpool.opts |= PF_POOL_ROUNDROBIN;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN &&
- disallow_table($5.host, "tables are only "
- "supported in round-robin routing pools"))
- YYERROR;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN &&
- disallow_alias($5.host, "interface (%s) "
- "is only supported in round-robin "
- "routing pools"))
- YYERROR;
- if ($5.host->next != NULL) {
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) {
- yyerror("r.rpool.opts must "
- "be PF_POOL_ROUNDROBIN");
+
+ if (!($5.redirspec->pool_opts.opts & PF_POOL_IPV6NH)) {
+ decide_address_family($5.redirspec->host, &r.af);
+ if (!(r.rule_flag & PFRULE_AFTO))
+ remove_invalid_hosts(&($5.redirspec->host), &r.af);
+ if ($5.redirspec->host == NULL) {
+ yyerror("no routing address with "
+ "matching address family found.");
YYERROR;
}
}
}
- if ($9.queues.qname != NULL) {
- if (strlcpy(r.qname, $9.queues.qname,
- sizeof(r.qname)) >= sizeof(r.qname)) {
- yyerror("rule qname too long (max "
- "%d chars)", sizeof(r.qname)-1);
- YYERROR;
- }
- free($9.queues.qname);
- }
- if ($9.queues.pqname != NULL) {
- if (strlcpy(r.pqname, $9.queues.pqname,
- sizeof(r.pqname)) >= sizeof(r.pqname)) {
- yyerror("rule pqname too long (max "
- "%d chars)", sizeof(r.pqname)-1);
- YYERROR;
- }
- free($9.queues.pqname);
- }
#ifdef __FreeBSD__
r.divert.port = $9.divert.port;
#else
@@ -2713,9 +2674,40 @@ pfrule : action dir logquick interface route af proto fromto
r.free_flags |= PFRULE_DN_IS_QUEUE;
}
- expand_rule(&r, $4, $5.host, $7, $8.src_os,
- $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
- $9.uid, $9.gid, $9.icmpspec, "");
+ if ($9.marker & FOM_AFTO) {
+ r.naf = $9.nat->af;
+ } else {
+ if ($9.nat) {
+ if (!r.af && ! $9.nat->host->ifindex)
+ r.af = $9.nat->host->af;
+ remove_invalid_hosts(&($9.nat->host), &r.af);
+ if (invalid_redirect($9.nat->host, r.af))
+ YYERROR;
+ if ($9.nat->host->addr.type == PF_ADDR_DYNIFTL) {
+ if (($9.nat->host = gen_dynnode($9.nat->host, r.af)) == NULL)
+ err(1, "calloc");
+ }
+ if (check_netmask($9.nat->host, r.af))
+ YYERROR;
+ }
+ if ($9.rdr) {
+ if (!r.af && ! $9.rdr->host->ifindex)
+ r.af = $9.rdr->host->af;
+ remove_invalid_hosts(&($9.rdr->host), &r.af);
+ if (invalid_redirect($9.rdr->host, r.af))
+ YYERROR;
+ if ($9.rdr->host->addr.type == PF_ADDR_DYNIFTL) {
+ if (($9.rdr->host = gen_dynnode($9.rdr->host, r.af)) == NULL)
+ err(1, "calloc");
+ }
+ if (check_netmask($9.rdr->host, r.af))
+ YYERROR;
+ }
+ }
+
+ expand_rule(&r, false, $4, $9.nat, $9.rdr, $5.redirspec,
+ $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host,
+ $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec);
}
;
@@ -2850,6 +2842,14 @@ filter_opt : USER uids {
filter_opts.match_tag = $3;
filter_opts.match_tag_not = $1;
}
+ | not RECEIVEDON if_item {
+ if (filter_opts.rcv) {
+ yyerror("cannot respecify received-on");
+ YYERROR;
+ }
+ filter_opts.rcv = $3;
+ filter_opts.rcv->not = $1;
+ }
| PROBABILITY probability {
double p;
@@ -2880,7 +2880,7 @@ filter_opt : USER uids {
}
| DIVERTTO STRING PORT portplain {
#ifndef __FreeBSD__
- if ((filter_opts.divert.addr = host($2)) == NULL) {
+ if ((filter_opts.divert.addr = host($2, pf->opts)) == NULL) {
yyerror("could not parse divert address: %s",
$2);
free($2);
@@ -2904,6 +2904,112 @@ filter_opt : USER uids {
filter_opts.divert.port = 1; /* some random value */
#endif
}
+ | SCRUB '(' scrub_opts ')' {
+ filter_opts.nodf = $3.nodf;
+ filter_opts.minttl = $3.minttl;
+ if ($3.marker & FOM_SETTOS) {
+ /* Old style rules are "scrub set-tos 0x42"
+ * New style are "set tos 0x42 scrub (...)"
+ * What is in "scrub(...)"" is unfortunately the
+ * original scrub syntax so it would overwrite
+ * "set tos" of a pass/match rule.
+ */
+ filter_opts.settos = $3.settos;
+ }
+ filter_opts.randomid = $3.randomid;
+ filter_opts.max_mss = $3.maxmss;
+ if ($3.reassemble_tcp)
+ filter_opts.marker |= FOM_SCRUB_TCP;
+ filter_opts.marker |= $3.marker;
+ }
+ | NATTO port_redirspec {
+ if (filter_opts.nat) {
+ yyerror("cannot respecify nat-to/binat-to");
+ YYERROR;
+ }
+ filter_opts.nat = $2;
+ }
+ | RDRTO port_redirspec {
+ if (filter_opts.rdr) {
+ yyerror("cannot respecify rdr-to");
+ YYERROR;
+ }
+ filter_opts.rdr = $2;
+ }
+ | BINATTO port_redirspec {
+ if (filter_opts.nat) {
+ yyerror("cannot respecify nat-to/binat-to");
+ YYERROR;
+ }
+ filter_opts.nat = $2;
+ filter_opts.nat->binat = 1;
+ filter_opts.nat->pool_opts.staticport = 1;
+ }
+ | AFTO af FROM port_redirspec {
+ if (filter_opts.nat) {
+ yyerror("cannot respecify af-to");
+ YYERROR;
+ }
+ if ($2 == 0) {
+ yyerror("no address family specified");
+ YYERROR;
+ }
+
+ filter_opts.nat = $4;
+ filter_opts.nat->af = $2;
+ remove_invalid_hosts(&($4->host), &(filter_opts.nat->af));
+ if ($4->host == NULL) {
+ yyerror("af-to addresses must be in the "
+ "target address family");
+ YYERROR;
+ }
+ filter_opts.marker |= FOM_AFTO;
+ }
+ | AFTO af FROM port_redirspec TO port_redirspec {
+ if (filter_opts.nat) {
+ yyerror("cannot respecify af-to");
+ YYERROR;
+ }
+ if ($2 == 0) {
+ yyerror("no address family specified");
+ YYERROR;
+ }
+ filter_opts.nat = $4;
+ filter_opts.nat->af = $2;
+ filter_opts.rdr = $6;
+ filter_opts.rdr->af = $2;
+ remove_invalid_hosts(&($4->host), &(filter_opts.nat->af));
+ remove_invalid_hosts(&($6->host), &(filter_opts.rdr->af));
+ if ($4->host == NULL || $6->host == NULL) {
+ yyerror("af-to addresses must be in the "
+ "target address family");
+ YYERROR;
+ }
+ filter_opts.marker |= FOM_AFTO;
+ }
+ | MAXPKTRATE NUMBER '/' NUMBER {
+ if ($2 < 0 || $2 > UINT_MAX ||
+ $4 < 0 || $4 > UINT_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
+ if (filter_opts.pktrate.limit) {
+ yyerror("cannot respecify max-pkt-rate");
+ YYERROR;
+ }
+ filter_opts.pktrate.limit = $2;
+ filter_opts.pktrate.seconds = $4;
+ }
+ | MAXPKTSIZE NUMBER {
+ if ($2 < 0 || $2 > UINT16_MAX) {
+ yyerror("only positive values permitted");
+ YYERROR;
+ }
+ filter_opts.max_pkt_size = $2;
+ }
+ | ONCE {
+ filter_opts.marker |= FOM_ONCE;
+ }
| filter_sets
;
@@ -2924,6 +3030,14 @@ filter_set : prio {
filter_opts.set_prio[0] = $1.b1;
filter_opts.set_prio[1] = $1.b2;
}
+ | TOS tos {
+ if (filter_opts.marker & FOM_SETTOS) {
+ yyerror("tos cannot be respecified");
+ YYERROR;
+ }
+ filter_opts.marker |= FOM_SETTOS;
+ filter_opts.settos = $2;
+ }
prio : PRIO NUMBER {
if ($2 < 0 || $2 > PF_PRIO_MAX) {
yyerror("prio must be 0 - %u", PF_PRIO_MAX);
@@ -3101,8 +3215,8 @@ logopts : logopt { $$ = $1; }
;
logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; }
- | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
- | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
+ | MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; }
+ | USER { $$.log = PF_LOG_USER; $$.logif = 0; }
| TO string {
const char *errstr;
u_int i;
@@ -3162,6 +3276,15 @@ if_item : STRING {
$$->next = NULL;
$$->tail = $$;
}
+ | ANY {
+ $$ = calloc(1, sizeof(struct node_if));
+ if ($$ == NULL)
+ err(1, "if_item: calloc");
+ strlcpy($$->ifname, "any", sizeof($$->ifname));
+ $$->not = 0;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
;
af : /* empty */ { $$ = 0; }
@@ -3451,11 +3574,13 @@ toipspec : TO ipspec { $$ = $2; }
host_list : ipspec optnl { $$ = $1; }
| host_list comma ipspec optnl {
- if ($3 == NULL)
+ if ($1 == NULL) {
+ freehostlist($3);
$$ = $1;
- else if ($1 == NULL)
+ } else if ($3 == NULL) {
+ freehostlist($1);
$$ = $3;
- else {
+ } else {
$1->tail->next = $3;
$1->tail = $3->tail;
$$ = $1;
@@ -3491,7 +3616,7 @@ xhost : not host {
;
host : STRING {
- if (($$ = host($1)) == NULL) {
+ if (($$ = host($1, pf->opts)) == NULL) {
/* error. "any" is handled elsewhere */
free($1);
yyerror("could not parse host specification");
@@ -3503,7 +3628,8 @@ host : STRING {
| STRING '-' STRING {
struct node_host *b, *e;
- if ((b = host($1)) == NULL || (e = host($3)) == NULL) {
+ if ((b = host($1, pf->opts)) == NULL ||
+ (e = host($3, pf->opts)) == NULL) {
free($1);
free($3);
yyerror("could not parse host specification");
@@ -3512,9 +3638,9 @@ host : STRING {
if (b->af != e->af ||
b->addr.type != PF_ADDR_ADDRMASK ||
e->addr.type != PF_ADDR_ADDRMASK ||
- unmask(&b->addr.v.a.mask, b->af) !=
+ unmask(&b->addr.v.a.mask) !=
(b->af == AF_INET ? 32 : 128) ||
- unmask(&e->addr.v.a.mask, e->af) !=
+ unmask(&e->addr.v.a.mask) !=
(e->af == AF_INET ? 32 : 128) ||
b->next != NULL || b->not ||
e->next != NULL || e->not) {
@@ -3539,7 +3665,7 @@ host : STRING {
if (asprintf(&buf, "%s/%lld", $1, (long long)$3) == -1)
err(1, "host: asprintf");
free($1);
- if (($$ = host(buf)) == NULL) {
+ if (($$ = host(buf, pf->opts)) == NULL) {
/* error. "any" is handled elsewhere */
free(buf);
yyerror("could not parse host specification");
@@ -3557,7 +3683,7 @@ host : STRING {
if (asprintf(&buf, "%lld/%lld", $1, $3) == -1)
#endif
err(1, "host: asprintf");
- if (($$ = host(buf)) == NULL) {
+ if (($$ = host(buf, pf->opts)) == NULL) {
/* error. "any" is handled elsewhere */
free(buf);
yyerror("could not parse host specification");
@@ -3683,9 +3809,14 @@ port_item : portrange {
err(1, "port_item: calloc");
$$->port[0] = $1.a;
$$->port[1] = $1.b;
- if ($1.t)
+ if ($1.t) {
$$->op = PF_OP_RRG;
- else
+ if (validate_range($$->op, $$->port[0],
+ $$->port[1])) {
+ yyerror("invalid port range");
+ YYERROR;
+ }
+ } else
$$->op = PF_OP_EQ;
$$->next = NULL;
$$->tail = $$;
@@ -3702,6 +3833,10 @@ port_item : portrange {
$$->port[0] = $2.a;
$$->port[1] = $2.b;
$$->op = $1;
+ if (validate_range($$->op, $$->port[0], $$->port[1])) {
+ yyerror("invalid port range");
+ YYERROR;
+ }
$$->next = NULL;
$$->tail = $$;
}
@@ -3717,6 +3852,10 @@ port_item : portrange {
$$->port[0] = $1.a;
$$->port[1] = $3.a;
$$->op = $2;
+ if (validate_range($$->op, $$->port[0], $$->port[1])) {
+ yyerror("invalid port range");
+ YYERROR;
+ }
$$->next = NULL;
$$->tail = $$;
}
@@ -3763,7 +3902,7 @@ uid_item : uid {
$$->tail = $$;
}
| unaryop uid {
- if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
+ if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
yyerror("user unknown requires operator = or "
"!=");
YYERROR;
@@ -3778,7 +3917,7 @@ uid_item : uid {
$$->tail = $$;
}
| uid PORTBINARY uid {
- if ($1 == UID_MAX || $3 == UID_MAX) {
+ if ($1 == -1 || $3 == -1) {
yyerror("user unknown requires operator = or "
"!=");
YYERROR;
@@ -3796,16 +3935,16 @@ uid_item : uid {
uid : STRING {
if (!strcmp($1, "unknown"))
- $$ = UID_MAX;
+ $$ = -1;
else {
- struct passwd *pw;
+ uid_t uid;
- if ((pw = getpwnam($1)) == NULL) {
+ if (uid_from_user($1, &uid) == -1) {
yyerror("unknown user %s", $1);
free($1);
YYERROR;
}
- $$ = pw->pw_uid;
+ $$ = uid;
}
free($1);
}
@@ -3841,7 +3980,7 @@ gid_item : gid {
$$->tail = $$;
}
| unaryop gid {
- if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
+ if ($2 == -1 && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
yyerror("group unknown requires operator = or "
"!=");
YYERROR;
@@ -3856,7 +3995,7 @@ gid_item : gid {
$$->tail = $$;
}
| gid PORTBINARY gid {
- if ($1 == GID_MAX || $3 == GID_MAX) {
+ if ($1 == -1 || $3 == -1) {
yyerror("group unknown requires operator = or "
"!=");
YYERROR;
@@ -3874,16 +4013,16 @@ gid_item : gid {
gid : STRING {
if (!strcmp($1, "unknown"))
- $$ = GID_MAX;
+ $$ = -1;
else {
- struct group *grp;
+ gid_t gid;
- if ((grp = getgrnam($1)) == NULL) {
+ if (gid_from_group($1, &gid) == -1) {
yyerror("unknown group %s", $1);
free($1);
YYERROR;
}
- $$ = grp->gr_gid;
+ $$ = gid;
}
free($1);
}
@@ -4090,7 +4229,7 @@ tos : STRING {
| NUMBER {
$$ = $1;
if ($$ < 0 || $$ > 255) {
- yyerror("illegal tos value %s", $1);
+ yyerror("illegal tos value %lu", $1);
YYERROR;
}
}
@@ -4265,6 +4404,22 @@ state_opt_item : MAXIMUM NUMBER {
$$->next = NULL;
$$->tail = $$;
}
+ | PFLOW {
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_PFLOW;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
+ | ALLOW_RELATED {
+ $$ = calloc(1, sizeof(struct node_state_opt));
+ if ($$ == NULL)
+ err(1, "state_opt_item: calloc");
+ $$->type = PF_STATE_OPT_ALLOW_RELATED;
+ $$->next = NULL;
+ $$->tail = $$;
+ }
| STRING NUMBER {
int i;
@@ -4337,7 +4492,7 @@ portstar : numberstring {
}
;
-redirspec : host { $$ = $1; }
+redir_host : host { $$ = $1; }
| '{' optnl redir_host_list '}' { $$ = $3; }
;
@@ -4349,20 +4504,42 @@ redir_host_list : host optnl { $$ = $1; }
}
;
-redirpool : /* empty */ { $$ = NULL; }
- | ARROW redirspec {
- $$ = calloc(1, sizeof(struct redirection));
+/* Redirection without port */
+no_port_redirspec: redir_host pool_opts {
+ $$ = calloc(1, sizeof(struct redirspec));
if ($$ == NULL)
- err(1, "redirection: calloc");
- $$->host = $2;
+ err(1, "redirspec: calloc");
+ $$->host = $1;
+ $$->pool_opts = $2;
$$->rport.a = $$->rport.b = $$->rport.t = 0;
}
- | ARROW redirspec PORT portstar {
- $$ = calloc(1, sizeof(struct redirection));
+ ;
+
+/* Redirection with optional port */
+port_redirspec : no_port_redirspec;
+ | redir_host PORT portstar pool_opts {
+ $$ = calloc(1, sizeof(struct redirspec));
if ($$ == NULL)
- err(1, "redirection: calloc");
- $$->host = $2;
- $$->rport = $4;
+ err(1, "redirspec: calloc");
+ $$->host = $1;
+ $$->rport = $3;
+ $$->pool_opts = $4;
+ }
+
+/* Redirection with an arrow and an optional port: FreeBSD NAT rules */
+nat_redirspec : /* empty */ { $$ = NULL; }
+ | ARROW port_redirspec {
+ $$ = $2;
+ }
+ ;
+
+/* Redirection with interfaces and without ports: route-to rules */
+route_redirspec : routespec pool_opts {
+ $$ = calloc(1, sizeof(struct redirspec));
+ if ($$ == NULL)
+ err(1, "redirspec: calloc");
+ $$->host = $1;
+ $$->pool_opts = $2;
}
;
@@ -4466,13 +4643,29 @@ pool_opt : BITMASK {
pool_opts.staticport = 1;
}
| STICKYADDRESS {
- if (filter_opts.marker & POM_STICKYADDRESS) {
+ if (pool_opts.marker & POM_STICKYADDRESS) {
yyerror("sticky-address cannot be redefined");
YYERROR;
}
pool_opts.marker |= POM_STICKYADDRESS;
pool_opts.opts |= PF_POOL_STICKYADDR;
}
+ | ENDPI {
+ if (pool_opts.marker & POM_ENDPI) {
+ yyerror("endpoint-independent cannot be redefined");
+ YYERROR;
+ }
+ pool_opts.marker |= POM_ENDPI;
+ pool_opts.opts |= PF_POOL_ENDPI;
+ }
+ | IPV6NH {
+ if (pool_opts.marker & POM_IPV6NH) {
+ yyerror("prefer-ipv6-nexthop cannot be redefined");
+ YYERROR;
+ }
+ pool_opts.marker |= POM_IPV6NH;
+ pool_opts.opts |= PF_POOL_IPV6NH;
+ }
| MAPEPORTSET number '/' number '/' number {
if (pool_opts.mape.offset) {
yyerror("map-e-portset cannot be redefined");
@@ -4505,18 +4698,18 @@ pool_opt : BITMASK {
}
;
-redirection : /* empty */ { $$ = NULL; }
+binat_redirspec : /* empty */ { $$ = NULL; }
| ARROW host {
- $$ = calloc(1, sizeof(struct redirection));
+ $$ = calloc(1, sizeof(struct redirspec));
if ($$ == NULL)
- err(1, "redirection: calloc");
+ err(1, "redirspec: calloc");
$$->host = $2;
$$->rport.a = $$->rport.b = $$->rport.t = 0;
}
| ARROW host PORT portstar {
- $$ = calloc(1, sizeof(struct redirection));
+ $$ = calloc(1, sizeof(struct redirspec));
if ($$ == NULL)
- err(1, "redirection: calloc");
+ err(1, "redirspec: calloc");
$$->host = $2;
$$->rport = $4;
}
@@ -4557,14 +4750,15 @@ nataction : no NAT natpasslog {
;
natrule : nataction interface af proto fromto tag tagged rtable
- redirpool pool_opts
+ nat_redirspec
{
struct pfctl_rule r;
+ struct node_state_opt *o;
if (check_rulestate(PFCTL_STATE_NAT))
YYERROR;
- memset(&r, 0, sizeof(r));
+ pfctl_init_rule(&r);
r.action = $1.b1;
r.natpass = $1.b2;
@@ -4611,138 +4805,52 @@ natrule : nataction interface af proto fromto tag tagged rtable
"address'");
YYERROR;
}
+ if ($9->pool_opts.opts & PF_POOL_IPV6NH) {
+ yyerror("The prefer-ipv6-nexthop option "
+ "can't be used for nat/rdr/binat pools"
+ );
+ YYERROR;
+ }
if (!r.af && ! $9->host->ifindex)
r.af = $9->host->af;
remove_invalid_hosts(&$9->host, &r.af);
if (invalid_redirect($9->host, r.af))
YYERROR;
+ if ($9->host->addr.type == PF_ADDR_DYNIFTL) {
+ if (($9->host = gen_dynnode($9->host, r.af)) == NULL)
+ err(1, "calloc");
+ }
if (check_netmask($9->host, r.af))
YYERROR;
+ }
- r.rpool.proxy_port[0] = ntohs($9->rport.a);
-
- switch (r.action) {
- case PF_RDR:
- if (!$9->rport.b && $9->rport.t &&
- $5.dst.port != NULL) {
- r.rpool.proxy_port[1] =
- ntohs($9->rport.a) +
- (ntohs(
- $5.dst.port->port[1]) -
- ntohs(
- $5.dst.port->port[0]));
- } else
- r.rpool.proxy_port[1] =
- ntohs($9->rport.b);
- break;
- case PF_NAT:
- r.rpool.proxy_port[1] =
- ntohs($9->rport.b);
- if (!r.rpool.proxy_port[0] &&
- !r.rpool.proxy_port[1]) {
- r.rpool.proxy_port[0] =
- PF_NAT_PROXY_PORT_LOW;
- r.rpool.proxy_port[1] =
- PF_NAT_PROXY_PORT_HIGH;
- } else if (!r.rpool.proxy_port[1])
- r.rpool.proxy_port[1] =
- r.rpool.proxy_port[0];
- break;
- default:
- break;
- }
-
- r.rpool.opts = $10.type;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
- PF_POOL_NONE && ($9->host->next != NULL ||
- $9->host->addr.type == PF_ADDR_TABLE ||
- DYNIF_MULTIADDR($9->host->addr)))
- r.rpool.opts = PF_POOL_ROUNDROBIN;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN &&
- disallow_table($9->host, "tables are only "
- "supported in round-robin redirection "
- "pools"))
- YYERROR;
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN &&
- disallow_alias($9->host, "interface (%s) "
- "is only supported in round-robin "
- "redirection pools"))
- YYERROR;
- if ($9->host->next != NULL) {
- if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
- PF_POOL_ROUNDROBIN) {
- yyerror("only round-robin "
- "valid for multiple "
- "redirection addresses");
+ o = keep_state_defaults;
+ while (o) {
+ switch (o->type) {
+ case PF_STATE_OPT_PFLOW:
+ if (r.rule_flag & PFRULE_PFLOW) {
+ yyerror("state pflow option: "
+ "multiple definitions");
YYERROR;
}
+ r.rule_flag |= PFRULE_PFLOW;
+ break;
}
+ o = o->next;
}
- if ($10.key != NULL)
- memcpy(&r.rpool.key, $10.key,
- sizeof(struct pf_poolhashkey));
-
- if ($10.opts)
- r.rpool.opts |= $10.opts;
-
- if ($10.staticport) {
- if (r.action != PF_NAT) {
- yyerror("the 'static-port' option is "
- "only valid with nat rules");
- YYERROR;
- }
- if (r.rpool.proxy_port[0] !=
- PF_NAT_PROXY_PORT_LOW &&
- r.rpool.proxy_port[1] !=
- PF_NAT_PROXY_PORT_HIGH) {
- yyerror("the 'static-port' option can't"
- " be used when specifying a port"
- " range");
- YYERROR;
- }
- r.rpool.proxy_port[0] = 0;
- r.rpool.proxy_port[1] = 0;
- }
-
- if ($10.mape.offset) {
- if (r.action != PF_NAT) {
- yyerror("the 'map-e-portset' option is"
- " only valid with nat rules");
- YYERROR;
- }
- if ($10.staticport) {
- yyerror("the 'map-e-portset' option"
- " can't be used 'static-port'");
- YYERROR;
- }
- if (r.rpool.proxy_port[0] !=
- PF_NAT_PROXY_PORT_LOW &&
- r.rpool.proxy_port[1] !=
- PF_NAT_PROXY_PORT_HIGH) {
- yyerror("the 'map-e-portset' option"
- " can't be used when specifying"
- " a port range");
- YYERROR;
- }
- r.rpool.mape = $10.mape;
- }
-
- expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4,
+ expand_rule(&r, false, $2, NULL, $9, NULL, $4,
$5.src_os, $5.src.host, $5.src.port, $5.dst.host,
- $5.dst.port, 0, 0, 0, "");
- free($9);
+ $5.dst.port, 0, 0, 0, 0);
}
;
binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag
- tagged rtable redirection
+ tagged rtable binat_redirspec
{
struct pfctl_rule binat;
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
if (check_rulestate(PFCTL_STATE_NAT))
YYERROR;
@@ -4750,7 +4858,7 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag
"permitted as a binat destination"))
YYERROR;
- memset(&binat, 0, sizeof(binat));
+ pfctl_init_rule(&binat);
if ($1 && $3.b1) {
yyerror("\"pass\" not valid with \"no\"");
@@ -4833,6 +4941,10 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag
yyerror("binat ip versions must match");
YYERROR;
}
+ if ($8->addr.type == PF_ADDR_DYNIFTL) {
+ if (($8 = gen_dynnode($8, binat.af)) == NULL)
+ err(1, "calloc");
+ }
if (check_netmask($8, binat.af))
YYERROR;
memcpy(&binat.src.addr, &$8->addr,
@@ -4848,6 +4960,10 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag
yyerror("binat ip versions must match");
YYERROR;
}
+ if ($9->addr.type == PF_ADDR_DYNIFTL) {
+ if (($9 = gen_dynnode($9, binat.af)) == NULL)
+ err(1, "calloc");
+ }
if (check_netmask($9, binat.af))
YYERROR;
memcpy(&binat.dst.addr, &$9->addr,
@@ -4877,6 +4993,10 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag
"a single address");
YYERROR;
}
+ if ($13->host->addr.type == PF_ADDR_DYNIFTL) {
+ if (($13->host = gen_dynnode($13->host, binat.af)) == NULL)
+ err(1, "calloc");
+ }
if (check_netmask($13->host, binat.af))
YYERROR;
@@ -4889,19 +5009,19 @@ binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag
YYERROR;
}
- TAILQ_INIT(&binat.rpool.list);
- pa = calloc(1, sizeof(struct pf_pooladdr));
+ pa = calloc(1, sizeof(struct pfctl_pooladdr));
if (pa == NULL)
err(1, "binat: calloc");
pa->addr = $13->host->addr;
pa->ifname[0] = 0;
- TAILQ_INSERT_TAIL(&binat.rpool.list,
+ pa->af = $13->host->af;
+ TAILQ_INSERT_TAIL(&binat.rdr.list,
pa, entries);
free($13);
}
- pfctl_append_rule(pf, &binat, "");
+ pfctl_append_rule(pf, &binat);
}
;
@@ -4952,13 +5072,6 @@ route_host : STRING {
route_host_list : route_host optnl { $$ = $1; }
| route_host_list comma route_host optnl {
- if ($1->af == 0)
- $1->af = $3->af;
- if ($1->af != $3->af) {
- yyerror("all pool addresses must be in the "
- "same address family");
- YYERROR;
- }
$1->tail->next = $3;
$1->tail = $3->tail;
$$ = $1;
@@ -4970,36 +5083,23 @@ routespec : route_host { $$ = $1; }
;
route : /* empty */ {
- $$.host = NULL;
- $$.rt = 0;
- $$.pool_opts = 0;
+ $$.rt = PF_NOPFROUTE;
}
| FASTROUTE {
/* backwards-compat */
- $$.host = NULL;
- $$.rt = 0;
- $$.pool_opts = 0;
+ $$.rt = PF_NOPFROUTE;
}
- | ROUTETO routespec pool_opts {
- $$.host = $2;
+ | ROUTETO route_redirspec {
$$.rt = PF_ROUTETO;
- $$.pool_opts = $3.type | $3.opts;
- if ($3.key != NULL)
- $$.key = $3.key;
+ $$.redirspec = $2;
}
- | REPLYTO routespec pool_opts {
- $$.host = $2;
+ | REPLYTO route_redirspec {
$$.rt = PF_REPLYTO;
- $$.pool_opts = $3.type | $3.opts;
- if ($3.key != NULL)
- $$.key = $3.key;
+ $$.redirspec = $2;
}
- | DUPTO routespec pool_opts {
- $$.host = $2;
+ | DUPTO route_redirspec {
$$.rt = PF_DUPTO;
- $$.pool_opts = $3.type | $3.opts;
- if ($3.key != NULL)
- $$.key = $3.key;
+ $$.redirspec = $2;
}
;
@@ -5013,7 +5113,7 @@ timeout_spec : STRING NUMBER
yyerror("only positive values permitted");
YYERROR;
}
- if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
+ if (pfctl_apply_timeout(pf, $1, $2, 0) != 0) {
yyerror("unknown timeout %s", $1);
free($1);
YYERROR;
@@ -5027,7 +5127,7 @@ timeout_spec : STRING NUMBER
yyerror("only positive values permitted");
YYERROR;
}
- if (pfctl_set_timeout(pf, "interval", $2, 0) != 0)
+ if (pfctl_apply_timeout(pf, "interval", $2, 0) != 0)
YYERROR;
}
;
@@ -5046,7 +5146,7 @@ limit_spec : STRING NUMBER
yyerror("only positive values permitted");
YYERROR;
}
- if (pfctl_set_limit(pf, $1, $2) != 0) {
+ if (pfctl_apply_limit(pf, $1, $2) != 0) {
yyerror("unable to set limit %s %u", $1, $2);
free($1);
YYERROR;
@@ -5078,10 +5178,10 @@ yesno : NO { $$ = 0; }
;
unaryop : '=' { $$ = PF_OP_EQ; }
- | '!' '=' { $$ = PF_OP_NE; }
- | '<' '=' { $$ = PF_OP_LE; }
+ | NE { $$ = PF_OP_NE; }
+ | LE { $$ = PF_OP_LE; }
| '<' { $$ = PF_OP_LT; }
- | '>' '=' { $$ = PF_OP_GE; }
+ | GE { $$ = PF_OP_GE; }
| '>' { $$ = PF_OP_GT; }
;
@@ -5102,6 +5202,19 @@ yyerror(const char *fmt, ...)
}
int
+validate_range(uint8_t op, uint16_t p1, uint16_t p2)
+{
+ uint16_t a = ntohs(p1);
+ uint16_t b = ntohs(p2);
+
+ if ((op == PF_OP_RRG && a > b) || /* 34:12, i.e. none */
+ (op == PF_OP_IRG && a >= b) || /* 34><12, i.e. none */
+ (op == PF_OP_XRG && a > b)) /* 34<>22, i.e. all */
+ return 1;
+ return 0;
+}
+
+int
disallow_table(struct node_host *h, const char *fmt)
{
for (; h != NULL; h = h->next)
@@ -5135,16 +5248,17 @@ disallow_alias(struct node_host *h, const char *fmt)
}
int
-rule_consistent(struct pfctl_rule *r, int anchor_call)
+rule_consistent(struct pfctl_rule *r)
{
int problems = 0;
switch (r->action) {
case PF_PASS:
+ case PF_MATCH:
case PF_DROP:
case PF_SCRUB:
case PF_NOSCRUB:
- problems = filter_consistent(r, anchor_call);
+ problems = filter_consistent(r);
break;
case PF_NAT:
case PF_NONAT:
@@ -5163,13 +5277,14 @@ rule_consistent(struct pfctl_rule *r, int anchor_call)
}
int
-filter_consistent(struct pfctl_rule *r, int anchor_call)
+filter_consistent(struct pfctl_rule *r)
{
int problems = 0;
if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
+ r->proto != IPPROTO_SCTP &&
(r->src.port_op || r->dst.port_op)) {
- yyerror("port only applies to tcp/udp");
+ yyerror("port only applies to tcp/udp/sctp");
problems++;
}
if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
@@ -5181,6 +5296,10 @@ filter_consistent(struct pfctl_rule *r, int anchor_call)
yyerror("must indicate address family with icmp-type/code");
problems++;
}
+ if (r->rule_flag & PFRULE_AFTO && r->af == r->naf) {
+ yyerror("must indicate different address family with af-to");
+ problems++;
+ }
if (r->overload_tblname[0] &&
r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
yyerror("'overload' requires 'max-src-conn' "
@@ -5194,8 +5313,9 @@ filter_consistent(struct pfctl_rule *r, int anchor_call)
r->af == AF_INET ? "inet" : "inet6");
problems++;
}
- if (r->allow_opts && r->action != PF_PASS) {
- yyerror("allow-opts can only be specified for pass rules");
+ if (r->allow_opts && r->action != PF_PASS && r->action != PF_MATCH) {
+ yyerror("allow-opts can only be specified for pass or "
+ "match rules");
problems++;
}
if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
@@ -5211,8 +5331,8 @@ filter_consistent(struct pfctl_rule *r, int anchor_call)
yyerror("max-src-nodes requires 'source-track rule'");
problems++;
}
- if (r->action == PF_DROP && r->keep_state) {
- yyerror("keep state on block rules doesn't make sense");
+ if (r->action != PF_PASS && r->keep_state) {
+ yyerror("keep state is great, but only for pass rules");
problems++;
}
if (r->rule_flag & PFRULE_STATESLOPPY &&
@@ -5222,6 +5342,56 @@ filter_consistent(struct pfctl_rule *r, int anchor_call)
"synproxy state or modulate state");
problems++;
}
+ if ((r->keep_state == PF_STATE_SYNPROXY) && (r->direction != PF_IN))
+ fprintf(stderr, "%s:%d: warning: "
+ "synproxy used for inbound rules only, "
+ "ignored for outbound\n", file->name, yylval.lineno);
+ if (r->rule_flag & PFRULE_AFTO && r->rt) {
+ if (r->rt != PF_ROUTETO && r->rt != PF_REPLYTO) {
+ yyerror("dup-to "
+ "must not be used on af-to rules");
+ problems++;
+ }
+ }
+ /* Basic rule sanity check. */
+ switch (r->action) {
+ case PF_MATCH:
+ if (r->divert.port) {
+ yyerror("divert is not supported on match rules");
+ problems++;
+ }
+ if (r->rt) {
+ yyerror("route-to, reply-to, dup-to and fastroute "
+ "must not be used on match rules");
+ problems++;
+ }
+ if (r->rule_flag & PFRULE_AFTO) {
+ yyerror("af-to is not supported on match rules");
+ problems++;
+ }
+ break;
+ case PF_DROP:
+ if (r->rt) {
+ yyerror("route-to, reply-to and dup-to "
+ "are not supported on block rules");
+ problems++;
+ }
+ break;
+ default:;
+ }
+ if (!TAILQ_EMPTY(&(r->nat.list)) || !TAILQ_EMPTY(&(r->rdr.list))) {
+ if (r->action != PF_MATCH && !r->keep_state) {
+ yyerror("nat-to and rdr-to require keep state");
+ problems++;
+ }
+ if (r->direction == PF_INOUT) {
+ yyerror("nat-to and rdr-to require a direction");
+ problems++;
+ }
+ }
+ if (r->route.opts & PF_POOL_STICKYADDR && !r->keep_state) {
+ yyerror("'sticky-address' requires 'keep state'");
+ }
return (-problems);
}
@@ -5236,17 +5406,18 @@ rdr_consistent(struct pfctl_rule *r)
{
int problems = 0;
- if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) {
+ if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
+ r->proto != IPPROTO_SCTP) {
if (r->src.port_op) {
- yyerror("src port only applies to tcp/udp");
+ yyerror("src port only applies to tcp/udp/sctp");
problems++;
}
if (r->dst.port_op) {
- yyerror("dst port only applies to tcp/udp");
+ yyerror("dst port only applies to tcp/udp/sctp");
problems++;
}
- if (r->rpool.proxy_port[0]) {
- yyerror("rpool port only applies to tcp/udp");
+ if (r->rdr.proxy_port[0]) {
+ yyerror("rdr port only applies to tcp/udp/sctp");
problems++;
}
}
@@ -5259,10 +5430,11 @@ rdr_consistent(struct pfctl_rule *r)
}
int
-process_tabledef(char *name, struct table_opts *opts)
+process_tabledef(char *name, struct table_opts *opts, int popts)
{
struct pfr_buffer ab;
struct node_tinit *ti;
+ struct pfr_uktable *ukt;
unsigned long maxcount;
size_t s = sizeof(maxcount);
@@ -5270,7 +5442,7 @@ process_tabledef(char *name, struct table_opts *opts)
ab.pfrb_type = PFRB_ADDRS;
SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
if (ti->file)
- if (pfr_buf_load(&ab, ti->file, 0, append_addr)) {
+ if (pfr_buf_load(&ab, ti->file, 0, append_addr, popts)) {
if (errno)
yyerror("cannot load \"%s\": %s",
ti->file, strerror(errno));
@@ -5289,9 +5461,29 @@ process_tabledef(char *name, struct table_opts *opts)
if (pf->opts & PF_OPT_VERBOSE)
print_tabledef(name, opts->flags, opts->init_addr,
&opts->init_nodes);
+ if (!(pf->opts & PF_OPT_NOACTION) ||
+ (pf->opts & PF_OPT_DUMMYACTION))
+ warn_duplicate_tables(name, pf->anchor->path);
+ else if (pf->opts & PF_OPT_VERBOSE)
+ fprintf(stderr, "%s:%d: skipping duplicate table checks"
+ " for <%s>\n", file->name, yylval.lineno, name);
+ /*
+ * postpone definition of non-root tables to moment
+ * when path is fully resolved.
+ */
+ if (pf->asd > 0) {
+ ukt = calloc(1, sizeof(struct pfr_uktable));
+ if (ukt == NULL) {
+ DBGPRINT(
+ "%s:%d: not enough memory for <%s>\n", file->name,
+ yylval.lineno, name);
+ goto _error;
+ }
+ } else
+ ukt = NULL;
if (!(pf->opts & PF_OPT_NOACTION) &&
pfctl_define_table(name, opts->flags, opts->init_addr,
- pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) {
+ pf->anchor->path, &ab, pf->anchor->ruleset.tticket, ukt)) {
if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s,
NULL, 0) == -1)
@@ -5303,10 +5495,32 @@ process_tabledef(char *name, struct table_opts *opts)
name);
else
yyerror("cannot define table %s: %s", name,
- pfr_strerror(errno));
+ pf_strerror(errno));
goto _error;
}
+
+ if (ukt != NULL) {
+ ukt->pfrukt_init_addr = opts->init_addr;
+ if (RB_INSERT(pfr_ktablehead, &pfr_ktables,
+ &ukt->pfrukt_kt) != NULL) {
+ /*
+ * I think this should not happen, because
+ * pfctl_define_table() above does the same check
+ * effectively.
+ */
+ DBGPRINT(
+ "%s:%d table %s already exists in %s\n",
+ file->name, yylval.lineno,
+ ukt->pfrukt_name, pf->anchor->path);
+ free(ukt);
+ goto _error;
+ }
+ DBGPRINT("%s %s@%s inserted to tree\n",
+ __func__, ukt->pfrukt_name, pf->anchor->path);
+ } else
+ DBGPRINT("%s ukt is null\n", __func__);
+
pf->tdirty = 1;
pfr_buf_clear(&ab);
return (0);
@@ -5357,18 +5571,18 @@ expand_label_str(char *label, size_t len, const char *srch, const char *repl)
char *p, *q;
if ((tmp = calloc(1, len)) == NULL)
- err(1, "expand_label_str: calloc");
+ err(1, "%s: calloc", __func__);
p = q = label;
while ((q = strstr(p, srch)) != NULL) {
*q = '\0';
if ((strlcat(tmp, p, len) >= len) ||
(strlcat(tmp, repl, len) >= len))
- errx(1, "expand_label: label too long");
+ errx(1, "%s: label too long", __func__);
q += strlen(srch);
p = q;
}
if (strlcat(tmp, p, len) >= len)
- errx(1, "expand_label: label too long");
+ errx(1, "%s: label too long", __func__);
strlcpy(label, tmp, len); /* always fits */
free(tmp);
}
@@ -5416,7 +5630,7 @@ expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
sizeof(a)) == NULL)
snprintf(tmp, sizeof(tmp), "?");
else {
- bits = unmask(&addr->addr.v.a.mask, af);
+ bits = unmask(&addr->addr.v.a.mask);
if ((af == AF_INET && bits < 32) ||
(af == AF_INET6 && bits < 128))
snprintf(tmp, sizeof(tmp),
@@ -5534,7 +5748,7 @@ expand_altq(struct pf_altq *a, struct node_if *interfaces,
memcpy(&pa, a, sizeof(struct pf_altq));
if (strlcpy(pa.ifname, interface->ifname,
sizeof(pa.ifname)) >= sizeof(pa.ifname))
- errx(1, "expand_altq: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (interface->not) {
yyerror("altq on ! <interface> is not supported");
@@ -5568,16 +5782,16 @@ expand_altq(struct pf_altq *a, struct node_if *interfaces,
memset(&pb, 0, sizeof(struct pf_altq));
if (strlcpy(qname, "root_", sizeof(qname)) >=
sizeof(qname))
- errx(1, "expand_altq: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcat(qname, interface->ifname,
sizeof(qname)) >= sizeof(qname))
- errx(1, "expand_altq: strlcat");
+ errx(1, "%s: strlcat", __func__);
if (strlcpy(pb.qname, qname,
sizeof(pb.qname)) >= sizeof(pb.qname))
- errx(1, "expand_altq: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(pb.ifname, interface->ifname,
sizeof(pb.ifname)) >= sizeof(pb.ifname))
- errx(1, "expand_altq: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
pb.qlimit = pa.qlimit;
pb.scheduler = pa.scheduler;
bw.bw_absolute = pa.ifbandwidth;
@@ -5592,20 +5806,20 @@ expand_altq(struct pf_altq *a, struct node_if *interfaces,
LOOP_THROUGH(struct node_queue, queue, nqueues,
n = calloc(1, sizeof(struct node_queue));
if (n == NULL)
- err(1, "expand_altq: calloc");
+ err(1, "%s: calloc", __func__);
if (pa.scheduler == ALTQT_CBQ ||
pa.scheduler == ALTQT_HFSC ||
pa.scheduler == ALTQT_FAIRQ)
if (strlcpy(n->parent, qname,
sizeof(n->parent)) >=
sizeof(n->parent))
- errx(1, "expand_altq: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(n->queue, queue->queue,
sizeof(n->queue)) >= sizeof(n->queue))
- errx(1, "expand_altq: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(n->ifname, interface->ifname,
sizeof(n->ifname)) >= sizeof(n->ifname))
- errx(1, "expand_altq: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
n->scheduler = pa.scheduler;
n->next = NULL;
n->tail = n;
@@ -5688,10 +5902,10 @@ expand_queue(struct pf_altq *a, struct node_if *interfaces,
if (strlcpy(pa.ifname, tqueue->ifname,
sizeof(pa.ifname)) >= sizeof(pa.ifname))
- errx(1, "expand_queue: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(pa.parent, tqueue->parent,
sizeof(pa.parent)) >= sizeof(pa.parent))
- errx(1, "expand_queue: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (eval_pfqueue(pf, &pa, &bwspec, opts))
errs++;
@@ -5709,19 +5923,19 @@ expand_queue(struct pf_altq *a, struct node_if *interfaces,
n = calloc(1,
sizeof(struct node_queue));
if (n == NULL)
- err(1, "expand_queue: calloc");
+ err(1, "%s: calloc", __func__);
if (strlcpy(n->parent, a->qname,
sizeof(n->parent)) >=
sizeof(n->parent))
- errx(1, "expand_queue strlcpy");
+ errx(1, "%s strlcpy", __func__);
if (strlcpy(n->queue, nq->queue,
sizeof(n->queue)) >=
sizeof(n->queue))
- errx(1, "expand_queue strlcpy");
+ errx(1, "%s strlcpy", __func__);
if (strlcpy(n->ifname, tqueue->ifname,
sizeof(n->ifname)) >=
sizeof(n->ifname))
- errx(1, "expand_queue strlcpy");
+ errx(1, "%s strlcpy", __func__);
n->scheduler = tqueue->scheduler;
n->next = NULL;
n->tail = n;
@@ -5782,19 +5996,20 @@ void
expand_eth_rule(struct pfctl_eth_rule *r,
struct node_if *interfaces, struct node_etherproto *protos,
struct node_mac *srcs, struct node_mac *dsts,
- struct node_host *ipsrcs, struct node_host *ipdsts, const char *anchor_call)
+ struct node_host *ipsrcs, struct node_host *ipdsts,
+ const char *bridge_to, const char *anchor_call)
{
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
char qname[PF_QNAME_SIZE];
if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
- errx(1, "expand_eth_rule: tagname");
+ errx(1, "%s: tagname", __func__);
if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
sizeof(match_tagname))
- errx(1, "expand_eth_rule: match_tagname");
+ errx(1, "%s: match_tagname", __func__);
if (strlcpy(qname, r->qname, sizeof(qname)) >= sizeof(qname))
- errx(1, "expand_eth_rule: qname");
+ errx(1, "%s: qname", __func__);
LOOP_THROUGH(struct node_if, interface, interfaces,
LOOP_THROUGH(struct node_etherproto, proto, protos,
@@ -5826,12 +6041,15 @@ expand_eth_rule(struct pfctl_eth_rule *r,
if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
sizeof(r->tagname))
- errx(1, "expand_eth_rule: r->tagname");
+ errx(1, "%s: r->tagname", __func__);
if (strlcpy(r->match_tagname, match_tagname,
sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
- errx(1, "expand_eth_rule: r->match_tagname");
+ errx(1, "%s: r->match_tagname", __func__);
if (strlcpy(r->qname, qname, sizeof(r->qname)) >= sizeof(r->qname))
- errx(1, "expand_eth_rule: r->qname");
+ errx(1, "%s: r->qname", __func__);
+
+ if (bridge_to)
+ strlcpy(r->bridge_to, bridge_to, sizeof(r->bridge_to));
pfctl_append_eth_rule(pf, r, anchor_call);
))))));
@@ -5844,14 +6062,262 @@ expand_eth_rule(struct pfctl_eth_rule *r,
FREE_LIST(struct node_host, ipdsts);
}
+int
+apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *rpool, struct redirspec *rs)
+{
+ if (rs == NULL)
+ return 0;
+
+ rpool->proxy_port[0] = ntohs(rs->rport.a);
+
+ if (!rs->rport.b && rs->rport.t) {
+ rpool->proxy_port[1] = ntohs(rs->rport.a) +
+ (ntohs(r->dst.port[1]) - ntohs(r->dst.port[0]));
+ } else {
+ if (validate_range(rs->rport.t, rs->rport.a,
+ rs->rport.b)) {
+ yyerror("invalid rdr-to port range");
+ return (1);
+ }
+ r->rdr.proxy_port[1] = ntohs(rs->rport.b);
+ }
+
+ if (rs->pool_opts.staticport) {
+ yyerror("the 'static-port' option is only valid with nat rules");
+ return 1;
+ }
+
+ if (rs->pool_opts.mape.offset) {
+ yyerror("the 'map-e-portset' option is only valid with nat rules");
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+apply_nat_ports(struct pfctl_pool *rpool, struct redirspec *rs)
+{
+ if (rs == NULL)
+ return 0;
+
+ rpool->proxy_port[0] = ntohs(rs->rport.a);
+ rpool->proxy_port[1] = ntohs(rs->rport.b);
+ if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) {
+ rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW;
+ rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH;
+ } else if (!rpool->proxy_port[1])
+ rpool->proxy_port[1] = rpool->proxy_port[0];
+
+ if (rs->pool_opts.staticport) {
+ if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
+ rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
+ yyerror("the 'static-port' option can't"
+ " be used when specifying a port"
+ " range");
+ return 1;
+ }
+ rpool->proxy_port[0] = 0;
+ rpool->proxy_port[1] = 0;
+ }
+
+ if (rs->pool_opts.mape.offset) {
+ if (rs->pool_opts.staticport) {
+ yyerror("the 'map-e-portset' option"
+ " can't be used 'static-port'");
+ return 1;
+ }
+ if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
+ rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
+ yyerror("the 'map-e-portset' option"
+ " can't be used when specifying"
+ " a port range");
+ return 1;
+ }
+ rpool->mape = rs->pool_opts.mape;
+ }
+
+ return 0;
+}
+
+int
+apply_redirspec(struct pfctl_pool *rpool, struct redirspec *rs)
+{
+ struct node_host *h;
+ struct pfctl_pooladdr *pa;
+
+ if (rs == NULL)
+ return 0;
+
+ rpool->opts = rs->pool_opts.type;
+
+ if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE &&
+ (rs->host->next != NULL ||
+ rs->host->addr.type == PF_ADDR_TABLE ||
+ DYNIF_MULTIADDR(rs->host->addr)))
+ rpool->opts = PF_POOL_ROUNDROBIN;
+
+ if (!PF_POOL_DYNTYPE(rpool->opts) &&
+ (disallow_table(rs->host, "tables are not supported by pool type") ||
+ disallow_alias(rs->host, "interface (%s) is not supported by pool type")))
+ return 1;
+
+ if (rs->host->next != NULL &&
+ ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)) {
+ yyerror("r.route.opts must be PF_POOL_ROUNDROBIN");
+ return 1;
+ }
+
+ if (rs->host->next != NULL) {
+ if ((rpool->opts & PF_POOL_TYPEMASK) !=
+ PF_POOL_ROUNDROBIN) {
+ yyerror("only round-robin valid for multiple "
+ "redirection addresses");
+ return 1;
+ }
+ }
+
+ rpool->opts |= rs->pool_opts.opts;
+
+ if (rs->pool_opts.key != NULL)
+ memcpy(&(rpool->key), rs->pool_opts.key,
+ sizeof(struct pf_poolhashkey));
+
+ for (h = rs->host; h != NULL; h = h->next) {
+ pa = calloc(1, sizeof(struct pfctl_pooladdr));
+ if (pa == NULL)
+ err(1, "%s: calloc", __func__);
+ pa->addr = h->addr;
+ pa->af = h->af;
+ if (h->ifname != NULL) {
+ if (strlcpy(pa->ifname, h->ifname,
+ sizeof(pa->ifname)) >= sizeof(pa->ifname))
+ errx(1, "%s: strlcpy", __func__);
+ } else
+ pa->ifname[0] = 0;
+ TAILQ_INSERT_TAIL(&(rpool->list), pa, entries);
+ }
+
+ return 0;
+}
+
+int
+check_binat_redirspec(struct node_host *src_host, struct pfctl_rule *r,
+ sa_family_t af)
+{
+ struct pfctl_pooladdr *nat_pool = TAILQ_FIRST(&(r->nat.list));
+ int error = 0;
+
+ /* XXX: FreeBSD allows syntax like "{ host1 host2 }" for redirection
+ * pools but does not covert them to tables automatically, because
+ * syntax "{ (iface1 host1), (iface2 iface2) }" is allowed for route-to
+ * redirection. Add a FreeBSD-specific guard against using multiple
+ * hosts for source and redirection.
+ */
+ if (src_host->next) {
+ yyerror("invalid use of table as the source address "
+ "of a binat-to rule");
+ error++;
+ }
+ if (TAILQ_NEXT(nat_pool, entries)) {
+ yyerror ("tables cannot be used as the redirect "
+ "address of a binat-to rule");
+ error++;
+ }
+
+ if (disallow_table(src_host, "invalid use of table "
+ "<%s> as the source address of a binat-to rule") ||
+ disallow_alias(src_host, "invalid use of interface "
+ "(%s) as the source address of a binat-to rule")) {
+ error++;
+ } else if ((r->src.addr.type != PF_ADDR_ADDRMASK &&
+ r->src.addr.type != PF_ADDR_DYNIFTL) ||
+ (nat_pool->addr.type != PF_ADDR_ADDRMASK &&
+ nat_pool->addr.type != PF_ADDR_DYNIFTL)) {
+ yyerror("binat-to requires a specified "
+ "source and redirect address");
+ error++;
+ }
+ if (DYNIF_MULTIADDR(r->src.addr) ||
+ DYNIF_MULTIADDR(nat_pool->addr)) {
+ yyerror ("dynamic interfaces must be "
+ "used with:0 in a binat-to rule");
+ error++;
+ }
+ if (PF_AZERO(&r->src.addr.v.a.mask, af) ||
+ PF_AZERO(&(nat_pool->addr.v.a.mask), af)) {
+ yyerror ("source and redir addresess must have "
+ "a matching network mask in binat-rule");
+ error++;
+ }
+ if (nat_pool->addr.type == PF_ADDR_TABLE) {
+ yyerror ("tables cannot be used as the redirect "
+ "address of a binat-to rule");
+ error++;
+ }
+ if (r->direction != PF_INOUT) {
+ yyerror("binat-to cannot be specified "
+ "with a direction");
+ error++;
+ }
+
+ /* first specify outbound NAT rule */
+ r->direction = PF_OUT;
+
+ return (error);
+}
+
+void
+add_binat_rdr_rule(
+ struct pfctl_rule *binat_rule,
+ struct redirspec *binat_nat_redirspec, struct node_host *binat_src_host,
+ struct pfctl_rule *rdr_rule, struct redirspec **rdr_redirspec,
+ struct node_host **rdr_dst_host)
+{
+ struct node_host *rdr_src_host;
+
+ /*
+ * We're copying the whole rule, but we must re-init redir pools.
+ * FreeBSD uses lists of pfctl_pooladdr, we can't just overwrite them.
+ */
+ bcopy(binat_rule, rdr_rule, sizeof(struct pfctl_rule));
+ TAILQ_INIT(&(rdr_rule->rdr.list));
+ TAILQ_INIT(&(rdr_rule->nat.list));
+
+ /* now specify inbound rdr rule */
+ rdr_rule->direction = PF_IN;
+
+ if ((rdr_src_host = calloc(1, sizeof(*rdr_src_host))) == NULL)
+ err(1, "%s", __func__);
+ bcopy(binat_src_host, rdr_src_host, sizeof(*rdr_src_host));
+ rdr_src_host->ifname = NULL;
+ rdr_src_host->next = NULL;
+ rdr_src_host->tail = NULL;
+
+ if (((*rdr_dst_host) = calloc(1, sizeof(**rdr_dst_host))) == NULL)
+ err(1, "%s", __func__);
+ bcopy(&(binat_nat_redirspec->host->addr), &((*rdr_dst_host)->addr),
+ sizeof((*rdr_dst_host)->addr));
+ (*rdr_dst_host)->ifname = NULL;
+ (*rdr_dst_host)->next = NULL;
+ (*rdr_dst_host)->tail = NULL;
+
+ if (((*rdr_redirspec) = calloc(1, sizeof(**rdr_redirspec))) == NULL)
+ err(1, "%s", __func__);
+ bcopy(binat_nat_redirspec, (*rdr_redirspec), sizeof(**rdr_redirspec));
+ (*rdr_redirspec)->pool_opts.staticport = 0;
+ (*rdr_redirspec)->host = rdr_src_host;
+}
+
void
-expand_rule(struct pfctl_rule *r,
- struct node_if *interfaces, struct node_host *rpool_hosts,
- struct node_proto *protos, struct node_os *src_oses,
- struct node_host *src_hosts, struct node_port *src_ports,
- struct node_host *dst_hosts, struct node_port *dst_ports,
- struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types,
- const char *anchor_call)
+expand_rule(struct pfctl_rule *r, bool keeprule,
+ struct node_if *interfaces, struct redirspec *nat,
+ struct redirspec *rdr, struct redirspec *route,
+ struct node_proto *protos,
+ struct node_os *src_oses, struct node_host *src_hosts,
+ struct node_port *src_ports, struct node_host *dst_hosts,
+ struct node_port *dst_ports, struct node_uid *uids, struct node_gid *gids,
+ struct node_if *rcv, struct node_icmp *icmp_types)
{
sa_family_t af = r->af;
int added = 0, error = 0;
@@ -5859,17 +6325,16 @@ expand_rule(struct pfctl_rule *r,
char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
- struct pf_pooladdr *pa;
- struct node_host *h;
+ struct node_host *osrch, *odsth;
u_int8_t flags, flagset, keep_state;
memcpy(label, r->label, sizeof(r->label));
assert(sizeof(r->label) == sizeof(label));
if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
- errx(1, "expand_rule: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
sizeof(match_tagname))
- errx(1, "expand_rule: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
flags = r->flags;
flagset = r->flagset;
keep_state = r->keep_state;
@@ -5878,14 +6343,20 @@ expand_rule(struct pfctl_rule *r,
LOOP_THROUGH(struct node_proto, proto, protos,
LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
LOOP_THROUGH(struct node_host, src_host, src_hosts,
- LOOP_THROUGH(struct node_port, src_port, src_ports,
- LOOP_THROUGH(struct node_os, src_os, src_oses,
LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
+ LOOP_THROUGH(struct node_port, src_port, src_ports,
LOOP_THROUGH(struct node_port, dst_port, dst_ports,
+ LOOP_THROUGH(struct node_os, src_os, src_oses,
LOOP_THROUGH(struct node_uid, uid, uids,
LOOP_THROUGH(struct node_gid, gid, gids,
r->af = af;
+
+ if (r->rule_flag & PFRULE_AFTO) {
+ assert(nat != NULL);
+ r->naf = nat->af;
+ }
+
/* for link-local IPv6 address, interface must match up */
if ((r->af && src_host->af && r->af != src_host->af) ||
(r->af && dst_host->af && r->af != dst_host->af) ||
@@ -5894,9 +6365,9 @@ expand_rule(struct pfctl_rule *r,
(src_host->ifindex && dst_host->ifindex &&
src_host->ifindex != dst_host->ifindex) ||
(src_host->ifindex && *interface->ifname &&
- src_host->ifindex != if_nametoindex(interface->ifname)) ||
+ src_host->ifindex != ifa_nametoindex(interface->ifname)) ||
(dst_host->ifindex && *interface->ifname &&
- dst_host->ifindex != if_nametoindex(interface->ifname)))
+ dst_host->ifindex != ifa_nametoindex(interface->ifname)))
continue;
if (!r->af && src_host->af)
r->af = src_host->af;
@@ -5906,9 +6377,9 @@ expand_rule(struct pfctl_rule *r,
if (*interface->ifname)
strlcpy(r->ifname, interface->ifname,
sizeof(r->ifname));
- else if (if_indextoname(src_host->ifindex, ifname))
+ else if (ifa_indextoname(src_host->ifindex, ifname))
strlcpy(r->ifname, ifname, sizeof(r->ifname));
- else if (if_indextoname(dst_host->ifindex, ifname))
+ else if (ifa_indextoname(dst_host->ifindex, ifname))
strlcpy(r->ifname, ifname, sizeof(r->ifname));
else
memset(r->ifname, '\0', sizeof(r->ifname));
@@ -5916,10 +6387,22 @@ expand_rule(struct pfctl_rule *r,
memcpy(r->label, label, sizeof(r->label));
if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
sizeof(r->tagname))
- errx(1, "expand_rule: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(r->match_tagname, match_tagname,
sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
- errx(1, "expand_rule: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
+
+ osrch = odsth = NULL;
+ if (src_host->addr.type == PF_ADDR_DYNIFTL) {
+ osrch = src_host;
+ if ((src_host = gen_dynnode(src_host, r->af)) == NULL)
+ err(1, "%s: calloc", __func__);
+ }
+ if (dst_host->addr.type == PF_ADDR_DYNIFTL) {
+ odsth = dst_host;
+ if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL)
+ err(1, "%s: calloc", __func__);
+ }
error += check_netmask(src_host, r->af);
error += check_netmask(dst_host, r->af);
@@ -5942,6 +6425,11 @@ expand_rule(struct pfctl_rule *r,
r->gid.op = gid->op;
r->gid.gid[0] = gid->gid[0];
r->gid.gid[1] = gid->gid[1];
+ if (rcv) {
+ strlcpy(r->rcv_ifname, rcv->ifname,
+ sizeof(r->rcv_ifname));
+ r->rcvifnot = rcv->not;
+ }
r->type = icmp_type->type;
r->code = icmp_type->code;
@@ -5975,43 +6463,85 @@ expand_rule(struct pfctl_rule *r,
r->os_fingerprint = PF_OSFP_ANY;
}
- TAILQ_INIT(&r->rpool.list);
- for (h = rpool_hosts; h != NULL; h = h->next) {
- pa = calloc(1, sizeof(struct pf_pooladdr));
- if (pa == NULL)
- err(1, "expand_rule: calloc");
- pa->addr = h->addr;
- if (h->ifname != NULL) {
- if (strlcpy(pa->ifname, h->ifname,
- sizeof(pa->ifname)) >=
- sizeof(pa->ifname))
- errx(1, "expand_rule: strlcpy");
- } else
- pa->ifname[0] = 0;
- TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
+ if (r->action == PF_RDR) {
+ /* Pre-FreeBSD 15 "rdr" rule */
+ error += apply_rdr_ports(r, &(r->rdr), rdr);
+ error += apply_redirspec(&(r->rdr), rdr);
+ } else if (r->action == PF_NAT) {
+ /* Pre-FreeBSD 15 "nat" rule */
+ error += apply_nat_ports(&(r->rdr), rdr);
+ error += apply_redirspec(&(r->rdr), rdr);
+ } else {
+ /* Modern rule with optional NAT, BINAT, RDR or ROUTE*/
+ error += apply_redirspec(&(r->route), route);
+
+ error += apply_nat_ports(&(r->nat), nat);
+ error += apply_redirspec(&(r->nat), nat);
+ error += apply_rdr_ports(r, &(r->rdr), rdr);
+ error += apply_redirspec(&(r->rdr), rdr);
+
+ if (nat && nat->binat)
+ error += check_binat_redirspec(src_host, r, af);
}
- if (rule_consistent(r, anchor_call[0]) < 0 || error)
+ if (rule_consistent(r) < 0 || error)
yyerror("skipping rule due to errors");
else {
r->nr = pf->astack[pf->asd]->match++;
- pfctl_append_rule(pf, r, anchor_call);
+ pfctl_append_rule(pf, r);
added++;
}
+ /* Generate binat's matching inbound rule */
+ if (!error && nat && nat->binat) {
+ struct pfctl_rule rdr_rule;
+ struct redirspec *rdr_redirspec;
+ struct node_host *rdr_dst_host;
+
+ add_binat_rdr_rule(
+ r, nat, src_hosts,
+ &rdr_rule, &rdr_redirspec, &rdr_dst_host);
+
+ expand_rule(&rdr_rule, true, interface, NULL, rdr_redirspec,
+ NULL, proto, src_os, dst_host, dst_port,
+ rdr_dst_host, src_port, uid, gid, rcv, icmp_type);
+ }
+
+ if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) {
+ free(src_host);
+ src_host = osrch;
+ }
+ if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) {
+ free(dst_host);
+ dst_host = odsth;
+ }
+
))))))))));
- FREE_LIST(struct node_if, interfaces);
- FREE_LIST(struct node_proto, protos);
- FREE_LIST(struct node_host, src_hosts);
- FREE_LIST(struct node_port, src_ports);
- FREE_LIST(struct node_os, src_oses);
- FREE_LIST(struct node_host, dst_hosts);
- FREE_LIST(struct node_port, dst_ports);
- FREE_LIST(struct node_uid, uids);
- FREE_LIST(struct node_gid, gids);
- FREE_LIST(struct node_icmp, icmp_types);
- FREE_LIST(struct node_host, rpool_hosts);
+ if (!keeprule) {
+ FREE_LIST(struct node_if, interfaces);
+ FREE_LIST(struct node_proto, protos);
+ FREE_LIST(struct node_host, src_hosts);
+ FREE_LIST(struct node_port, src_ports);
+ FREE_LIST(struct node_os, src_oses);
+ FREE_LIST(struct node_host, dst_hosts);
+ FREE_LIST(struct node_port, dst_ports);
+ FREE_LIST(struct node_uid, uids);
+ FREE_LIST(struct node_gid, gids);
+ FREE_LIST(struct node_icmp, icmp_types);
+ if (nat) {
+ FREE_LIST(struct node_host, nat->host);
+ free(nat);
+ }
+ if (rdr) {
+ FREE_LIST(struct node_host, rdr->host);
+ free(rdr);
+ }
+ if (route) {
+ FREE_LIST(struct node_host, route->host);
+ free(route);
+ }
+ }
if (!added)
yyerror("rule expands to no valid combination");
@@ -6053,6 +6583,12 @@ expand_skip_interface(struct node_if *interfaces)
return (0);
}
+void
+freehostlist(struct node_host *h)
+{
+ FREE_LIST(struct node_host, h);
+}
+
#undef FREE_LIST
#undef LOOP_THROUGH
@@ -6079,8 +6615,10 @@ lookup(char *s)
{
/* this has to be sorted always */
static const struct keywords keywords[] = {
+ { "af-to", AFTO},
{ "all", ALL},
{ "allow-opts", ALLOWOPTS},
+ { "allow-related", ALLOW_RELATED},
{ "altq", ALTQ},
{ "anchor", ANCHOR},
{ "antispoof", ANTISPOOF},
@@ -6088,22 +6626,23 @@ lookup(char *s)
{ "bandwidth", BANDWIDTH},
{ "binat", BINAT},
{ "binat-anchor", BINATANCHOR},
+ { "binat-to", BINATTO},
{ "bitmask", BITMASK},
{ "block", BLOCK},
{ "block-policy", BLOCKPOLICY},
+ { "bridge-to", BRIDGE_TO},
{ "buckets", BUCKETS},
{ "cbq", CBQ},
{ "code", CODE},
{ "codelq", CODEL},
- { "crop", FRAGCROP},
{ "debug", DEBUG},
{ "divert-reply", DIVERTREPLY},
{ "divert-to", DIVERTTO},
{ "dnpipe", DNPIPE},
{ "dnqueue", DNQUEUE},
{ "drop", DROP},
- { "drop-ovl", FRAGDROP},
{ "dup-to", DUPTO},
+ { "endpoint-independent", ENDPI},
{ "ether", ETHER},
{ "fail-policy", FAILPOLICY},
{ "fairq", FAIRQ},
@@ -6140,8 +6679,11 @@ lookup(char *s)
{ "loginterface", LOGINTERFACE},
{ "map-e-portset", MAPEPORTSET},
{ "match", MATCH},
+ { "matches", MATCHES},
{ "max", MAXIMUM},
{ "max-mss", MAXMSS},
+ { "max-pkt-rate", MAXPKTRATE},
+ { "max-pkt-size", MAXPKTSIZE},
{ "max-src-conn", MAXSRCCONN},
{ "max-src-conn-rate", MAXSRCCONNRATE},
{ "max-src-nodes", MAXSRCNODES},
@@ -6150,17 +6692,21 @@ lookup(char *s)
{ "modulate", MODULATE},
{ "nat", NAT},
{ "nat-anchor", NATANCHOR},
+ { "nat-to", NATTO},
{ "no", NO},
{ "no-df", NODF},
{ "no-route", NOROUTE},
{ "no-sync", NOSYNC},
{ "on", ON},
+ { "once", ONCE},
{ "optimization", OPTIMIZATION},
{ "os", OS},
{ "out", OUT},
{ "overload", OVERLOAD},
{ "pass", PASS},
+ { "pflow", PFLOW},
{ "port", PORT},
+ { "prefer-ipv6-nexthop", IPV6NH},
{ "prio", PRIO},
{ "priority", PRIORITY},
{ "priq", PRIQ},
@@ -6173,8 +6719,10 @@ lookup(char *s)
{ "random-id", RANDOMID},
{ "rdr", RDR},
{ "rdr-anchor", RDRANCHOR},
+ { "rdr-to", RDRTO},
{ "realtime", REALTIME},
{ "reassemble", REASSEMBLE},
+ { "received-on", RECEIVEDON},
{ "reply-to", REPLYTO},
{ "require-order", REQUIREORDER},
{ "return", RETURN},
@@ -6231,44 +6779,47 @@ lookup(char *s)
}
}
-#define MAXPUSHBACK 128
+#define START_EXPAND 1
+#define DONE_EXPAND 2
-static char *parsebuf;
-static int parseindex;
-static char pushback_buffer[MAXPUSHBACK];
-static int pushback_index = 0;
+static int expanding;
int
-lgetc(int quotec)
+igetc(void)
{
- int c, next;
-
- if (parsebuf) {
- /* Read character from the parsebuffer instead of input. */
- if (parseindex >= 0) {
- c = parsebuf[parseindex++];
- if (c != '\0')
- return (c);
- parsebuf = NULL;
- } else
- parseindex++;
+ int c;
+ while (1) {
+ if (file->ungetpos > 0)
+ c = file->ungetbuf[--file->ungetpos];
+ else
+ c = getc(file->stream);
+ if (c == START_EXPAND)
+ expanding = 1;
+ else if (c == DONE_EXPAND)
+ expanding = 0;
+ else
+ break;
}
+ return (c);
+}
- if (pushback_index)
- return (pushback_buffer[--pushback_index]);
+int
+lgetc(int quotec)
+{
+ int c, next;
if (quotec) {
- if ((c = getc(file->stream)) == EOF) {
+ if ((c = igetc()) == EOF) {
yyerror("reached end of file while parsing quoted string");
- if (popfile() == EOF)
+ if (file == topfile || popfile() == EOF)
return (EOF);
return (quotec);
}
return (c);
}
- while ((c = getc(file->stream)) == '\\') {
- next = getc(file->stream);
+ while ((c = igetc()) == '\\') {
+ next = igetc();
if (next != '\n') {
c = next;
break;
@@ -6277,28 +6828,38 @@ lgetc(int quotec)
file->lineno++;
}
- while (c == EOF) {
- if (popfile() == EOF)
- return (EOF);
- c = getc(file->stream);
+ if (c == EOF) {
+ /*
+ * Fake EOL when hit EOF for the first time. This gets line
+ * count right if last line in included file is syntactically
+ * invalid and has no newline.
+ */
+ if (file->eof_reached == 0) {
+ file->eof_reached = 1;
+ return ('\n');
+ }
+ while (c == EOF) {
+ if (file == topfile || popfile() == EOF)
+ return (EOF);
+ c = igetc();
+ }
}
return (c);
}
-int
+void
lungetc(int c)
{
if (c == EOF)
- return (EOF);
- if (parsebuf) {
- parseindex--;
- if (parseindex >= 0)
- return (c);
+ return;
+ if (file->ungetpos >= file->ungetsize) {
+ void *p = reallocarray(file->ungetbuf, file->ungetsize, 2);
+ if (p == NULL)
+ err(1, "%s", __func__);
+ file->ungetbuf = p;
+ file->ungetsize *= 2;
}
- if (pushback_index < MAXPUSHBACK-1)
- return (pushback_buffer[pushback_index++] = c);
- else
- return (EOF);
+ file->ungetbuf[file->ungetpos++] = c;
}
int
@@ -6306,14 +6867,9 @@ findeol(void)
{
int c;
- parsebuf = NULL;
-
/* skip to either EOF or the first real EOL */
while (1) {
- if (pushback_index)
- c = pushback_buffer[--pushback_index];
- else
- c = lgetc(0);
+ c = lgetc(0);
if (c == '\n') {
file->lineno++;
break;
@@ -6341,7 +6897,7 @@ top:
if (c == '#')
while ((c = lgetc(0)) != '\n' && c != EOF)
; /* nothing */
- if (c == '$' && parsebuf == NULL) {
+ if (c == '$' && !expanding) {
while (1) {
if ((c = lgetc(0)) == EOF)
return (0);
@@ -6363,8 +6919,13 @@ top:
yyerror("macro '%s' not defined", buf);
return (findeol());
}
- parsebuf = val;
- parseindex = 0;
+ p = val + strlen(val) - 1;
+ lungetc(DONE_EXPAND);
+ while (p >= val) {
+ lungetc(*p);
+ p--;
+ }
+ lungetc(START_EXPAND);
goto top;
}
@@ -6381,7 +6942,8 @@ top:
} else if (c == '\\') {
if ((next = lgetc(quotec)) == EOF)
return (0);
- if (next == quotec || c == ' ' || c == '\t')
+ if (next == quotec || next == ' ' ||
+ next == '\t')
c = next;
else if (next == '\n') {
file->lineno++;
@@ -6392,6 +6954,9 @@ top:
} else if (c == quotec) {
*p = '\0';
break;
+ } else if (c == '\0') {
+ yyerror("syntax error");
+ return (findeol());
}
if (p + 1 >= buf + sizeof(buf) - 1) {
yyerror("string too long");
@@ -6401,14 +6966,21 @@ top:
}
yylval.v.string = strdup(buf);
if (yylval.v.string == NULL)
- err(1, "yylex: strdup");
+ err(1, "%s: strdup", __func__);
return (STRING);
+ case '!':
+ next = lgetc(0);
+ if (next == '=')
+ return (NE);
+ lungetc(next);
+ break;
case '<':
next = lgetc(0);
if (next == '>') {
yylval.v.i = PF_OP_XRG;
return (PORTBINARY);
- }
+ } else if (next == '=')
+ return (LE);
lungetc(next);
break;
case '>':
@@ -6416,7 +6988,8 @@ top:
if (next == '<') {
yylval.v.i = PF_OP_IRG;
return (PORTBINARY);
- }
+ } else if (next == '=')
+ return (GE);
lungetc(next);
break;
case '-':
@@ -6433,7 +7006,7 @@ top:
if (c == '-' || isdigit(c)) {
do {
*p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
+ if ((size_t)(p-buf) >= sizeof(buf)) {
yyerror("string too long");
return (findeol());
}
@@ -6472,7 +7045,7 @@ nodigits:
if (isalnum(c) || c == ':' || c == '_') {
do {
*p++ = c;
- if ((unsigned)(p-buf) >= sizeof(buf)) {
+ if ((size_t)(p-buf) >= sizeof(buf)) {
yyerror("string too long");
return (findeol());
}
@@ -6481,7 +7054,7 @@ nodigits:
*p = '\0';
if ((token = lookup(buf)) == STRING)
if ((yylval.v.string = strdup(buf)) == NULL)
- err(1, "yylex: strdup");
+ err(1, "%s: strdup", __func__);
return (token);
}
if (c == '\n') {
@@ -6506,8 +7079,8 @@ check_file_secrecy(int fd, const char *fname)
warnx("%s: owner not root or current user", fname);
return (-1);
}
- if (st.st_mode & (S_IRWXG | S_IRWXO)) {
- warnx("%s: group/world readable/writeable", fname);
+ if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
+ warnx("%s: group writable or world read/writable", fname);
return (-1);
}
return (0);
@@ -6520,19 +7093,21 @@ pushfile(const char *name, int secret)
if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
(nfile->name = strdup(name)) == NULL) {
- warn("malloc");
+ warn("%s", __func__);
+ if (nfile)
+ free(nfile);
return (NULL);
}
if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) {
nfile->stream = stdin;
free(nfile->name);
if ((nfile->name = strdup("stdin")) == NULL) {
- warn("strdup");
+ warn("%s", __func__);
free(nfile);
return (NULL);
}
- } else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
- warn("%s", nfile->name);
+ } else if ((nfile->stream = pfctl_fopen(nfile->name, "r")) == NULL) {
+ warn("%s: %s", __func__, nfile->name);
free(nfile->name);
free(nfile);
return (NULL);
@@ -6543,7 +7118,16 @@ pushfile(const char *name, int secret)
free(nfile);
return (NULL);
}
- nfile->lineno = 1;
+ nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0;
+ nfile->ungetsize = 16;
+ nfile->ungetbuf = malloc(nfile->ungetsize);
+ if (nfile->ungetbuf == NULL) {
+ warn("%s", __func__);
+ fclose(nfile->stream);
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ }
TAILQ_INSERT_TAIL(&files, nfile, entry);
return (nfile);
}
@@ -6553,16 +7137,17 @@ popfile(void)
{
struct file *prev;
- if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
+ if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
prev->errors += file->errors;
- TAILQ_REMOVE(&files, file, entry);
- fclose(file->stream);
- free(file->name);
- free(file);
- file = prev;
- return (0);
- }
- return (EOF);
+
+ TAILQ_REMOVE(&files, file, entry);
+ fclose(file->stream);
+ free(file->name);
+ free(file->ungetbuf);
+ free(file);
+ file = prev;
+
+ return (file ? 0 : EOF);
}
int
@@ -6585,6 +7170,7 @@ parse_config(char *filename, struct pfctl *xpf)
warn("cannot open the main config file!");
return (-1);
}
+ topfile = file;
yyparse();
errors = file->errors;
@@ -6609,9 +7195,10 @@ symset(const char *nam, const char *val, int persist)
{
struct sym *sym;
- for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
- sym = TAILQ_NEXT(sym, entry))
- ; /* nothing */
+ TAILQ_FOREACH(sym, &symhead, entry) {
+ if (strcmp(nam, sym->nam) == 0)
+ break;
+ }
if (sym != NULL) {
if (sym->persist == 1)
@@ -6652,10 +7239,9 @@ pfctl_cmdline_symset(char *s)
if ((val = strrchr(s, '=')) == NULL)
return (-1);
- if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL)
- err(1, "pfctl_cmdline_symset: malloc");
-
- strlcpy(sym, s, strlen(s) - strlen(val) + 1);
+ sym = strndup(s, val - s);
+ if (sym == NULL)
+ err(1, "%s: malloc", __func__);
ret = symset(sym, val + 1, 1);
free(sym);
@@ -6668,11 +7254,12 @@ symget(const char *nam)
{
struct sym *sym;
- TAILQ_FOREACH(sym, &symhead, entry)
+ TAILQ_FOREACH(sym, &symhead, entry) {
if (strcmp(nam, sym->nam) == 0) {
sym->used = 1;
return (sym->val);
}
+ }
return (NULL);
}
@@ -6683,19 +7270,11 @@ mv_rules(struct pfctl_ruleset *src, struct pfctl_ruleset *dst)
struct pfctl_rule *r;
for (i = 0; i < PF_RULESET_MAX; ++i) {
- while ((r = TAILQ_FIRST(src->rules[i].active.ptr))
- != NULL) {
- TAILQ_REMOVE(src->rules[i].active.ptr, r, entries);
- TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries);
+ TAILQ_FOREACH(r, src->rules[i].active.ptr, entries)
dst->anchor->match++;
- }
+ TAILQ_CONCAT(dst->rules[i].active.ptr, src->rules[i].active.ptr, entries);
src->anchor->match = 0;
- while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr))
- != NULL) {
- TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries);
- TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr,
- r, entries);
- }
+ TAILQ_CONCAT(dst->rules[i].inactive.ptr, src->rules[i].inactive.ptr, entries);
}
}
@@ -6713,6 +7292,61 @@ mv_eth_rules(struct pfctl_eth_ruleset *src, struct pfctl_eth_ruleset *dst)
}
void
+mv_tables(struct pfctl *pf, struct pfr_ktablehead *ktables,
+ struct pfctl_anchor *a, struct pfctl_anchor *alast)
+{
+ struct pfr_ktable *kt, *kt_safe;
+ char new_path[PF_ANCHOR_MAXPATH];
+ char *path_cut;
+ int sz;
+ struct pfr_uktable *ukt;
+ SLIST_HEAD(, pfr_uktable) ukt_list;
+
+ /*
+ * Here we need to rename anchor path from temporal names such as
+ * _1/_2/foo to _1/bar/foo etc.
+ *
+ * This also means we need to remove and insert table to ktables
+ * tree as anchor path is being updated.
+ */
+ SLIST_INIT(&ukt_list);
+ DBGPRINT("%s [ %s ] (%s)\n", __func__, a->path, alast->path);
+ RB_FOREACH_SAFE(kt, pfr_ktablehead, ktables, kt_safe) {
+ path_cut = strstr(kt->pfrkt_anchor, alast->path);
+ if (path_cut != NULL) {
+ path_cut += strlen(alast->path);
+ if (*path_cut)
+ sz = snprintf(new_path, sizeof (new_path),
+ "%s%s", a->path, path_cut);
+ else
+ sz = snprintf(new_path, sizeof (new_path),
+ "%s", a->path);
+ if (sz >= sizeof (new_path))
+ errx(1, "new path is too long for %s@%s\n",
+ kt->pfrkt_name, kt->pfrkt_anchor);
+
+ DBGPRINT("%s %s@%s -> %s@%s\n", __func__,
+ kt->pfrkt_name, kt->pfrkt_anchor,
+ kt->pfrkt_name, new_path);
+ RB_REMOVE(pfr_ktablehead, ktables, kt);
+ strlcpy(kt->pfrkt_anchor, new_path,
+ sizeof(kt->pfrkt_anchor));
+ SLIST_INSERT_HEAD(&ukt_list, (struct pfr_uktable *)kt,
+ pfrukt_entry);
+ }
+ }
+
+ while ((ukt = SLIST_FIRST(&ukt_list)) != NULL) {
+ SLIST_REMOVE_HEAD(&ukt_list, pfrukt_entry);
+ if (RB_INSERT(pfr_ktablehead, ktables,
+ (struct pfr_ktable *)ukt) != NULL)
+ errx(1, "%s@%s exists already\n",
+ ukt->pfrukt_name,
+ ukt->pfrukt_anchor);
+ }
+}
+
+void
decide_address_family(struct node_host *n, sa_family_t *af)
{
if (*af != 0 || n == NULL)
@@ -6815,6 +7449,8 @@ getservice(char *n)
s = getservbyname(n, "tcp");
if (s == NULL)
s = getservbyname(n, "udp");
+ if (s == NULL)
+ s = getservbyname(n, "sctp");
if (s == NULL) {
yyerror("unknown port %s", n);
return (-1);
@@ -6840,6 +7476,23 @@ rule_label(struct pfctl_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
return (0);
}
+int
+eth_rule_label(struct pfctl_eth_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
+{
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
+ if (s[i] == NULL)
+ return (0);
+
+ if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >=
+ sizeof(r->label[0])) {
+ yyerror("rule label too long (max %d chars)",
+ sizeof(r->label[0])-1);
+ return (-1);
+ }
+ }
+ return (0);
+}
+
u_int16_t
parseicmpspec(char *w, sa_family_t af)
{
@@ -6902,7 +7555,7 @@ parseport(char *port, struct range *r, int extensions)
}
int
-pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
+pfctl_load_anchors(int dev, struct pfctl *pf)
{
struct loadanchors *la;
@@ -6911,7 +7564,7 @@ pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
fprintf(stderr, "\nLoading anchor %s from %s\n",
la->anchorname, la->filename);
if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize,
- la->anchorname, trans) == -1)
+ la->anchorname, pf->trans) == -1)
return (-1);
}
@@ -6997,7 +7650,7 @@ node_mac_from_string(const char *str)
m = calloc(1, sizeof(struct node_mac));
if (m == NULL)
- err(1, "mac: calloc");
+ err(1, "%s: calloc", __func__);
if (sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
&m->mac[0], &m->mac[1], &m->mac[2], &m->mac[3], &m->mac[4],
@@ -7055,3 +7708,172 @@ node_mac_from_string_mask(const char *str, const char *mask)
return (m);
}
+
+int
+filteropts_to_rule(struct pfctl_rule *r, struct filter_opts *opts)
+{
+ if (opts->marker & FOM_ONCE) {
+ if ((r->action != PF_PASS && r->action != PF_DROP) || r->anchor) {
+ yyerror("'once' only applies to pass/block rules");
+ return (1);
+ }
+ r->rule_flag |= PFRULE_ONCE;
+ }
+
+ r->keep_state = opts->keep.action;
+ r->pktrate.limit = opts->pktrate.limit;
+ r->pktrate.seconds = opts->pktrate.seconds;
+ r->prob = opts->prob;
+ r->rtableid = opts->rtableid;
+ r->ridentifier = opts->ridentifier;
+ r->max_pkt_size = opts->max_pkt_size;
+ r->tos = opts->tos;
+
+ if (opts->nodf)
+ r->scrub_flags |= PFSTATE_NODF;
+ if (opts->randomid)
+ r->scrub_flags |= PFSTATE_RANDOMID;
+ if (opts->minttl)
+ r->min_ttl = opts->minttl;
+ if (opts->max_mss)
+ r->max_mss = opts->max_mss;
+
+ if (opts->tag)
+ if (strlcpy(r->tagname, opts->tag,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ return (1);
+ }
+ if (opts->match_tag)
+ if (strlcpy(r->match_tagname, opts->match_tag,
+ PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
+ yyerror("tag too long, max %u chars",
+ PF_TAG_NAME_SIZE - 1);
+ return (1);
+ }
+ r->match_tag_not = opts->match_tag_not;
+
+ if (rule_label(r, opts->label))
+ return (1);
+ for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
+ free(opts->label[i]);
+
+ if (opts->marker & FOM_AFTO)
+ r->rule_flag |= PFRULE_AFTO;
+ if (opts->marker & FOM_SCRUB_TCP)
+ r->scrub_flags |= PFSTATE_SCRUB_TCP;
+ if (opts->marker & FOM_PRIO)
+ r->prio = opts->prio ? opts->prio : PF_PRIO_ZERO;
+ if (opts->marker & FOM_SETPRIO) {
+ r->set_prio[0] = opts->set_prio[0];
+ r->set_prio[1] = opts->set_prio[1];
+ r->scrub_flags |= PFSTATE_SETPRIO;
+ }
+ if (opts->marker & FOM_SETTOS) {
+ r->scrub_flags |= PFSTATE_SETTOS;
+ r->set_tos = opts->settos;
+ }
+
+ r->flags = opts->flags.b1;
+ r->flagset = opts->flags.b2;
+ if ((opts->flags.b1 & opts->flags.b2) != opts->flags.b1) {
+ yyerror("flags always false");
+ return (1);
+ }
+
+ if (opts->queues.qname != NULL) {
+ if (strlcpy(r->qname, opts->queues.qname,
+ sizeof(r->qname)) >= sizeof(r->qname)) {
+ yyerror("rule qname too long (max "
+ "%d chars)", sizeof(r->qname)-1);
+ return (1);
+ }
+ free(opts->queues.qname);
+ }
+ if (opts->queues.pqname != NULL) {
+ if (strlcpy(r->pqname, opts->queues.pqname,
+ sizeof(r->pqname)) >= sizeof(r->pqname)) {
+ yyerror("rule pqname too long (max "
+ "%d chars)", sizeof(r->pqname)-1);
+ return (1);
+ }
+ free(opts->queues.pqname);
+ }
+
+ if (opts->fragment)
+ r->rule_flag |= PFRULE_FRAGMENT;
+ r->allow_opts = opts->allowopts;
+
+ return (0);
+}
+
+static bool
+pfctl_setup_anchor(struct pfctl_rule *r, struct pfctl *pf, char *anchorname)
+{
+ char *p;
+
+ if (pf->astack[pf->asd + 1]) {
+ if (anchorname && strchr(anchorname, '/') != NULL) {
+ free(anchorname);
+ yyerror("anchor paths containing '/' "
+ "cannot be used for inline anchors.");
+ return (false);
+ }
+
+ /* Move inline rules into relative location. */
+ pfctl_anchor_setup(r,
+ &pf->astack[pf->asd]->ruleset,
+ anchorname ? anchorname : pf->alast->name);
+
+ if (r->anchor == NULL)
+ err(1, "anchorrule: unable to "
+ "create ruleset");
+
+ if (pf->alast != r->anchor) {
+ if (r->anchor->match) {
+ yyerror("inline anchor '%s' "
+ "already exists",
+ r->anchor->name);
+ return (false);
+ }
+ mv_rules(&pf->alast->ruleset,
+ &r->anchor->ruleset);
+ mv_tables(pf, &pfr_ktables, r->anchor, pf->alast);
+ }
+ pf_remove_if_empty_ruleset(&pf->alast->ruleset);
+ pf->alast = r->anchor;
+ } else {
+ if (! anchorname) {
+ yyerror("anchors without explicit "
+ "rules must specify a name");
+ return (false);
+ }
+ /*
+ * Don't make non-brace anchors part of the main anchor pool.
+ */
+ if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL) {
+ err(1, "anchorrule: calloc");
+ }
+ pf_init_ruleset(&r->anchor->ruleset);
+ r->anchor->ruleset.anchor = r->anchor;
+ if (strlcpy(r->anchor->path, anchorname,
+ sizeof(r->anchor->path)) >= sizeof(r->anchor->path)) {
+ errx(1, "anchorrule: strlcpy");
+ }
+ if ((p = strrchr(anchorname, '/')) != NULL) {
+ if (strlen(p) == 1) {
+ yyerror("anchorrule: bad anchor name %s",
+ anchorname);
+ return (false);
+ }
+ } else
+ p = anchorname;
+ if (strlcpy(r->anchor->name, p,
+ sizeof(r->anchor->name)) >= sizeof(r->anchor->name)) {
+ errx(1, "anchorrule: strlcpy");
+ }
+ }
+
+ return (true);
+}
diff --git a/sbin/pfctl/pf.os b/sbin/pfctl/pf.os
index 81f06994e37b..e131d1b54756 100644
--- a/sbin/pfctl/pf.os
+++ b/sbin/pfctl/pf.os
@@ -1,4 +1,3 @@
-# $FreeBSD$
# $OpenBSD: pf.os,v 1.27 2016/09/03 17:08:57 sthen Exp $
# passive OS fingerprinting
# -------------------------
diff --git a/sbin/pfctl/pf_print_state.c b/sbin/pfctl/pf_print_state.c
index b66a296d6080..417ff70de975 100644
--- a/sbin/pfctl/pf_print_state.c
+++ b/sbin/pfctl/pf_print_state.c
@@ -32,15 +32,13 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/endian.h>
#include <net/if.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
+#include <netinet/sctp.h>
#include <net/pfvar.h>
#include <arpa/inet.h>
#include <netdb.h>
@@ -87,31 +85,18 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
printf("<%s>", addr->v.tblname);
return;
case PF_ADDR_RANGE: {
- char buf[48];
+ print_addr_str(af, &addr->v.a.addr);
+ printf(" - ");
+ print_addr_str(af, &addr->v.a.mask);
- if (inet_ntop(af, &addr->v.a.addr, buf, sizeof(buf)) == NULL)
- printf("?");
- else
- printf("%s", buf);
- if (inet_ntop(af, &addr->v.a.mask, buf, sizeof(buf)) == NULL)
- printf(" - ?");
- else
- printf(" - %s", buf);
break;
}
case PF_ADDR_ADDRMASK:
if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
PF_AZERO(&addr->v.a.mask, AF_INET6))
printf("any");
- else {
- char buf[48];
-
- if (inet_ntop(af, &addr->v.a.addr, buf,
- sizeof(buf)) == NULL)
- printf("?");
- else
- printf("%s", buf);
- }
+ else
+ print_addr_str(af, &addr->v.a.addr);
break;
case PF_ADDR_NOROUTE:
printf("no-route");
@@ -128,62 +113,63 @@ print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
if (addr->type != PF_ADDR_RANGE &&
!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
PF_AZERO(&addr->v.a.mask, AF_INET6))) {
- int bits = unmask(&addr->v.a.mask, af);
-
- if (bits != (af == AF_INET ? 32 : 128))
- printf("/%d", bits);
+ if (af == AF_INET || af == AF_INET6) {
+ int bits = unmask(&addr->v.a.mask);
+ if (bits < (af == AF_INET ? 32 : 128))
+ printf("/%d", bits);
+ }
}
}
void
+print_addr_str(sa_family_t af, struct pf_addr *addr)
+{
+ static char buf[48];
+
+ if (inet_ntop(af, addr, buf, sizeof(buf)) == NULL)
+ printf("?");
+ else
+ printf("%s", buf);
+}
+
+void
print_name(struct pf_addr *addr, sa_family_t af)
{
- char host[NI_MAXHOST];
-
- strlcpy(host, "?", sizeof(host));
- switch (af) {
- case AF_INET: {
- struct sockaddr_in sin;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_len = sizeof(sin);
- sin.sin_family = AF_INET;
- sin.sin_addr = addr->v4;
- getnameinfo((struct sockaddr *)&sin, sin.sin_len,
- host, sizeof(host), NULL, 0, NI_NOFQDN);
- break;
- }
- case AF_INET6: {
- struct sockaddr_in6 sin6;
-
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_len = sizeof(sin6);
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = addr->v6;
- getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
- host, sizeof(host), NULL, 0, NI_NOFQDN);
- break;
- }
+ struct sockaddr_storage ss;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ char host[NI_MAXHOST];
+
+ memset(&ss, 0, sizeof(ss));
+ ss.ss_family = af;
+ if (ss.ss_family == AF_INET) {
+ sin = (struct sockaddr_in *)&ss;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = addr->v4;
+ } else {
+ sin6 = (struct sockaddr_in6 *)&ss;
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_addr = addr->v6;
}
- printf("%s", host);
+
+ if (getnameinfo((struct sockaddr *)&ss, ss.ss_len, host, sizeof(host),
+ NULL, 0, NI_NOFQDN) != 0)
+ printf("?");
+ else
+ printf("%s", host);
}
void
print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts)
{
+ struct pf_addr_wrap aw;
+
if (opts & PF_OPT_USEDNS)
print_name(addr, af);
else {
- struct pf_addr_wrap aw;
-
memset(&aw, 0, sizeof(aw));
aw.v.a.addr = *addr;
- if (af == AF_INET)
- aw.v.a.mask.addr32[0] = 0xffffffff;
- else {
- memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
- af = AF_INET6;
- }
+ memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
}
@@ -206,6 +192,36 @@ print_seq(struct pfctl_state_peer *p)
p->seqhi - p->seqlo);
}
+
+static const char *
+sctp_state_name(int state)
+{
+ switch (state) {
+ case SCTP_CLOSED:
+ return ("CLOSED");
+ case SCTP_BOUND:
+ return ("BOUND");
+ case SCTP_LISTEN:
+ return ("LISTEN");
+ case SCTP_COOKIE_WAIT:
+ return ("COOKIE_WAIT");
+ case SCTP_COOKIE_ECHOED:
+ return ("COOKIE_ECHOED");
+ case SCTP_ESTABLISHED:
+ return ("ESTABLISHED");
+ case SCTP_SHUTDOWN_SENT:
+ return ("SHUTDOWN_SENT");
+ case SCTP_SHUTDOWN_RECEIVED:
+ return ("SHUTDOWN_RECEIVED");
+ case SCTP_SHUTDOWN_ACK_SENT:
+ return ("SHUTDOWN_ACK_SENT");
+ case SCTP_SHUTDOWN_PENDING:
+ return ("SHUTDOWN_PENDING");
+ default:
+ return ("?");
+ }
+}
+
void
print_state(struct pfctl_state *s, int opts)
{
@@ -213,8 +229,10 @@ print_state(struct pfctl_state *s, int opts)
struct pfctl_state_key *key, *sk, *nk;
const char *protoname;
int min, sec;
- sa_family_t af;
uint8_t proto;
+ int afto = (s->key[PF_SK_STACK].af != s->key[PF_SK_WIRE].af);
+ int idx;
+ const char *sn_type_names[] = PF_SN_TYPE_NAMES;
#ifndef __NO_STRICT_ALIGNMENT
struct pfctl_state_key aligned_key[2];
@@ -224,7 +242,6 @@ print_state(struct pfctl_state *s, int opts)
key = s->key;
#endif
- af = s->key[PF_SK_WIRE].af;
proto = s->key[PF_SK_WIRE].proto;
if (s->direction == PF_OUT) {
@@ -248,22 +265,26 @@ print_state(struct pfctl_state *s, int opts)
else
printf("%u ", proto);
- print_host(&nk->addr[1], nk->port[1], af, opts);
- if (PF_ANEQ(&nk->addr[1], &sk->addr[1], af) ||
+ print_host(&nk->addr[1], nk->port[1], nk->af, opts);
+ if (nk->af != sk->af || PF_ANEQ(&nk->addr[1], &sk->addr[1], nk->af) ||
nk->port[1] != sk->port[1]) {
+ idx = afto ? 0 : 1;
printf(" (");
- print_host(&sk->addr[1], sk->port[1], af, opts);
+ print_host(&sk->addr[idx], sk->port[idx], sk->af,
+ opts);
printf(")");
}
- if (s->direction == PF_OUT)
+ if (s->direction == PF_OUT || (afto && s->direction == PF_IN))
printf(" -> ");
else
printf(" <- ");
- print_host(&nk->addr[0], nk->port[0], af, opts);
- if (PF_ANEQ(&nk->addr[0], &sk->addr[0], af) ||
+ print_host(&nk->addr[0], nk->port[0], nk->af, opts);
+ if (nk->af != sk->af || PF_ANEQ(&nk->addr[0], &sk->addr[0], nk->af) ||
nk->port[0] != sk->port[0]) {
+ idx = afto ? 1 : 0;
printf(" (");
- print_host(&sk->addr[0], sk->port[0], af, opts);
+ print_host(&sk->addr[idx], sk->port[idx], sk->af,
+ opts);
printf(")");
}
@@ -300,6 +321,9 @@ print_state(struct pfctl_state *s, int opts)
const char *states[] = PFUDPS_NAMES;
printf(" %s:%s\n", states[src->state], states[dst->state]);
+ } else if (proto == IPPROTO_SCTP) {
+ printf(" %s:%s\n", sctp_state_name(src->state),
+ sctp_state_name(dst->state));
#ifndef INET6
} else if (proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
dst->state < PFOTHERS_NSTATES) {
@@ -339,12 +363,51 @@ print_state(struct pfctl_state *s, int opts)
printf(", anchor %u", s->anchor);
if (s->rule != -1)
printf(", rule %u", s->rule);
+ if (s->state_flags & PFSTATE_ALLOWOPTS)
+ printf(", allow-opts");
if (s->state_flags & PFSTATE_SLOPPY)
printf(", sloppy");
- if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
- printf(", source-track");
- if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
- printf(", sticky-address");
+ if (s->state_flags & PFSTATE_NOSYNC)
+ printf(", no-sync");
+ if (s->state_flags & PFSTATE_PFLOW)
+ printf(", pflow");
+ if (s->state_flags & PFSTATE_ACK)
+ printf(", psync-ack");
+ if (s->state_flags & PFSTATE_NODF)
+ printf(", no-df");
+ if (s->state_flags & PFSTATE_SETTOS)
+ printf(", set-tos 0x%2.2x", s->set_tos);
+ if (s->state_flags & PFSTATE_RANDOMID)
+ printf(", random-id");
+ if (s->state_flags & PFSTATE_SCRUB_TCP)
+ printf(", reassemble-tcp");
+ if (s->state_flags & PFSTATE_SETPRIO)
+ printf(", set-prio (0x%02x 0x%02x)",
+ s->set_prio[0], s->set_prio[1]);
+ if (s->dnpipe || s->dnrpipe) {
+ if (s->state_flags & PFSTATE_DN_IS_PIPE)
+ printf(", dummynet pipe (%d %d)",
+ s->dnpipe, s->dnrpipe);
+ if (s->state_flags & PFSTATE_DN_IS_QUEUE)
+ printf(", dummynet queue (%d %d)",
+ s->dnpipe, s->dnrpipe);
+ }
+ if (s->src_node_flags & PFSTATE_SRC_NODE_LIMIT)
+ printf(", %s", sn_type_names[PF_SN_LIMIT]);
+ if (s->src_node_flags & PFSTATE_SRC_NODE_LIMIT_GLOBAL)
+ printf(" global");
+ if (s->src_node_flags & PFSTATE_SRC_NODE_NAT)
+ printf(", %s", sn_type_names[PF_SN_NAT]);
+ if (s->src_node_flags & PFSTATE_SRC_NODE_ROUTE)
+ printf(", %s", sn_type_names[PF_SN_ROUTE]);
+ if (s->log)
+ printf(", log");
+ if (s->log & PF_LOG_ALL)
+ printf(" (all)");
+ if (s->min_ttl)
+ printf(", min-ttl %d", s->min_ttl);
+ if (s->max_mss)
+ printf(", max-mss %d", s->max_mss);
printf("\n");
}
if (opts & PF_OPT_VERBOSE2) {
@@ -352,8 +415,26 @@ print_state(struct pfctl_state *s, int opts)
bcopy(&s->id, &id, sizeof(u_int64_t));
printf(" id: %016jx creatorid: %08x", id, s->creatorid);
- printf(" gateway: ");
- print_host(&s->rt_addr, 0, af, opts);
+ if (s->rt) {
+ switch (s->rt) {
+ case PF_ROUTETO:
+ printf(" route-to: ");
+ break;
+ case PF_DUPTO:
+ printf(" dup-to: ");
+ break;
+ case PF_REPLYTO:
+ printf(" reply-to: ");
+ break;
+ default:
+ printf(" gateway: ");
+ }
+ print_host(&s->rt_addr, 0, s->rt_af, opts);
+ if (s->rt_ifname[0])
+ printf("@%s", s->rt_ifname);
+ }
+ if (s->rtableid != -1)
+ printf(" rtable: %d", s->rtableid);
printf("\n");
if (strcmp(s->ifname, s->orig_ifname) != 0)
@@ -362,7 +443,7 @@ print_state(struct pfctl_state *s, int opts)
}
int
-unmask(struct pf_addr *m, sa_family_t af)
+unmask(struct pf_addr *m)
{
int i = 31, j = 0, b = 0;
u_int32_t tmp;
diff --git a/sbin/pfctl/pf_ruleset.c b/sbin/pfctl/pf_ruleset.c
index a7f31366f48c..2b7ec09f28aa 100644
--- a/sbin/pfctl/pf_ruleset.c
+++ b/sbin/pfctl/pf_ruleset.c
@@ -36,9 +36,6 @@
* $OpenBSD: pf_ruleset.c,v 1.2 2008/12/18 15:31:37 dhill Exp $
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/mbuf.h>
diff --git a/sbin/pfctl/pfctl.8 b/sbin/pfctl/pfctl.8
index 25c8b1aef9f8..58de54cdf923 100644
--- a/sbin/pfctl/pfctl.8
+++ b/sbin/pfctl/pfctl.8
@@ -24,9 +24,7 @@
.\" (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 February 22, 2021
+.Dd August 28, 2025
.Dt PFCTL 8
.Os
.Sh NAME
@@ -45,7 +43,7 @@
.Op Fl K Ar host | network
.Xo
.Oo Fl k
-.Ar host | network | label | id | gateway
+.Ar host | network | label | id | gateway | nat
.Oc Xc
.Op Fl o Ar level
.Op Fl p Ar device
@@ -84,7 +82,7 @@ Translation rules are described in
.Xr pf.conf 5 .
.Pp
When the variable
-.Va pf
+.Va pf_enable
is set to
.Dv YES
in
@@ -106,9 +104,7 @@ to 1.
Set them permanently in
.Xr sysctl.conf 5 .
.Pp
-The
-.Nm
-utility provides several commands.
+At least one option must be specified.
The options are as follows:
.Bl -tag -width Ds
.It Fl A
@@ -118,8 +114,10 @@ Other rules and options are ignored.
Apply flags
.Fl f ,
.Fl F ,
+.Fl s ,
+.Fl T ,
and
-.Fl s
+.Fl z
only to the rules in the specified
.Ar anchor .
In addition to the main ruleset,
@@ -189,6 +187,13 @@ as the anchor name:
.Bd -literal -offset indent
# pfctl -a '*' -sr
.Ed
+.Pp
+To flush all rulesets and tables recursively, specify only
+.Sq *
+as the anchor name:
+.Bd -literal -offset indent
+# pfctl -a '*' -Fa
+.Ed
.It Fl D Ar macro Ns = Ns Ar value
Define
.Ar macro
@@ -207,28 +212,46 @@ Flush the filter parameters specified by
.Ar modifier
(may be abbreviated):
.Pp
-.Bl -tag -width xxxxxxxxxxxx -compact
-.It Fl F Cm nat
+.Bl -tag -width xxxxxxxxx -compact
+.It Cm nat
Flush the NAT rules.
-.It Fl F Cm queue
+.It Cm queue
Flush the queue rules.
-.It Fl F Cm ethernet
+.It Cm ethernet
Flush the Ethernet filter rules.
-.It Fl F Cm rules
+.It Cm rules
Flush the filter rules.
-.It Fl F Cm states
+.It Cm states
Flush the state table (NAT and filter).
-.It Fl F Cm Sources
+.It Cm Sources
Flush the source tracking table.
-.It Fl F Cm info
+.It Cm info
Flush the filter information (statistics that are not bound to rules).
-.It Fl F Cm Tables
+.It Cm Tables
Flush the tables.
-.It Fl F Cm osfp
+.It Cm osfp
Flush the passive operating system fingerprints.
-.It Fl F Cm all
+.It Cm Reset
+Reset limits, timeouts and other options back to default settings.
+See the OPTIONS section in
+.Xr pf.conf 5
+for details.
+.It Cm all
Flush all of the above.
.El
+.Pp
+If
+.Fl a
+is specified as well and
+.Ar anchor
+is terminated with a
+.Sq *
+character,
+.Cm rules ,
+.Cm Tables
+and
+.Cm all
+flush the given anchor recursively.
.It Fl f Ar file
Load the rules contained in
.Ar file .
@@ -258,15 +281,17 @@ option may be specified, which will kill all the source tracking
entries from the first host/network to the second.
.It Xo
.Fl k
-.Ar host | network | label | id | gateway
+.Ar host | network | label | id | key | gateway | nat
.Xc
Kill all of the state entries matching the specified
.Ar host ,
.Ar network ,
.Ar label ,
.Ar id ,
+.Ar key ,
+.Ar gateway,
or
-.Ar gateway.
+.Ar nat.
.Pp
For example, to kill all of the state entries originating from
.Dq host :
@@ -296,7 +321,7 @@ To kill all states with the target
.Pp
.Dl # pfctl -k 0.0.0.0/0 -k host2
.Pp
-It is also possible to kill states by rule label or state ID.
+It is also possible to kill states by rule label, state key or state ID.
In this mode the first
.Fl k
argument is used to specify the type
@@ -307,6 +332,17 @@ from rules carrying the label
.Pp
.Dl # pfctl -k label -k foobar
.Pp
+To kill one specific state by its key
+(protocol, host1, port1, direction, host2 and port2 in the same format
+of pfctl -s state),
+use the
+.Ar key
+modifier and as a second argument the state key.
+To kill a state whose protocol is TCP and originating from
+10.0.0.101:32123 to 10.0.0.1:80 use:
+.Pp
+.Dl # pfctl -k key -k 'tcp 10.0.0.1:80 <- 10.0.0.101:32123'
+.Pp
To kill one specific state by its unique state ID
(as shown by pfctl -s state -vv),
use the
@@ -334,6 +370,10 @@ To kill all states using a gateway in 192.168.0.0/24:
.Pp
.Dl # pfctl -k gateway -k 192.168.0.0/24
.Pp
+States can also be killed based on their pre-NAT address:
+.Pp
+.Dl # pfctl -k nat -k 192.168.0.1
+.Pp
.It Fl M
Kill matching states in the opposite direction (on other interfaces) when
killing states.
@@ -362,15 +402,16 @@ Other rules and options are ignored.
.It Fl o Ar level
Control the ruleset optimizer, overriding any rule file settings.
.Pp
-.Bl -tag -width xxxxxxxxxxxx -compact
-.It Fl o Cm none
+.Bl -tag -width xxxxxxxxx -compact
+.It Cm none
Disable the ruleset optimizer.
-.It Fl o Cm basic
+.It Cm basic
Enable basic ruleset optimizations.
This is the default behaviour.
-.It Fl o Cm profile
+.It Cm profile
Enable basic ruleset optimizations with profiling.
.El
+.Pp
For further information on the ruleset optimizer, see
.Xr pf.conf 5 .
.It Fl P
@@ -387,16 +428,20 @@ Only print errors and warnings.
Load only the filter rules present in the rule file.
Other rules and options are ignored.
.It Fl r
-Perform reverse DNS lookups on states when displaying them.
-.It Fl s Ar modifier
+Perform reverse DNS lookups on states and tables when displaying them.
+.Fl N
+and
+.Fl r
+are mutually exclusive.
+.It Fl s Ar modifier Op Fl R Ar id
Show the filter parameters specified by
.Ar modifier
(may be abbreviated):
.Pp
-.Bl -tag -width xxxxxxxxxxxxx -compact
-.It Fl s Cm nat
+.Bl -tag -width xxxxxxxxxxx -compact
+.It Cm nat
Show the currently loaded NAT rules.
-.It Fl s Cm queue
+.It Cm queue
Show the currently loaded queue rules.
When used together with
.Fl v ,
@@ -406,18 +451,25 @@ When used together with
.Nm
will loop and show updated queue statistics every five seconds, including
measured bandwidth and packets per second.
-.It Fl s Cm ether
+.It Cm ether
Show the currently loaded Ethernet rules.
When used together with
.Fl v ,
the per-rule statistics (number of evaluations,
packets, and bytes) are also shown.
-.It Fl s Cm rules
+.It Cm rules
Show the currently loaded filter rules.
When used together with
.Fl v ,
the per-rule statistics (number of evaluations,
packets, and bytes) are also shown.
+When used together with
+.Fl g
+or
+.Fl vv ,
+expired rules
+.Pq marked as Dq # expired
+are also shown.
Note that the
.Dq skip step
optimization done automatically by the kernel
@@ -425,7 +477,7 @@ will skip evaluation of rules where possible.
Packets passed statefully are counted in the rule that created the state
(even though the rule is not evaluated more than once for the entire
connection).
-.It Fl s Cm Anchors
+.It Cm Anchors
Show the currently loaded anchors directly attached to the main ruleset.
If
.Fl a Ar anchor
@@ -436,31 +488,34 @@ If
.Fl v
is specified, all anchors attached under the target anchor will be
displayed recursively.
-.It Fl s Cm states
+.It Cm states
Show the contents of the state table.
-.It Fl s Cm Sources
+.It Cm Sources
Show the contents of the source tracking table.
-.It Fl s Cm info
+.It Cm info
Show filter information (statistics and counters).
When used together with
.Fl v ,
-source tracking statistics are also shown.
-.It Fl s Cm Running
+source tracking statistics, the firewall's 32-bit hostid number and the
+main ruleset's MD5 checksum for use with
+.Xr pfsync 4
+are also shown.
+.It Cm Running
Show the running status and provide a non-zero exit status when disabled.
-.It Fl s Cm labels
+.It Cm labels
Show per-rule statistics (label, evaluations, packets total, bytes total,
packets in, bytes in, packets out, bytes out, state creations) of
filter rules with labels, useful for accounting.
-.It Fl s Cm timeouts
+.It Cm timeouts
Show the current global timeouts.
-.It Fl s Cm memory
+.It Cm memory
Show the current pool memory hard limits.
-.It Fl s Cm Tables
+.It Cm Tables
Show the list of tables.
-.It Fl s Cm osfp
+.It Cm osfp
Show the list of operating system fingerprints.
-.It Fl s Cm Interfaces
-Show the list of interfaces and interface drivers available to PF.
+.It Cm Interfaces
+Show the list of interfaces and interface groups available to PF.
When used together with
.Fl v ,
it additionally lists which interfaces have skip rules activated.
@@ -469,43 +524,93 @@ When used together with
interface statistics are also shown.
.Fl i
can be used to select an interface or a group of interfaces.
-.It Fl s Cm all
+.It Cm all
Show all of the above, except for the lists of interfaces and operating
system fingerprints.
.El
-.It Fl T Ar command Op Ar address ...
+.Pp
+Counters shown with
+.Fl s Cm info
+are:
+.Pp
+.Bl -tag -width xxxxxxxxxxxxxx -compact
+.It match
+explicit rule match
+.It bad-offset
+currently unused
+.It fragment
+invalid fragments dropped
+.It short
+short packets dropped
+.It normalize
+dropped by normalizer: illegal packets
+.It memory
+memory could not be allocated
+.It bad-timestamp
+bad TCP timestamp; RFC 1323
+.It congestion
+network interface queue congested
+.It ip-option
+bad IP/IPv6 options
+.It proto-cksum
+invalid protocol checksum
+.It state-mismatch
+packet was associated with a state entry, but sequence numbers did not match
+.It state-insert
+state insertion failure
+.It state-limit
+configured state limit was reached
+.It src-limit
+source node/connection limit
+.It synproxy
+dropped by synproxy
+.It map-failed
+address mapping failed
+.It translate
+no free ports in translation port range
+.El
+.It Fl S
+Do not perform domain name resolution.
+If a name cannot be resolved without DNS, an error will be reported.
+.It Fl t Ar table Fl T Ar command Op Ar address ...
Specify the
.Ar command
-(may be abbreviated) to apply to the table.
+(may be abbreviated) to apply to
+.Ar table .
Commands include:
.Pp
-.Bl -tag -width xxxxxxxxxxxx -compact
-.It Fl T Cm kill
-Kill a table.
-.It Fl T Cm flush
-Flush all addresses of a table.
-.It Fl T Cm add
-Add one or more addresses in a table.
-Automatically create a nonexisting table.
-.It Fl T Cm delete
+.Bl -tag -width "expire number" -compact
+.It Cm add
+Add one or more addresses to a table.
+Automatically create a persistent table if it does not exist.
+.It Cm delete
Delete one or more addresses from a table.
-.It Fl T Cm expire Ar number
+.It Cm expire Ar number
Delete addresses which had their statistics cleared more than
.Ar number
seconds ago.
For entries which have never had their statistics cleared,
.Ar number
refers to the time they were added to the table.
-.It Fl T Cm replace
+.It Cm flush
+Flush all addresses in a table.
+.It Cm kill
+Kill a table.
+.It Cm replace
Replace the addresses of the table.
-Automatically create a nonexisting table.
-.It Fl T Cm show
+Automatically create a persistent table if it does not exist.
+.It Cm show
Show the content (addresses) of a table.
-.It Fl T Cm test
+.It Cm test
Test if the given addresses match a table.
-.It Fl T Cm zero
-Clear all the statistics of a table.
-.It Fl T Cm load
+.It Cm zero Op Ar address ...
+Clear all the statistics of a table, or only for specified addresses.
+.It Cm reset
+Clear statistics only for addresses with non-zero statistics. Addresses
+with counter values at zero and their
+.Dq Cleared
+timestamp are left untouched.
+.It Cm load
Load only the table definitions from
.Xr pf.conf 5 .
This is used in conjunction with the
@@ -528,6 +633,8 @@ line and/or in an unformatted text file, using the
flag.
Comments starting with a
.Sq #
+or
+.Sq \;
are allowed in the text file.
With these commands, the
.Fl v
@@ -668,8 +775,6 @@ tables of the same name from anchors attached below it.
.It C
This flag is set when per-address counters are enabled on the table.
.El
-.It Fl t Ar table
-Specify the name of the table.
.It Fl v
Produce more verbose output.
A second use of
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 93d26e53d71d..ed317495c2e0 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -34,13 +34,10 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#define PFIOC_USE_LATEST
#include <sys/types.h>
#include <sys/ioctl.h>
-#include <sys/nv.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/endian.h>
@@ -50,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <net/pfvar.h>
#include <arpa/inet.h>
#include <net/altq/altq.h>
-#include <sys/sysctl.h>
#include <err.h>
#include <errno.h>
@@ -63,6 +59,8 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <stdarg.h>
+#include <libgen.h>
#include "pfctl_parser.h"
#include "pfctl.h"
@@ -70,23 +68,26 @@ __FBSDID("$FreeBSD$");
void usage(void);
int pfctl_enable(int, int);
int pfctl_disable(int, int);
-int pfctl_clear_stats(int, int);
-int pfctl_get_skip_ifaces(void);
-int pfctl_check_skip_ifaces(char *);
-int pfctl_adjust_skip_ifaces(struct pfctl *);
-int pfctl_clear_interface_flags(int, int);
-int pfctl_flush_eth_rules(int, int, char *);
+void pfctl_clear_stats(struct pfctl_handle *, int);
+void pfctl_get_skip_ifaces(void);
+void pfctl_check_skip_ifaces(char *);
+void pfctl_adjust_skip_ifaces(struct pfctl *);
+void pfctl_clear_interface_flags(int, int);
+void pfctl_flush_eth_rules(int, int, char *);
int pfctl_flush_rules(int, int, char *);
-int pfctl_flush_nat(int, int, char *);
+void pfctl_flush_nat(int, int, char *);
int pfctl_clear_altq(int, int);
-int pfctl_clear_src_nodes(int, int);
-int pfctl_clear_iface_states(int, const char *, int);
-void pfctl_addrprefix(char *, struct pf_addr *);
-int pfctl_kill_src_nodes(int, const char *, int);
-int pfctl_net_kill_states(int, const char *, int);
-int pfctl_gateway_kill_states(int, const char *, int);
-int pfctl_label_kill_states(int, const char *, int);
-int pfctl_id_kill_states(int, const char *, int);
+void pfctl_clear_src_nodes(int, int);
+void pfctl_clear_iface_states(int, const char *, int);
+struct addrinfo *
+ pfctl_addrprefix(char *, struct pf_addr *, int);
+void pfctl_kill_src_nodes(int, int);
+void pfctl_net_kill_states(int, const char *, int);
+void pfctl_gateway_kill_states(int, const char *, int);
+void pfctl_label_kill_states(int, const char *, int);
+void pfctl_id_kill_states(int, const char *, int);
+void pfctl_key_kill_states(int, const char *, int);
+int pfctl_parse_host(char *, struct pf_rule_addr *);
void pfctl_init_options(struct pfctl *);
int pfctl_load_options(struct pfctl *);
int pfctl_load_limit(struct pfctl *, unsigned int, unsigned int);
@@ -94,20 +95,23 @@ int pfctl_load_timeout(struct pfctl *, unsigned int, unsigned int);
int pfctl_load_debug(struct pfctl *, unsigned int);
int pfctl_load_logif(struct pfctl *, char *);
int pfctl_load_hostid(struct pfctl *, u_int32_t);
+int pfctl_load_reassembly(struct pfctl *, u_int32_t);
int pfctl_load_syncookies(struct pfctl *, u_int8_t);
int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int,
- char *);
+ const char *, int);
void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int);
void pfctl_print_rule_counters(struct pfctl_rule *, int);
-int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int);
-int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int);
-int pfctl_show_nat(int, char *, int, char *, int);
+int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int, int);
+int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int);
+int pfctl_show_nat(int, const char *, int, char *, int, int);
int pfctl_show_src_nodes(int, int);
int pfctl_show_states(int, const char *, int);
int pfctl_show_status(int, int);
int pfctl_show_running(int);
int pfctl_show_timeouts(int, int);
int pfctl_show_limits(int, int);
+void pfctl_read_limits(struct pfctl_handle *);
+void pfctl_restore_limits(void);
void pfctl_debug(int, u_int32_t, int);
int pfctl_test_altqsupport(int, int);
int pfctl_show_anchors(int, int, char *);
@@ -123,6 +127,19 @@ int pfctl_load_ruleset(struct pfctl *, char *,
struct pfctl_ruleset *, int, int);
int pfctl_load_rule(struct pfctl *, char *, struct pfctl_rule *, int);
const char *pfctl_lookup_option(char *, const char * const *);
+void pfctl_reset(int, int);
+int pfctl_walk_show(int, struct pfioc_ruleset *, void *);
+int pfctl_walk_get(int, struct pfioc_ruleset *, void *);
+int pfctl_walk_anchors(int, int, const char *,
+ int(*)(int, struct pfioc_ruleset *, void *), void *);
+struct pfr_anchors *
+ pfctl_get_anchors(int, const char *, int);
+int pfctl_recurse(int, int, const char *,
+ int(*)(int, int, struct pfr_anchoritem *));
+int pfctl_call_clearrules(int, int, struct pfr_anchoritem *);
+int pfctl_call_cleartables(int, int, struct pfr_anchoritem *);
+int pfctl_call_clearanchors(int, int, struct pfr_anchoritem *);
+int pfctl_call_showtables(int, int, struct pfr_anchoritem *);
static struct pfctl_anchor_global pf_anchors;
struct pfctl_anchor pf_main_anchor;
@@ -135,7 +152,7 @@ static const char *showopt;
static const char *debugopt;
static char *anchoropt;
static const char *optiopt = NULL;
-static const char *pf_device = "/dev/pf";
+static const char *pf_device = PF_DEVICE;
static char *ifaceopt;
static char *tableopt;
static const char *tblcmdopt;
@@ -147,8 +164,10 @@ int loadopt;
int altqsupport;
int dev = -1;
+struct pfctl_handle *pfh = NULL;
static int first_title = 1;
static int labels = 0;
+static int exit_val = 0;
#define INDENT(d, o) do { \
if (o) { \
@@ -167,9 +186,13 @@ static const struct {
{ "src-nodes", PF_LIMIT_SRC_NODES },
{ "frags", PF_LIMIT_FRAGS },
{ "table-entries", PF_LIMIT_TABLE_ENTRIES },
+ { "anchors", PF_LIMIT_ANCHORS },
+ { "eth-anchors", PF_LIMIT_ETH_ANCHORS },
{ NULL, 0 }
};
+static unsigned int limit_curr[PF_LIMIT_MAX];
+
struct pf_hint {
const char *name;
int timeout;
@@ -230,18 +253,18 @@ static const struct {
static const char * const clearopt_list[] = {
"nat", "queue", "rules", "Sources",
"states", "info", "Tables", "osfp", "all",
- "ethernet", NULL
+ "ethernet", "Reset", NULL
};
static const char * const showopt_list[] = {
"ether", "nat", "queue", "rules", "Anchors", "Sources", "states",
"info", "Interfaces", "labels", "timeouts", "memory", "Tables",
- "osfp", "Running", "all", NULL
+ "osfp", "Running", "all", "creatorids", NULL
};
static const char * const tblcmdopt_list[] = {
"kill", "flush", "add", "delete", "load", "replace", "show",
- "test", "zero", "expire", NULL
+ "test", "zero", "expire", "reset", NULL
};
static const char * const debugopt_list[] = {
@@ -258,7 +281,7 @@ usage(void)
extern char *__progname;
fprintf(stderr,
-"usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
+"usage: %s [-AdeghMmNnOPqRSrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
"\t[-f file] [-i interface] [-K host | network]\n"
"\t[-k host | network | gateway | label | id] [-o level] [-p device]\n"
"\t[-s modifier] [-t table -T command [address ...]] [-x level]\n",
@@ -267,6 +290,40 @@ usage(void)
exit(1);
}
+void
+pfctl_err(int opts, int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ if ((opts & PF_OPT_IGNFAIL) == 0)
+ verr(eval, fmt, ap);
+ else
+ vwarn(fmt, ap);
+
+ va_end(ap);
+
+ exit_val = eval;
+}
+
+void
+pfctl_errx(int opts, int eval, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ if ((opts & PF_OPT_IGNFAIL) == 0)
+ verrx(eval, fmt, ap);
+ else
+ vwarnx(fmt, ap);
+
+ va_end(ap);
+
+ exit_val = eval;
+}
+
/*
* Cache protocol number to name translations.
*
@@ -313,13 +370,15 @@ pfctl_proto2name(int proto)
int
pfctl_enable(int dev, int opts)
{
- if (ioctl(dev, DIOCSTART)) {
- if (errno == EEXIST)
+ int ret;
+
+ if ((ret = pfctl_startstop(pfh, 1)) != 0) {
+ if (ret == EEXIST)
errx(1, "pf already enabled");
- else if (errno == ESRCH)
+ else if (ret == ESRCH)
errx(1, "pfil registeration failed");
else
- err(1, "DIOCSTART");
+ errc(1, ret, "DIOCSTART");
}
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "pf enabled\n");
@@ -334,11 +393,13 @@ pfctl_enable(int dev, int opts)
int
pfctl_disable(int dev, int opts)
{
- if (ioctl(dev, DIOCSTOP)) {
- if (errno == ENOENT)
+ int ret;
+
+ if ((ret = pfctl_startstop(pfh, 0)) != 0) {
+ if (ret == ENOENT)
errx(1, "pf not enabled");
else
- err(1, "DIOCSTOP");
+ errc(1, ret, "DIOCSTOP");
}
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "pf disabled\n");
@@ -350,17 +411,17 @@ pfctl_disable(int dev, int opts)
return (0);
}
-int
-pfctl_clear_stats(int dev, int opts)
+void
+pfctl_clear_stats(struct pfctl_handle *h, int opts)
{
- if (ioctl(dev, DIOCCLRSTATUS))
- err(1, "DIOCCLRSTATUS");
+ int ret;
+ if ((ret = pfctl_clear_status(h)) != 0)
+ pfctl_err(opts, 1, "DIOCCLRSTATUS");
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "pf: statistics cleared\n");
- return (0);
}
-int
+void
pfctl_get_skip_ifaces(void)
{
bzero(&skip_b, sizeof(skip_b));
@@ -373,10 +434,9 @@ pfctl_get_skip_ifaces(void)
if (skip_b.pfrb_size <= skip_b.pfrb_msize)
break;
}
- return (0);
}
-int
+void
pfctl_check_skip_ifaces(char *ifname)
{
struct pfi_kif *p;
@@ -391,8 +451,6 @@ pfctl_check_skip_ifaces(char *ifname)
continue;
for (n = h; n != NULL; n = n->next) {
- if (p->pfik_ifp == NULL)
- continue;
if (strncmp(p->pfik_name, ifname, IFNAMSIZ))
continue;
@@ -400,10 +458,9 @@ pfctl_check_skip_ifaces(char *ifname)
}
}
}
- return (0);
}
-int
+void
pfctl_adjust_skip_ifaces(struct pfctl *pf)
{
struct pfi_kif *p, *pp;
@@ -419,9 +476,6 @@ pfctl_adjust_skip_ifaces(struct pfctl *pf)
for (n = h; n != NULL; n = n->next)
PFRB_FOREACH(pp, &skip_b) {
- if (pp->pfik_ifp == NULL)
- continue;
-
if (strncmp(pp->pfik_name, n->ifname, IFNAMSIZ))
continue;
@@ -434,16 +488,14 @@ pfctl_adjust_skip_ifaces(struct pfctl *pf)
}
PFRB_FOREACH(p, &skip_b) {
- if (p->pfik_ifp == NULL || ! (p->pfik_flags & PFI_IFLAG_SKIP))
+ if (! (p->pfik_flags & PFI_IFLAG_SKIP))
continue;
pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
}
-
- return (0);
}
-int
+void
pfctl_clear_interface_flags(int dev, int opts)
{
struct pfioc_iface pi;
@@ -457,10 +509,9 @@ pfctl_clear_interface_flags(int dev, int opts)
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "pf: interface flags reset\n");
}
- return (0);
}
-int
+void
pfctl_flush_eth_rules(int dev, int opts, char *anchorname)
{
int ret;
@@ -471,8 +522,6 @@ pfctl_flush_eth_rules(int dev, int opts, char *anchorname)
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "Ethernet rules cleared\n");
-
- return (ret);
}
int
@@ -481,14 +530,16 @@ pfctl_flush_rules(int dev, int opts, char *anchorname)
int ret;
ret = pfctl_clear_rules(dev, anchorname);
- if (ret != 0)
- err(1, "pfctl_clear_rules");
- if ((opts & PF_OPT_QUIET) == 0)
+ if (ret != 0) {
+ pfctl_err(opts, 1, "%s", __func__);
+ return (1);
+ } else if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "rules cleared\n");
+
return (0);
}
-int
+void
pfctl_flush_nat(int dev, int opts, char *anchorname)
{
int ret;
@@ -498,7 +549,6 @@ pfctl_flush_nat(int dev, int opts, char *anchorname)
err(1, "pfctl_clear_nat");
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "nat cleared\n");
- return (0);
}
int
@@ -519,66 +569,66 @@ pfctl_clear_altq(int dev, int opts)
return (0);
}
-int
+void
pfctl_clear_src_nodes(int dev, int opts)
{
if (ioctl(dev, DIOCCLRSRCNODES))
- err(1, "DIOCCLRSRCNODES");
+ pfctl_err(opts, 1, "DIOCCLRSRCNODES");
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "source tracking entries cleared\n");
- return (0);
}
-int
+void
pfctl_clear_iface_states(int dev, const char *iface, int opts)
{
struct pfctl_kill kill;
unsigned int killed;
+ int ret;
memset(&kill, 0, sizeof(kill));
if (iface != NULL && strlcpy(kill.ifname, iface,
sizeof(kill.ifname)) >= sizeof(kill.ifname))
- errx(1, "invalid interface: %s", iface);
+ pfctl_errx(opts, 1, "invalid interface: %s", iface);
if (opts & PF_OPT_KILLMATCH)
kill.kill_match = true;
- if (pfctl_clear_states(dev, &kill, &killed))
- err(1, "DIOCCLRSTATES");
+ if ((ret = pfctl_clear_states_h(pfh, &kill, &killed)) != 0)
+ pfctl_err(opts, 1, "DIOCCLRSTATUS");
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "%d states cleared\n", killed);
- return (0);
}
-void
-pfctl_addrprefix(char *addr, struct pf_addr *mask)
+struct addrinfo *
+pfctl_addrprefix(char *addr, struct pf_addr *mask, int numeric)
{
char *p;
const char *errstr;
int prefix, ret_ga, q, r;
struct addrinfo hints, *res;
- if ((p = strchr(addr, '/')) == NULL)
- return;
-
- *p++ = '\0';
- prefix = strtonum(p, 0, 128, &errstr);
- if (errstr)
- errx(1, "prefix is %s: %s", errstr, p);
-
bzero(&hints, sizeof(hints));
- /* prefix only with numeric addresses */
- hints.ai_flags |= AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_DGRAM; /* dummy */
+ if (numeric)
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if ((p = strchr(addr, '/')) != NULL) {
+ *p++ = '\0';
+ /* prefix only with numeric addresses */
+ hints.ai_flags |= AI_NUMERICHOST;
+ }
if ((ret_ga = getaddrinfo(addr, NULL, &hints, &res))) {
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
/* NOTREACHED */
}
- if (res->ai_family == AF_INET && prefix > 32)
- errx(1, "prefix too long for AF_INET");
- else if (res->ai_family == AF_INET6 && prefix > 128)
- errx(1, "prefix too long for AF_INET6");
+ if (p == NULL)
+ return (res);
+
+ prefix = strtonum(p, 0, res->ai_family == AF_INET6 ? 128 : 32, &errstr);
+ if (errstr)
+ errx(1, "prefix is %s: %s", errstr, p);
q = prefix >> 3;
r = prefix & 7;
@@ -597,17 +647,17 @@ pfctl_addrprefix(char *addr, struct pf_addr *mask)
(0xff00 >> r) & 0xff;
break;
}
- freeaddrinfo(res);
+
+ return (res);
}
-int
-pfctl_kill_src_nodes(int dev, const char *iface, int opts)
+void
+pfctl_kill_src_nodes(int dev, int opts)
{
struct pfioc_src_node_kill psnk;
struct addrinfo *res[2], *resp[2];
struct sockaddr last_src, last_dst;
int killed, sources, dests;
- int ret_ga;
killed = sources = dests = 0;
@@ -617,12 +667,9 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
memset(&last_src, 0xff, sizeof(last_src));
memset(&last_dst, 0xff, sizeof(last_dst));
- pfctl_addrprefix(src_node_kill[0], &psnk.psnk_src.addr.v.a.mask);
+ res[0] = pfctl_addrprefix(src_node_kill[0],
+ &psnk.psnk_src.addr.v.a.mask, (opts & PF_OPT_NODNS));
- if ((ret_ga = getaddrinfo(src_node_kill[0], NULL, NULL, &res[0]))) {
- errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
- /* NOTREACHED */
- }
for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
if (resp[0]->ai_addr == NULL)
continue;
@@ -634,29 +681,16 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
psnk.psnk_af = resp[0]->ai_family;
sources++;
- if (psnk.psnk_af == AF_INET)
- psnk.psnk_src.addr.v.a.addr.v4 =
- ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
- else if (psnk.psnk_af == AF_INET6)
- psnk.psnk_src.addr.v.a.addr.v6 =
- ((struct sockaddr_in6 *)resp[0]->ai_addr)->
- sin6_addr;
- else
- errx(1, "Unknown address family %d", psnk.psnk_af);
+ copy_satopfaddr(&psnk.psnk_src.addr.v.a.addr, resp[0]->ai_addr);
if (src_node_killers > 1) {
dests = 0;
memset(&psnk.psnk_dst.addr.v.a.mask, 0xff,
sizeof(psnk.psnk_dst.addr.v.a.mask));
memset(&last_dst, 0xff, sizeof(last_dst));
- pfctl_addrprefix(src_node_kill[1],
- &psnk.psnk_dst.addr.v.a.mask);
- if ((ret_ga = getaddrinfo(src_node_kill[1], NULL, NULL,
- &res[1]))) {
- errx(1, "getaddrinfo: %s",
- gai_strerror(ret_ga));
- /* NOTREACHED */
- }
+ res[1] = pfctl_addrprefix(src_node_kill[1],
+ &psnk.psnk_dst.addr.v.a.mask,
+ (opts & PF_OPT_NODNS));
for (resp[1] = res[1]; resp[1];
resp[1] = resp[1]->ai_next) {
if (resp[1]->ai_addr == NULL)
@@ -671,18 +705,8 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
dests++;
- if (psnk.psnk_af == AF_INET)
- psnk.psnk_dst.addr.v.a.addr.v4 =
- ((struct sockaddr_in *)resp[1]->
- ai_addr)->sin_addr;
- else if (psnk.psnk_af == AF_INET6)
- psnk.psnk_dst.addr.v.a.addr.v6 =
- ((struct sockaddr_in6 *)resp[1]->
- ai_addr)->sin6_addr;
- else
- errx(1, "Unknown address family %d",
- psnk.psnk_af);
-
+ copy_satopfaddr(&psnk.psnk_dst.addr.v.a.addr,
+ resp[1]->ai_addr);
if (ioctl(dev, DIOCKILLSRCNODES, &psnk))
err(1, "DIOCKILLSRCNODES");
killed += psnk.psnk_killed;
@@ -700,10 +724,9 @@ pfctl_kill_src_nodes(int dev, const char *iface, int opts)
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "killed %d src nodes from %d sources and %d "
"destinations\n", killed, sources, dests);
- return (0);
}
-int
+void
pfctl_net_kill_states(int dev, const char *iface, int opts)
{
struct pfctl_kill kill;
@@ -711,7 +734,7 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
struct sockaddr last_src, last_dst;
unsigned int newkilled;
int killed, sources, dests;
- int ret_ga;
+ int ret;
killed = sources = dests = 0;
@@ -722,17 +745,20 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
memset(&last_dst, 0xff, sizeof(last_dst));
if (iface != NULL && strlcpy(kill.ifname, iface,
sizeof(kill.ifname)) >= sizeof(kill.ifname))
- errx(1, "invalid interface: %s", iface);
+ pfctl_errx(opts, 1, "invalid interface: %s", iface);
- pfctl_addrprefix(state_kill[0], &kill.src.addr.v.a.mask);
+ if (state_killers == 2 && (strcmp(state_kill[0], "nat") == 0)) {
+ kill.nat = true;
+ state_kill[0] = state_kill[1];
+ state_killers = 1;
+ }
+
+ res[0] = pfctl_addrprefix(state_kill[0],
+ &kill.src.addr.v.a.mask, (opts & PF_OPT_NODNS));
if (opts & PF_OPT_KILLMATCH)
kill.kill_match = true;
- if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
- errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
- /* NOTREACHED */
- }
for (resp[0] = res[0]; resp[0]; resp[0] = resp[0]->ai_next) {
if (resp[0]->ai_addr == NULL)
continue;
@@ -744,29 +770,16 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
kill.af = resp[0]->ai_family;
sources++;
- if (kill.af == AF_INET)
- kill.src.addr.v.a.addr.v4 =
- ((struct sockaddr_in *)resp[0]->ai_addr)->sin_addr;
- else if (kill.af == AF_INET6)
- kill.src.addr.v.a.addr.v6 =
- ((struct sockaddr_in6 *)resp[0]->ai_addr)->
- sin6_addr;
- else
- errx(1, "Unknown address family %d", kill.af);
+ copy_satopfaddr(&kill.src.addr.v.a.addr, resp[0]->ai_addr);
if (state_killers > 1) {
dests = 0;
memset(&kill.dst.addr.v.a.mask, 0xff,
sizeof(kill.dst.addr.v.a.mask));
memset(&last_dst, 0xff, sizeof(last_dst));
- pfctl_addrprefix(state_kill[1],
- &kill.dst.addr.v.a.mask);
- if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL,
- &res[1]))) {
- errx(1, "getaddrinfo: %s",
- gai_strerror(ret_ga));
- /* NOTREACHED */
- }
+ res[1] = pfctl_addrprefix(state_kill[1],
+ &kill.dst.addr.v.a.mask,
+ (opts & PF_OPT_NODNS));
for (resp[1] = res[1]; resp[1];
resp[1] = resp[1]->ai_next) {
if (resp[1]->ai_addr == NULL)
@@ -781,26 +794,17 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
dests++;
- if (kill.af == AF_INET)
- kill.dst.addr.v.a.addr.v4 =
- ((struct sockaddr_in *)resp[1]->
- ai_addr)->sin_addr;
- else if (kill.af == AF_INET6)
- kill.dst.addr.v.a.addr.v6 =
- ((struct sockaddr_in6 *)resp[1]->
- ai_addr)->sin6_addr;
- else
- errx(1, "Unknown address family %d",
- kill.af);
+ copy_satopfaddr(&kill.dst.addr.v.a.addr,
+ resp[1]->ai_addr);
- if (pfctl_kill_states(dev, &kill, &newkilled))
- err(1, "DIOCKILLSTATES");
+ if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0)
+ pfctl_errx(opts, 1, "DIOCKILLSTATES");
killed += newkilled;
}
freeaddrinfo(res[1]);
} else {
- if (pfctl_kill_states(dev, &kill, &newkilled))
- err(1, "DIOCKILLSTATES");
+ if ((ret = pfctl_kill_states_h(pfh, &kill, &newkilled)) != 0)
+ pfctl_errx(opts, 1, "DIOCKILLSTATES");
killed += newkilled;
}
}
@@ -810,10 +814,9 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "killed %d states from %d sources and %d "
"destinations\n", killed, sources, dests);
- return (0);
}
-int
+void
pfctl_gateway_kill_states(int dev, const char *iface, int opts)
{
struct pfctl_kill kill;
@@ -821,7 +824,6 @@ pfctl_gateway_kill_states(int dev, const char *iface, int opts)
struct sockaddr last_src;
unsigned int newkilled;
int killed = 0;
- int ret_ga;
if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
warnx("no gateway specified");
@@ -834,17 +836,14 @@ pfctl_gateway_kill_states(int dev, const char *iface, int opts)
memset(&last_src, 0xff, sizeof(last_src));
if (iface != NULL && strlcpy(kill.ifname, iface,
sizeof(kill.ifname)) >= sizeof(kill.ifname))
- errx(1, "invalid interface: %s", iface);
+ pfctl_errx(opts, 1, "invalid interface: %s", iface);
if (opts & PF_OPT_KILLMATCH)
kill.kill_match = true;
- pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask);
+ res = pfctl_addrprefix(state_kill[1], &kill.rt_addr.addr.v.a.mask,
+ (opts & PF_OPT_NODNS));
- if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) {
- errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
- /* NOTREACHED */
- }
for (resp = res; resp; resp = resp->ai_next) {
if (resp->ai_addr == NULL)
continue;
@@ -855,18 +854,10 @@ pfctl_gateway_kill_states(int dev, const char *iface, int opts)
kill.af = resp->ai_family;
- if (kill.af == AF_INET)
- kill.rt_addr.addr.v.a.addr.v4 =
- ((struct sockaddr_in *)resp->ai_addr)->sin_addr;
- else if (kill.af == AF_INET6)
- kill.rt_addr.addr.v.a.addr.v6 =
- ((struct sockaddr_in6 *)resp->ai_addr)->
- sin6_addr;
- else
- errx(1, "Unknown address family %d", kill.af);
-
- if (pfctl_kill_states(dev, &kill, &newkilled))
- err(1, "DIOCKILLSTATES");
+ copy_satopfaddr(&kill.rt_addr.addr.v.a.addr,
+ resp->ai_addr);
+ if (pfctl_kill_states_h(pfh, &kill, &newkilled))
+ pfctl_errx(opts, 1, "DIOCKILLSTATES");
killed += newkilled;
}
@@ -874,14 +865,14 @@ pfctl_gateway_kill_states(int dev, const char *iface, int opts)
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "killed %d states\n", killed);
- return (0);
}
-int
+void
pfctl_label_kill_states(int dev, const char *iface, int opts)
{
struct pfctl_kill kill;
unsigned int killed;
+ int ret;
if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
warnx("no label specified");
@@ -890,7 +881,7 @@ pfctl_label_kill_states(int dev, const char *iface, int opts)
memset(&kill, 0, sizeof(kill));
if (iface != NULL && strlcpy(kill.ifname, iface,
sizeof(kill.ifname)) >= sizeof(kill.ifname))
- errx(1, "invalid interface: %s", iface);
+ pfctl_errx(opts, 1, "invalid interface: %s", iface);
if (opts & PF_OPT_KILLMATCH)
kill.kill_match = true;
@@ -899,20 +890,19 @@ pfctl_label_kill_states(int dev, const char *iface, int opts)
sizeof(kill.label))
errx(1, "label too long: %s", state_kill[1]);
- if (pfctl_kill_states(dev, &kill, &killed))
- err(1, "DIOCKILLSTATES");
+ if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0)
+ pfctl_errx(opts, 1, "DIOCKILLSTATES");
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "killed %d states\n", killed);
-
- return (0);
}
-int
+void
pfctl_id_kill_states(int dev, const char *iface, int opts)
{
struct pfctl_kill kill;
unsigned int killed;
+ int ret;
if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
warnx("no id specified");
@@ -938,44 +928,144 @@ pfctl_id_kill_states(int dev, const char *iface, int opts)
usage();
}
- if (pfctl_kill_states(dev, &kill, &killed))
- err(1, "DIOCKILLSTATES");
+ if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0)
+ pfctl_errx(opts, 1, "DIOCKILLSTATES");
if ((opts & PF_OPT_QUIET) == 0)
fprintf(stderr, "killed %d states\n", killed);
+}
+
+void
+pfctl_key_kill_states(int dev, const char *iface, int opts)
+{
+ struct pfctl_kill kill;
+ char *s, *token, *tokens[4];
+ struct protoent *p;
+ u_int i, sidx, didx;
+ int ret, killed;
+
+ if (state_killers != 2 || (strlen(state_kill[1]) == 0)) {
+ warnx("no key specified");
+ usage();
+ }
+ memset(&kill, 0, sizeof(kill));
+
+ if (iface != NULL &&
+ strlcpy(kill.ifname, iface, sizeof(kill.ifname)) >=
+ sizeof(kill.ifname))
+ pfctl_errx(opts, 1, "invalid interface: %s", iface);
+
+ s = strdup(state_kill[1]);
+ if (!s)
+ errx(1, "%s: strdup", __func__);
+ i = 0;
+ while ((token = strsep(&s, " \t")) != NULL)
+ if (*token != '\0') {
+ if (i < 4)
+ tokens[i] = token;
+ i++;
+ }
+ if (i != 4)
+ errx(1, "%s: key must be "
+ "\"protocol host1:port1 direction host2:port2\" format",
+ __func__);
+
+ if ((p = getprotobyname(tokens[0])) == NULL)
+ errx(1, "invalid protocol: %s", tokens[0]);
+ kill.proto = p->p_proto;
+
+ if (strcmp(tokens[2], "->") == 0) {
+ sidx = 1;
+ didx = 3;
+ } else if (strcmp(tokens[2], "<-") == 0) {
+ sidx = 3;
+ didx = 1;
+ } else
+ errx(1, "invalid direction: %s", tokens[2]);
+
+ if (pfctl_parse_host(tokens[sidx], &kill.src) == -1)
+ errx(1, "invalid host: %s", tokens[sidx]);
+ if (pfctl_parse_host(tokens[didx], &kill.dst) == -1)
+ errx(1, "invalid host: %s", tokens[didx]);
+
+ if ((ret = pfctl_kill_states_h(pfh, &kill, &killed)) != 0)
+ pfctl_errx(opts, 1, "DIOCKILLSTATES");
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d states\n", killed);
+}
+
+int
+pfctl_parse_host(char *str, struct pf_rule_addr *addr)
+{
+ char *s = NULL, *sbs, *sbe;
+ struct addrinfo hints, *ai;
+
+ s = strdup(str);
+ if (!s)
+ errx(1, "pfctl_parse_host: strdup");
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM; /* dummy */
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if ((sbs = strchr(s, '[')) != NULL && (sbe = strrchr(s, ']')) != NULL) {
+ hints.ai_family = AF_INET6;
+ *(sbs++) = *sbe = '\0';
+ } else if ((sbs = strchr(s, ':')) != NULL) {
+ hints.ai_family = AF_INET;
+ *(sbs++) = '\0';
+ } else {
+ /* Assume that no ':<number>' means port 0 */
+ }
+
+ if (getaddrinfo(s, sbs, &hints, &ai) != 0)
+ goto error;
+
+ copy_satopfaddr(&addr->addr.v.a.addr, ai->ai_addr);
+ addr->port[0] = ai->ai_family == AF_INET6 ?
+ ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port :
+ ((struct sockaddr_in *)ai->ai_addr)->sin_port;
+ freeaddrinfo(ai);
+ free(s);
+
+ memset(&addr->addr.v.a.mask, 0xff, sizeof(struct pf_addr));
+ addr->port_op = PF_OP_EQ;
+ addr->addr.type = PF_ADDR_ADDRMASK;
return (0);
+
+error:
+ free(s);
+ return (-1);
}
int
pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr,
- u_int32_t ticket, int r_action, char *anchorname)
+ u_int32_t ticket, int r_action, const char *anchorname, int which)
{
struct pfioc_pooladdr pp;
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
u_int32_t pnr, mpnr;
+ int ret;
memset(&pp, 0, sizeof(pp));
- memcpy(pp.anchor, anchorname, sizeof(pp.anchor));
- pp.r_action = r_action;
- pp.r_num = nr;
- pp.ticket = ticket;
- if (ioctl(dev, DIOCGETADDRS, &pp)) {
- warn("DIOCGETADDRS");
+ if ((ret = pfctl_get_addrs(pfh, ticket, nr, r_action, anchorname, &mpnr, which)) != 0) {
+ warnc(ret, "DIOCGETADDRS");
return (-1);
}
- mpnr = pp.nr;
+
TAILQ_INIT(&pool->list);
for (pnr = 0; pnr < mpnr; ++pnr) {
- pp.nr = pnr;
- if (ioctl(dev, DIOCGETADDR, &pp)) {
- warn("DIOCGETADDR");
+ if ((ret = pfctl_get_addr(pfh, ticket, nr, r_action, anchorname, pnr, &pp, which)) != 0) {
+ warnc(ret, "DIOCGETADDR");
return (-1);
}
- pa = calloc(1, sizeof(struct pf_pooladdr));
+ pa = calloc(1, sizeof(struct pfctl_pooladdr));
if (pa == NULL)
err(1, "calloc");
- bcopy(&pp.addr, pa, sizeof(struct pf_pooladdr));
+ bcopy(&pp.addr, pa, sizeof(struct pfctl_pooladdr));
+ pa->af = pp.af;
TAILQ_INSERT_TAIL(&pool->list, pa, entries);
}
@@ -985,7 +1075,7 @@ pfctl_get_pool(int dev, struct pfctl_pool *pool, u_int32_t nr,
void
pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst)
{
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
while ((pa = TAILQ_FIRST(&src->list)) != NULL) {
TAILQ_REMOVE(&src->list, pa, entries);
@@ -996,7 +1086,7 @@ pfctl_move_pool(struct pfctl_pool *src, struct pfctl_pool *dst)
void
pfctl_clear_pool(struct pfctl_pool *pool)
{
- struct pf_pooladdr *pa;
+ struct pfctl_pooladdr *pa;
while ((pa = TAILQ_FIRST(&pool->list)) != NULL) {
TAILQ_REMOVE(&pool->list, pa, entries);
@@ -1020,8 +1110,8 @@ pfctl_print_eth_rule_counters(struct pfctl_eth_rule *rule, int opts)
char timestr[30];
if (rule->last_active_timestamp != 0) {
- time_t last_active = rule->last_active_timestamp;
- bcopy(ctime(&last_active), timestr, sizeof(timestr));
+ bcopy(ctime(&rule->last_active_timestamp), timestr,
+ sizeof(timestr));
*strchr(timestr, '\n') = '\0';
} else {
snprintf(timestr, sizeof(timestr), "N/A");
@@ -1035,7 +1125,7 @@ pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
{
if (opts & PF_OPT_DEBUG) {
const char *t[PF_SKIP_COUNT] = { "i", "d", "f",
- "p", "sa", "sp", "da", "dp" };
+ "p", "sa", "da", "sp", "dp" };
int i;
printf(" [ Skip steps: ");
@@ -1052,6 +1142,9 @@ pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
printf(" [ queue: qname=%s qid=%u pqname=%s pqid=%u ]\n",
rule->qname, rule->qid, rule->pqname, rule->pqid);
+ if (rule->rule_flag & PFRULE_EXPIRED)
+ printf(" [ Expired: %lld secs ago ]\n",
+ (long long)(time(NULL) - rule->exptime));
}
if (opts & PF_OPT_VERBOSE) {
printf(" [ Evaluations: %-8llu Packets: %-8llu "
@@ -1061,6 +1154,15 @@ pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
rule->packets[1]),
(unsigned long long)(rule->bytes[0] +
rule->bytes[1]), (uintmax_t)rule->states_cur);
+ printf(" [ Source Nodes: %-6ju "
+ "Limit: %-6ju "
+ "NAT/RDR: %-6ju "
+ "Route: %-6ju "
+ "]\n",
+ (uintmax_t)rule->src_nodes,
+ (uintmax_t)rule->src_nodes_type[PF_SN_LIMIT],
+ (uintmax_t)rule->src_nodes_type[PF_SN_NAT],
+ (uintmax_t)rule->src_nodes_type[PF_SN_ROUTE]);
if (!(opts & PF_OPT_DEBUG))
printf(" [ Inserted: uid %u pid %u "
"State Creations: %-6ju]\n",
@@ -1070,8 +1172,8 @@ pfctl_print_rule_counters(struct pfctl_rule *rule, int opts)
if (opts & PF_OPT_VERBOSE2) {
char timestr[30];
if (rule->last_active_timestamp != 0) {
- time_t last_active = rule->last_active_timestamp;
- bcopy(ctime(&last_active), timestr, sizeof(timestr));
+ bcopy(ctime(&rule->last_active_timestamp), timestr,
+ sizeof(timestr));
*strchr(timestr, '\n') = '\0';
} else {
snprintf(timestr, sizeof(timestr), "N/A");
@@ -1091,31 +1193,85 @@ pfctl_print_title(char *title)
int
pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format,
- char *anchorname, int depth)
+ char *anchorname, int depth, int wildcard)
{
char anchor_call[MAXPATHLEN];
struct pfctl_eth_rules_info info;
struct pfctl_eth_rule rule;
+ int brace;
int dotitle = opts & PF_OPT_SHOWALL;
int len = strlen(path);
- int brace;
- char *p;
+ int ret;
+ char *npath, *p;
- if (path[0])
- snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
- else
- snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
+ /*
+ * Truncate a trailing / and * on an anchorname before searching for
+ * the ruleset, this is syntactic sugar that doesn't actually make it
+ * to the kernel.
+ */
+ if ((p = strrchr(anchorname, '/')) != NULL &&
+ p[1] == '*' && p[2] == '\0') {
+ p[0] = '\0';
+ }
+
+ if (anchorname[0] == '/') {
+ if ((npath = calloc(1, MAXPATHLEN)) == NULL)
+ errx(1, "calloc");
+ snprintf(npath, MAXPATHLEN, "%s", anchorname);
+ } else {
+ if (path[0])
+ snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
+ else
+ snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
+ npath = path;
+ }
+
+ /*
+ * If this anchor was called with a wildcard path, go through
+ * the rulesets in the anchor rather than the rules.
+ */
+ if (wildcard && (opts & PF_OPT_RECURSE)) {
+ struct pfctl_eth_rulesets_info ri;
+ u_int32_t mnr, nr;
+
+ if ((ret = pfctl_get_eth_rulesets_info(dev, &ri, npath)) != 0) {
+ if (ret == EINVAL) {
+ fprintf(stderr, "Anchor '%s' "
+ "not found.\n", anchorname);
+ } else {
+ warnc(ret, "DIOCGETETHRULESETS");
+ return (-1);
+ }
+ }
+ mnr = ri.nr;
- if (pfctl_get_eth_rules_info(dev, &info, path)) {
- warn("DIOCGETETHRULES");
+ pfctl_print_eth_rule_counters(&rule, opts);
+ for (nr = 0; nr < mnr; ++nr) {
+ struct pfctl_eth_ruleset_info rs;
+
+ if ((ret = pfctl_get_eth_ruleset(dev, npath, nr, &rs)) != 0)
+ errc(1, ret, "DIOCGETETHRULESET");
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("anchor \"%s\" all {\n", rs.name);
+ pfctl_show_eth_rules(dev, npath, opts,
+ format, rs.name, depth + 1, 0);
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("}\n");
+ }
+ path[len] = '\0';
+ return (0);
+ }
+
+ if ((ret = pfctl_get_eth_rules_info(dev, &info, path)) != 0) {
+ warnc(ret, "DIOCGETETHRULES");
return (-1);
}
for (int nr = 0; nr < info.nr; nr++) {
brace = 0;
INDENT(depth, !(opts & PF_OPT_VERBOSE));
- if (pfctl_get_eth_rule(dev, nr, info.ticket, path, &rule,
- opts & PF_OPT_CLRRULECTRS, anchor_call) != 0) {
- warn("DIOCGETETHRULE");
+ if ((ret = pfctl_get_eth_rule(dev, nr, info.ticket, path, &rule,
+ opts & PF_OPT_CLRRULECTRS, anchor_call)) != 0) {
+ warnc(ret, "DIOCGETETHRULE");
return (-1);
}
if (anchor_call[0] &&
@@ -1123,13 +1279,11 @@ pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format,
(p == anchor_call ||
*(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
brace++;
- if ((p = strrchr(anchor_call, '/')) !=
- NULL)
- p++;
- else
- p = &anchor_call[0];
- } else
- p = &anchor_call[0];
+ int aclen = strlen(anchor_call);
+ if (anchor_call[aclen - 1] == '*')
+ anchor_call[aclen - 2] = '\0';
+ }
+ p = &anchor_call[0];
if (dotitle) {
pfctl_print_title("ETH RULES:");
dotitle = 0;
@@ -1143,7 +1297,7 @@ pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format,
pfctl_print_eth_rule_counters(&rule, opts);
if (brace) {
pfctl_show_eth_rules(dev, path, opts, format,
- p, depth + 1);
+ p, depth + 1, rule.anchor_wildcard);
INDENT(depth, !(opts & PF_OPT_VERBOSE));
printf("}\n");
}
@@ -1155,35 +1309,75 @@ pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format,
int
pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
- char *anchorname, int depth)
+ char *anchorname, int depth, int wildcard)
{
struct pfctl_rules_info ri;
struct pfctl_rule rule;
char anchor_call[MAXPATHLEN];
u_int32_t nr, header = 0;
- int rule_numbers = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
int numeric = opts & PF_OPT_NUMERIC;
- int len = strlen(path);
- int brace;
- int ret;
- char *p;
+ int len = strlen(path), ret = 0;
+ char *npath, *p;
- if (path[0])
- snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
- else
- snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
+ /*
+ * Truncate a trailing / and * on an anchorname before searching for
+ * the ruleset, this is syntactic sugar that doesn't actually make it
+ * to the kernel.
+ */
+ if ((p = strrchr(anchorname, '/')) != NULL &&
+ p[1] == '*' && p[2] == '\0') {
+ p[0] = '\0';
+ }
+
+ if (anchorname[0] == '/') {
+ if ((npath = calloc(1, MAXPATHLEN)) == NULL)
+ errx(1, "calloc");
+ strlcpy(npath, anchorname, MAXPATHLEN);
+ } else {
+ if (path[0])
+ snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
+ else
+ snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
+ npath = path;
+ }
+
+ /*
+ * If this anchor was called with a wildcard path, go through
+ * the rulesets in the anchor rather than the rules.
+ */
+ if (wildcard && (opts & PF_OPT_RECURSE)) {
+ struct pfioc_ruleset prs;
+ u_int32_t mnr, nr;
+
+ memset(&prs, 0, sizeof(prs));
+ if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0)
+ errx(1, "%s", pf_strerror(ret));
+
+ for (nr = 0; nr < mnr; ++nr) {
+ if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0)
+ errx(1, "%s", pf_strerror(ret));
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("anchor \"%s\" all {\n", prs.name);
+ pfctl_show_rules(dev, npath, opts,
+ format, prs.name, depth + 1, 0);
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("}\n");
+ }
+ path[len] = '\0';
+ return (0);
+ }
if (opts & PF_OPT_SHOWALL) {
- ret = pfctl_get_rules_info(dev, &ri, PF_PASS, path);
+ ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path);
if (ret != 0) {
- warn("DIOCGETRULES");
+ warnx("%s", pf_strerror(ret));
goto error;
}
header++;
}
- ret = pfctl_get_rules_info(dev, &ri, PF_SCRUB, path);
+ ret = pfctl_get_rules_info_h(pfh, &ri, PF_SCRUB, path);
if (ret != 0) {
- warn("DIOCGETRULES");
+ warnx("%s", pf_strerror(ret));
goto error;
}
if (opts & PF_OPT_SHOWALL) {
@@ -1194,45 +1388,69 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
}
for (nr = 0; nr < ri.nr; ++nr) {
- if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_SCRUB,
- &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) {
- warn("DIOCGETRULENV");
+ if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_SCRUB,
+ &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) {
+ warnc(ret, "DIOCGETRULENV");
goto error;
}
- if (pfctl_get_pool(dev, &rule.rpool,
- nr, ri.ticket, PF_SCRUB, path) != 0)
+ if (pfctl_get_pool(dev, &rule.rdr,
+ nr, ri.ticket, PF_SCRUB, path, PF_RDR) != 0)
+ goto error;
+
+ if (pfctl_get_pool(dev, &rule.nat,
+ nr, ri.ticket, PF_SCRUB, path, PF_NAT) != 0)
+ goto error;
+
+ if (pfctl_get_pool(dev, &rule.route,
+ nr, ri.ticket, PF_SCRUB, path, PF_RT) != 0)
goto error;
switch (format) {
case PFCTL_SHOW_LABELS:
break;
case PFCTL_SHOW_RULES:
- if (rule.label[0] && (opts & PF_OPT_SHOWALL))
+ if (rule.label[0][0] && (opts & PF_OPT_SHOWALL))
labels = 1;
- print_rule(&rule, anchor_call, rule_numbers, numeric);
- printf("\n");
+ print_rule(&rule, anchor_call, opts, numeric);
+ /*
+ * Do not print newline, when we have not
+ * printed expired rule.
+ */
+ if (!(rule.rule_flag & PFRULE_EXPIRED) ||
+ (opts & (PF_OPT_VERBOSE2|PF_OPT_DEBUG)))
+ printf("\n");
pfctl_print_rule_counters(&rule, opts);
break;
case PFCTL_SHOW_NOTHING:
break;
}
- pfctl_clear_pool(&rule.rpool);
+ pfctl_clear_pool(&rule.rdr);
+ pfctl_clear_pool(&rule.nat);
+ pfctl_clear_pool(&rule.route);
}
- ret = pfctl_get_rules_info(dev, &ri, PF_PASS, path);
+ ret = pfctl_get_rules_info_h(pfh, &ri, PF_PASS, path);
if (ret != 0) {
- warn("DIOCGETRULES");
+ warnc(ret, "DIOCGETRULES");
goto error;
}
for (nr = 0; nr < ri.nr; ++nr) {
- if (pfctl_get_clear_rule(dev, nr, ri.ticket, path, PF_PASS,
- &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) {
- warn("DIOCGETRULE");
+ if ((ret = pfctl_get_clear_rule_h(pfh, nr, ri.ticket, path, PF_PASS,
+ &rule, anchor_call, opts & PF_OPT_CLRRULECTRS)) != 0) {
+ warnc(ret, "DIOCGETRULE");
goto error;
}
- if (pfctl_get_pool(dev, &rule.rpool,
- nr, ri.ticket, PF_PASS, path) != 0)
+ if (pfctl_get_pool(dev, &rule.rdr,
+ nr, ri.ticket, PF_PASS, path, PF_RDR) != 0)
+ goto error;
+
+ if (pfctl_get_pool(dev, &rule.nat,
+ nr, ri.ticket, PF_PASS, path, PF_NAT) != 0)
+ goto error;
+
+ if (pfctl_get_pool(dev, &rule.route,
+ nr, ri.ticket, PF_PASS, path, PF_RT) != 0)
goto error;
switch (format) {
@@ -1259,52 +1477,58 @@ pfctl_show_rules(int dev, char *path, int opts, enum pfctl_show format,
(unsigned long long)rule.bytes[1],
(uintmax_t)rule.states_tot);
}
+
+ if (anchor_call[0] &&
+ (((p = strrchr(anchor_call, '/')) ?
+ p[1] == '_' : anchor_call[0] == '_') ||
+ opts & PF_OPT_RECURSE)) {
+ pfctl_show_rules(dev, npath, opts, format,
+ anchor_call, depth, rule.anchor_wildcard);
+ }
break;
}
case PFCTL_SHOW_RULES:
- brace = 0;
- if (rule.label[0] && (opts & PF_OPT_SHOWALL))
+ if (rule.label[0][0] && (opts & PF_OPT_SHOWALL))
labels = 1;
INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ print_rule(&rule, anchor_call, opts, numeric);
+
+ /*
+ * If this is a 'unnamed' brace notation
+ * anchor, OR the user has explicitly requested
+ * recursion, print it recursively.
+ */
if (anchor_call[0] &&
- ((((p = strrchr(anchor_call, '_')) != NULL) &&
- ((void *)p == (void *)anchor_call ||
- *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
- brace++;
- int aclen = strlen(anchor_call);
- if (anchor_call[aclen - 1] == '*')
- anchor_call[aclen - 2] = '\0';
- }
- p = &anchor_call[0];
-
- print_rule(&rule, p, rule_numbers, numeric);
- if (brace)
+ (((p = strrchr(anchor_call, '/')) ?
+ p[1] == '_' : anchor_call[0] == '_') ||
+ opts & PF_OPT_RECURSE)) {
printf(" {\n");
- else
- printf("\n");
- pfctl_print_rule_counters(&rule, opts);
- if (brace) {
- pfctl_show_rules(dev, path, opts, format,
- p, depth + 1);
+ pfctl_print_rule_counters(&rule, opts);
+ pfctl_show_rules(dev, npath, opts, format,
+ anchor_call, depth + 1,
+ rule.anchor_wildcard);
INDENT(depth, !(opts & PF_OPT_VERBOSE));
printf("}\n");
+ } else {
+ printf("\n");
+ pfctl_print_rule_counters(&rule, opts);
}
break;
case PFCTL_SHOW_NOTHING:
break;
}
- pfctl_clear_pool(&rule.rpool);
+ pfctl_clear_pool(&rule.rdr);
+ pfctl_clear_pool(&rule.nat);
}
- path[len] = '\0';
- return (0);
error:
path[len] = '\0';
- return (-1);
+ return (ret);
}
int
-pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth)
+pfctl_show_nat(int dev, const char *path, int opts, char *anchorname, int depth,
+ int wildcard)
{
struct pfctl_rules_info ri;
struct pfctl_rule rule;
@@ -1312,46 +1536,86 @@ pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth)
u_int32_t nr;
static int nattype[3] = { PF_NAT, PF_RDR, PF_BINAT };
int i, dotitle = opts & PF_OPT_SHOWALL;
- int brace, ret;
+ int ret;
int len = strlen(path);
- char *p;
+ char *npath, *p;
- if (path[0])
- snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
- else
- snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
+ /*
+ * Truncate a trailing / and * on an anchorname before searching for
+ * the ruleset, this is syntactic sugar that doesn't actually make it
+ * to the kernel.
+ */
+ if ((p = strrchr(anchorname, '/')) != NULL &&
+ p[1] == '*' && p[2] == '\0') {
+ p[0] = '\0';
+ }
+
+ if ((npath = calloc(1, MAXPATHLEN)) == NULL)
+ errx(1, "calloc");
+
+ if (anchorname[0] == '/') {
+ snprintf(npath, MAXPATHLEN, "%s", anchorname);
+ } else {
+ snprintf(npath, MAXPATHLEN, "%s", path);
+ if (npath[0])
+ snprintf(&npath[len], MAXPATHLEN - len, "/%s", anchorname);
+ else
+ snprintf(&npath[len], MAXPATHLEN - len, "%s", anchorname);
+ }
+
+ /*
+ * If this anchor was called with a wildcard path, go through
+ * the rulesets in the anchor rather than the rules.
+ */
+ if (wildcard && (opts & PF_OPT_RECURSE)) {
+ struct pfioc_ruleset prs;
+ u_int32_t mnr, nr;
+ memset(&prs, 0, sizeof(prs));
+ if ((ret = pfctl_get_rulesets(pfh, npath, &mnr)) != 0) {
+ if (ret == EINVAL)
+ fprintf(stderr, "NAT anchor '%s' "
+ "not found.\n", anchorname);
+ else
+ errx(1, "%s", pf_strerror(ret));
+ }
+
+ for (nr = 0; nr < mnr; ++nr) {
+ if ((ret = pfctl_get_ruleset(pfh, npath, nr, &prs)) != 0)
+ errx(1, "%s", pf_strerror(ret));
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("nat-anchor \"%s\" all {\n", prs.name);
+ pfctl_show_nat(dev, npath, opts,
+ prs.name, depth + 1, 0);
+ INDENT(depth, !(opts & PF_OPT_VERBOSE));
+ printf("}\n");
+ }
+ npath[len] = '\0';
+ return (0);
+ }
for (i = 0; i < 3; i++) {
- ret = pfctl_get_rules_info(dev, &ri, nattype[i], path);
+ ret = pfctl_get_rules_info_h(pfh, &ri, nattype[i], npath);
if (ret != 0) {
- warn("DIOCGETRULES");
+ warnc(ret, "DIOCGETRULES");
return (-1);
}
for (nr = 0; nr < ri.nr; ++nr) {
- brace = 0;
INDENT(depth, !(opts & PF_OPT_VERBOSE));
- if (pfctl_get_rule(dev, nr, ri.ticket, path,
- nattype[i], &rule, anchor_call)) {
- warn("DIOCGETRULE");
+ if ((ret = pfctl_get_rule_h(pfh, nr, ri.ticket, npath,
+ nattype[i], &rule, anchor_call)) != 0) {
+ warnc(ret, "DIOCGETRULE");
return (-1);
}
- if (pfctl_get_pool(dev, &rule.rpool, nr,
- ri.ticket, nattype[i], path) != 0)
+ if (pfctl_get_pool(dev, &rule.rdr, nr,
+ ri.ticket, nattype[i], npath, PF_RDR) != 0)
+ return (-1);
+ if (pfctl_get_pool(dev, &rule.nat, nr,
+ ri.ticket, nattype[i], npath, PF_NAT) != 0)
+ return (-1);
+ if (pfctl_get_pool(dev, &rule.route, nr,
+ ri.ticket, nattype[i], npath, PF_RT) != 0)
return (-1);
-
- if (anchor_call[0] &&
- ((((p = strrchr(anchor_call, '_')) != NULL) &&
- (p == anchor_call ||
- *(--p) == '/')) || (opts & PF_OPT_RECURSE))) {
- brace++;
- if ((p = strrchr(anchor_call, '/')) !=
- NULL)
- p++;
- else
- p = &anchor_call[0];
- } else
- p = &anchor_call[0];
if (dotitle) {
pfctl_print_title("TRANSLATION RULES:");
@@ -1359,90 +1623,85 @@ pfctl_show_nat(int dev, char *path, int opts, char *anchorname, int depth)
}
print_rule(&rule, anchor_call,
opts & PF_OPT_VERBOSE2, opts & PF_OPT_NUMERIC);
- if (brace)
+ if (anchor_call[0] &&
+ (((p = strrchr(anchor_call, '/')) ?
+ p[1] == '_' : anchor_call[0] == '_') ||
+ opts & PF_OPT_RECURSE)) {
printf(" {\n");
- else
- printf("\n");
- pfctl_print_rule_counters(&rule, opts);
- pfctl_clear_pool(&rule.rpool);
- if (brace) {
- pfctl_show_nat(dev, path, opts, p, depth + 1);
+ pfctl_print_rule_counters(&rule, opts);
+ pfctl_show_nat(dev, npath, opts, anchor_call,
+ depth + 1, rule.anchor_wildcard);
INDENT(depth, !(opts & PF_OPT_VERBOSE));
printf("}\n");
+ } else {
+ printf("\n");
+ pfctl_print_rule_counters(&rule, opts);
}
}
}
return (0);
}
-int
-pfctl_show_src_nodes(int dev, int opts)
+static int
+pfctl_print_src_node(struct pfctl_src_node *sn, void *arg)
{
- struct pfioc_src_nodes psn;
- struct pf_src_node *p;
- char *inbuf = NULL, *newinbuf = NULL;
- unsigned int len = 0;
- int i;
+ int *opts = (int *)arg;
- memset(&psn, 0, sizeof(psn));
- for (;;) {
- psn.psn_len = len;
- if (len) {
- newinbuf = realloc(inbuf, len);
- if (newinbuf == NULL)
- err(1, "realloc");
- psn.psn_buf = inbuf = newinbuf;
- }
- if (ioctl(dev, DIOCGETSRCNODES, &psn) < 0) {
- warn("DIOCGETSRCNODES");
- free(inbuf);
- return (-1);
- }
- if (psn.psn_len + sizeof(struct pfioc_src_nodes) < len)
- break;
- if (len == 0 && psn.psn_len == 0)
- goto done;
- if (len == 0 && psn.psn_len != 0)
- len = psn.psn_len;
- if (psn.psn_len == 0)
- goto done; /* no src_nodes */
- len *= 2;
- }
- p = psn.psn_src_nodes;
- if (psn.psn_len > 0 && (opts & PF_OPT_SHOWALL))
+ if (*opts & PF_OPT_SHOWALL) {
pfctl_print_title("SOURCE TRACKING NODES:");
- for (i = 0; i < psn.psn_len; i += sizeof(*p)) {
- print_src_node(p, opts);
- p++;
+ *opts &= ~PF_OPT_SHOWALL;
}
-done:
- free(inbuf);
+
+ print_src_node(sn, *opts);
+
return (0);
}
int
-pfctl_show_states(int dev, const char *iface, int opts)
+pfctl_show_src_nodes(int dev, int opts)
{
- struct pfctl_states states;
- struct pfctl_state *s;
- int dotitle = (opts & PF_OPT_SHOWALL);
+ int error;
- memset(&states, 0, sizeof(states));
+ error = pfctl_get_srcnodes(pfh, pfctl_print_src_node, &opts);
- if (pfctl_get_states(dev, &states))
- return (-1);
+ return (error);
+}
- TAILQ_FOREACH(s, &states.states, entry) {
- if (iface != NULL && strcmp(s->ifname, iface))
- continue;
- if (dotitle) {
- pfctl_print_title("STATES:");
- dotitle = 0;
- }
- print_state(s, opts);
+struct pfctl_show_state_arg {
+ int opts;
+ int dotitle;
+ const char *iface;
+};
+
+static int
+pfctl_show_state(struct pfctl_state *s, void *arg)
+{
+ struct pfctl_show_state_arg *a = (struct pfctl_show_state_arg *)arg;
+
+ if (a->dotitle) {
+ pfctl_print_title("STATES:");
+ a->dotitle = 0;
}
+ print_state(s, a->opts);
+
+ return (0);
+}
+
+int
+pfctl_show_states(int dev, const char *iface, int opts)
+{
+ struct pfctl_show_state_arg arg;
+ struct pfctl_state_filter filter = {};
- pfctl_free_states(&states);
+ if (iface != NULL)
+ strlcpy(filter.ifname, iface, IFNAMSIZ);
+
+ arg.opts = opts;
+ arg.dotitle = opts & PF_OPT_SHOWALL;
+ arg.iface = iface;
+
+ if (pfctl_get_filtered_states_iter(&filter, pfctl_show_state, &arg))
+ return (-1);
return (0);
}
@@ -1452,14 +1711,15 @@ pfctl_show_status(int dev, int opts)
{
struct pfctl_status *status;
struct pfctl_syncookies cookies;
+ int ret;
- if ((status = pfctl_get_status(dev)) == NULL) {
+ if ((status = pfctl_get_status_h(pfh)) == NULL) {
warn("DIOCGETSTATUS");
return (-1);
}
- if (pfctl_get_syncookies(dev, &cookies)) {
+ if ((ret = pfctl_get_syncookies(dev, &cookies)) != 0) {
pfctl_free_status(status);
- warn("DIOCGETSYNCOOKIES");
+ warnc(ret, "DIOCGETSYNCOOKIES");
return (-1);
}
if (opts & PF_OPT_SHOWALL)
@@ -1475,7 +1735,7 @@ pfctl_show_running(int dev)
struct pfctl_status *status;
int running;
- if ((status = pfctl_get_status(dev)) == NULL) {
+ if ((status = pfctl_get_status_h(pfh)) == NULL) {
warn("DIOCGETSTATUS");
return (-1);
}
@@ -1490,17 +1750,16 @@ pfctl_show_running(int dev)
int
pfctl_show_timeouts(int dev, int opts)
{
- struct pfioc_tm pt;
+ uint32_t seconds;
int i;
+ int ret;
if (opts & PF_OPT_SHOWALL)
pfctl_print_title("TIMEOUTS:");
- memset(&pt, 0, sizeof(pt));
for (i = 0; pf_timeouts[i].name; i++) {
- pt.timeout = pf_timeouts[i].timeout;
- if (ioctl(dev, DIOCGETTIMEOUT, &pt))
- err(1, "DIOCGETTIMEOUT");
- printf("%-20s %10d", pf_timeouts[i].name, pt.seconds);
+ if ((ret = pfctl_get_timeout(pfh, pf_timeouts[i].timeout, &seconds)) != 0)
+ errc(1, ret, "DIOCGETTIMEOUT");
+ printf("%-20s %10d", pf_timeouts[i].name, seconds);
if (pf_timeouts[i].timeout >= PFTM_ADAPTIVE_START &&
pf_timeouts[i].timeout <= PFTM_ADAPTIVE_END)
printf(" states");
@@ -1515,55 +1774,98 @@ pfctl_show_timeouts(int dev, int opts)
int
pfctl_show_limits(int dev, int opts)
{
- struct pfioc_limit pl;
+ unsigned int limit;
int i;
+ int ret;
if (opts & PF_OPT_SHOWALL)
pfctl_print_title("LIMITS:");
- memset(&pl, 0, sizeof(pl));
for (i = 0; pf_limits[i].name; i++) {
- pl.index = pf_limits[i].index;
- if (ioctl(dev, DIOCGETLIMIT, &pl))
- err(1, "DIOCGETLIMIT");
+ if ((ret = pfctl_get_limit(pfh, pf_limits[i].index, &limit)) != 0)
+ errc(1, ret, "DIOCGETLIMIT");
printf("%-13s ", pf_limits[i].name);
- if (pl.limit == UINT_MAX)
+ if (limit == UINT_MAX)
printf("unlimited\n");
else
- printf("hard limit %8u\n", pl.limit);
+ printf("hard limit %8u\n", limit);
}
return (0);
}
-/* callbacks for rule/nat/rdr/addr */
-int
-pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af)
+void
+pfctl_read_limits(struct pfctl_handle *h)
{
- struct pf_pooladdr *pa;
+ int i;
- if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
- err(1, "DIOCBEGINADDRS");
+ for (i = 0; pf_limits[i].name; i++) {
+ if (pfctl_get_limit(h, i, &limit_curr[i]))
+ err(1, "DIOCGETLIMIT");
}
+}
+
+void
+pfctl_restore_limits(void)
+{
+ int i;
+
+ if (pfh == NULL)
+ return;
+
+ for (i = 0; pf_limits[i].name; i++) {
+ if (pfctl_set_limit(pfh, i, limit_curr[i]))
+ warn("DIOCSETLIMIT (%s)", pf_limits[i].name);
+ }
+}
+
+void
+pfctl_show_creators(int opts)
+{
+ int ret;
+ uint32_t creators[16];
+ size_t count = nitems(creators);
+
+ ret = pfctl_get_creatorids(pfh, creators, &count);
+ if (ret != 0)
+ errx(ret, "Failed to retrieve creators");
+
+ printf("Creator IDs:\n");
+ for (size_t i = 0; i < count; i++)
+ printf("%08x\n", creators[i]);
+}
+
+/* callbacks for rule/nat/rdr/addr */
+int
+pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, int which)
+{
+ struct pfctl_pooladdr *pa;
+ int ret;
- pf->paddr.af = af;
TAILQ_FOREACH(pa, &p->list, entries) {
- memcpy(&pf->paddr.addr, pa, sizeof(struct pf_pooladdr));
+ memcpy(&pf->paddr.addr, pa, sizeof(struct pfctl_pooladdr));
+ pf->paddr.af = pa->af;
if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (ioctl(pf->dev, DIOCADDADDR, &pf->paddr))
- err(1, "DIOCADDADDR");
+ if ((ret = pfctl_add_addr(pf->h, &pf->paddr, which)) != 0)
+ errc(1, ret, "DIOCADDADDR");
}
}
return (0);
}
-int
-pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r,
- const char *anchor_call)
+void
+pfctl_init_rule(struct pfctl_rule *r)
+{
+ memset(r, 0, sizeof(struct pfctl_rule));
+ TAILQ_INIT(&(r->rdr.list));
+ TAILQ_INIT(&(r->nat.list));
+ TAILQ_INIT(&(r->route.list));
+}
+
+void
+pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r)
{
u_int8_t rs_num;
struct pfctl_rule *rule;
struct pfctl_ruleset *rs;
- char *p;
rs_num = pf_get_ruleset_number(r->action);
if (rs_num == PF_RULESET_MAX)
@@ -1571,37 +1873,17 @@ pfctl_append_rule(struct pfctl *pf, struct pfctl_rule *r,
rs = &pf->anchor->ruleset;
- if (anchor_call[0] && r->anchor == NULL) {
- /*
- * Don't make non-brace anchors part of the main anchor pool.
- */
- if ((r->anchor = calloc(1, sizeof(*r->anchor))) == NULL)
- err(1, "pfctl_append_rule: calloc");
-
- pf_init_ruleset(&r->anchor->ruleset);
- r->anchor->ruleset.anchor = r->anchor;
- if (strlcpy(r->anchor->path, anchor_call,
- sizeof(rule->anchor->path)) >= sizeof(rule->anchor->path))
- errx(1, "pfctl_append_rule: strlcpy");
- if ((p = strrchr(anchor_call, '/')) != NULL) {
- if (!strlen(p))
- err(1, "pfctl_append_rule: bad anchor name %s",
- anchor_call);
- } else
- p = (char *)anchor_call;
- if (strlcpy(r->anchor->name, p,
- sizeof(rule->anchor->name)) >= sizeof(rule->anchor->name))
- errx(1, "pfctl_append_rule: strlcpy");
- }
-
if ((rule = calloc(1, sizeof(*rule))) == NULL)
err(1, "calloc");
bcopy(r, rule, sizeof(*rule));
- TAILQ_INIT(&rule->rpool.list);
- pfctl_move_pool(&r->rpool, &rule->rpool);
+ TAILQ_INIT(&rule->rdr.list);
+ pfctl_move_pool(&r->rdr, &rule->rdr);
+ TAILQ_INIT(&rule->nat.list);
+ pfctl_move_pool(&r->nat, &rule->nat);
+ TAILQ_INIT(&rule->route.list);
+ pfctl_move_pool(&r->route, &rule->route);
TAILQ_INSERT_TAIL(rs->rules[rs_num].active.ptr, rule, entries);
- return (0);
}
int
@@ -1759,6 +2041,7 @@ pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r,
char *name;
char anchor[PF_ANCHOR_NAME_SIZE];
int len = strlen(path);
+ int ret;
if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor))
errx(1, "pfctl_load_eth_rule: strlcpy");
@@ -1778,9 +2061,9 @@ pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r,
name = "";
if ((pf->opts & PF_OPT_NOACTION) == 0)
- if (pfctl_add_eth_rule(pf->dev, r, anchor, name,
- pf->eth_ticket))
- err(1, "DIOCADDETHRULENV");
+ if ((ret = pfctl_add_eth_rule(pf->dev, r, anchor, name,
+ pf->eth_ticket)) != 0)
+ errc(1, ret, "DIOCADDETHRULENV");
if (pf->opts & PF_OPT_VERBOSE) {
INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
@@ -1793,6 +2076,41 @@ pfctl_load_eth_rule(struct pfctl *pf, char *path, struct pfctl_eth_rule *r,
return (0);
}
+static int
+pfctl_load_tables(struct pfctl *pf, char *path, struct pfctl_anchor *a,
+ int rs_num)
+{
+ struct pfr_ktable *kt, *ktw;
+ struct pfr_uktable *ukt;
+ char anchor_path[PF_ANCHOR_MAXPATH];
+ int e;
+
+ RB_FOREACH_SAFE(kt, pfr_ktablehead, &pfr_ktables, ktw) {
+ if (strcmp(kt->pfrkt_anchor, a->path) != 0)
+ continue;
+
+ if (path != NULL && *path) {
+ strlcpy(anchor_path, kt->pfrkt_anchor,
+ sizeof(anchor_path));
+ snprintf(kt->pfrkt_anchor, PF_ANCHOR_MAXPATH, "%s/%s",
+ path, anchor_path);
+ }
+ ukt = (struct pfr_uktable *)kt;
+ e = pfr_ina_define(&ukt->pfrukt_t, ukt->pfrukt_addrs.pfrb_caddr,
+ ukt->pfrukt_addrs.pfrb_size, NULL, NULL,
+ pf->anchor->ruleset.tticket,
+ ukt->pfrukt_init_addr ? PFR_FLAG_ADDRSTOO : 0);
+ if (e != 0)
+ err(1, "%s pfr_ina_define() %s@%s", __func__,
+ kt->pfrkt_name, kt->pfrkt_anchor);
+ RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt);
+ pfr_buf_clear(&ukt->pfrukt_addrs);
+ free(ukt);
+ }
+
+ return (0);
+}
+
int
pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs,
int rs_num, int depth)
@@ -1816,13 +2134,12 @@ pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs,
if ((pf->opts & PF_OPT_NOACTION) == 0 &&
(error = pfctl_ruleset_trans(pf,
path, rs->anchor, false))) {
- printf("pfctl_load_rulesets: "
- "pfctl_ruleset_trans %d\n", error);
+ printf("%s: "
+ "pfctl_ruleset_trans %d\n", __func__, error);
goto error;
}
} else if (pf->opts & PF_OPT_VERBOSE)
printf("\n");
-
}
if (pf->optimize && rs_num == PF_RULESET_FILTER)
@@ -1842,6 +2159,8 @@ pfctl_load_ruleset(struct pfctl *pf, char *path, struct pfctl_ruleset *rs,
if ((error = pfctl_load_ruleset(pf, path,
&r->anchor->ruleset, rs_num, depth + 1)))
goto error;
+ if ((error = pfctl_load_tables(pf, path, r->anchor, rs_num)))
+ goto error;
} else if (pf->opts & PF_OPT_VERBOSE)
printf("\n");
free(r);
@@ -1864,15 +2183,20 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth)
{
u_int8_t rs_num = pf_get_ruleset_number(r->action);
char *name;
- u_int32_t ticket;
+ uint32_t ticket;
char anchor[PF_ANCHOR_NAME_SIZE];
int len = strlen(path);
int error;
bool was_present;
/* set up anchor before adding to path for anchor_call */
- if ((pf->opts & PF_OPT_NOACTION) == 0)
+ if ((pf->opts & PF_OPT_NOACTION) == 0) {
+ if (pf->trans == NULL)
+ errx(1, "pfctl_load_rule: no transaction");
ticket = pfctl_get_ticket(pf->trans, rs_num, path);
+ if (rs_num == PF_RULESET_FILTER)
+ pf->anchor->ruleset.tticket = ticket;
+ }
if (strlcpy(anchor, path, sizeof(anchor)) >= sizeof(anchor))
errx(1, "pfctl_load_rule: strlcpy");
@@ -1892,9 +2216,19 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth)
was_present = false;
if ((pf->opts & PF_OPT_NOACTION) == 0) {
- if (pfctl_add_pool(pf, &r->rpool, r->af))
+ if ((pf->opts & PF_OPT_NOACTION) == 0) {
+ if ((error = pfctl_begin_addrs(pf->h,
+ &pf->paddr.ticket)) != 0)
+ errc(1, error, "DIOCBEGINADDRS");
+ }
+
+ if (pfctl_add_pool(pf, &r->rdr, PF_RDR))
+ return (1);
+ if (pfctl_add_pool(pf, &r->nat, PF_NAT))
return (1);
- error = pfctl_add_rule(pf->dev, r, anchor, name, ticket,
+ if (pfctl_add_pool(pf, &r->route, PF_RT))
+ return (1);
+ error = pfctl_add_rule_h(pf->h, r, anchor, name, ticket,
pf->paddr.ticket);
switch (error) {
case 0:
@@ -1905,20 +2239,21 @@ pfctl_load_rule(struct pfctl *pf, char *path, struct pfctl_rule *r, int depth)
was_present = true;
break;
default:
- err(1, "DIOCADDRULENV");
+ errc(1, error, "DIOCADDRULE");
}
}
if (pf->opts & PF_OPT_VERBOSE) {
INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
- print_rule(r, r->anchor ? r->anchor->name : "",
+ print_rule(r, name,
pf->opts & PF_OPT_VERBOSE2,
pf->opts & PF_OPT_NUMERIC);
if (was_present)
printf(" -- rule was already present");
}
path[len] = '\0';
- pfctl_clear_pool(&r->rpool);
+ pfctl_clear_pool(&r->rdr);
+ pfctl_clear_pool(&r->nat);
return (0);
}
@@ -1948,8 +2283,8 @@ int
pfctl_rules(int dev, char *filename, int opts, int optimize,
char *anchorname, struct pfr_buffer *trans)
{
-#define ERR(x) do { warn(x); goto _error; } while(0)
-#define ERRX(x) do { warnx(x); goto _error; } while(0)
+#define ERR(...) do { warn(__VA_ARGS__); goto _error; } while(0)
+#define ERRX(...) do { warnx(__VA_ARGS__); goto _error; } while(0)
struct pfr_buffer *t, buf;
struct pfioc_altq pa;
@@ -1957,12 +2292,14 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
struct pfctl_ruleset *rs;
struct pfctl_eth_ruleset *ethrs;
struct pfr_table trs;
- char *path;
+ char *path = NULL;
int osize;
RB_INIT(&pf_anchors);
memset(&pf_main_anchor, 0, sizeof(pf_main_anchor));
pf_init_ruleset(&pf_main_anchor.ruleset);
+ memset(&pf, 0, sizeof(pf));
+ memset(&trs, 0, sizeof(trs));
pf_main_anchor.ruleset.anchor = &pf_main_anchor;
memset(&pf_eth_main_anchor, 0, sizeof(pf_eth_main_anchor));
@@ -1972,6 +2309,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
if (trans == NULL) {
bzero(&buf, sizeof(buf));
buf.pfrb_type = PFRB_TRANS;
+ pf.trans = &buf;
t = &buf;
osize = 0;
} else {
@@ -1984,27 +2322,28 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
memset(&pf, 0, sizeof(pf));
memset(&trs, 0, sizeof(trs));
if ((path = calloc(1, MAXPATHLEN)) == NULL)
- ERRX("pfctl_rules: calloc");
+ ERRX("%s: calloc", __func__);
if (strlcpy(trs.pfrt_anchor, anchorname,
sizeof(trs.pfrt_anchor)) >= sizeof(trs.pfrt_anchor))
- ERRX("pfctl_rules: strlcpy");
+ ERRX("%s: strlcpy", __func__);
pf.dev = dev;
+ pf.h = pfh;
pf.opts = opts;
pf.optimize = optimize;
pf.loadopt = loadopt;
/* non-brace anchor, create without resolving the path */
if ((pf.anchor = calloc(1, sizeof(*pf.anchor))) == NULL)
- ERRX("pfctl_rules: calloc");
+ ERRX("%s: calloc", __func__);
rs = &pf.anchor->ruleset;
pf_init_ruleset(rs);
rs->anchor = pf.anchor;
if (strlcpy(pf.anchor->path, anchorname,
sizeof(pf.anchor->path)) >= sizeof(pf.anchor->path))
- errx(1, "pfctl_rules: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(pf.anchor->name, anchorname,
sizeof(pf.anchor->name)) >= sizeof(pf.anchor->name))
- errx(1, "pfctl_rules: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
pf.astack[0] = pf.anchor;
@@ -2017,14 +2356,14 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
/* Set up ethernet anchor */
if ((pf.eanchor = calloc(1, sizeof(*pf.eanchor))) == NULL)
- ERRX("pfctl_rules: calloc");
+ ERRX("%s: calloc", __func__);
if (strlcpy(pf.eanchor->path, anchorname,
sizeof(pf.eanchor->path)) >= sizeof(pf.eanchor->path))
- errx(1, "pfctl_rules: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
if (strlcpy(pf.eanchor->name, anchorname,
sizeof(pf.eanchor->name)) >= sizeof(pf.eanchor->name))
- errx(1, "pfctl_rules: strlcpy");
+ errx(1, "%s: strlcpy", __func__);
ethrs = &pf.eanchor->ruleset;
pf_init_eth_ruleset(ethrs);
@@ -2038,7 +2377,7 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
* loaded at parse time.
*/
if (pfctl_ruleset_trans(&pf, anchorname, pf.anchor, true))
- ERRX("pfctl_rules");
+ ERRX("%s", __func__);
if (pf.loadopt & PFCTL_FLAG_ETH)
pf.eth_ticket = pfctl_get_ticket(t, PF_RULESET_ETH, anchorname);
if (altqsupport && (pf.loadopt & PFCTL_FLAG_ALTQ))
@@ -2079,17 +2418,17 @@ pfctl_rules(int dev, char *filename, int opts, int optimize,
if (check_commit_altq(dev, opts) != 0)
ERRX("errors in altq config");
- /* process "load anchor" directives */
- if (!anchorname[0])
- if (pfctl_load_anchors(dev, &pf, t) == -1)
+ if (trans == NULL) {
+ /* process "load anchor" directives */
+ if (pfctl_load_anchors(dev, &pf) == -1)
ERRX("load anchors");
- if (trans == NULL && (opts & PF_OPT_NOACTION) == 0) {
- if (!anchorname[0])
- if (pfctl_load_options(&pf))
+ if ((opts & PF_OPT_NOACTION) == 0) {
+ if (!anchorname[0] && pfctl_load_options(&pf))
goto _error;
- if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
- ERR("DIOCXCOMMIT");
+ if (pfctl_trans(dev, t, DIOCXCOMMIT, osize))
+ ERR("DIOCXCOMMIT");
+ }
}
free(path);
return (0);
@@ -2140,6 +2479,11 @@ pfctl_init_options(struct pfctl *pf)
pf->timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
pf->timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
pf->timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
+ pf->timeout[PFTM_SCTP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
+ pf->timeout[PFTM_SCTP_OPENING] = PFTM_TCP_OPENING_VAL;
+ pf->timeout[PFTM_SCTP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
+ pf->timeout[PFTM_SCTP_CLOSING] = PFTM_TCP_CLOSING_VAL;
+ pf->timeout[PFTM_SCTP_CLOSED] = PFTM_TCP_CLOSED_VAL;
pf->timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
pf->timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
pf->timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
@@ -2157,10 +2501,17 @@ pfctl_init_options(struct pfctl *pf)
pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
- pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
- pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
+
+ pf->limit[PF_LIMIT_SRC_NODES] = (limit_curr[PF_LIMIT_SRC_NODES] == 0) ?
+ PFSNODE_HIWAT : limit_curr[PF_LIMIT_SRC_NODES];
+ pf->limit[PF_LIMIT_TABLE_ENTRIES] =
+ (limit_curr[PF_LIMIT_TABLE_ENTRIES] == 0) ?
+ PFR_KENTRY_HIWAT : limit_curr[PF_LIMIT_TABLE_ENTRIES];
+ pf->limit[PF_LIMIT_ANCHORS] = (limit_curr[PF_LIMIT_ANCHORS] == 0) ?
+ PF_ANCHOR_HIWAT : limit_curr[PF_LIMIT_ANCHORS];
pf->debug = PF_DEBUG_URGENT;
+ pf->reassemble = 0;
pf->syncookies = false;
pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT;
@@ -2184,7 +2535,7 @@ pfctl_load_options(struct pfctl *pf)
}
/*
- * If we've set the limit, but haven't explicitly set adaptive
+ * If we've set the states limit, but haven't explicitly set adaptive
* timeouts, do it now with a start of 60% and end of 120%.
*/
if (pf->limit_set[PF_LIMIT_STATES] &&
@@ -2221,6 +2572,11 @@ pfctl_load_options(struct pfctl *pf)
if (pfctl_load_hostid(pf, pf->hostid))
error = 1;
+ /* load reassembly settings */
+ if (!(pf->opts & PF_OPT_MERGE) || pf->reass_set)
+ if (pfctl_load_reassembly(pf, pf->reassemble))
+ error = 1;
+
/* load keepcounters */
if (pfctl_set_keepcounters(pf->dev, pf->keep_counters))
error = 1;
@@ -2233,7 +2589,7 @@ pfctl_load_options(struct pfctl *pf)
}
int
-pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
+pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit)
{
int i;
@@ -2253,29 +2609,29 @@ pfctl_set_limit(struct pfctl *pf, const char *opt, unsigned int limit)
if (pf->opts & PF_OPT_VERBOSE)
printf("set limit %s %d\n", opt, limit);
+ if ((pf->opts & PF_OPT_NOACTION) == 0)
+ pfctl_load_options(pf);
+
return (0);
}
int
pfctl_load_limit(struct pfctl *pf, unsigned int index, unsigned int limit)
{
- struct pfioc_limit pl;
-
- memset(&pl, 0, sizeof(pl));
- pl.index = index;
- pl.limit = limit;
- if (ioctl(pf->dev, DIOCSETLIMIT, &pl)) {
+ if (pfctl_set_limit(pf->h, index, limit)) {
if (errno == EBUSY)
- warnx("Current pool size exceeds requested hard limit");
+ warnx("Current pool size exceeds requested %s limit %u",
+ pf_limits[index].name, limit);
else
- warnx("DIOCSETLIMIT");
+ warnx("Cannot set %s limit to %u",
+ pf_limits[index].name, limit);
return (1);
}
return (0);
}
int
-pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
+pfctl_apply_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
{
int i;
@@ -2305,12 +2661,7 @@ pfctl_set_timeout(struct pfctl *pf, const char *opt, int seconds, int quiet)
int
pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
{
- struct pfioc_tm pt;
-
- memset(&pt, 0, sizeof(pt));
- pt.timeout = timeout;
- pt.seconds = seconds;
- if (ioctl(pf->dev, DIOCSETTIMEOUT, &pt)) {
+ if (pfctl_set_timeout(pf->h, timeout, seconds)) {
warnx("DIOCSETTIMEOUT");
return (1);
}
@@ -2318,6 +2669,28 @@ pfctl_load_timeout(struct pfctl *pf, unsigned int timeout, unsigned int seconds)
}
int
+pfctl_set_reassembly(struct pfctl *pf, int on, int nodf)
+{
+ if ((loadopt & PFCTL_FLAG_OPTION) == 0)
+ return (0);
+
+ pf->reass_set = 1;
+ if (on) {
+ pf->reassemble = PF_REASS_ENABLED;
+ if (nodf)
+ pf->reassemble |= PF_REASS_NODF;
+ } else {
+ pf->reassemble = 0;
+ }
+
+ if (pf->opts & PF_OPT_VERBOSE)
+ printf("set reassemble %s %s\n", on ? "yes" : "no",
+ nodf ? "no-df" : "");
+
+ return (0);
+}
+
+int
pfctl_set_optimization(struct pfctl *pf, const char *opt)
{
const struct pf_hint *hint;
@@ -2337,7 +2710,7 @@ pfctl_set_optimization(struct pfctl *pf, const char *opt)
}
for (i = 0; hint[i].name; i++)
- if ((r = pfctl_set_timeout(pf, hint[i].name,
+ if ((r = pfctl_apply_timeout(pf, hint[i].name,
hint[i].timeout, 1)))
return (r);
@@ -2373,26 +2746,18 @@ pfctl_set_logif(struct pfctl *pf, char *ifname)
int
pfctl_load_logif(struct pfctl *pf, char *ifname)
{
- struct pfioc_if pi;
-
- memset(&pi, 0, sizeof(pi));
- if (ifname && strlcpy(pi.ifname, ifname,
- sizeof(pi.ifname)) >= sizeof(pi.ifname)) {
+ if (ifname != NULL && strlen(ifname) >= IFNAMSIZ) {
warnx("pfctl_load_logif: strlcpy");
return (1);
}
- if (ioctl(pf->dev, DIOCSETSTATUSIF, &pi)) {
- warnx("DIOCSETSTATUSIF");
- return (1);
- }
- return (0);
+ return (pfctl_set_statusif(pfh, ifname ? ifname : ""));
}
-int
+void
pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
{
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
- return (0);
+ return;
HTONL(hostid);
@@ -2401,8 +2766,6 @@ pfctl_set_hostid(struct pfctl *pf, u_int32_t hostid)
if (pf->opts & PF_OPT_VERBOSE)
printf("set hostid 0x%08x\n", ntohl(hostid));
-
- return (0);
}
int
@@ -2416,6 +2779,16 @@ pfctl_load_hostid(struct pfctl *pf, u_int32_t hostid)
}
int
+pfctl_load_reassembly(struct pfctl *pf, u_int32_t reassembly)
+{
+ if (ioctl(dev, DIOCSETREASS, &reassembly)) {
+ warnx("DIOCSETREASS");
+ return (1);
+ }
+ return (0);
+}
+
+int
pfctl_load_syncookies(struct pfctl *pf, u_int8_t val)
{
struct pfctl_syncookies cookies;
@@ -2477,9 +2850,10 @@ pfctl_cfg_syncookies(struct pfctl *pf, uint8_t val, struct pfctl_watermarks *w)
}
int
-pfctl_set_debug(struct pfctl *pf, char *d)
+pfctl_do_set_debug(struct pfctl *pf, char *d)
{
u_int32_t level;
+ int ret;
if ((loadopt & PFCTL_FLAG_OPTION) == 0)
return (0);
@@ -2501,8 +2875,8 @@ pfctl_set_debug(struct pfctl *pf, char *d)
level = pf->debug;
if ((pf->opts & PF_OPT_NOACTION) == 0)
- if (ioctl(dev, DIOCSETDEBUG, &level))
- err(1, "DIOCSETDEBUG");
+ if ((ret = pfctl_set_debug(pfh, level)) != 0)
+ errc(1, ret, "DIOCSETDEBUG");
if (pf->opts & PF_OPT_VERBOSE)
printf("set debug %s\n", d);
@@ -2513,7 +2887,7 @@ pfctl_set_debug(struct pfctl *pf, char *d)
int
pfctl_load_debug(struct pfctl *pf, unsigned int level)
{
- if (ioctl(pf->dev, DIOCSETDEBUG, &level)) {
+ if (pfctl_set_debug(pf->h, level)) {
warnx("DIOCSETDEBUG");
return (1);
}
@@ -2546,7 +2920,7 @@ pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
if ((pf->opts & PF_OPT_NOACTION) == 0) {
if (how == 0) {
if (ioctl(pf->dev, DIOCCLRIFFLAG, &pi))
- err(1, "DIOCCLRIFFLAG");
+ pfctl_err(pf->opts, 1, "DIOCCLRIFFLAG");
} else {
if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
err(1, "DIOCSETIFFLAG");
@@ -2559,8 +2933,10 @@ pfctl_set_interface_flags(struct pfctl *pf, char *ifname, int flags, int how)
void
pfctl_debug(int dev, u_int32_t level, int opts)
{
- if (ioctl(dev, DIOCSETDEBUG, &level))
- err(1, "DIOCSETDEBUG");
+ int ret;
+
+ if ((ret = pfctl_set_debug(pfh, level)) != 0)
+ errc(1, ret, "DIOCSETDEBUG");
if ((opts & PF_OPT_QUIET) == 0) {
fprintf(stderr, "debug level set to '");
switch (level) {
@@ -2603,45 +2979,187 @@ pfctl_test_altqsupport(int dev, int opts)
}
int
-pfctl_show_anchors(int dev, int opts, char *anchorname)
+pfctl_walk_show(int opts, struct pfioc_ruleset *pr, void *warg)
+{
+ if (pr->path[0]) {
+ if (pr->path[0] != '_' || (opts & PF_OPT_VERBOSE))
+ printf(" %s/%s\n", pr->path, pr->name);
+ } else if (pr->name[0] != '_' || (opts & PF_OPT_VERBOSE))
+ printf(" %s\n", pr->name);
+
+ return (0);
+}
+
+int
+pfctl_walk_get(int opts, struct pfioc_ruleset *pr, void *warg)
+{
+ struct pfr_anchoritem *pfra;
+ struct pfr_anchors *anchors;
+ int e;
+
+ anchors = (struct pfr_anchors *)warg;
+
+ pfra = malloc(sizeof(*pfra));
+ if (pfra == NULL)
+ err(1, "%s", __func__);
+
+ if (pr->path[0])
+ e = asprintf(&pfra->pfra_anchorname, "%s/%s", pr->path,
+ pr->name);
+ else
+ e = asprintf(&pfra->pfra_anchorname, "%s", pr->name);
+
+ if (e == -1)
+ err(1, "%s", __func__);
+
+ SLIST_INSERT_HEAD(anchors, pfra, pfra_sle);
+
+ return (0);
+}
+
+int
+pfctl_walk_anchors(int dev, int opts, const char *anchor,
+ int(walkf)(int, struct pfioc_ruleset *, void *), void *warg)
{
struct pfioc_ruleset pr;
u_int32_t mnr, nr;
+ int ret;
memset(&pr, 0, sizeof(pr));
- memcpy(pr.path, anchorname, sizeof(pr.path));
- if (ioctl(dev, DIOCGETRULESETS, &pr)) {
- if (errno == EINVAL)
- fprintf(stderr, "Anchor '%s' not found.\n",
- anchorname);
- else
- err(1, "DIOCGETRULESETS");
- return (-1);
- }
- mnr = pr.nr;
+ if ((ret = pfctl_get_rulesets(pfh, anchor, &mnr)) != 0)
+ errx(1, "%s", pf_strerror(ret));
for (nr = 0; nr < mnr; ++nr) {
char sub[MAXPATHLEN];
- pr.nr = nr;
- if (ioctl(dev, DIOCGETRULESET, &pr))
- err(1, "DIOCGETRULESET");
+ if ((ret = pfctl_get_ruleset(pfh, anchor, nr, &pr)) != 0)
+ errc(1, ret, "DIOCGETRULESET");
if (!strcmp(pr.name, PF_RESERVED_ANCHOR))
continue;
- sub[0] = 0;
- if (pr.path[0]) {
- strlcat(sub, pr.path, sizeof(sub));
- strlcat(sub, "/", sizeof(sub));
- }
- strlcat(sub, pr.name, sizeof(sub));
- if (sub[0] != '_' || (opts & PF_OPT_VERBOSE))
- printf(" %s\n", sub);
- if ((opts & PF_OPT_VERBOSE) && pfctl_show_anchors(dev, opts, sub))
+ sub[0] = '\0';
+ if (walkf(opts, &pr, warg))
+ return (-1);
+
+ if (pr.path[0])
+ snprintf(sub, sizeof(sub), "%s/%s", pr.path, pr.name);
+ else
+ snprintf(sub, sizeof(sub), "%s", pr.name);
+ if (pfctl_walk_anchors(dev, opts, sub, walkf, warg))
return (-1);
}
return (0);
}
int
+pfctl_show_anchors(int dev, int opts, char *anchor)
+{
+ return (
+ pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_show, NULL));
+}
+
+struct pfr_anchors *
+pfctl_get_anchors(int dev, const char *anchor, int opts)
+{
+ struct pfioc_ruleset pr;
+ static struct pfr_anchors anchors;
+ char anchorbuf[PATH_MAX];
+ char *n;
+
+ SLIST_INIT(&anchors);
+
+ memset(&pr, 0, sizeof(pr));
+ if (*anchor != '\0') {
+ strlcpy(anchorbuf, anchor, sizeof(anchorbuf));
+ n = dirname(anchorbuf);
+ if (n[0] != '.' && n[1] != '\0')
+ strlcpy(pr.path, n, sizeof(pr.path));
+ strlcpy(anchorbuf, anchor, sizeof(anchorbuf));
+ n = basename(anchorbuf);
+ if (n != NULL)
+ strlcpy(pr.name, n, sizeof(pr.name));
+ }
+
+ /* insert a root anchor first. */
+ pfctl_walk_get(opts, &pr, &anchors);
+
+ if (pfctl_walk_anchors(dev, opts, anchor, pfctl_walk_get, &anchors))
+ errx(1, "%s failed to retrieve list of anchors, can't continue",
+ __func__);
+
+ return (&anchors);
+}
+
+int
+pfctl_call_cleartables(int dev, int opts, struct pfr_anchoritem *pfra)
+{
+ /*
+ * PF_OPT_QUIET makes pfctl_clear_tables() to stop printing number of
+ * tables cleared for given anchor.
+ */
+ opts |= PF_OPT_QUIET;
+ return ((pfctl_do_clear_tables(pfra->pfra_anchorname, opts) == -1) ?
+ 1 : 0);
+}
+
+int
+pfctl_call_clearrules(int dev, int opts, struct pfr_anchoritem *pfra)
+{
+ /*
+ * PF_OPT_QUIET makes pfctl_clear_rules() to stop printing a 'rules
+ * cleared' message for every anchor it deletes.
+ */
+ opts |= PF_OPT_QUIET;
+ return (pfctl_flush_rules(dev, opts, pfra->pfra_anchorname));
+}
+
+int
+pfctl_call_clearanchors(int dev, int opts, struct pfr_anchoritem *pfra)
+{
+ int rv = 0;
+
+ rv |= pfctl_call_cleartables(dev, opts, pfra);
+ rv |= pfctl_call_clearrules(dev, opts, pfra);
+
+ return (rv);
+}
+
+int
+pfctl_call_showtables(int dev, int opts, struct pfr_anchoritem *pfra)
+{
+ pfctl_show_tables(pfra->pfra_anchorname, opts);
+ return (0);
+}
+
+int
+pfctl_recurse(int dev, int opts, const char *anchorname,
+ int(*walkf)(int, int, struct pfr_anchoritem *))
+{
+ int rv = 0;
+ struct pfr_anchors *anchors;
+ struct pfr_anchoritem *pfra, *pfra_save;
+
+ anchors = pfctl_get_anchors(dev, anchorname, opts);
+ /*
+ * While traversing the list, pfctl_clear_*() must always return
+ * so that failures on one anchor do not prevent clearing others.
+ */
+ opts |= PF_OPT_IGNFAIL;
+ if ((opts & PF_OPT_CALLSHOW) == 0)
+ printf("Removing:\n");
+ SLIST_FOREACH_SAFE(pfra, anchors, pfra_sle, pfra_save) {
+ if ((opts & PF_OPT_CALLSHOW) == 0)
+ printf(" %s\n",
+ (*pfra->pfra_anchorname == '\0') ? "/" :
+ pfra->pfra_anchorname);
+ rv |= walkf(dev, opts, pfra);
+ SLIST_REMOVE(anchors, pfra, pfr_anchoritem, pfra_sle);
+ free(pfra->pfra_anchorname);
+ free(pfra);
+ }
+
+ return (rv);
+}
+
+int
pfctl_show_eth_anchors(int dev, int opts, char *anchorname)
{
struct pfctl_eth_rulesets_info ri;
@@ -2653,15 +3171,15 @@ pfctl_show_eth_anchors(int dev, int opts, char *anchorname)
fprintf(stderr, "Anchor '%s' not found.\n",
anchorname);
else
- err(1, "DIOCGETETHRULESETS");
+ errc(1, ret, "DIOCGETETHRULESETS");
return (-1);
}
for (int nr = 0; nr < ri.nr; nr++) {
char sub[MAXPATHLEN];
- if (pfctl_get_eth_ruleset(dev, anchorname, nr, &rs) != 0)
- err(1, "DIOCGETETHRULESET");
+ if ((ret = pfctl_get_eth_ruleset(dev, anchorname, nr, &rs)) != 0)
+ errc(1, ret, "DIOCGETETHRULESET");
if (!strcmp(rs.name, PF_RESERVED_ANCHOR))
continue;
@@ -2689,10 +3207,49 @@ pfctl_lookup_option(char *cmd, const char * const *list)
return (NULL);
}
+void
+pfctl_reset(int dev, int opts)
+{
+ struct pfctl pf;
+ struct pfr_buffer t;
+ int i;
+
+ memset(&pf, 0, sizeof(pf));
+ pf.dev = dev;
+ pf.h = pfh;
+ pfctl_init_options(&pf);
+
+ /* Force reset upon pfctl_load_options() */
+ pf.debug_set = 1;
+ pf.reass_set = 1;
+ pf.syncookieswat_set = 1;
+ pf.ifname = strdup("none");
+ if (pf.ifname == NULL)
+ err(1, "%s: strdup", __func__);
+ pf.ifname_set = 1;
+
+ memset(&t, 0, sizeof(t));
+ t.pfrb_type = PFRB_TRANS;
+ if (pfctl_trans(dev, &t, DIOCXBEGIN, 0))
+ err(1, "%s: DIOCXBEGIN", __func__);
+
+ for (i = 0; pf_limits[i].name; i++)
+ pf.limit_set[pf_limits[i].index] = 1;
+
+ for (i = 0; pf_timeouts[i].name; i++)
+ pf.timeout_set[pf_timeouts[i].timeout] = 1;
+
+ pfctl_load_options(&pf);
+
+ if (pfctl_trans(dev, &t, DIOCXCOMMIT, 0))
+ err(1, "%s: DIOCXCOMMIT", __func__);
+
+ pfctl_clear_interface_flags(dev, opts);
+}
+
int
main(int argc, char *argv[])
{
- int error = 0;
int ch;
int mode = O_RDONLY;
int opts = 0;
@@ -2704,7 +3261,7 @@ main(int argc, char *argv[])
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:St:T:vx:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -2806,6 +3363,9 @@ main(int argc, char *argv[])
usage();
}
break;
+ case 'S':
+ opts |= PF_OPT_NODNS;
+ break;
case 't':
tableopt = optarg;
break;
@@ -2841,6 +3401,12 @@ main(int argc, char *argv[])
}
}
+ if ((opts & PF_OPT_NODNS) && (opts & PF_OPT_USEDNS))
+ errx(1, "-N and -r are mutually exclusive");
+
+ if ((tblcmdopt == NULL) ^ (tableopt == NULL))
+ usage();
+
if (tblcmdopt != NULL) {
argc -= optind;
argv += optind;
@@ -2849,7 +3415,7 @@ main(int argc, char *argv[])
loadopt |= PFCTL_FLAG_TABLE;
tblcmdopt = NULL;
} else
- mode = strchr("acdefkrz", ch) ? O_RDWR : O_RDONLY;
+ mode = strchr("st", ch) ? O_RDONLY : O_RDWR;
} else if (argc != optind) {
warnx("unknown command line argument: %s ...", argv[optind]);
usage();
@@ -2858,12 +3424,21 @@ main(int argc, char *argv[])
if (loadopt == 0)
loadopt = ~0;
- if ((path = calloc(1, MAXPATHLEN)) == NULL)
- errx(1, "pfctl: calloc");
memset(anchorname, 0, sizeof(anchorname));
if (anchoropt != NULL) {
int len = strlen(anchoropt);
+ if (anchoropt[0] == '\0')
+ errx(1, "anchor name must not be empty");
+ if (mode == O_RDONLY && showopt == NULL && tblcmdopt == NULL) {
+ warnx("anchors apply to -f, -F, -s, and -T only");
+ usage();
+ }
+ if (mode == O_RDWR && tblcmdopt == NULL &&
+ (anchoropt[0] == '_' || strstr(anchoropt, "/_") != NULL))
+ errx(1, "anchor names beginning with '_' cannot "
+ "be modified from the command line");
+
if (len >= 1 && anchoropt[len - 1] == '*') {
if (len >= 2 && anchoropt[len - 2] == '/')
anchoropt[len - 2] = '\0';
@@ -2896,30 +3471,43 @@ main(int argc, char *argv[])
altqsupport = 1;
#endif
}
+ pfh = pfctl_open(pf_device);
+ if (pfh == NULL)
+ err(1, "Failed to open netlink");
+
+ if ((opts & PF_OPT_NOACTION) == 0) {
+ pfctl_read_limits(pfh);
+ atexit(pfctl_restore_limits);
+ }
if (opts & PF_OPT_DISABLE)
if (pfctl_disable(dev, opts))
- error = 1;
+ exit_val = 1;
+
+ if ((path = calloc(1, MAXPATHLEN)) == NULL)
+ errx(1, "%s: calloc", __func__);
if (showopt != NULL) {
switch (*showopt) {
case 'A':
pfctl_show_anchors(dev, opts, anchorname);
+ if (opts & PF_OPT_VERBOSE2)
+ printf("Ethernet:\n");
pfctl_show_eth_anchors(dev, opts, anchorname);
break;
case 'r':
pfctl_load_fingerprints(dev, opts);
pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
- anchorname, 0);
+ anchorname, 0, 0);
break;
case 'l':
pfctl_load_fingerprints(dev, opts);
pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
- anchorname, 0);
+ anchorname, 0, 0);
break;
case 'n':
pfctl_load_fingerprints(dev, opts);
- pfctl_show_nat(dev, path, opts, anchorname, 0);
+ pfctl_show_nat(dev, path, opts, anchorname, 0, 0);
break;
case 'q':
pfctl_show_altq(dev, ifaceopt, opts,
@@ -2935,7 +3523,7 @@ main(int argc, char *argv[])
pfctl_show_status(dev, opts);
break;
case 'R':
- error = pfctl_show_running(dev);
+ exit_val = pfctl_show_running(dev);
break;
case 't':
pfctl_show_timeouts(dev, opts);
@@ -2944,28 +3532,37 @@ main(int argc, char *argv[])
pfctl_show_limits(dev, opts);
break;
case 'e':
- pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0);
+ pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0,
+ 0);
break;
case 'a':
opts |= PF_OPT_SHOWALL;
pfctl_load_fingerprints(dev, opts);
- pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0);
+ pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0,
+ 0);
- pfctl_show_nat(dev, path, opts, anchorname, 0);
- pfctl_show_rules(dev, path, opts, 0, anchorname, 0);
+ pfctl_show_nat(dev, path, opts, anchorname, 0, 0);
+ pfctl_show_rules(dev, path, opts, PFCTL_SHOW_RULES,
+ anchorname, 0, 0);
pfctl_show_altq(dev, ifaceopt, opts, 0);
pfctl_show_states(dev, ifaceopt, opts);
pfctl_show_src_nodes(dev, opts);
pfctl_show_status(dev, opts);
- pfctl_show_rules(dev, path, opts, 1, anchorname, 0);
+ pfctl_show_rules(dev, path, opts, PFCTL_SHOW_LABELS,
+ anchorname, 0, 0);
pfctl_show_timeouts(dev, opts);
pfctl_show_limits(dev, opts);
pfctl_show_tables(anchorname, opts);
pfctl_show_fingerprints(opts);
break;
case 'T':
- pfctl_show_tables(anchorname, opts);
+ if (opts & PF_OPT_RECURSE) {
+ opts |= PF_OPT_CALLSHOW;
+ pfctl_recurse(dev, opts, anchorname,
+ pfctl_call_showtables);
+ } else
+ pfctl_show_tables(anchorname, opts);
break;
case 'o':
pfctl_load_fingerprints(dev, opts);
@@ -2974,27 +3571,36 @@ main(int argc, char *argv[])
case 'I':
pfctl_show_ifaces(ifaceopt, opts);
break;
+ case 'c':
+ pfctl_show_creators(opts);
+ break;
}
}
if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) {
pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
- anchorname, 0);
+ anchorname, 0, 0);
pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
- anchorname, 0);
+ anchorname, 0, 0);
}
if (clearopt != NULL) {
- if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
- errx(1, "anchor names beginning with '_' cannot "
- "be modified from the command line");
+ int mnr;
+
+ /* Check if anchor exists. */
+ if ((pfctl_get_rulesets(pfh, anchorname, &mnr)) == ENOENT)
+ errx(1, "No such anchor %s", anchorname);
switch (*clearopt) {
case 'e':
pfctl_flush_eth_rules(dev, opts, anchorname);
break;
case 'r':
- pfctl_flush_rules(dev, opts, anchorname);
+ if (opts & PF_OPT_RECURSE)
+ pfctl_recurse(dev, opts, anchorname,
+ pfctl_call_clearrules);
+ else
+ pfctl_flush_rules(dev, opts, anchorname);
break;
case 'n':
pfctl_flush_nat(dev, opts, anchorname);
@@ -3009,27 +3615,45 @@ main(int argc, char *argv[])
pfctl_clear_src_nodes(dev, opts);
break;
case 'i':
- pfctl_clear_stats(dev, opts);
+ pfctl_clear_stats(pfh, opts);
break;
case 'a':
+ if (ifaceopt) {
+ warnx("don't specify an interface with -Fall");
+ usage();
+ /* NOTREACHED */
+ }
pfctl_flush_eth_rules(dev, opts, anchorname);
pfctl_flush_rules(dev, opts, anchorname);
pfctl_flush_nat(dev, opts, anchorname);
- pfctl_clear_tables(anchorname, opts);
+ if (opts & PF_OPT_RECURSE)
+ pfctl_recurse(dev, opts, anchorname,
+ pfctl_call_clearanchors);
+ else {
+ pfctl_do_clear_tables(anchorname, opts);
+ pfctl_flush_rules(dev, opts, anchorname);
+ }
if (!*anchorname) {
pfctl_clear_altq(dev, opts);
pfctl_clear_iface_states(dev, ifaceopt, opts);
pfctl_clear_src_nodes(dev, opts);
- pfctl_clear_stats(dev, opts);
+ pfctl_clear_stats(pfh, opts);
pfctl_clear_fingerprints(dev, opts);
- pfctl_clear_interface_flags(dev, opts);
+ pfctl_reset(dev, opts);
}
break;
case 'o':
pfctl_clear_fingerprints(dev, opts);
break;
case 'T':
- pfctl_clear_tables(anchorname, opts);
+ if ((opts & PF_OPT_RECURSE) == 0)
+ pfctl_do_clear_tables(anchorname, opts);
+ else
+ pfctl_recurse(dev, opts, anchorname,
+ pfctl_call_cleartables);
+ break;
+ case 'R':
+ pfctl_reset(dev, opts);
break;
}
}
@@ -3040,15 +3664,17 @@ main(int argc, char *argv[])
pfctl_id_kill_states(dev, ifaceopt, opts);
else if (!strcmp(state_kill[0], "gateway"))
pfctl_gateway_kill_states(dev, ifaceopt, opts);
+ else if (!strcmp(state_kill[0], "key"))
+ pfctl_key_kill_states(dev, ifaceopt, opts);
else
pfctl_net_kill_states(dev, ifaceopt, opts);
}
if (src_node_killers)
- pfctl_kill_src_nodes(dev, ifaceopt, opts);
+ pfctl_kill_src_nodes(dev, opts);
if (tblcmdopt != NULL) {
- error = pfctl_command_tables(argc, argv, tableopt,
+ exit_val = pfctl_table(argc, argv, tableopt,
tblcmdopt, rulesopt, anchorname, opts);
rulesopt = NULL;
}
@@ -3069,29 +3695,22 @@ main(int argc, char *argv[])
if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
!anchorname[0] && !(opts & PF_OPT_NOACTION))
- if (pfctl_get_skip_ifaces())
- error = 1;
+ pfctl_get_skip_ifaces();
- if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) &&
+ if (rulesopt != NULL && !(opts & PF_OPT_MERGE) &&
!anchorname[0] && (loadopt & PFCTL_FLAG_OPTION))
if (pfctl_file_fingerprints(dev, opts, PF_OSFP_FILE))
- error = 1;
+ exit_val = 1;
if (rulesopt != NULL) {
- if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
- errx(1, "anchor names beginning with '_' cannot "
- "be modified from the command line");
if (pfctl_rules(dev, rulesopt, opts, optimize,
anchorname, NULL))
- error = 1;
- else if (!(opts & PF_OPT_NOACTION) &&
- (loadopt & PFCTL_FLAG_TABLE))
- warn_namespace_collision(NULL);
+ exit_val = 1;
}
if (opts & PF_OPT_ENABLE)
if (pfctl_enable(dev, opts))
- error = 1;
+ exit_val = 1;
if (debugopt != NULL) {
switch (*debugopt) {
@@ -3110,5 +3729,30 @@ main(int argc, char *argv[])
}
}
- exit(error);
+ /*
+ * prevent pfctl_restore_limits() exit handler from restoring
+ * pf(4) options settings on successful exit.
+ */
+ if (exit_val == 0) {
+ close(dev);
+ dev = -1;
+ pfctl_close(pfh);
+ pfh = NULL;
+ }
+
+ return (exit_val);
+}
+
+char *
+pf_strerror(int errnum)
+{
+ switch (errnum) {
+ case ESRCH:
+ return "Table does not exist.";
+ case EINVAL:
+ case ENOENT:
+ return "Anchor does not exist.";
+ default:
+ return strerror(errnum);
+ }
}
diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h
index b4f27e5b9b21..136f51ea08f9 100644
--- a/sbin/pfctl/pfctl.h
+++ b/sbin/pfctl/pfctl.h
@@ -29,8 +29,6 @@
* 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 _PFCTL_H_
@@ -38,6 +36,14 @@
#include <libpfctl.h>
+#ifdef PFCTL_DEBUG
+#define DBGPRINT(...) fprintf(stderr, __VA_ARGS__)
+#else
+#define DBGPRINT(...) (void)(0)
+#endif
+
+extern struct pfctl_handle *pfh;
+
struct pfctl;
enum pfctl_show { PFCTL_SHOW_RULES, PFCTL_SHOW_LABELS, PFCTL_SHOW_NOTHING };
@@ -55,13 +61,52 @@ struct pfr_buffer {
(var) != NULL; \
(var) = pfr_buf_next((buf), (var)))
-int pfr_get_fd(void);
-int pfr_clr_tables(struct pfr_table *, int *, int);
-int pfr_add_tables(struct pfr_table *, int, int *, int);
-int pfr_del_tables(struct pfr_table *, int, int *, int);
+RB_HEAD(pfr_ktablehead, pfr_ktable);
+struct pfr_ktable {
+ struct pfr_tstats pfrkt_ts;
+ RB_ENTRY(pfr_ktable) pfrkt_tree;
+ SLIST_ENTRY(pfr_ktable) pfrkt_workq;
+ struct radix_node_head *pfrkt_ip4;
+ struct radix_node_head *pfrkt_ip6;
+ struct pfr_ktable *pfrkt_shadow;
+ struct pfr_ktable *pfrkt_root;
+ struct pf_kruleset *pfrkt_rs;
+ long pfrkt_larg;
+ int pfrkt_nflags;
+};
+#define pfrkt_t pfrkt_ts.pfrts_t
+#define pfrkt_name pfrkt_t.pfrt_name
+#define pfrkt_anchor pfrkt_t.pfrt_anchor
+#define pfrkt_ruleset pfrkt_t.pfrt_ruleset
+#define pfrkt_flags pfrkt_t.pfrt_flags
+#define pfrkt_cnt pfrkt_kts.pfrkts_cnt
+#define pfrkt_refcnt pfrkt_kts.pfrkts_refcnt
+#define pfrkt_tzero pfrkt_kts.pfrkts_tzero
+
+struct pfr_uktable {
+ struct pfr_ktable pfrukt_kt;
+ struct pfr_buffer pfrukt_addrs;
+ int pfrukt_init_addr;
+ SLIST_ENTRY(pfr_uktable) pfrukt_entry;
+};
+
+#define pfrukt_t pfrukt_kt.pfrkt_ts.pfrts_t
+#define pfrukt_name pfrukt_kt.pfrkt_t.pfrt_name
+#define pfrukt_anchor pfrukt_kt.pfrkt_t.pfrt_anchor
+
+extern struct pfr_ktablehead pfr_ktables;
+
+struct pfr_anchoritem {
+ SLIST_ENTRY(pfr_anchoritem) pfra_sle;
+ char *pfra_anchorname;
+};
+
+SLIST_HEAD(pfr_anchors, pfr_anchoritem);
+
+int pfr_add_table(struct pfr_table *, int *, int);
+int pfr_del_table(struct pfr_table *, int *, int);
int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int);
-int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int);
-int pfr_clr_tstats(struct pfr_table *, int, int *, int);
+int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *, int);
int pfr_clr_addrs(struct pfr_table *, int *, int);
int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *, int);
@@ -77,19 +122,19 @@ int pfr_buf_add(struct pfr_buffer *, const void *);
void *pfr_buf_next(struct pfr_buffer *, const void *);
int pfr_buf_grow(struct pfr_buffer *, int);
int pfr_buf_load(struct pfr_buffer *, char *, int,
- int (*)(struct pfr_buffer *, char *, int));
-char *pfr_strerror(int);
+ int (*)(struct pfr_buffer *, char *, int, int), int);
+char *pf_strerror(int);
int pfi_get_ifaces(const char *, struct pfi_kif *, int *);
-int pfi_clr_istats(const char *, int *, int);
void pfctl_print_title(char *);
-int pfctl_clear_tables(const char *, int);
-int pfctl_show_tables(const char *, int);
-int pfctl_command_tables(int, char *[], char *, const char *, char *,
+int pfctl_do_clear_tables(const char *, int);
+void pfctl_show_tables(const char *, int);
+int pfctl_table(int, char *[], char *, const char *, char *,
const char *, int);
int pfctl_show_altq(int, const char *, int, int);
-void warn_namespace_collision(const char *);
-int pfctl_show_ifaces(const char *, int);
+void warn_duplicate_tables(const char *, const char *);
+void pfctl_show_ifaces(const char *, int);
+void pfctl_show_creators(int);
FILE *pfctl_fopen(const char *, const char *);
#ifdef __FreeBSD__
@@ -121,10 +166,10 @@ void pfaltq_store(struct pf_altq *);
char *rate2str(double);
void print_addr(struct pf_addr_wrap *, sa_family_t, int);
+void print_addr_str(sa_family_t, struct pf_addr *);
void print_host(struct pf_addr *, u_int16_t p, sa_family_t, int);
void print_seq(struct pfctl_state_peer *);
void print_state(struct pfctl_state *, int);
-int unmask(struct pf_addr *, sa_family_t);
int pfctl_cmdline_symset(char *);
int pfctl_add_trans(struct pfr_buffer *, int, const char *);
@@ -151,4 +196,7 @@ void expand_label(char *, size_t, struct pfctl_rule *);
const char *pfctl_proto2name(int);
+void pfctl_err(int, int, const char *, ...);
+void pfctl_errx(int, int, const char *, ...);
+
#endif /* _PFCTL_H_ */
diff --git a/sbin/pfctl/pfctl_altq.c b/sbin/pfctl/pfctl_altq.c
index 6d35ae77240f..1b32e90aea10 100644
--- a/sbin/pfctl/pfctl_altq.c
+++ b/sbin/pfctl/pfctl_altq.c
@@ -19,8 +19,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#define PFIOC_USE_LATEST
#define _WANT_FREEBSD_BITSET
@@ -1227,7 +1225,7 @@ char *
rate2str(double rate)
{
char *buf;
- static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring bufer */
+ static char r2sbuf[R2S_BUFS][RATESTR_MAX]; /* ring buffer */
static int idx = 0;
int i;
static const char unit[] = " KMG";
diff --git a/sbin/pfctl/pfctl_optimize.c b/sbin/pfctl/pfctl_optimize.c
index d999734a906c..2d16bbd22b39 100644
--- a/sbin/pfctl/pfctl_optimize.c
+++ b/sbin/pfctl/pfctl_optimize.c
@@ -16,9 +16,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -138,7 +135,9 @@ static struct pf_rule_field {
PF_RULE_FIELD(return_ttl, BREAK),
PF_RULE_FIELD(overload_tblname, BREAK),
PF_RULE_FIELD(flush, BREAK),
- PF_RULE_FIELD(rpool, BREAK),
+ PF_RULE_FIELD(rdr, BREAK),
+ PF_RULE_FIELD(nat, BREAK),
+ PF_RULE_FIELD(route, BREAK),
PF_RULE_FIELD(logif, BREAK),
/*
@@ -175,6 +174,7 @@ static struct pf_rule_field {
PF_RULE_FIELD(dst.port_op, NOMERGE),
PF_RULE_FIELD(src.neg, NOMERGE),
PF_RULE_FIELD(dst.neg, NOMERGE),
+ PF_RULE_FIELD(af, NOMERGE),
/* These fields can be merged */
PF_RULE_FIELD(src.addr, COMBINED),
@@ -241,6 +241,8 @@ int skip_cmp_src_addr(struct pfctl_rule *, struct pfctl_rule *);
int skip_cmp_src_port(struct pfctl_rule *, struct pfctl_rule *);
int superblock_inclusive(struct superblock *, struct pf_opt_rule *);
void superblock_free(struct pfctl *, struct superblock *);
+struct pf_opt_tbl *pf_opt_table_ref(struct pf_opt_tbl *);
+void pf_opt_table_unref(struct pf_opt_tbl *);
static int (*skip_comparitors[PF_SKIP_COUNT])(struct pfctl_rule *,
@@ -252,8 +254,8 @@ static const char *skip_comparitors_names[PF_SKIP_COUNT];
{ "af", PF_SKIP_AF, skip_cmp_af }, \
{ "proto", PF_SKIP_PROTO, skip_cmp_proto }, \
{ "saddr", PF_SKIP_SRC_ADDR, skip_cmp_src_addr }, \
- { "sport", PF_SKIP_SRC_PORT, skip_cmp_src_port }, \
{ "daddr", PF_SKIP_DST_ADDR, skip_cmp_dst_addr }, \
+ { "sport", PF_SKIP_SRC_PORT, skip_cmp_src_port }, \
{ "dport", PF_SKIP_DST_PORT, skip_cmp_dst_port } \
}
@@ -271,7 +273,10 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pfctl_ruleset *rs)
struct pfctl_rule *r;
struct pfctl_rulequeue *old_rules;
- DEBUG("optimizing ruleset");
+ if (TAILQ_EMPTY(rs->rules[PF_RULESET_FILTER].active.ptr))
+ return (0);
+
+ DEBUG("optimizing ruleset \"%s\"", rs->anchor->path);
memset(&table_buffer, 0, sizeof(table_buffer));
skip_init();
TAILQ_INIT(&opt_queue);
@@ -292,13 +297,24 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pfctl_ruleset *rs)
if ((por = calloc(1, sizeof(*por))) == NULL)
err(1, "calloc");
memcpy(&por->por_rule, r, sizeof(*r));
- if (TAILQ_FIRST(&r->rpool.list) != NULL) {
- TAILQ_INIT(&por->por_rule.rpool.list);
- pfctl_move_pool(&r->rpool, &por->por_rule.rpool);
+ if (TAILQ_FIRST(&r->rdr.list) != NULL) {
+ TAILQ_INIT(&por->por_rule.rdr.list);
+ pfctl_move_pool(&r->rdr, &por->por_rule.rdr);
} else
- bzero(&por->por_rule.rpool,
- sizeof(por->por_rule.rpool));
-
+ bzero(&por->por_rule.rdr,
+ sizeof(por->por_rule.rdr));
+ if (TAILQ_FIRST(&r->nat.list) != NULL) {
+ TAILQ_INIT(&por->por_rule.nat.list);
+ pfctl_move_pool(&r->nat, &por->por_rule.nat);
+ } else
+ bzero(&por->por_rule.nat,
+ sizeof(por->por_rule.nat));
+ if (TAILQ_FIRST(&r->route.list) != NULL) {
+ TAILQ_INIT(&por->por_rule.route.list);
+ pfctl_move_pool(&r->route, &por->por_rule.route);
+ } else
+ bzero(&por->por_rule.route,
+ sizeof(por->por_rule.route));
TAILQ_INSERT_TAIL(&opt_queue, por, por_entry);
}
@@ -327,14 +343,18 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pfctl_ruleset *rs)
if ((r = calloc(1, sizeof(*r))) == NULL)
err(1, "calloc");
memcpy(r, &por->por_rule, sizeof(*r));
- TAILQ_INIT(&r->rpool.list);
- pfctl_move_pool(&por->por_rule.rpool, &r->rpool);
+ TAILQ_INIT(&r->rdr.list);
+ pfctl_move_pool(&por->por_rule.rdr, &r->rdr);
+ TAILQ_INIT(&r->nat.list);
+ pfctl_move_pool(&por->por_rule.nat, &r->nat);
TAILQ_INSERT_TAIL(
rs->rules[PF_RULESET_FILTER].active.ptr,
r, entries);
+ pf_opt_table_unref(por->por_src_tbl);
+ pf_opt_table_unref(por->por_dst_tbl);
free(por);
}
- free(block);
+ superblock_free(pf, block);
}
return (0);
@@ -342,16 +362,8 @@ pfctl_optimize_ruleset(struct pfctl *pf, struct pfctl_ruleset *rs)
error:
while ((por = TAILQ_FIRST(&opt_queue))) {
TAILQ_REMOVE(&opt_queue, por, por_entry);
- if (por->por_src_tbl) {
- pfr_buf_clear(por->por_src_tbl->pt_buf);
- free(por->por_src_tbl->pt_buf);
- free(por->por_src_tbl);
- }
- if (por->por_dst_tbl) {
- pfr_buf_clear(por->por_dst_tbl->pt_buf);
- free(por->por_dst_tbl->pt_buf);
- free(por->por_dst_tbl);
- }
+ pf_opt_table_unref(por->por_src_tbl);
+ pf_opt_table_unref(por->por_dst_tbl);
free(por);
}
while ((block = TAILQ_FIRST(&superblocks))) {
@@ -524,12 +536,14 @@ combine_rules(struct pfctl *pf, struct superblock *block)
if (add_opt_table(pf, &p1->por_dst_tbl,
p1->por_rule.af, &p2->por_rule.dst))
return (1);
- p2->por_dst_tbl = p1->por_dst_tbl;
if (p1->por_dst_tbl->pt_rulecount >=
TABLE_THRESHOLD) {
TAILQ_REMOVE(&block->sb_rules, p2,
por_entry);
free(p2);
+ } else {
+ p2->por_dst_tbl =
+ pf_opt_table_ref(p1->por_dst_tbl);
}
} else if (!src_eq && dst_eq && p1->por_dst_tbl == NULL
&& p2->por_src_tbl == NULL &&
@@ -546,12 +560,14 @@ combine_rules(struct pfctl *pf, struct superblock *block)
if (add_opt_table(pf, &p1->por_src_tbl,
p1->por_rule.af, &p2->por_rule.src))
return (1);
- p2->por_src_tbl = p1->por_src_tbl;
if (p1->por_src_tbl->pt_rulecount >=
TABLE_THRESHOLD) {
TAILQ_REMOVE(&block->sb_rules, p2,
por_entry);
free(p2);
+ } else {
+ p2->por_src_tbl =
+ pf_opt_table_ref(p1->por_src_tbl);
}
}
}
@@ -707,11 +723,7 @@ reorder_rules(struct pfctl *pf, struct superblock *block, int depth)
* it based on a more optimal skipstep order.
*/
TAILQ_INIT(&head);
- while ((por = TAILQ_FIRST(&block->sb_rules))) {
- TAILQ_REMOVE(&block->sb_rules, por, por_entry);
- TAILQ_INSERT_TAIL(&head, por, por_entry);
- }
-
+ TAILQ_CONCAT(&head, &block->sb_rules, por_entry);
while (!TAILQ_EMPTY(&head)) {
largest = 1;
@@ -732,11 +744,7 @@ reorder_rules(struct pfctl *pf, struct superblock *block, int depth)
* Nothing useful left. Leave remaining rules in order.
*/
DEBUG("(%d) no more commonality for skip steps", depth);
- while ((por = TAILQ_FIRST(&head))) {
- TAILQ_REMOVE(&head, por, por_entry);
- TAILQ_INSERT_TAIL(&block->sb_rules, por,
- por_entry);
- }
+ TAILQ_CONCAT(&block->sb_rules, &head, por_entry);
} else {
/*
* There is commonality. Extract those common rules
@@ -847,10 +855,7 @@ block_feedback(struct pfctl *pf, struct superblock *block)
*/
TAILQ_INIT(&queue);
- while ((por1 = TAILQ_FIRST(&block->sb_rules)) != NULL) {
- TAILQ_REMOVE(&block->sb_rules, por1, por_entry);
- TAILQ_INSERT_TAIL(&queue, por1, por_entry);
- }
+ TAILQ_CONCAT(&queue, &block->sb_rules, por_entry);
while ((por1 = TAILQ_FIRST(&queue)) != NULL) {
TAILQ_REMOVE(&queue, por1, por_entry);
@@ -880,24 +885,23 @@ block_feedback(struct pfctl *pf, struct superblock *block)
int
load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks)
{
+ char anchor_call[MAXPATHLEN] = "";
struct superblock *block, *blockcur;
struct superblocks prof_superblocks;
struct pf_opt_rule *por;
struct pf_opt_queue queue;
- struct pfioc_rule pr;
+ struct pfctl_rules_info rules;
struct pfctl_rule a, b, rule;
- int nr, mnr;
+ int nr, mnr, ret;
TAILQ_INIT(&queue);
TAILQ_INIT(&prof_superblocks);
- memset(&pr, 0, sizeof(pr));
- pr.rule.action = PF_PASS;
- if (ioctl(pf->dev, DIOCGETRULES, &pr)) {
- warn("DIOCGETRULES");
+ if ((ret = pfctl_get_rules_info_h(pf->h, &rules, PF_PASS, "")) != 0) {
+ warnx("%s", pf_strerror(ret));
return (1);
}
- mnr = pr.nr;
+ mnr = rules.nr;
DEBUG("Loading %d active rules for a feedback profile", mnr);
for (nr = 0; nr < mnr; ++nr) {
@@ -906,24 +910,27 @@ load_feedback_profile(struct pfctl *pf, struct superblocks *superblocks)
warn("calloc");
return (1);
}
- pr.nr = nr;
- if (pfctl_get_rule(pf->dev, nr, pr.ticket, "", PF_PASS,
- &rule, pr.anchor_call)) {
- warn("DIOCGETRULENV");
+ if (pfctl_get_rule_h(pf->h, nr, rules.ticket, "", PF_PASS,
+ &rule, anchor_call)) {
+ warnx("%s", pf_strerror(ret));
+ free(por);
return (1);
}
memcpy(&por->por_rule, &rule, sizeof(por->por_rule));
- rs = pf_find_or_create_ruleset(pr.anchor_call);
+ rs = pf_find_or_create_ruleset(anchor_call);
por->por_rule.anchor = rs->anchor;
- if (TAILQ_EMPTY(&por->por_rule.rpool.list))
- memset(&por->por_rule.rpool, 0,
- sizeof(por->por_rule.rpool));
+ if (TAILQ_EMPTY(&por->por_rule.rdr.list))
+ memset(&por->por_rule.rdr, 0,
+ sizeof(por->por_rule.rdr));
+ if (TAILQ_EMPTY(&por->por_rule.nat.list))
+ memset(&por->por_rule.nat, 0,
+ sizeof(por->por_rule.nat));
TAILQ_INSERT_TAIL(&queue, por, por_entry);
- /* XXX pfctl_get_pool(pf->dev, &rule.rpool, nr, pr.ticket,
+ /* XXX pfctl_get_pool(pf->dev, &rule.rdr, nr, pr.ticket,
* PF_PASS, pf->anchor) ???
- * ... pfctl_clear_pool(&rule.rpool)
+ * ... pfctl_clear_pool(&rule.rdr)
*/
}
@@ -1235,12 +1242,13 @@ add_opt_table(struct pfctl *pf, struct pf_opt_tbl **tbl, sa_family_t af,
((*tbl)->pt_buf = calloc(1, sizeof(*(*tbl)->pt_buf))) ==
NULL)
err(1, "calloc");
+ (*tbl)->pt_refcnt = 1;
(*tbl)->pt_buf->pfrb_type = PFRB_ADDRS;
SIMPLEQ_INIT(&(*tbl)->pt_nodes);
/* This is just a temporary table name */
snprintf((*tbl)->pt_name, sizeof((*tbl)->pt_name), "%s%d",
- PF_OPT_TABLE_PREFIX, tablenum++);
+ PF_OPTIMIZER_TABLE_PFX, tablenum++);
DEBUG("creating table <%s>", (*tbl)->pt_name);
}
@@ -1251,7 +1259,7 @@ add_opt_table(struct pfctl *pf, struct pf_opt_tbl **tbl, sa_family_t af,
#ifdef OPT_DEBUG
DEBUG("<%s> adding %s/%d", (*tbl)->pt_name, inet_ntop(af,
&node_host.addr.v.a.addr, buf, sizeof(buf)),
- unmask(&node_host.addr.v.a.mask, af));
+ unmask(&node_host.addr.v.a.mask));
#endif /* OPT_DEBUG */
if (append_addr_host((*tbl)->pt_buf, &node_host, 0, 0)) {
@@ -1307,9 +1315,9 @@ pf_opt_create_table(struct pfctl *pf, struct pf_opt_tbl *tbl)
/* Now we have to pick a table name that isn't used */
again:
DEBUG("translating temporary table <%s> to <%s%x_%d>", tbl->pt_name,
- PF_OPT_TABLE_PREFIX, table_identifier, tablenum);
+ PF_OPTIMIZER_TABLE_PFX, table_identifier, tablenum);
snprintf(tbl->pt_name, sizeof(tbl->pt_name), "%s%x_%d",
- PF_OPT_TABLE_PREFIX, table_identifier, tablenum);
+ PF_OPTIMIZER_TABLE_PFX, table_identifier, tablenum);
PFRB_FOREACH(t, &table_buffer) {
if (strcasecmp(t->pfrt_name, tbl->pt_name) == 0) {
/* Collision. Try again */
@@ -1323,7 +1331,8 @@ again:
if (pfctl_define_table(tbl->pt_name, PFR_TFLAG_CONST, 1,
- pf->astack[0]->name, tbl->pt_buf, pf->astack[0]->ruleset.tticket)) {
+ pf->astack[0]->path, tbl->pt_buf, pf->astack[0]->ruleset.tticket,
+ NULL)) {
warn("failed to create table %s in %s",
tbl->pt_name, pf->astack[0]->name);
return (1);
@@ -1476,7 +1485,7 @@ superblock_inclusive(struct superblock *block, struct pf_opt_rule *por)
}
if (closest >= 0)
- DEBUG("superblock break @ %d on %s+%xh",
+ DEBUG("superblock break @ %d on %s+%zxh",
por->por_rule.nr,
pf_rule_desc[closest].prf_name,
i - pf_rule_desc[closest].prf_offset -
@@ -1586,8 +1595,8 @@ exclude_supersets(struct pfctl_rule *super, struct pfctl_rule *sub)
sub->src.addr.type == PF_ADDR_ADDRMASK &&
super->src.neg == sub->src.neg &&
super->af == sub->af &&
- unmask(&super->src.addr.v.a.mask, super->af) <
- unmask(&sub->src.addr.v.a.mask, sub->af) &&
+ unmask(&super->src.addr.v.a.mask) <
+ unmask(&sub->src.addr.v.a.mask) &&
super->src.addr.v.a.addr.addr32[0] ==
(sub->src.addr.v.a.addr.addr32[0] &
super->src.addr.v.a.mask.addr32[0]) &&
@@ -1614,8 +1623,8 @@ exclude_supersets(struct pfctl_rule *super, struct pfctl_rule *sub)
sub->dst.addr.type == PF_ADDR_ADDRMASK &&
super->dst.neg == sub->dst.neg &&
super->af == sub->af &&
- unmask(&super->dst.addr.v.a.mask, super->af) <
- unmask(&sub->dst.addr.v.a.mask, sub->af) &&
+ unmask(&super->dst.addr.v.a.mask) <
+ unmask(&sub->dst.addr.v.a.mask) &&
super->dst.addr.v.a.addr.addr32[0] ==
(sub->dst.addr.v.a.addr.addr32[0] &
super->dst.addr.v.a.mask.addr32[0]) &&
@@ -1643,20 +1652,8 @@ superblock_free(struct pfctl *pf, struct superblock *block)
struct pf_opt_rule *por;
while ((por = TAILQ_FIRST(&block->sb_rules))) {
TAILQ_REMOVE(&block->sb_rules, por, por_entry);
- if (por->por_src_tbl) {
- if (por->por_src_tbl->pt_buf) {
- pfr_buf_clear(por->por_src_tbl->pt_buf);
- free(por->por_src_tbl->pt_buf);
- }
- free(por->por_src_tbl);
- }
- if (por->por_dst_tbl) {
- if (por->por_dst_tbl->pt_buf) {
- pfr_buf_clear(por->por_dst_tbl->pt_buf);
- free(por->por_dst_tbl->pt_buf);
- }
- free(por->por_dst_tbl);
- }
+ pf_opt_table_unref(por->por_src_tbl);
+ pf_opt_table_unref(por->por_dst_tbl);
free(por);
}
if (block->sb_profiled_block)
@@ -1664,3 +1661,24 @@ superblock_free(struct pfctl *pf, struct superblock *block)
free(block);
}
+struct pf_opt_tbl *
+pf_opt_table_ref(struct pf_opt_tbl *pt)
+{
+ /* parser does not run concurrently, we don't need atomic ops. */
+ if (pt != NULL)
+ pt->pt_refcnt++;
+
+ return (pt);
+}
+
+void
+pf_opt_table_unref(struct pf_opt_tbl *pt)
+{
+ if ((pt != NULL) && ((--pt->pt_refcnt) == 0)) {
+ if (pt->pt_buf != NULL) {
+ pfr_buf_clear(pt->pt_buf);
+ free(pt->pt_buf);
+ }
+ free(pt);
+ }
+}
diff --git a/sbin/pfctl/pfctl_osfp.c b/sbin/pfctl/pfctl_osfp.c
index e26578051574..5770c8343a46 100644
--- a/sbin/pfctl/pfctl_osfp.c
+++ b/sbin/pfctl/pfctl_osfp.c
@@ -16,9 +16,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -115,16 +112,11 @@ pfctl_file_fingerprints(int dev, int opts, const char *fp_filename)
while ((line = fgetln(in, &len)) != NULL) {
lineno++;
- if (class)
- free(class);
- if (version)
- free(version);
- if (subtype)
- free(subtype);
- if (desc)
- free(desc);
- if (tcpopts)
- free(tcpopts);
+ free(class);
+ free(version);
+ free(subtype);
+ free(desc);
+ free(tcpopts);
class = version = subtype = desc = tcpopts = NULL;
memset(&fp, 0, sizeof(fp));
@@ -253,16 +245,11 @@ pfctl_file_fingerprints(int dev, int opts, const char *fp_filename)
add_fingerprint(dev, opts, &fp);
}
- if (class)
- free(class);
- if (version)
- free(version);
- if (subtype)
- free(subtype);
- if (desc)
- free(desc);
- if (tcpopts)
- free(tcpopts);
+ free(class);
+ free(version);
+ free(subtype);
+ free(desc);
+ free(tcpopts);
fclose(in);
@@ -277,7 +264,7 @@ void
pfctl_clear_fingerprints(int dev, int opts)
{
if (ioctl(dev, DIOCOSFPFLUSH))
- err(1, "DIOCOSFPFLUSH");
+ pfctl_err(opts, 1, "DIOCOSFPFLUSH");
}
/* flush pfctl's view of the fingerprints */
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
index a05683f0cbce..b8531067d3f6 100644
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -33,20 +33,19 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/proc.h>
+#include <net/if_dl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
+#include <netinet/tcp.h>
#include <net/pfvar.h>
#include <arpa/inet.h>
@@ -61,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <err.h>
#include <ifaddrs.h>
+#include <inttypes.h>
#include <unistd.h>
#include "pfctl_parser.h"
@@ -68,18 +68,17 @@ __FBSDID("$FreeBSD$");
void print_op (u_int8_t, const char *, const char *);
void print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int);
-void print_ugid (u_int8_t, unsigned, unsigned, const char *, unsigned);
-void print_flags (u_int8_t);
+void print_ugid (u_int8_t, id_t, id_t, const char *);
+void print_flags (uint16_t);
void print_fromto(struct pf_rule_addr *, pf_osfp_t,
- struct pf_rule_addr *, u_int8_t, u_int8_t, int, int);
+ struct pf_rule_addr *, sa_family_t, u_int8_t, int, int);
int ifa_skip_if(const char *filter, struct node_host *p);
struct node_host *host_if(const char *, int);
-struct node_host *host_v4(const char *, int);
-struct node_host *host_v6(const char *, int);
+struct node_host *host_ip(const char *, int);
struct node_host *host_dns(const char *, int, int);
-const char * const tcpflags = "FSRPAUEW";
+const char * const tcpflags = "FSRPAUEWe";
static const struct icmptypeent icmp_type[] = {
{ "echoreq", ICMP_ECHO },
@@ -135,7 +134,8 @@ static const struct icmptypeent icmp6_type[] = {
{ "niqry", ICMP6_NI_QUERY },
{ "nirep", ICMP6_NI_REPLY },
{ "mtraceresp", MLD_MTRACE_RESP },
- { "mtrace", MLD_MTRACE }
+ { "mtrace", MLD_MTRACE },
+ { "listenrepv2", MLDV2_LISTENER_REPORT },
};
static const struct icmpcodeent icmp_code[] = {
@@ -194,6 +194,11 @@ const struct pf_timeout pf_timeouts[] = {
{ "tcp.finwait", PFTM_TCP_FIN_WAIT },
{ "tcp.closed", PFTM_TCP_CLOSED },
{ "tcp.tsdiff", PFTM_TS_DIFF },
+ { "sctp.first", PFTM_SCTP_FIRST_PACKET },
+ { "sctp.opening", PFTM_SCTP_OPENING },
+ { "sctp.established", PFTM_SCTP_ESTABLISHED },
+ { "sctp.closing", PFTM_SCTP_CLOSING },
+ { "sctp.closed", PFTM_SCTP_CLOSED },
{ "udp.first", PFTM_UDP_FIRST_PACKET },
{ "udp.single", PFTM_UDP_SINGLE },
{ "udp.multiple", PFTM_UDP_MULTIPLE },
@@ -223,10 +228,21 @@ pfctl_parser_init(void)
err(1, "Failed to create interface group query response map");
}
+void
+copy_satopfaddr(struct pf_addr *pfa, struct sockaddr *sa)
+{
+ if (sa->sa_family == AF_INET6)
+ pfa->v6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
+ else if (sa->sa_family == AF_INET)
+ pfa->v4 = ((struct sockaddr_in *)sa)->sin_addr;
+ else
+ warnx("unhandled af %d", sa->sa_family);
+}
+
const struct icmptypeent *
geticmptypebynumber(u_int8_t type, sa_family_t af)
{
- unsigned int i;
+ size_t i;
if (af != AF_INET6) {
for (i=0; i < nitems(icmp_type); i++) {
@@ -245,7 +261,7 @@ geticmptypebynumber(u_int8_t type, sa_family_t af)
const struct icmptypeent *
geticmptypebyname(char *w, sa_family_t af)
{
- unsigned int i;
+ size_t i;
if (af != AF_INET6) {
for (i=0; i < nitems(icmp_type); i++) {
@@ -264,7 +280,7 @@ geticmptypebyname(char *w, sa_family_t af)
const struct icmpcodeent *
geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af)
{
- unsigned int i;
+ size_t i;
if (af != AF_INET6) {
for (i=0; i < nitems(icmp_code); i++) {
@@ -285,7 +301,7 @@ geticmpcodebynumber(u_int8_t type, u_int8_t code, sa_family_t af)
const struct icmpcodeent *
geticmpcodebyname(u_long type, char *w, sa_family_t af)
{
- unsigned int i;
+ size_t i;
if (af != AF_INET6) {
for (i=0; i < nitems(icmp_code); i++) {
@@ -348,21 +364,21 @@ print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int numer
}
void
-print_ugid(u_int8_t op, unsigned u1, unsigned u2, const char *t, unsigned umax)
+print_ugid(u_int8_t op, id_t i1, id_t i2, const char *t)
{
char a1[11], a2[11];
- snprintf(a1, sizeof(a1), "%u", u1);
- snprintf(a2, sizeof(a2), "%u", u2);
+ snprintf(a1, sizeof(a1), "%ju", (uintmax_t)i1);
+ snprintf(a2, sizeof(a2), "%ju", (uintmax_t)i2);
printf(" %s", t);
- if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE))
+ if (i1 == -1 && (op == PF_OP_EQ || op == PF_OP_NE))
print_op(op, "unknown", a2);
else
print_op(op, a1, a2);
}
void
-print_flags(u_int8_t f)
+print_flags(uint16_t f)
{
int i;
@@ -373,9 +389,11 @@ print_flags(u_int8_t f)
void
print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
- sa_family_t af, u_int8_t proto, int verbose, int numeric)
+ sa_family_t af, u_int8_t proto, int opts, int numeric)
{
char buf[PF_OSFP_LEN*3];
+ int verbose = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
+
if (src->addr.type == PF_ADDR_ADDRMASK &&
dst->addr.type == PF_ADDR_ADDRMASK &&
PF_AZERO(&src->addr.v.a.addr, AF_INET6) &&
@@ -413,10 +431,9 @@ print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr *dst,
}
void
-print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2,
- sa_family_t af, int id)
+print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2, int id)
{
- struct pf_pooladdr *pooladdr;
+ struct pfctl_pooladdr *pooladdr;
if ((TAILQ_FIRST(&pool->list) != NULL) &&
TAILQ_NEXT(TAILQ_FIRST(&pool->list), entries) != NULL)
@@ -426,14 +443,15 @@ print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2,
case PF_NAT:
case PF_RDR:
case PF_BINAT:
- print_addr(&pooladdr->addr, af, 0);
+ print_addr(&pooladdr->addr, pooladdr->af, 0);
break;
case PF_PASS:
- if (PF_AZERO(&pooladdr->addr.v.a.addr, af))
+ case PF_MATCH:
+ if (PF_AZERO(&pooladdr->addr.v.a.addr, pooladdr->af))
printf("%s", pooladdr->ifname);
else {
printf("(%s ", pooladdr->ifname);
- print_addr(&pooladdr->addr, af, 0);
+ print_addr(&pooladdr->addr, pooladdr->af, 0);
printf(")");
}
break;
@@ -485,18 +503,17 @@ print_pool(struct pfctl_pool *pool, u_int16_t p1, u_int16_t p2,
}
if (pool->opts & PF_POOL_STICKYADDR)
printf(" sticky-address");
+ if (pool->opts & PF_POOL_ENDPI)
+ printf(" endpoint-independent");
if (id == PF_NAT && p1 == 0 && p2 == 0)
printf(" static-port");
if (pool->mape.offset > 0)
printf(" map-e-portset %u/%u/%u",
pool->mape.offset, pool->mape.psidlen, pool->mape.psid);
+ if (pool->opts & PF_POOL_IPV6NH)
+ printf(" prefer-ipv6-nexthop");
}
-const char * const pf_reasons[PFRES_MAX+1] = PFRES_NAMES;
-const char * const pf_lcounters[LCNT_MAX+1] = LCNT_NAMES;
-const char * const pf_fcounters[FCNT_MAX+1] = FCNT_NAMES;
-const char * const pf_scounters[FCNT_MAX+1] = FCNT_NAMES;
-
void
print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts)
{
@@ -511,7 +528,8 @@ print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts)
running = s->running ? "Enabled" : "Disabled";
if (s->since) {
- unsigned int sec, min, hrs, day = runtime;
+ unsigned int sec, min, hrs;
+ time_t day = runtime;
sec = day % 60;
day /= 60;
@@ -520,8 +538,8 @@ print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts)
hrs = day % 24;
day /= 24;
snprintf(statline, sizeof(statline),
- "Status: %s for %u days %.2u:%.2u:%.2u",
- running, day, hrs, min, sec);
+ "Status: %s for %lld days %.2u:%.2u:%.2u",
+ running, (long long)day, hrs, min, sec);
} else
snprintf(statline, sizeof(statline), "Status: %s", running);
printf("%-44s", statline);
@@ -598,6 +616,20 @@ print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts)
printf("%14s\n", "");
}
}
+ if (opts & PF_OPT_VERBOSE) {
+ printf("Fragments\n");
+ printf(" %-25s %14ju %14s\n", "current entries",
+ s->fragments, "");
+ TAILQ_FOREACH(c, &s->ncounters, entry) {
+ printf(" %-25s %14ju ", c->name,
+ c->counter);
+ if (runtime > 0)
+ printf("%14.1f/s\n",
+ (double)c->counter / (double)runtime);
+ else
+ printf("%14s\n", "");
+ }
+ }
printf("Counters\n");
TAILQ_FOREACH(c, &s->counters, entry) {
printf(" %-25s %14ju ", c->name, c->counter);
@@ -622,6 +654,17 @@ print_status(struct pfctl_status *s, struct pfctl_syncookies *cookies, int opts)
assert(cookies->mode <= PFCTL_SYNCOOKIES_ADAPTIVE);
printf(" %-25s %s\n", "mode",
PFCTL_SYNCOOKIES_MODE_NAMES[cookies->mode]);
+ printf(" %-25s %s\n", "active",
+ s->syncookies_active ? "active" : "inactive");
+ if (opts & PF_OPT_VERBOSE2) {
+ printf(" %-25s %d %%\n", "highwater", cookies->highwater);
+ printf(" %-25s %d %%\n", "lowwater", cookies->lowwater);
+ printf(" %-25s %d\n", "halfopen states", cookies->halfopen_states);
+ }
+ printf("Reassemble %24s %s\n",
+ s->reass & PF_REASS_ENABLED ? "yes" : "no",
+ s->reass & PF_REASS_NODF ? "no-df" : ""
+ );
}
}
@@ -632,10 +675,11 @@ print_running(struct pfctl_status *status)
}
void
-print_src_node(struct pf_src_node *sn, int opts)
+print_src_node(struct pfctl_src_node *sn, int opts)
{
struct pf_addr_wrap aw;
- int min, sec;
+ uint64_t min, sec;
+ const char *sn_type_names[] = PF_SN_TYPE_NAMES;
memset(&aw, 0, sizeof(aw));
if (sn->af == AF_INET)
@@ -647,7 +691,7 @@ print_src_node(struct pf_src_node *sn, int opts)
print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
printf(" -> ");
aw.v.a.addr = sn->raddr;
- print_addr(&aw, sn->af, opts & PF_OPT_VERBOSE2);
+ print_addr(&aw, sn->raf, opts & PF_OPT_VERBOSE2);
printf(" ( states %u, connections %u, rate %u.%u/%us )\n", sn->states,
sn->conn, sn->conn_rate.count / 1000,
(sn->conn_rate.count % 1000) / 100, sn->conn_rate.seconds);
@@ -656,37 +700,35 @@ print_src_node(struct pf_src_node *sn, int opts)
sn->creation /= 60;
min = sn->creation % 60;
sn->creation /= 60;
- printf(" age %.2u:%.2u:%.2u", sn->creation, min, sec);
+ printf(" age %.2" PRIu64 ":%.2" PRIu64 ":%.2" PRIu64,
+ sn->creation, min, sec);
if (sn->states == 0) {
sec = sn->expire % 60;
sn->expire /= 60;
min = sn->expire % 60;
sn->expire /= 60;
- printf(", expires in %.2u:%.2u:%.2u",
+ printf(", expires in %.2" PRIu64 ":%.2" PRIu64 ":%.2" PRIu64,
sn->expire, min, sec);
}
- printf(", %llu pkts, %llu bytes",
-#ifdef __FreeBSD__
- (unsigned long long)(sn->packets[0] + sn->packets[1]),
- (unsigned long long)(sn->bytes[0] + sn->bytes[1]));
-#else
+ printf(", %" PRIu64 " pkts, %" PRIu64 " bytes",
sn->packets[0] + sn->packets[1],
sn->bytes[0] + sn->bytes[1]);
-#endif
switch (sn->ruletype) {
case PF_NAT:
- if (sn->rule.nr != -1)
- printf(", nat rule %u", sn->rule.nr);
+ if (sn->rule != -1)
+ printf(", nat rule %u", sn->rule);
break;
case PF_RDR:
- if (sn->rule.nr != -1)
- printf(", rdr rule %u", sn->rule.nr);
+ if (sn->rule != -1)
+ printf(", rdr rule %u", sn->rule);
break;
case PF_PASS:
- if (sn->rule.nr != -1)
- printf(", filter rule %u", sn->rule.nr);
+ case PF_MATCH:
+ if (sn->rule != -1)
+ printf(", filter rule %u", sn->rule);
break;
}
+ printf(", %s", sn_type_names[sn->type]);
printf("\n");
}
}
@@ -747,6 +789,8 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
static const char *actiontypes[] = { "pass", "block", "", "", "", "",
"", "", "", "", "", "", "match" };
+ int i;
+
if (rule_numbers)
printf("@%u ", r->nr);
@@ -772,6 +816,8 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
else
printf(" on %s", r->ifname);
}
+ if (r->bridge_to[0])
+ printf(" bridge-to %s", r->bridge_to);
if (r->proto)
printf(" proto 0x%04x", r->proto);
@@ -787,6 +833,13 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
print_fromto(&r->ipsrc, PF_OSFP_ANY, &r->ipdst,
r->proto == ETHERTYPE_IP ? AF_INET : AF_INET6, 0,
0, 0);
+
+ i = 0;
+ while (r->label[i][0])
+ printf(" label \"%s\"", r->label[i++]);
+ if (r->ridentifier)
+ printf(" ridentifier %u", r->ridentifier);
+
if (r->qname[0])
printf(" queue %s", r->qname);
if (r->tagname[0])
@@ -803,31 +856,39 @@ print_eth_rule(struct pfctl_eth_rule *r, const char *anchor_call,
}
void
-print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numeric)
+print_rule(struct pfctl_rule *r, const char *anchor_call, int opts, int numeric)
{
static const char *actiontypes[] = { "pass", "block", "scrub",
- "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr" };
+ "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr",
+ "synproxy drop", "defer", "match", "af-rt", "route-to" };
static const char *anchortypes[] = { "anchor", "anchor", "anchor",
"anchor", "nat-anchor", "nat-anchor", "binat-anchor",
"binat-anchor", "rdr-anchor", "rdr-anchor" };
- int i, opts;
+ int i, ropts;
+ int verbose = opts & (PF_OPT_VERBOSE2 | PF_OPT_DEBUG);
+ char *p;
+
+ if ((r->rule_flag & PFRULE_EXPIRED) && (!verbose))
+ return;
if (verbose)
printf("@%d ", r->nr);
- if (r->action == PF_MATCH)
- printf("match");
- else if (r->action > PF_NORDR)
- printf("action(%d)", r->action);
- else if (anchor_call[0]) {
- if (anchor_call[0] == '_') {
- printf("%s", anchortypes[r->action]);
- } else
- printf("%s \"%s\"", anchortypes[r->action],
- anchor_call);
+ if (anchor_call[0]) {
+ if (r->action >= nitems(anchortypes)) {
+ printf("anchor(%d)", r->action);
+ } else {
+ p = strrchr(anchor_call, '/');
+ if (p ? p[1] == '_' : anchor_call[0] == '_')
+ printf("%s", anchortypes[r->action]);
+ else
+ printf("%s \"%s\"", anchortypes[r->action],
+ anchor_call);
+ }
} else {
- printf("%s", actiontypes[r->action]);
- if (r->natpass)
- printf(" pass");
+ if (r->action >= nitems(actiontypes))
+ printf("action(%d)", r->action);
+ else
+ printf("%s", actiontypes[r->action]);
}
if (r->action == PF_DROP) {
if (r->rule_flag & PFRULE_RETURN)
@@ -887,7 +948,9 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
printf(" (");
if (r->log & PF_LOG_ALL)
printf("%sall", count++ ? ", " : "");
- if (r->log & PF_LOG_SOCKET_LOOKUP)
+ if (r->log & PF_LOG_MATCHES)
+ printf("%smatches", count++ ? ", " : "");
+ if (r->log & PF_LOG_USER)
printf("%suser", count++ ? ", " : "");
if (r->logif)
printf("%sto pflog%u", count++ ? ", " : "",
@@ -911,7 +974,7 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
else if (r->rt == PF_DUPTO)
printf(" dup-to");
printf(" ");
- print_pool(&r->rpool, 0, 0, r->af, PF_PASS);
+ print_pool(&r->route, 0, 0, PF_PASS);
}
if (r->af) {
if (r->af == AF_INET)
@@ -928,19 +991,20 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
printf(" proto %u", r->proto);
}
print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto,
- verbose, numeric);
+ opts, numeric);
+ if (r->rcv_ifname[0])
+ printf(" %sreceived-on %s", r->rcvifnot ? "!" : "",
+ r->rcv_ifname);
if (r->uid.op)
- print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user",
- UID_MAX);
+ print_ugid(r->uid.op, r->uid.uid[0], r->uid.uid[1], "user");
if (r->gid.op)
- print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group",
- GID_MAX);
+ print_ugid(r->gid.op, r->gid.gid[0], r->gid.gid[1], "group");
if (r->flags || r->flagset) {
printf(" flags ");
print_flags(r->flags);
printf("/");
print_flags(r->flagset);
- } else if (r->action == PF_PASS &&
+ } else if ((r->action == PF_PASS || r->action == PF_MATCH) &&
(!r->proto || r->proto == IPPROTO_TCP) &&
!(r->rule_flag & PFRULE_FRAGMENT) &&
!anchor_call[0] && r->keep_state)
@@ -971,6 +1035,11 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
printf(" tos 0x%2.2x", r->tos);
if (r->prio)
printf(" prio %u", r->prio == PF_PRIO_ZERO ? 0 : r->prio);
+ if (r->pktrate.limit)
+ printf(" max-pkt-rate %u/%u", r->pktrate.limit,
+ r->pktrate.seconds);
+ if (r->max_pkt_size)
+ printf( " max-pkt-size %u", r->max_pkt_size);
if (r->scrub_flags & PFSTATE_SETMASK) {
char *comma = "";
printf(" set (");
@@ -982,6 +1051,10 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
r->set_prio[1]);
comma = ",";
}
+ if (r->scrub_flags & PFSTATE_SETTOS) {
+ printf("%s tos 0x%2.2x", comma, r->set_tos);
+ comma = ",";
+ }
printf(" )");
}
if (!r->keep_state && r->action == PF_PASS && !anchor_call[0])
@@ -1007,70 +1080,72 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
}
printf(" probability %s%%", buf);
}
- opts = 0;
+ ropts = 0;
if (r->max_states || r->max_src_nodes || r->max_src_states)
- opts = 1;
+ ropts = 1;
if (r->rule_flag & PFRULE_NOSYNC)
- opts = 1;
+ ropts = 1;
if (r->rule_flag & PFRULE_SRCTRACK)
- opts = 1;
+ ropts = 1;
if (r->rule_flag & PFRULE_IFBOUND)
- opts = 1;
+ ropts = 1;
if (r->rule_flag & PFRULE_STATESLOPPY)
- opts = 1;
- for (i = 0; !opts && i < PFTM_MAX; ++i)
+ ropts = 1;
+ if (r->rule_flag & PFRULE_PFLOW)
+ ropts = 1;
+ for (i = 0; !ropts && i < PFTM_MAX; ++i)
if (r->timeout[i])
- opts = 1;
- if (opts) {
+ ropts = 1;
+ if (ropts) {
printf(" (");
if (r->max_states) {
printf("max %u", r->max_states);
- opts = 0;
+ ropts = 0;
}
if (r->rule_flag & PFRULE_NOSYNC) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("no-sync");
- opts = 0;
+ ropts = 0;
}
if (r->rule_flag & PFRULE_SRCTRACK) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("source-track");
if (r->rule_flag & PFRULE_RULESRCTRACK)
printf(" rule");
else
printf(" global");
- opts = 0;
+ ropts = 0;
}
if (r->max_src_states) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("max-src-states %u", r->max_src_states);
- opts = 0;
+ ropts = 0;
}
if (r->max_src_conn) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("max-src-conn %u", r->max_src_conn);
- opts = 0;
+ ropts = 0;
}
if (r->max_src_conn_rate.limit) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("max-src-conn-rate %u/%u",
r->max_src_conn_rate.limit,
r->max_src_conn_rate.seconds);
- opts = 0;
+ ropts = 0;
}
if (r->max_src_nodes) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("max-src-nodes %u", r->max_src_nodes);
- opts = 0;
+ ropts = 0;
}
if (r->overload_tblname[0]) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("overload <%s>", r->overload_tblname);
if (r->flush)
@@ -1079,24 +1154,30 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
printf(" global");
}
if (r->rule_flag & PFRULE_IFBOUND) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("if-bound");
- opts = 0;
+ ropts = 0;
}
if (r->rule_flag & PFRULE_STATESLOPPY) {
- if (!opts)
+ if (!ropts)
printf(", ");
printf("sloppy");
- opts = 0;
+ ropts = 0;
+ }
+ if (r->rule_flag & PFRULE_PFLOW) {
+ if (!ropts)
+ printf(", ");
+ printf("pflow");
+ ropts = 0;
}
for (i = 0; i < PFTM_MAX; ++i)
if (r->timeout[i]) {
int j;
- if (!opts)
+ if (!ropts)
printf(", ");
- opts = 0;
+ ropts = 0;
for (j = 0; pf_timeouts[j].name != NULL;
++j)
if (pf_timeouts[j].timeout == i)
@@ -1107,25 +1188,43 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
}
printf(")");
}
- if (r->rule_flag & PFRULE_FRAGMENT)
- printf(" fragment");
- if (r->rule_flag & PFRULE_NODF)
- printf(" no-df");
- if (r->rule_flag & PFRULE_RANDOMID)
- printf(" random-id");
- if (r->min_ttl)
- printf(" min-ttl %d", r->min_ttl);
- if (r->max_mss)
- printf(" max-mss %d", r->max_mss);
- if (r->rule_flag & PFRULE_SET_TOS)
- printf(" set-tos 0x%2.2x", r->set_tos);
if (r->allow_opts)
printf(" allow-opts");
+ if (r->rule_flag & PFRULE_FRAGMENT)
+ printf(" fragment");
if (r->action == PF_SCRUB) {
+ /* Scrub flags for old-style scrub. */
+ if (r->rule_flag & PFRULE_NODF)
+ printf(" no-df");
+ if (r->rule_flag & PFRULE_RANDOMID)
+ printf(" random-id");
+ if (r->min_ttl)
+ printf(" min-ttl %d", r->min_ttl);
+ if (r->max_mss)
+ printf(" max-mss %d", r->max_mss);
+ if (r->rule_flag & PFRULE_SET_TOS)
+ printf(" set-tos 0x%2.2x", r->set_tos);
if (r->rule_flag & PFRULE_REASSEMBLE_TCP)
printf(" reassemble tcp");
-
- printf(" fragment reassemble");
+ /* The PFRULE_FRAGMENT_NOREASS is set on all rules by default! */
+ printf(" fragment %sreassemble",
+ r->rule_flag & PFRULE_FRAGMENT_NOREASS ? "no " : "");
+ } else if (r->scrub_flags & PFSTATE_SCRUBMASK || r->min_ttl || r->max_mss) {
+ /* Scrub actions on normal rules. */
+ printf(" scrub(");
+ if (r->scrub_flags & PFSTATE_NODF)
+ printf(" no-df");
+ if (r->scrub_flags & PFSTATE_RANDOMID)
+ printf(" random-id");
+ if (r->min_ttl)
+ printf(" min-ttl %d", r->min_ttl);
+ if (r->scrub_flags & PFSTATE_SETTOS)
+ printf(" set-tos 0x%2.2x", r->set_tos);
+ if (r->scrub_flags & PFSTATE_SCRUB_TCP)
+ printf(" reassemble tcp");
+ if (r->max_mss)
+ printf(" max-mss %d", r->max_mss);
+ printf(")");
}
i = 0;
while (r->label[i][0])
@@ -1141,6 +1240,8 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
printf(" %s %d",
r->free_flags & PFRULE_DN_IS_PIPE ? "dnpipe" : "dnqueue",
r->dnpipe);
+ if (r->rule_flag & PFRULE_ONCE)
+ printf(" once");
if (r->qname[0] && r->pqname[0])
printf(" queue(%s, %s)", r->qname, r->pqname);
else if (r->qname[0])
@@ -1161,24 +1262,44 @@ print_rule(struct pfctl_rule *r, const char *anchor_call, int verbose, int numer
if (PF_AZERO(&r->divert.addr, r->af)) {
printf(" divert-reply");
} else {
- /* XXX cut&paste from print_addr */
- char buf[48];
-
printf(" divert-to ");
- if (inet_ntop(r->af, &r->divert.addr, buf,
- sizeof(buf)) == NULL)
- printf("?");
- else
- printf("%s", buf);
+ print_addr_str(r->af, &r->divert.addr);
printf(" port %u", ntohs(r->divert.port));
}
#endif
}
- if (!anchor_call[0] && (r->action == PF_NAT ||
- r->action == PF_BINAT || r->action == PF_RDR)) {
+ if (anchor_call[0])
+ return;
+ if (r->action == PF_NAT || r->action == PF_BINAT || r->action == PF_RDR) {
printf(" -> ");
- print_pool(&r->rpool, r->rpool.proxy_port[0],
- r->rpool.proxy_port[1], r->af, r->action);
+ print_pool(&r->rdr, r->rdr.proxy_port[0],
+ r->rdr.proxy_port[1], r->action);
+ } else {
+ if (!TAILQ_EMPTY(&r->nat.list)) {
+ if (r->rule_flag & PFRULE_AFTO) {
+ printf(" af-to %s from ", r->naf == AF_INET ? "inet" : (r->naf == AF_INET6 ? "inet6" : "? "));
+ } else {
+ printf(" nat-to ");
+ }
+ print_pool(&r->nat, r->nat.proxy_port[0],
+ r->nat.proxy_port[1], PF_NAT);
+ }
+ if (!TAILQ_EMPTY(&r->rdr.list)) {
+ if (r->rule_flag & PFRULE_AFTO) {
+ printf(" to ");
+ } else {
+ printf(" rdr-to ");
+ }
+ print_pool(&r->rdr, r->rdr.proxy_port[0],
+ r->rdr.proxy_port[1], PF_RDR);
+ }
+ }
+
+ if (r->rule_flag & PFRULE_EXPIRED) {
+ printf(" # expired");
+
+ if (r->exptime != 0)
+ printf(" %s", ctime(&r->exptime));
}
}
@@ -1224,7 +1345,7 @@ int
parse_flags(char *s)
{
char *p, *q;
- u_int8_t f = 0;
+ uint16_t f = 0;
for (p = s; *p; p++) {
if ((q = strchr(tcpflags, *p)) == NULL)
@@ -1232,18 +1353,24 @@ parse_flags(char *s)
else
f |= 1 << (q - tcpflags);
}
- return (f ? f : PF_TH_ALL);
+ return (f ? f : TH_FLAGS);
}
void
-set_ipmask(struct node_host *h, u_int8_t b)
+set_ipmask(struct node_host *h, int bb)
{
struct pf_addr *m, *n;
int i, j = 0;
+ uint8_t b;
m = &h->addr.v.a.mask;
memset(m, 0, sizeof(*m));
+ if (bb == -1)
+ b = h->af == AF_INET ? 32 : 128;
+ else
+ b = bb;
+
while (b >= 32) {
m->addr32[j++] = 0xffffffff;
b -= 32;
@@ -1264,27 +1391,45 @@ int
check_netmask(struct node_host *h, sa_family_t af)
{
struct node_host *n = NULL;
- struct pf_addr *m;
+ struct pf_addr *m;
for (n = h; n != NULL; n = n->next) {
if (h->addr.type == PF_ADDR_TABLE)
continue;
m = &h->addr.v.a.mask;
- /* fix up netmask for dynaddr */
- if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL &&
- unmask(m, AF_INET6) > 32)
- set_ipmask(n, 32);
/* netmasks > 32 bit are invalid on v4 */
if (af == AF_INET &&
(m->addr32[1] || m->addr32[2] || m->addr32[3])) {
fprintf(stderr, "netmask %u invalid for IPv4 address\n",
- unmask(m, AF_INET6));
+ unmask(m));
return (1);
}
}
return (0);
}
+struct node_host *
+gen_dynnode(struct node_host *h, sa_family_t af)
+{
+ struct node_host *n;
+
+ if (h->addr.type != PF_ADDR_DYNIFTL)
+ return (NULL);
+
+ if ((n = calloc(1, sizeof(*n))) == NULL)
+ return (NULL);
+ bcopy(h, n, sizeof(*n));
+ n->ifname = NULL;
+ n->next = NULL;
+ n->tail = NULL;
+
+ /* fix up netmask */
+ if (af == AF_INET && unmask(&n->addr.v.a.mask) > 32)
+ set_ipmask(n, 32);
+
+ return (n);
+}
+
/* interface lookup routines */
static struct node_host *iftab;
@@ -1325,7 +1470,7 @@ ifa_add_groups_to_map(char *ifa_name)
ENTRY item;
ENTRY *ret_item;
int *answer;
-
+
item.key = ifg->ifgrq_group;
if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0) {
struct ifgroupreq ifgr2;
@@ -1364,13 +1509,14 @@ ifa_load(void)
err(1, "getifaddrs");
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (!(ifa->ifa_addr->sa_family == AF_INET ||
+ if (ifa->ifa_addr == NULL ||
+ !(ifa->ifa_addr->sa_family == AF_INET ||
ifa->ifa_addr->sa_family == AF_INET6 ||
ifa->ifa_addr->sa_family == AF_LINK))
continue;
n = calloc(1, sizeof(struct node_host));
if (n == NULL)
- err(1, "address: calloc");
+ err(1, "%s: calloc", __func__);
n->af = ifa->ifa_addr->sa_family;
n->ifa_flags = ifa->ifa_flags;
#ifdef __KAME__
@@ -1389,43 +1535,28 @@ ifa_load(void)
}
#endif
n->ifindex = 0;
- if (n->af == AF_INET) {
- memcpy(&n->addr.v.a.addr, &((struct sockaddr_in *)
- ifa->ifa_addr)->sin_addr.s_addr,
- sizeof(struct in_addr));
- memcpy(&n->addr.v.a.mask, &((struct sockaddr_in *)
- ifa->ifa_netmask)->sin_addr.s_addr,
- sizeof(struct in_addr));
- if (ifa->ifa_broadaddr != NULL)
- memcpy(&n->bcast, &((struct sockaddr_in *)
- ifa->ifa_broadaddr)->sin_addr.s_addr,
- sizeof(struct in_addr));
- if (ifa->ifa_dstaddr != NULL)
- memcpy(&n->peer, &((struct sockaddr_in *)
- ifa->ifa_dstaddr)->sin_addr.s_addr,
- sizeof(struct in_addr));
- } else if (n->af == AF_INET6) {
- memcpy(&n->addr.v.a.addr, &((struct sockaddr_in6 *)
- ifa->ifa_addr)->sin6_addr.s6_addr,
- sizeof(struct in6_addr));
- memcpy(&n->addr.v.a.mask, &((struct sockaddr_in6 *)
- ifa->ifa_netmask)->sin6_addr.s6_addr,
- sizeof(struct in6_addr));
- if (ifa->ifa_broadaddr != NULL)
- memcpy(&n->bcast, &((struct sockaddr_in6 *)
- ifa->ifa_broadaddr)->sin6_addr.s6_addr,
- sizeof(struct in6_addr));
- if (ifa->ifa_dstaddr != NULL)
- memcpy(&n->peer, &((struct sockaddr_in6 *)
- ifa->ifa_dstaddr)->sin6_addr.s6_addr,
- sizeof(struct in6_addr));
- n->ifindex = ((struct sockaddr_in6 *)
- ifa->ifa_addr)->sin6_scope_id;
- } else if (n->af == AF_LINK) {
+ if (n->af == AF_LINK) {
+ n->ifindex = ((struct sockaddr_dl *)
+ ifa->ifa_addr)->sdl_index;
ifa_add_groups_to_map(ifa->ifa_name);
+ } else {
+ copy_satopfaddr(&n->addr.v.a.addr, ifa->ifa_addr);
+ ifa->ifa_netmask->sa_family = ifa->ifa_addr->sa_family;
+ copy_satopfaddr(&n->addr.v.a.mask, ifa->ifa_netmask);
+ if (ifa->ifa_broadaddr != NULL) {
+ ifa->ifa_broadaddr->sa_family = ifa->ifa_addr->sa_family;
+ copy_satopfaddr(&n->bcast, ifa->ifa_broadaddr);
+ }
+ if (ifa->ifa_dstaddr != NULL) {
+ ifa->ifa_dstaddr->sa_family = ifa->ifa_addr->sa_family;
+ copy_satopfaddr(&n->peer, ifa->ifa_dstaddr);
+ }
+ if (n->af == AF_INET6)
+ n->ifindex = ((struct sockaddr_in6 *)
+ ifa->ifa_addr) ->sin6_scope_id;
}
if ((n->ifname = strdup(ifa->ifa_name)) == NULL)
- err(1, "ifa_load: strdup");
+ err(1, "%s: strdup", __func__);
n->next = NULL;
n->tail = n;
if (h == NULL)
@@ -1481,7 +1612,7 @@ is_a_group(char *name)
{
ENTRY item;
ENTRY *ret_item;
-
+
item.key = name;
if (hsearch_r(item, FIND, &ret_item, &isgroup_map) == 0)
return (0);
@@ -1489,6 +1620,34 @@ is_a_group(char *name)
return (*(int *)ret_item->data);
}
+unsigned int
+ifa_nametoindex(const char *ifa_name)
+{
+ struct node_host *p;
+
+ for (p = iftab; p; p = p->next) {
+ if (p->af == AF_LINK && strcmp(p->ifname, ifa_name) == 0)
+ return (p->ifindex);
+ }
+ errno = ENXIO;
+ return (0);
+}
+
+char *
+ifa_indextoname(unsigned int ifindex, char *ifa_name)
+{
+ struct node_host *p;
+
+ for (p = iftab; p; p = p->next) {
+ if (p->af == AF_LINK && ifindex == p->ifindex) {
+ strlcpy(ifa_name, p->ifname, IFNAMSIZ);
+ return (ifa_name);
+ }
+ }
+ errno = ENXIO;
+ return (NULL);
+}
+
struct node_host *
ifa_exists(char *ifa_name)
{
@@ -1577,6 +1736,8 @@ ifa_lookup(char *ifa_name, int flags)
if ((flags & PFI_AFLAG_BROADCAST) &&
!(p->ifa_flags & IFF_BROADCAST))
continue;
+ if ((flags & PFI_AFLAG_BROADCAST) && p->bcast.v4.s_addr == 0)
+ continue;
if ((flags & PFI_AFLAG_PEER) &&
!(p->ifa_flags & IFF_POINTOPOINT))
continue;
@@ -1598,7 +1759,7 @@ ifa_lookup(char *ifa_name, int flags)
got6 = 1;
n = calloc(1, sizeof(struct node_host));
if (n == NULL)
- err(1, "address: calloc");
+ err(1, "%s: calloc", __func__);
n->af = p->af;
if (flags & PFI_AFLAG_BROADCAST)
memcpy(&n->addr.v.a.addr, &p->bcast,
@@ -1610,19 +1771,9 @@ ifa_lookup(char *ifa_name, int flags)
memcpy(&n->addr.v.a.addr, &p->addr.v.a.addr,
sizeof(struct pf_addr));
if (flags & PFI_AFLAG_NETWORK)
- set_ipmask(n, unmask(&p->addr.v.a.mask, n->af));
- else {
- if (n->af == AF_INET) {
- if (p->ifa_flags & IFF_LOOPBACK &&
- p->ifa_flags & IFF_LINK1)
- memcpy(&n->addr.v.a.mask,
- &p->addr.v.a.mask,
- sizeof(struct pf_addr));
- else
- set_ipmask(n, 32);
- } else
- set_ipmask(n, 128);
- }
+ set_ipmask(n, unmask(&p->addr.v.a.mask));
+ else
+ set_ipmask(n, -1);
n->ifindex = p->ifindex;
n->ifname = strdup(p->ifname);
@@ -1661,52 +1812,36 @@ ifa_skip_if(const char *filter, struct node_host *p)
struct node_host *
-host(const char *s)
+host(const char *s, int opts)
{
struct node_host *h = NULL;
- int mask, v4mask, v6mask, cont = 1;
- char *p, *q, *ps;
-
- if ((p = strrchr(s, '/')) != NULL) {
- mask = strtol(p+1, &q, 0);
- if (!q || *q || mask > 128 || q == (p+1)) {
- fprintf(stderr, "invalid netmask '%s'\n", p);
- return (NULL);
+ int mask = -1;
+ char *p, *ps;
+ const char *errstr;
+
+ if ((p = strchr(s, '/')) != NULL) {
+ mask = strtonum(p+1, 0, 128, &errstr);
+ if (errstr) {
+ fprintf(stderr, "netmask is %s: %s\n", errstr, p);
+ goto error;
}
if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
- err(1, "host: malloc");
+ err(1, "%s: malloc", __func__);
strlcpy(ps, s, strlen(s) - strlen(p) + 1);
- v4mask = v6mask = mask;
} else {
if ((ps = strdup(s)) == NULL)
- err(1, "host: strdup");
- v4mask = 32;
- v6mask = 128;
- mask = -1;
+ err(1, "%s: strdup", __func__);
}
- /* IPv4 address? */
- if (cont && (h = host_v4(s, mask)) != NULL)
- cont = 0;
-
- /* IPv6 address? */
- if (cont && (h = host_v6(ps, v6mask)) != NULL)
- cont = 0;
-
- /* interface with this name exists? */
- /* expensive with thousands of interfaces - prioritze IPv4/6 check */
- if (cont && (h = host_if(ps, mask)) != NULL)
- cont = 0;
-
- /* dns lookup */
- if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL)
- cont = 0;
- free(ps);
-
- if (h == NULL || cont == 1) {
+ if ((h = host_ip(ps, mask)) == NULL &&
+ (h = host_if(ps, mask)) == NULL &&
+ (h = host_dns(ps, mask, (opts & PF_OPT_NODNS))) == NULL) {
fprintf(stderr, "no IP address found for %s\n", s);
- return (NULL);
+ goto error;
}
+
+error:
+ free(ps);
return (h);
}
@@ -1728,100 +1863,79 @@ host_if(const char *s, int mask)
flags |= PFI_AFLAG_PEER;
else if (!strcmp(p+1, "0"))
flags |= PFI_AFLAG_NOALIAS;
- else {
- free(ps);
- return (NULL);
- }
+ else
+ goto error;
*p = '\0';
}
if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { /* Yep! */
fprintf(stderr, "illegal combination of interface modifiers\n");
- free(ps);
- return (NULL);
+ goto error;
}
if ((flags & (PFI_AFLAG_NETWORK|PFI_AFLAG_BROADCAST)) && mask > -1) {
fprintf(stderr, "network or broadcast lookup, but "
"extra netmask given\n");
- free(ps);
- return (NULL);
+ goto error;
}
if (ifa_exists(ps) || !strncmp(ps, "self", IFNAMSIZ)) {
/* interface with this name exists */
h = ifa_lookup(ps, flags);
- for (n = h; n != NULL && mask > -1; n = n->next)
- set_ipmask(n, mask);
+ if (mask > -1)
+ for (n = h; n != NULL; n = n->next)
+ set_ipmask(n, mask);
}
+error:
free(ps);
return (h);
}
struct node_host *
-host_v4(const char *s, int mask)
+host_ip(const char *s, int mask)
{
+ struct addrinfo hints, *res;
struct node_host *h = NULL;
- struct in_addr ina;
- int bits = 32;
- memset(&ina, 0, sizeof(struct in_addr));
- if (strrchr(s, '/') != NULL) {
- if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
- return (NULL);
- } else {
- if (inet_pton(AF_INET, s, &ina) != 1)
- return (NULL);
- }
-
- h = calloc(1, sizeof(struct node_host));
+ h = calloc(1, sizeof(*h));
if (h == NULL)
- err(1, "address: calloc");
- h->ifname = NULL;
- h->af = AF_INET;
- h->addr.v.a.addr.addr32[0] = ina.s_addr;
- set_ipmask(h, bits);
- h->next = NULL;
- h->tail = h;
-
- return (h);
-}
-
-struct node_host *
-host_v6(const char *s, int mask)
-{
- struct addrinfo hints, *res;
- struct node_host *h = NULL;
+ err(1, "%s: calloc", __func__);
+ if (mask != -1) {
+ /* Try to parse 10/8 */
+ h->af = AF_INET;
+ if (inet_net_pton(AF_INET, s, &h->addr.v.a.addr.v4,
+ sizeof(h->addr.v.a.addr.v4)) != -1)
+ goto out;
+ }
memset(&hints, 0, sizeof(hints));
- hints.ai_family = AF_INET6;
+ hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
- if (getaddrinfo(s, "0", &hints, &res) == 0) {
- h = calloc(1, sizeof(struct node_host));
- if (h == NULL)
- err(1, "address: calloc");
- h->ifname = NULL;
- h->af = AF_INET6;
- memcpy(&h->addr.v.a.addr,
- &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr,
- sizeof(h->addr.v.a.addr));
- h->ifindex =
- ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
- set_ipmask(h, mask);
+ if (getaddrinfo(s, NULL, &hints, &res) == 0) {
+ h->af = res->ai_family;
+ copy_satopfaddr(&h->addr.v.a.addr, res->ai_addr);
+ if (h->af == AF_INET6)
+ h->ifindex =
+ ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
freeaddrinfo(res);
- h->next = NULL;
- h->tail = h;
+ } else {
+ free(h);
+ return (NULL);
}
+out:
+ set_ipmask(h, mask);
+ h->ifname = NULL;
+ h->next = NULL;
+ h->tail = h;
return (h);
}
struct node_host *
-host_dns(const char *s, int v4mask, int v6mask)
+host_dns(const char *s, int mask, int numeric)
{
struct addrinfo hints, *res0, *res;
struct node_host *n, *h = NULL;
- int error, noalias = 0;
- int got4 = 0, got6 = 0;
+ int noalias = 0, got4 = 0, got6 = 0;
char *p, *ps;
if ((ps = strdup(s)) == NULL)
@@ -1833,11 +1947,10 @@ host_dns(const char *s, int v4mask, int v6mask)
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; /* DUMMY */
- error = getaddrinfo(ps, NULL, &hints, &res0);
- if (error) {
- free(ps);
- return (h);
- }
+ if (numeric)
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(ps, NULL, &hints, &res0) != 0)
+ goto error;
for (res = res0; res; res = res->ai_next) {
if (res->ai_family != AF_INET &&
@@ -1859,22 +1972,11 @@ host_dns(const char *s, int v4mask, int v6mask)
err(1, "host_dns: calloc");
n->ifname = NULL;
n->af = res->ai_family;
- if (res->ai_family == AF_INET) {
- memcpy(&n->addr.v.a.addr,
- &((struct sockaddr_in *)
- res->ai_addr)->sin_addr.s_addr,
- sizeof(struct in_addr));
- set_ipmask(n, v4mask);
- } else {
- memcpy(&n->addr.v.a.addr,
- &((struct sockaddr_in6 *)
- res->ai_addr)->sin6_addr.s6_addr,
- sizeof(struct in6_addr));
+ copy_satopfaddr(&n->addr.v.a.addr, res->ai_addr);
+ if (res->ai_family == AF_INET6)
n->ifindex =
- ((struct sockaddr_in6 *)
- res->ai_addr)->sin6_scope_id;
- set_ipmask(n, v6mask);
- }
+ ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
+ set_ipmask(n, mask);
n->next = NULL;
n->tail = n;
if (h == NULL)
@@ -1885,6 +1987,7 @@ host_dns(const char *s, int v4mask, int v6mask)
}
}
freeaddrinfo(res0);
+error:
free(ps);
return (h);
@@ -1896,7 +1999,7 @@ host_dns(const char *s, int v4mask, int v6mask)
* if set to 1, only simple addresses are accepted (no netblock, no "!").
*/
int
-append_addr(struct pfr_buffer *b, char *s, int test)
+append_addr(struct pfr_buffer *b, char *s, int test, int opts)
{
char *r;
struct node_host *h, *n;
@@ -1904,7 +2007,7 @@ append_addr(struct pfr_buffer *b, char *s, int test)
for (r = s; *r == '!'; r++)
not = !not;
- if ((n = host(r)) == NULL) {
+ if ((n = host(r, opts)) == NULL) {
errno = 0;
return (-1);
}
@@ -1933,7 +2036,7 @@ append_addr_host(struct pfr_buffer *b, struct node_host *n, int test, int not)
bzero(&addr, sizeof(addr));
addr.pfra_not = n->not ^ not;
addr.pfra_af = n->af;
- addr.pfra_net = unmask(&n->addr.v.a.mask, n->af);
+ addr.pfra_net = unmask(&n->addr.v.a.mask);
switch (n->af) {
case AF_INET:
addr.pfra_ip4addr.s_addr = n->addr.v.a.addr.addr32[0];
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index 13151cc33829..44ddfb45fbe1 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -29,8 +29,6 @@
* 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 _PFCTL_PARSER_H_
@@ -38,26 +36,29 @@
#include <libpfctl.h>
+#include <pfctl.h>
+
#define PF_OSFP_FILE "/etc/pf.os"
-#define PF_OPT_DISABLE 0x0001
-#define PF_OPT_ENABLE 0x0002
-#define PF_OPT_VERBOSE 0x0004
-#define PF_OPT_NOACTION 0x0008
-#define PF_OPT_QUIET 0x0010
-#define PF_OPT_CLRRULECTRS 0x0020
-#define PF_OPT_USEDNS 0x0040
-#define PF_OPT_VERBOSE2 0x0080
-#define PF_OPT_DUMMYACTION 0x0100
-#define PF_OPT_DEBUG 0x0200
-#define PF_OPT_SHOWALL 0x0400
-#define PF_OPT_OPTIMIZE 0x0800
-#define PF_OPT_NUMERIC 0x1000
-#define PF_OPT_MERGE 0x2000
-#define PF_OPT_RECURSE 0x4000
-#define PF_OPT_KILLMATCH 0x8000
-
-#define PF_TH_ALL 0xFF
+#define PF_OPT_DISABLE 0x00001
+#define PF_OPT_ENABLE 0x00002
+#define PF_OPT_VERBOSE 0x00004
+#define PF_OPT_NOACTION 0x00008
+#define PF_OPT_QUIET 0x00010
+#define PF_OPT_CLRRULECTRS 0x00020
+#define PF_OPT_USEDNS 0x00040
+#define PF_OPT_VERBOSE2 0x00080
+#define PF_OPT_DUMMYACTION 0x00100
+#define PF_OPT_DEBUG 0x00200
+#define PF_OPT_SHOWALL 0x00400
+#define PF_OPT_OPTIMIZE 0x00800
+#define PF_OPT_NUMERIC 0x01000
+#define PF_OPT_MERGE 0x02000
+#define PF_OPT_RECURSE 0x04000
+#define PF_OPT_KILLMATCH 0x08000
+#define PF_OPT_NODNS 0x10000
+#define PF_OPT_IGNFAIL 0x20000
+#define PF_OPT_CALLSHOW 0x40000
#define PF_NAT_PROXY_PORT_LOW 50001
#define PF_NAT_PROXY_PORT_HIGH 65535
@@ -77,6 +78,7 @@ struct pfr_buffer; /* forward definition */
struct pfctl {
int dev;
+ struct pfctl_handle *h;
int opts;
int optimize;
int loadopt;
@@ -90,6 +92,7 @@ struct pfctl {
struct pfioc_queue *pqueue;
struct pfr_buffer *trans;
struct pfctl_anchor *anchor, *alast;
+ struct pfr_ktablehead pfr_ktlast;
int eth_nr;
struct pfctl_eth_anchor *eanchor, *ealast;
struct pfctl_eth_anchor *eastack[PFCTL_ANCHOR_STACK_DEPTH];
@@ -101,6 +104,7 @@ struct pfctl {
u_int32_t limit[PF_LIMIT_MAX];
u_int32_t debug;
u_int32_t hostid;
+ u_int32_t reassemble;
char *ifname;
bool keep_counters;
u_int8_t syncookies;
@@ -112,6 +116,7 @@ struct pfctl {
u_int8_t debug_set;
u_int8_t hostid_set;
u_int8_t ifname_set;
+ u_int8_t reass_set;
};
struct node_if {
@@ -136,6 +141,8 @@ struct node_host {
struct node_host *tail;
};
+void freehostlist(struct node_host *);
+
struct node_mac {
u_int8_t mac[ETHER_ADDR_LEN];
u_int8_t mask[ETHER_ADDR_LEN];
@@ -256,10 +263,10 @@ struct pf_opt_tbl {
char pt_name[PF_TABLE_NAME_SIZE];
int pt_rulecount;
int pt_generated;
+ uint32_t pt_refcnt;
struct node_tinithead pt_nodes;
struct pfr_buffer *pt_buf;
};
-#define PF_OPT_TABLE_PREFIX "__automatic_"
/* optimizer pf_rule container */
struct pf_opt_rule {
@@ -273,32 +280,38 @@ struct pf_opt_rule {
TAILQ_HEAD(pf_opt_queue, pf_opt_rule);
+struct pfr_uktable;
+
+void copy_satopfaddr(struct pf_addr *, struct sockaddr *);
+
int pfctl_rules(int, char *, int, int, char *, struct pfr_buffer *);
int pfctl_optimize_ruleset(struct pfctl *, struct pfctl_ruleset *);
-int pfctl_append_rule(struct pfctl *, struct pfctl_rule *, const char *);
+void pfctl_init_rule(struct pfctl_rule *r);
+void pfctl_append_rule(struct pfctl *, struct pfctl_rule *);
int pfctl_append_eth_rule(struct pfctl *, struct pfctl_eth_rule *,
const char *);
int pfctl_add_altq(struct pfctl *, struct pf_altq *);
-int pfctl_add_pool(struct pfctl *, struct pfctl_pool *, sa_family_t);
+int pfctl_add_pool(struct pfctl *, struct pfctl_pool *, int);
void pfctl_move_pool(struct pfctl_pool *, struct pfctl_pool *);
void pfctl_clear_pool(struct pfctl_pool *);
-int pfctl_set_timeout(struct pfctl *, const char *, int, int);
+int pfctl_apply_timeout(struct pfctl *, const char *, int, int);
+int pfctl_set_reassembly(struct pfctl *, int, int);
int pfctl_set_optimization(struct pfctl *, const char *);
-int pfctl_set_limit(struct pfctl *, const char *, unsigned int);
+int pfctl_apply_limit(struct pfctl *, const char *, unsigned int);
int pfctl_set_logif(struct pfctl *, char *);
-int pfctl_set_hostid(struct pfctl *, u_int32_t);
-int pfctl_set_debug(struct pfctl *, char *);
+void pfctl_set_hostid(struct pfctl *, u_int32_t);
+int pfctl_do_set_debug(struct pfctl *, char *);
int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
int pfctl_cfg_syncookies(struct pfctl *, uint8_t, struct pfctl_watermarks *);
int parse_config(char *, struct pfctl *);
int parse_flags(char *);
-int pfctl_load_anchors(int, struct pfctl *, struct pfr_buffer *);
+int pfctl_load_anchors(int, struct pfctl *);
-void print_pool(struct pfctl_pool *, u_int16_t, u_int16_t, sa_family_t, int);
-void print_src_node(struct pf_src_node *, int);
+void print_pool(struct pfctl_pool *, u_int16_t, u_int16_t, int);
+void print_src_node(struct pfctl_src_node *, int);
void print_eth_rule(struct pfctl_eth_rule *, const char *, int);
void print_rule(struct pfctl_rule *, const char *, int, int);
void print_tabledef(const char *, int, int, struct node_tinithead *);
@@ -316,7 +329,7 @@ void print_queue(const struct pf_altq *, unsigned, struct node_queue_bw *,
int, struct node_queue_opt *);
int pfctl_define_table(char *, int, int, const char *, struct pfr_buffer *,
- u_int32_t);
+ u_int32_t, struct pfr_uktable *);
void pfctl_clear_fingerprints(int, int);
int pfctl_file_fingerprints(int, int, const char *);
@@ -337,10 +350,10 @@ struct icmpcodeent {
u_int8_t code;
};
-const struct icmptypeent *geticmptypebynumber(u_int8_t, u_int8_t);
-const struct icmptypeent *geticmptypebyname(char *, u_int8_t);
-const struct icmpcodeent *geticmpcodebynumber(u_int8_t, u_int8_t, u_int8_t);
-const struct icmpcodeent *geticmpcodebyname(u_long, char *, u_int8_t);
+const struct icmptypeent *geticmptypebynumber(u_int8_t, sa_family_t);
+const struct icmptypeent *geticmptypebyname(char *, sa_family_t);
+const struct icmpcodeent *geticmpcodebynumber(u_int8_t, u_int8_t, sa_family_t);
+const struct icmpcodeent *geticmpcodebyname(u_long, char *, sa_family_t);
struct pf_timeout {
const char *name;
@@ -356,18 +369,24 @@ struct pf_timeout {
extern const struct pf_timeout pf_timeouts[];
-void set_ipmask(struct node_host *, u_int8_t);
+void set_ipmask(struct node_host *, int);
int check_netmask(struct node_host *, sa_family_t);
-int unmask(struct pf_addr *, sa_family_t);
+int unmask(struct pf_addr *);
+struct node_host *gen_dynnode(struct node_host *, sa_family_t);
void ifa_load(void);
+unsigned int ifa_nametoindex(const char *);
+char *ifa_indextoname(unsigned int, char *);
int get_query_socket(void);
struct node_host *ifa_exists(char *);
struct node_host *ifa_grouplookup(char *ifa_name, int flags);
struct node_host *ifa_lookup(char *, int);
-struct node_host *host(const char *);
+struct node_host *host(const char *, int);
-int append_addr(struct pfr_buffer *, char *, int);
+int append_addr(struct pfr_buffer *, char *, int, int);
int append_addr_host(struct pfr_buffer *,
struct node_host *, int, int);
+int pfr_ktable_compare(struct pfr_ktable *,
+ struct pfr_ktable *);
+RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
#endif /* _PFCTL_PARSER_H_ */
diff --git a/sbin/pfctl/pfctl_qstats.c b/sbin/pfctl/pfctl_qstats.c
index 5312a6da8eaa..397598b0c114 100644
--- a/sbin/pfctl/pfctl_qstats.c
+++ b/sbin/pfctl/pfctl_qstats.c
@@ -17,8 +17,6 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#define PFIOC_USE_LATEST
#include <sys/types.h>
diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c
index 5d71a4e6ac89..98f907738d95 100644
--- a/sbin/pfctl/pfctl_radix.c
+++ b/sbin/pfctl/pfctl_radix.c
@@ -32,9 +32,6 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -51,12 +48,26 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include "pfctl.h"
+#include "pfctl_parser.h"
#define BUF_SIZE 256
extern int dev;
-static int pfr_next_token(char buf[], FILE *);
+static int pfr_next_token(char buf[BUF_SIZE], FILE *);
+
+struct pfr_ktablehead pfr_ktables = { 0 };
+RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
+
+int
+pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
+{
+ int d;
+
+ if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
+ return (d);
+ return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor));
+}
static void
pfr_report_error(struct pfr_table *tbl, struct pfioc_table *io,
@@ -77,65 +88,15 @@ pfr_report_error(struct pfr_table *tbl, struct pfioc_table *io,
}
int
-pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
-{
- struct pfioc_table io;
-
- bzero(&io, sizeof io);
- io.pfrio_flags = flags;
- if (filter != NULL)
- io.pfrio_table = *filter;
- if (ioctl(dev, DIOCRCLRTABLES, &io))
- return (-1);
- if (ndel != NULL)
- *ndel = io.pfrio_ndel;
- return (0);
-}
-
-int
-pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
+pfr_add_table(struct pfr_table *tbl, int *nadd, int flags)
{
- struct pfioc_table io;
-
- if (size < 0 || (size && tbl == NULL)) {
- errno = EINVAL;
- return (-1);
- }
- bzero(&io, sizeof io);
- io.pfrio_flags = flags;
- io.pfrio_buffer = tbl;
- io.pfrio_esize = sizeof(*tbl);
- io.pfrio_size = size;
- if (ioctl(dev, DIOCRADDTABLES, &io)) {
- pfr_report_error(tbl, &io, "add table");
- return (-1);
- }
- if (nadd != NULL)
- *nadd = io.pfrio_nadd;
- return (0);
+ return (pfctl_add_table(pfh, tbl, nadd, flags));
}
int
-pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
+pfr_del_table(struct pfr_table *tbl, int *ndel, int flags)
{
- struct pfioc_table io;
-
- if (size < 0 || (size && tbl == NULL)) {
- errno = EINVAL;
- return (-1);
- }
- bzero(&io, sizeof io);
- io.pfrio_flags = flags;
- io.pfrio_buffer = tbl;
- io.pfrio_esize = sizeof(*tbl);
- io.pfrio_size = size;
- if (ioctl(dev, DIOCRDELTABLES, &io)) {
- pfr_report_error(tbl, &io, "delete table");
- return (-1);
- }
- if (ndel != NULL)
- *ndel = io.pfrio_ndel;
- return (0);
+ return (pfctl_del_table(pfh, tbl, ndel, flags));
}
int
@@ -164,47 +125,9 @@ pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
}
int
-pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
- int flags)
-{
- struct pfioc_table io;
-
- if (size == NULL || *size < 0 || (*size && tbl == NULL)) {
- errno = EINVAL;
- return (-1);
- }
- bzero(&io, sizeof io);
- io.pfrio_flags = flags;
- if (filter != NULL)
- io.pfrio_table = *filter;
- io.pfrio_buffer = tbl;
- io.pfrio_esize = sizeof(*tbl);
- io.pfrio_size = *size;
- if (ioctl(dev, DIOCRGETTSTATS, &io)) {
- pfr_report_error(filter, &io, "get tstats for");
- return (-1);
- }
- *size = io.pfrio_size;
- return (0);
-}
-
-int
pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
{
- struct pfioc_table io;
-
- if (tbl == NULL) {
- errno = EINVAL;
- return (-1);
- }
- bzero(&io, sizeof io);
- io.pfrio_flags = flags;
- io.pfrio_table = *tbl;
- if (ioctl(dev, DIOCRCLRADDRS, &io))
- return (-1);
- if (ndel != NULL)
- *ndel = io.pfrio_ndel;
- return (0);
+ return (pfctl_clear_addrs(pfh, tbl, ndel, flags));
}
int
@@ -213,7 +136,10 @@ pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
{
int ret;
- ret = pfctl_table_add_addrs(dev, tbl, addr, size, nadd, flags);
+ if (*nadd)
+ *nadd = 0;
+
+ ret = pfctl_table_add_addrs_h(pfh, tbl, addr, size, nadd, flags);
if (ret) {
errno = ret;
return (-1);
@@ -227,7 +153,7 @@ pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
{
int ret;
- ret = pfctl_table_del_addrs(dev, tbl, addr, size, ndel, flags);
+ ret = pfctl_table_del_addrs_h(pfh, tbl, addr, size, ndel, flags);
if (ret) {
errno = ret;
return (-1);
@@ -290,23 +216,23 @@ pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
}
int
-pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
+pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *nzero, int flags)
{
struct pfioc_table io;
- if (size < 0 || (size && !tbl)) {
+ if (size < 0 || !tbl || (size && !addr)) {
errno = EINVAL;
return (-1);
}
bzero(&io, sizeof io);
io.pfrio_flags = flags;
- io.pfrio_buffer = tbl;
- io.pfrio_esize = sizeof(*tbl);
+ io.pfrio_table = *tbl;
+ io.pfrio_buffer = addr;
+ io.pfrio_esize = sizeof(*addr);
io.pfrio_size = size;
- if (ioctl(dev, DIOCRCLRTSTATS, &io)) {
- pfr_report_error(tbl, &io, "clear tstats from");
+ if (ioctl(dev, DIOCRCLRASTATS, &io) == -1)
return (-1);
- }
if (nzero)
*nzero = io.pfrio_nzero;
return (0);
@@ -344,6 +270,7 @@ pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
struct pfioc_table io;
if (tbl == NULL || size < 0 || (size && addr == NULL)) {
+ DBGPRINT("%s %p %d %p\n", __func__, tbl, size, addr);
errno = EINVAL;
return (-1);
}
@@ -464,25 +391,15 @@ pfr_buf_grow(struct pfr_buffer *b, int minsize)
if (!b->pfrb_msize) {
if (minsize < 64)
minsize = 64;
- b->pfrb_caddr = calloc(bs, minsize);
- if (b->pfrb_caddr == NULL)
- return (-1);
- b->pfrb_msize = minsize;
- } else {
- if (minsize == 0)
- minsize = b->pfrb_msize * 2;
- if (minsize < 0 || minsize >= SIZE_T_MAX / bs) {
- /* msize overflow */
- errno = ENOMEM;
- return (-1);
- }
- p = realloc(b->pfrb_caddr, minsize * bs);
- if (p == NULL)
- return (-1);
- bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
- b->pfrb_caddr = p;
- b->pfrb_msize = minsize;
}
+ if (minsize == 0)
+ minsize = b->pfrb_msize * 2;
+ p = reallocarray(b->pfrb_caddr, minsize, bs);
+ if (p == NULL)
+ return (-1);
+ bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs);
+ b->pfrb_caddr = p;
+ b->pfrb_msize = minsize;
return (0);
}
@@ -494,15 +411,14 @@ pfr_buf_clear(struct pfr_buffer *b)
{
if (b == NULL)
return;
- if (b->pfrb_caddr != NULL)
- free(b->pfrb_caddr);
+ free(b->pfrb_caddr);
b->pfrb_caddr = NULL;
b->pfrb_size = b->pfrb_msize = 0;
}
int
pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
- int (*append_addr)(struct pfr_buffer *, char *, int))
+ int (*append_addr)(struct pfr_buffer *, char *, int, int), int opts)
{
FILE *fp;
char buf[BUF_SIZE];
@@ -518,7 +434,7 @@ pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork,
return (-1);
}
while ((rv = pfr_next_token(buf, fp)) == 1)
- if (append_addr(b, buf, nonetwork)) {
+ if (append_addr(b, buf, nonetwork, opts)) {
rv = -1;
break;
}
@@ -537,8 +453,8 @@ pfr_next_token(char buf[BUF_SIZE], FILE *fp)
/* skip spaces */
while (isspace(next_ch) && !feof(fp))
next_ch = fgetc(fp);
- /* remove from '#' until end of line */
- if (next_ch == '#')
+ /* remove from '#' or ';' until end of line */
+ if (next_ch == '#' || next_ch == ';')
while (!feof(fp)) {
next_ch = fgetc(fp);
if (next_ch == '\n')
@@ -563,16 +479,3 @@ pfr_next_token(char buf[BUF_SIZE], FILE *fp)
buf[i] = '\0';
return (1);
}
-
-char *
-pfr_strerror(int errnum)
-{
- switch (errnum) {
- case ESRCH:
- return "Table does not exist";
- case ENOENT:
- return "Anchor or Ruleset does not exist";
- default:
- return strerror(errnum);
- }
-}
diff --git a/sbin/pfctl/pfctl_table.c b/sbin/pfctl/pfctl_table.c
index db338fbe0876..4955e1791fd7 100644
--- a/sbin/pfctl/pfctl_table.c
+++ b/sbin/pfctl/pfctl_table.c
@@ -32,16 +32,14 @@
*
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include <net/if.h>
#include <net/pfvar.h>
-#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
@@ -57,14 +55,12 @@ __FBSDID("$FreeBSD$");
#include "pfctl.h"
extern void usage(void);
-static int pfctl_table(int, char *[], char *, const char *, char *,
- const char *, int);
-static void print_table(struct pfr_table *, int, int);
-static void print_tstats(struct pfr_tstats *, int);
-static int load_addr(struct pfr_buffer *, int, char *[], char *, int);
+static void print_table(const struct pfr_table *, int, int);
+static int print_tstats(const struct pfr_tstats *, int);
+static int load_addr(struct pfr_buffer *, int, char *[], char *, int, int);
static void print_addrx(struct pfr_addr *, struct pfr_addr *, int);
+static int nonzero_astats(struct pfr_astats *);
static void print_astats(struct pfr_astats *, int);
-static void radix_perror(void);
static void xprintf(int, const char *, ...);
static void print_iface(struct pfi_kif *, int);
@@ -78,26 +74,28 @@ static const char *istats_text[2][2][2] = {
{ { "In6/Pass:", "In6/Block:" }, { "Out6/Pass:", "Out6/Block:" } }
};
-#define RVTEST(fct) do { \
- if ((!(opts & PF_OPT_NOACTION) || \
- (opts & PF_OPT_DUMMYACTION)) && \
- (fct)) { \
- radix_perror(); \
- goto _error; \
- } \
+#define RVTEST(fct) do { \
+ if ((!(opts & PF_OPT_NOACTION) || \
+ (opts & PF_OPT_DUMMYACTION)) && \
+ (fct)) { \
+ if ((opts & PF_OPT_RECURSE) == 0) \
+ warnx("%s", pf_strerror(errno)); \
+ goto _error; \
+ } \
} while (0)
#define CREATE_TABLE do { \
+ warn_duplicate_tables(table.pfrt_name, \
+ table.pfrt_anchor); \
table.pfrt_flags |= PFR_TFLAG_PERSIST; \
if ((!(opts & PF_OPT_NOACTION) || \
(opts & PF_OPT_DUMMYACTION)) && \
- (pfr_add_tables(&table, 1, &nadd, flags)) && \
+ (pfr_add_table(&table, &nadd, flags)) && \
(errno != EPERM)) { \
- radix_perror(); \
+ warnx("%s", pf_strerror(errno)); \
goto _error; \
} \
if (nadd) { \
- warn_namespace_collision(table.pfrt_name); \
xprintf(opts, "%d table created", nadd); \
if (opts & PF_OPT_NOACTION) \
return (0); \
@@ -106,24 +104,23 @@ static const char *istats_text[2][2][2] = {
} while(0)
int
-pfctl_clear_tables(const char *anchor, int opts)
+pfctl_do_clear_tables(const char *anchor, int opts)
{
- return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts);
-}
+ int rv;
-int
-pfctl_show_tables(const char *anchor, int opts)
-{
- return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts);
+ if ((rv = pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts)) == -1) {
+ if ((opts & PF_OPT_IGNFAIL) == 0)
+ exit(1);
+ }
+
+ return (rv);
}
-int
-pfctl_command_tables(int argc, char *argv[], char *tname,
- const char *command, char *file, const char *anchor, int opts)
+void
+pfctl_show_tables(const char *anchor, int opts)
{
- if (tname == NULL || command == NULL)
- usage();
- return pfctl_table(argc, argv, tname, command, file, anchor, opts);
+ if (pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts))
+ exit(1);
}
int
@@ -159,39 +156,42 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
if (!strcmp(command, "-F")) {
if (argc || file != NULL)
usage();
- RVTEST(pfr_clr_tables(&table, &ndel, flags));
+ RVTEST(pfctl_clear_tables(pfh, &table, &ndel, flags));
xprintf(opts, "%d tables deleted", ndel);
} else if (!strcmp(command, "-s")) {
b.pfrb_type = (opts & PF_OPT_VERBOSE2) ?
PFRB_TSTATS : PFRB_TABLES;
if (argc || file != NULL)
usage();
- for (;;) {
- pfr_buf_grow(&b, b.pfrb_size);
- b.pfrb_size = b.pfrb_msize;
- if (opts & PF_OPT_VERBOSE2)
- RVTEST(pfr_get_tstats(&table,
- b.pfrb_caddr, &b.pfrb_size, flags));
- else
- RVTEST(pfr_get_tables(&table,
- b.pfrb_caddr, &b.pfrb_size, flags));
- if (b.pfrb_size <= b.pfrb_msize)
- break;
- }
if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
pfctl_print_title("TABLES:");
- PFRB_FOREACH(p, &b)
- if (opts & PF_OPT_VERBOSE2)
- print_tstats(p, opts & PF_OPT_DEBUG);
- else
+ if (opts & PF_OPT_VERBOSE2) {
+ uintptr_t arg = opts & PF_OPT_DEBUG;
+ pfctl_get_tstats(pfh, &table,
+ (pfctl_get_tstats_fn)print_tstats, (void *)arg);
+ } else {
+ for (;;) {
+ pfr_buf_grow(&b, b.pfrb_size);
+ b.pfrb_size = b.pfrb_msize;
+ RVTEST(pfr_get_tables(&table,
+ b.pfrb_caddr, &b.pfrb_size, flags));
+ if (b.pfrb_size <= b.pfrb_msize)
+ break;
+ }
+
+ if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0)
+ pfctl_print_title("TABLES:");
+
+ PFRB_FOREACH(p, &b)
print_table(p, opts & PF_OPT_VERBOSE,
opts & PF_OPT_DEBUG);
+ }
} else if (!strcmp(command, "kill")) {
if (argc || file != NULL)
usage();
- RVTEST(pfr_del_tables(&table, 1, &ndel, flags));
+ RVTEST(pfr_del_table(&table, &ndel, flags));
xprintf(opts, "%d table deleted", ndel);
} else if (!strcmp(command, "flush")) {
if (argc || file != NULL)
@@ -200,7 +200,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
xprintf(opts, "%d addresses deleted", ndel);
} else if (!strcmp(command, "add")) {
b.pfrb_type = PFRB_ADDRS;
- if (load_addr(&b, argc, argv, file, 0))
+ if (load_addr(&b, argc, argv, file, 0, opts))
goto _error;
CREATE_TABLE;
if (opts & PF_OPT_VERBOSE)
@@ -210,12 +210,13 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size);
if (opts & PF_OPT_VERBOSE)
PFRB_FOREACH(a, &b)
- if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
+ if ((opts & PF_OPT_VERBOSE2) ||
+ a->pfra_fback != PFR_FB_NONE)
print_addrx(a, NULL,
opts & PF_OPT_USEDNS);
} else if (!strcmp(command, "delete")) {
b.pfrb_type = PFRB_ADDRS;
- if (load_addr(&b, argc, argv, file, 0))
+ if (load_addr(&b, argc, argv, file, 0, opts))
goto _error;
if (opts & PF_OPT_VERBOSE)
flags |= PFR_FLAG_FEEDBACK;
@@ -224,12 +225,13 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size);
if (opts & PF_OPT_VERBOSE)
PFRB_FOREACH(a, &b)
- if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
+ if ((opts & PF_OPT_VERBOSE2) ||
+ a->pfra_fback != PFR_FB_NONE)
print_addrx(a, NULL,
opts & PF_OPT_USEDNS);
} else if (!strcmp(command, "replace")) {
b.pfrb_type = PFRB_ADDRS;
- if (load_addr(&b, argc, argv, file, 0))
+ if (load_addr(&b, argc, argv, file, 0, opts))
goto _error;
CREATE_TABLE;
if (opts & PF_OPT_VERBOSE)
@@ -255,7 +257,8 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
xprintf(opts, "no changes");
if (opts & PF_OPT_VERBOSE)
PFRB_FOREACH(a, &b)
- if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
+ if ((opts & PF_OPT_VERBOSE2) ||
+ a->pfra_fback != PFR_FB_NONE)
print_addrx(a, NULL,
opts & PF_OPT_USEDNS);
} else if (!strcmp(command, "expire")) {
@@ -278,7 +281,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
break;
}
PFRB_FOREACH(p, &b) {
- ((struct pfr_astats *)p)->pfras_a.pfra_fback = 0;
+ ((struct pfr_astats *)p)->pfras_a.pfra_fback = PFR_FB_NONE;
if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero >
lifetime)
if (pfr_buf_add(&b2,
@@ -293,6 +296,37 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
xprintf(opts, "%d/%d addresses expired", ndel, b2.pfrb_size);
if (opts & PF_OPT_VERBOSE)
PFRB_FOREACH(a, &b2)
+ if ((opts & PF_OPT_VERBOSE2) ||
+ a->pfra_fback != PFR_FB_NONE)
+ print_addrx(a, NULL,
+ opts & PF_OPT_USEDNS);
+ } else if (!strcmp(command, "reset")) {
+ struct pfr_astats *as;
+
+ b.pfrb_type = PFRB_ASTATS;
+ b2.pfrb_type = PFRB_ADDRS;
+ if (argc || file != NULL)
+ usage();
+ do {
+ pfr_buf_grow(&b, b.pfrb_size);
+ b.pfrb_size = b.pfrb_msize;
+ RVTEST(pfr_get_astats(&table, b.pfrb_caddr,
+ &b.pfrb_size, flags));
+ } while (b.pfrb_size > b.pfrb_msize);
+ PFRB_FOREACH(as, &b) {
+ as->pfras_a.pfra_fback = 0;
+ if (nonzero_astats(as))
+ if (pfr_buf_add(&b2, &as->pfras_a))
+ err(1, "duplicate buffer");
+ }
+
+ if (opts & PF_OPT_VERBOSE)
+ flags |= PFR_FLAG_FEEDBACK;
+ RVTEST(pfr_clr_astats(&table, b2.pfrb_caddr, b2.pfrb_size,
+ &nzero, flags));
+ xprintf(opts, "%d/%d stats cleared", nzero, b.pfrb_size);
+ if (opts & PF_OPT_VERBOSE)
+ PFRB_FOREACH(a, &b2)
if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback)
print_addrx(a, NULL,
opts & PF_OPT_USEDNS);
@@ -322,7 +356,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
b.pfrb_type = PFRB_ADDRS;
b2.pfrb_type = PFRB_ADDRS;
- if (load_addr(&b, argc, argv, file, 1))
+ if (load_addr(&b, argc, argv, file, 1, opts))
goto _error;
if (opts & PF_OPT_VERBOSE2) {
flags |= PFR_FLAG_REPLACE;
@@ -347,11 +381,24 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command,
}
if (nmatch < b.pfrb_size)
rv = 2;
+ } else if (!strcmp(command, "zero") && (argc || file != NULL)) {
+ b.pfrb_type = PFRB_ADDRS;
+ if (load_addr(&b, argc, argv, file, 0, opts))
+ goto _error;
+ if (opts & PF_OPT_VERBOSE)
+ flags |= PFR_FLAG_FEEDBACK;
+ RVTEST(pfr_clr_astats(&table, b.pfrb_caddr, b.pfrb_size,
+ &nzero, flags));
+ xprintf(opts, "%d/%d addresses cleared", nzero, b.pfrb_size);
+ if (opts & PF_OPT_VERBOSE)
+ PFRB_FOREACH(a, &b)
+ if (opts & PF_OPT_VERBOSE2 ||
+ a->pfra_fback != PFR_FB_NONE)
+ print_addrx(a, NULL,
+ opts & PF_OPT_USEDNS);
} else if (!strcmp(command, "zero")) {
- if (argc || file != NULL)
- usage();
flags |= PFR_FLAG_ADDRSTOO;
- RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags));
+ RVTEST(pfctl_clear_tstats(pfh, &table, &nzero, flags));
xprintf(opts, "%d table/stats cleared", nzero);
} else
warnx("pfctl_table: unknown command '%s'", command);
@@ -366,38 +413,43 @@ _cleanup:
}
void
-print_table(struct pfr_table *ta, int verbose, int debug)
+print_table(const struct pfr_table *ta, int verbose, int debug)
{
if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE))
return;
- if (verbose) {
- printf("%c%c%c%c%c%c%c\t%s",
+ if (verbose)
+ printf("%c%c%c%c%c%c%c\t",
(ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-',
(ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-',
(ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-',
(ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-',
(ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-',
(ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-',
- (ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-',
- ta->pfrt_name);
- if (ta->pfrt_anchor[0])
- printf("\t%s", ta->pfrt_anchor);
- puts("");
- } else
- puts(ta->pfrt_name);
+ (ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-');
+
+ printf("%s", ta->pfrt_name);
+ if (ta->pfrt_anchor[0] != '\0')
+ printf("@%s", ta->pfrt_anchor);
+
+ printf("\n");
}
-void
-print_tstats(struct pfr_tstats *ts, int debug)
+int
+print_tstats(const struct pfr_tstats *ts, int debug)
{
- time_t time = ts->pfrts_tzero;
- int dir, op;
+ time_t time = ts->pfrts_tzero;
+ int dir, op;
+ char *ct;
if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE))
- return;
+ return (0);
+ ct = ctime(&time);
print_table(&ts->pfrts_t, 1, debug);
printf("\tAddresses: %d\n", ts->pfrts_cnt);
- printf("\tCleared: %s", ctime(&time));
+ if (ct)
+ printf("\tCleared: %s", ct);
+ else
+ printf("\tCleared: %lld\n", (long long)time);
printf("\tReferences: [ Anchors: %-18d Rules: %-18d ]\n",
ts->pfrts_refcnt[PFR_REFCNT_ANCHOR],
ts->pfrts_refcnt[PFR_REFCNT_RULE]);
@@ -410,19 +462,21 @@ print_tstats(struct pfr_tstats *ts, int debug)
stats_text[dir][op],
(unsigned long long)ts->pfrts_packets[dir][op],
(unsigned long long)ts->pfrts_bytes[dir][op]);
+
+ return (0);
}
int
load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file,
- int nonetwork)
+ int nonetwork, int opts)
{
while (argc--)
- if (append_addr(b, *argv++, nonetwork)) {
+ if (append_addr(b, *argv++, nonetwork, opts)) {
if (errno)
warn("cannot decode %s", argv[-1]);
return (-1);
}
- if (pfr_buf_load(b, file, nonetwork, append_addr)) {
+ if (pfr_buf_load(b, file, nonetwork, append_addr, opts)) {
warn("cannot load %s", file);
return (-1);
}
@@ -455,34 +509,56 @@ print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns)
printf("\t nomatch");
if (dns && ad->pfra_net == hostnet) {
char host[NI_MAXHOST];
- union sockaddr_union sa;
+ struct sockaddr_storage ss;
strlcpy(host, "?", sizeof(host));
- bzero(&sa, sizeof(sa));
- sa.sa.sa_family = ad->pfra_af;
- if (sa.sa.sa_family == AF_INET) {
- sa.sa.sa_len = sizeof(sa.sin);
- sa.sin.sin_addr = ad->pfra_ip4addr;
+ bzero(&ss, sizeof(ss));
+ ss.ss_family = ad->pfra_af;
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
+
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = ad->pfra_ip4addr;
} else {
- sa.sa.sa_len = sizeof(sa.sin6);
- sa.sin6.sin6_addr = ad->pfra_ip6addr;
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
+
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_addr = ad->pfra_ip6addr;
}
- if (getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host),
- NULL, 0, NI_NAMEREQD) == 0)
+ if (getnameinfo((struct sockaddr *)&ss, ss.ss_len, host,
+ sizeof(host), NULL, 0, NI_NAMEREQD) == 0)
printf("\t(%s)", host);
}
printf("\n");
}
+int
+nonzero_astats(struct pfr_astats *as)
+{
+ uint64_t s = 0;
+
+ for (int dir = 0; dir < PFR_DIR_MAX; dir++)
+ for (int op = 0; op < PFR_OP_ADDR_MAX; op++)
+ s |= as->pfras_packets[dir][op] |
+ as->pfras_bytes[dir][op];
+
+ return (!!s);
+}
+
void
print_astats(struct pfr_astats *as, int dns)
{
- time_t time = as->pfras_tzero;
- int dir, op;
+ time_t time = as->pfras_tzero;
+ int dir, op;
+ char *ct;
+ ct = ctime(&time);
print_addrx(&as->pfras_a, NULL, dns);
- printf("\tCleared: %s", ctime(&time));
- if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT)
+ if (ct)
+ printf("\tCleared: %s", ct);
+ else
+ printf("\tCleared: %lld\n", (long long)time);
+ if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT)
return;
for (dir = 0; dir < PFR_DIR_MAX; dir++)
for (op = 0; op < PFR_OP_ADDR_MAX; op++)
@@ -492,37 +568,59 @@ print_astats(struct pfr_astats *as, int dns)
(unsigned long long)as->pfras_bytes[dir][op]);
}
-void
-radix_perror(void)
-{
- extern char *__progname;
- fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno));
-}
-
int
pfctl_define_table(char *name, int flags, int addrs, const char *anchor,
- struct pfr_buffer *ab, u_int32_t ticket)
+ struct pfr_buffer *ab, u_int32_t ticket, struct pfr_uktable *ukt)
{
- struct pfr_table tbl;
-
- bzero(&tbl, sizeof(tbl));
- if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >=
- sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor,
- sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor))
- errx(1, "pfctl_define_table: strlcpy");
- tbl.pfrt_flags = flags;
+ struct pfr_table tbl_buf;
+ struct pfr_table *tbl;
+
+ if (ukt == NULL) {
+ bzero(&tbl_buf, sizeof(tbl_buf));
+ tbl = &tbl_buf;
+ } else {
+ if (ab->pfrb_size != 0) {
+ /*
+ * copy IP addresses which come with table from
+ * temporal buffer to buffer attached to table.
+ */
+ ukt->pfrukt_addrs = *ab;
+ ab->pfrb_size = 0;
+ ab->pfrb_msize = 0;
+ ab->pfrb_caddr = NULL;
+ } else
+ memset(&ukt->pfrukt_addrs, 0,
+ sizeof(struct pfr_buffer));
+
+ tbl = &ukt->pfrukt_t;
+ }
- return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL,
- NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0);
+ if (strlcpy(tbl->pfrt_name, name, sizeof(tbl->pfrt_name)) >=
+ sizeof(tbl->pfrt_name) ||
+ strlcpy(tbl->pfrt_anchor, anchor, sizeof(tbl->pfrt_anchor)) >=
+ sizeof(tbl->pfrt_anchor))
+ errx(1, "%s: strlcpy", __func__);
+ tbl->pfrt_flags = flags;
+ DBGPRINT("%s %s@%s [%x]\n", __func__, tbl->pfrt_name, tbl->pfrt_anchor,
+ tbl->pfrt_flags);
+
+ /*
+ * non-root anchors processed by parse.y are loaded to kernel later.
+ * Here we load tables, which are either created for root anchor
+ * or by 'pfctl -t ... -T ...' command.
+ */
+ if (ukt != NULL)
+ return (0);
+
+ return (pfr_ina_define(tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, NULL,
+ ticket, addrs ? PFR_FLAG_ADDRSTOO : 0));
}
void
-warn_namespace_collision(const char *filter)
+warn_duplicate_tables(const char *tablename, const char *anchorname)
{
struct pfr_buffer b;
struct pfr_table *t;
- const char *name = NULL, *lastcoll;
- int coll = 0;
bzero(&b, sizeof(b));
b.pfrb_type = PFRB_TABLES;
@@ -538,22 +636,13 @@ warn_namespace_collision(const char *filter)
PFRB_FOREACH(t, &b) {
if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE))
continue;
- if (filter != NULL && strcmp(filter, t->pfrt_name))
+ if (!strcmp(anchorname, t->pfrt_anchor))
continue;
- if (!t->pfrt_anchor[0])
- name = t->pfrt_name;
- else if (name != NULL && !strcmp(name, t->pfrt_name)) {
- coll++;
- lastcoll = name;
- name = NULL;
- }
+ if (!strcmp(tablename, t->pfrt_name))
+ warnx("warning: table <%s> already defined"
+ " in anchor \"%s\"", tablename,
+ t->pfrt_anchor[0] ? t->pfrt_anchor : "/");
}
- if (coll == 1)
- warnx("warning: namespace collision with <%s> global table.",
- lastcoll);
- else if (coll > 1)
- warnx("warning: namespace collisions with %d global tables.",
- coll);
pfr_buf_clear(&b);
}
@@ -580,38 +669,34 @@ xprintf(int opts, const char *fmt, ...)
/* interface stuff */
-int
+void
pfctl_show_ifaces(const char *filter, int opts)
{
struct pfr_buffer b;
struct pfi_kif *p;
- int i = 0;
bzero(&b, sizeof(b));
b.pfrb_type = PFRB_IFACES;
for (;;) {
pfr_buf_grow(&b, b.pfrb_size);
b.pfrb_size = b.pfrb_msize;
- if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) {
- radix_perror();
- return (1);
- }
+ if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size))
+ errx(1, "%s", pf_strerror(errno));
if (b.pfrb_size <= b.pfrb_msize)
break;
- i++;
}
if (opts & PF_OPT_SHOWALL)
pfctl_print_title("INTERFACES:");
PFRB_FOREACH(p, &b)
print_iface(p, opts);
- return (0);
}
void
print_iface(struct pfi_kif *p, int opts)
{
- time_t tzero = p->pfik_tzero;
- int i, af, dir, act;
+ time_t tzero = p->pfik_tzero;
+ int i, af, dir, act;
+ char *ct;
printf("%s", p->pfik_name);
if (opts & PF_OPT_VERBOSE) {
@@ -622,7 +707,11 @@ print_iface(struct pfi_kif *p, int opts)
if (!(opts & PF_OPT_VERBOSE2))
return;
- printf("\tCleared: %s", ctime(&tzero));
+ ct = ctime(&tzero);
+ if (ct)
+ printf("\tCleared: %s", ct);
+ else
+ printf("\tCleared: %lld\n", (long long)tzero);
printf("\tReferences: %-18d\n", p->pfik_rulerefs);
for (i = 0; i < 8; i++) {
af = (i>>2) & 1;
diff --git a/sbin/pfctl/tests/Makefile b/sbin/pfctl/tests/Makefile
index 9ba132de9244..281cd97dee78 100644
--- a/sbin/pfctl/tests/Makefile
+++ b/sbin/pfctl/tests/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE= tests
ATF_TESTS_C= pfctl_test
@@ -9,4 +7,6 @@ LIBADD+= sbuf
SUBDIR+= files
WARNS=6
+pfctl_test.o: pfctl_test_list.inc
+
.include <bsd.test.mk>
diff --git a/sbin/pfctl/tests/Makefile.depend b/sbin/pfctl/tests/Makefile.depend
index f80275d86ab1..a59dba5bf1aa 100644
--- a/sbin/pfctl/tests/Makefile.depend
+++ b/sbin/pfctl/tests/Makefile.depend
@@ -1,7 +1,11 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
+ lib/${CSU_DIR} \
+ lib/atf/libatf-c \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libsbuf \
.include <dirdeps.mk>
diff --git a/sbin/pfctl/tests/files/Makefile b/sbin/pfctl/tests/files/Makefile
index aa066c0ff2ac..fc52b1db3c30 100644
--- a/sbin/pfctl/tests/files/Makefile
+++ b/sbin/pfctl/tests/files/Makefile
@@ -1,11 +1,9 @@
-# $FreeBSD$
-
PACKAGE= tests
TESTSDIR= ${TESTSBASE}/sbin/pfctl/files
BINDIR= ${TESTSDIR}
# We use ${.CURDIR} as workaround so that the glob patterns work.
-FILES!= echo ${.CURDIR}/pf????.in ${.CURDIR}/pf????.include ${.CURDIR}/pf????.ok
+FILES!= echo ${.CURDIR}/pf????.in ${.CURDIR}/pf????.include ${.CURDIR}/pf????.ok ${.CURDIR}/pf????.fail
.include <bsd.progs.mk>
diff --git a/sbin/pfctl/tests/files/Makefile.depend b/sbin/pfctl/tests/files/Makefile.depend
index f80275d86ab1..11aba52f82cf 100644
--- a/sbin/pfctl/tests/files/Makefile.depend
+++ b/sbin/pfctl/tests/files/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/pfctl/tests/files/pf0004.ok b/sbin/pfctl/tests/files/pf0004.ok
index 5fca4a50f7b1..87b71cdeff3d 100644
--- a/sbin/pfctl/tests/files/pf0004.ok
+++ b/sbin/pfctl/tests/files/pf0004.ok
@@ -15,48 +15,48 @@ block drop in proto tcp from any port >= 80 to any port 1024:2048
block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 192.168.0.0/16 port = ircd
block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 192.168.0.0/16 port = 6668
block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 192.168.0.0/16 port 6669:65535
-block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = ircd
-block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = 6668
-block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto tcp from 10.0.0.0/8 port = ftp to 192.168.0.0/16 port = ircd
block drop in inet proto tcp from 10.0.0.0/8 port = ftp to 192.168.0.0/16 port = 6668
block drop in inet proto tcp from 10.0.0.0/8 port = ftp to 192.168.0.0/16 port 6669:65535
+block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = ircd
+block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = 6668
+block drop in inet proto tcp from 10.0.0.0/8 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto tcp from 10.0.0.0/8 port = ftp to 12.34.56.78 port = ircd
block drop in inet proto tcp from 10.0.0.0/8 port = ftp to 12.34.56.78 port = 6668
block drop in inet proto tcp from 10.0.0.0/8 port = ftp to 12.34.56.78 port 6669:65535
block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 192.168.0.0/16 port = ircd
block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 192.168.0.0/16 port = 6668
block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 192.168.0.0/16 port 6669:65535
-block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = ircd
-block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = 6668
-block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto tcp from 172.16.0.0/12 port = ftp to 192.168.0.0/16 port = ircd
block drop in inet proto tcp from 172.16.0.0/12 port = ftp to 192.168.0.0/16 port = 6668
block drop in inet proto tcp from 172.16.0.0/12 port = ftp to 192.168.0.0/16 port 6669:65535
+block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = ircd
+block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = 6668
+block drop in inet proto tcp from 172.16.0.0/12 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto tcp from 172.16.0.0/12 port = ftp to 12.34.56.78 port = ircd
block drop in inet proto tcp from 172.16.0.0/12 port = ftp to 12.34.56.78 port = 6668
block drop in inet proto tcp from 172.16.0.0/12 port = ftp to 12.34.56.78 port 6669:65535
block drop in inet proto udp from 10.0.0.0/8 port = ssh to 192.168.0.0/16 port = 6667
block drop in inet proto udp from 10.0.0.0/8 port = ssh to 192.168.0.0/16 port = 6668
block drop in inet proto udp from 10.0.0.0/8 port = ssh to 192.168.0.0/16 port 6669:65535
-block drop in inet proto udp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = 6667
-block drop in inet proto udp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = 6668
-block drop in inet proto udp from 10.0.0.0/8 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto udp from 10.0.0.0/8 port = ftp to 192.168.0.0/16 port = 6667
block drop in inet proto udp from 10.0.0.0/8 port = ftp to 192.168.0.0/16 port = 6668
block drop in inet proto udp from 10.0.0.0/8 port = ftp to 192.168.0.0/16 port 6669:65535
+block drop in inet proto udp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = 6667
+block drop in inet proto udp from 10.0.0.0/8 port = ssh to 12.34.56.78 port = 6668
+block drop in inet proto udp from 10.0.0.0/8 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto udp from 10.0.0.0/8 port = ftp to 12.34.56.78 port = 6667
block drop in inet proto udp from 10.0.0.0/8 port = ftp to 12.34.56.78 port = 6668
block drop in inet proto udp from 10.0.0.0/8 port = ftp to 12.34.56.78 port 6669:65535
block drop in inet proto udp from 172.16.0.0/12 port = ssh to 192.168.0.0/16 port = 6667
block drop in inet proto udp from 172.16.0.0/12 port = ssh to 192.168.0.0/16 port = 6668
block drop in inet proto udp from 172.16.0.0/12 port = ssh to 192.168.0.0/16 port 6669:65535
-block drop in inet proto udp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = 6667
-block drop in inet proto udp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = 6668
-block drop in inet proto udp from 172.16.0.0/12 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto udp from 172.16.0.0/12 port = ftp to 192.168.0.0/16 port = 6667
block drop in inet proto udp from 172.16.0.0/12 port = ftp to 192.168.0.0/16 port = 6668
block drop in inet proto udp from 172.16.0.0/12 port = ftp to 192.168.0.0/16 port 6669:65535
+block drop in inet proto udp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = 6667
+block drop in inet proto udp from 172.16.0.0/12 port = ssh to 12.34.56.78 port = 6668
+block drop in inet proto udp from 172.16.0.0/12 port = ssh to 12.34.56.78 port 6669:65535
block drop in inet proto udp from 172.16.0.0/12 port = ftp to 12.34.56.78 port = 6667
block drop in inet proto udp from 172.16.0.0/12 port = ftp to 12.34.56.78 port = 6668
block drop in inet proto udp from 172.16.0.0/12 port = ftp to 12.34.56.78 port 6669:65535
diff --git a/sbin/pfctl/tests/files/pf0016.in b/sbin/pfctl/tests/files/pf0016.in
index 738bfb664395..7dbc53aa6a21 100644
--- a/sbin/pfctl/tests/files/pf0016.in
+++ b/sbin/pfctl/tests/files/pf0016.in
@@ -1,5 +1,5 @@
# Test rule order processing: should fail unless nat -> filter
-#match out on lo0 from 192.168.1.1 to any nat-to 10.0.0.1
-#match in on lo0 proto tcp from any to 1.2.3.4/32 port 2222 rdr-to 10.0.0.10 port 22
-#match on lo0 from 192.168.1.1 to any binat-to 10.0.0.1
+match out on lo0 from 192.168.1.1 to any nat-to 10.0.0.1
+match in on lo0 proto tcp from any to 1.2.3.4/32 port 2222 rdr-to 10.0.0.10 port 22
+match on lo0 from 192.168.1.1 to any binat-to 10.0.0.1
pass in on lo1000000 from any to any no state
diff --git a/sbin/pfctl/tests/files/pf0016.ok b/sbin/pfctl/tests/files/pf0016.ok
index 6f0c211a5b8a..d65374a16475 100644
--- a/sbin/pfctl/tests/files/pf0016.ok
+++ b/sbin/pfctl/tests/files/pf0016.ok
@@ -1 +1,5 @@
+match out on lo0 inet from 192.168.1.1 to any nat-to 10.0.0.1
+match in on lo0 inet proto tcp from any to 1.2.3.4 port = 2222 rdr-to 10.0.0.10 port 22
+match out on lo0 inet from 192.168.1.1 to any nat-to 10.0.0.1 static-port
+match in on lo0 inet from any to 10.0.0.1 rdr-to 192.168.1.1
pass in on lo1000000 all no state
diff --git a/sbin/pfctl/tests/files/pf0018.in b/sbin/pfctl/tests/files/pf0018.in
index 46606b476d79..ab3c81f86c5f 100644
--- a/sbin/pfctl/tests/files/pf0018.in
+++ b/sbin/pfctl/tests/files/pf0018.in
@@ -3,17 +3,17 @@
TEST_LIST1 = "{ 192.168.1.5, 192.168.1.6, 192.168.1.7 }"
TEST_LIST2 = "{ 172.6.1.1, 172.14.1.2/32, 172.16.2.0/24 }"
-#match out on lo0 from 192.168.1.1 to any nat-to 10.0.0.1
-#match out on lo0 proto tcp from 192.168.1.2 to any nat-to 10.0.0.2
-#match out on lo0 proto udp from 192.168.1.3 to any nat-to 10.0.0.3
-#match out on lo0 proto icmp from 192.168.1.4 to any nat-to 10.0.0.4
+match out on lo0 from 192.168.1.1 to any nat-to 10.0.0.1
+match out on lo0 proto tcp from 192.168.1.2 to any nat-to 10.0.0.2
+match out on lo0 proto udp from 192.168.1.3 to any nat-to 10.0.0.3
+match out on lo0 proto icmp from 192.168.1.4 to any nat-to 10.0.0.4
-#match out on lo0 inet from $TEST_LIST1 to $TEST_LIST2 nat-to lo0
+match out on lo0 inet from $TEST_LIST1 to $TEST_LIST2 nat-to lo0
-#match out on lo0 inet from 192.168.0.1/24 to any nat-to (lo0)
+match out on lo0 inet from 192.168.0.1/24 to any nat-to (lo0)
-#match out on lo0 from 192.168.1.8 to ! 172.17.0.0/16 nat-to 10.0.0.8
+match out on lo0 from 192.168.1.8 to ! 172.17.0.0/16 nat-to 10.0.0.8
-#match out on ! lo0 proto { udp, tcp } from any to any nat-to 10.0.0.8 static-port
+match out on ! lo0 proto { udp, tcp } from any to any nat-to 10.0.0.8 static-port
-#match out on { lo0, tun1000000 } from any to any nat-to 10.0.0.8
+match out on { lo0, tun1000000 } from any to any nat-to 10.0.0.8
diff --git a/sbin/pfctl/tests/files/pf0018.ok b/sbin/pfctl/tests/files/pf0018.ok
index c19ead6da1f0..6ba137ae84f8 100644
--- a/sbin/pfctl/tests/files/pf0018.ok
+++ b/sbin/pfctl/tests/files/pf0018.ok
@@ -1,2 +1,21 @@
TEST_LIST1 = "{ 192.168.1.5, 192.168.1.6, 192.168.1.7 }"
TEST_LIST2 = "{ 172.6.1.1, 172.14.1.2/32, 172.16.2.0/24 }"
+match out on lo0 inet from 192.168.1.1 to any nat-to 10.0.0.1
+match out on lo0 inet proto tcp from 192.168.1.2 to any nat-to 10.0.0.2
+match out on lo0 inet proto udp from 192.168.1.3 to any nat-to 10.0.0.3
+match out on lo0 inet proto icmp from 192.168.1.4 to any nat-to 10.0.0.4
+match out on lo0 inet from 192.168.1.5 to 172.6.1.1 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.5 to 172.14.1.2 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.5 to 172.16.2.0/24 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.6 to 172.6.1.1 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.6 to 172.14.1.2 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.6 to 172.16.2.0/24 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.7 to 172.6.1.1 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.7 to 172.14.1.2 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.1.7 to 172.16.2.0/24 nat-to 127.0.0.1
+match out on lo0 inet from 192.168.0.0/24 to any nat-to (lo0) round-robin
+match out on lo0 inet from 192.168.1.8 to ! 172.17.0.0/16 nat-to 10.0.0.8
+match out on ! lo0 inet proto udp all nat-to 10.0.0.8 static-port
+match out on ! lo0 inet proto tcp all nat-to 10.0.0.8 static-port
+match out on lo0 inet all nat-to 10.0.0.8
+match out on tun1000000 inet all nat-to 10.0.0.8
diff --git a/sbin/pfctl/tests/files/pf0019.in b/sbin/pfctl/tests/files/pf0019.in
index 0b1456e6fd03..e2bedbb64bd0 100644
--- a/sbin/pfctl/tests/files/pf0019.in
+++ b/sbin/pfctl/tests/files/pf0019.in
@@ -3,7 +3,7 @@ GOOD = "{ lo0, lo1000000 }"
GOOD_NET = "{ 127.0.0.0/24, 10.0.1.0/24 }"
DEST_NET = "{ 1.2.3.4/25, 2.4.6.8/30 }"
-#match in on lo0 proto tcp from any to 1.2.3.4/32 port 2222 rdr-to 10.0.0.10 port 22
+match in on lo0 proto tcp from any to 1.2.3.4/32 port 2222 rdr-to 10.0.0.10 port 22
# Test list processing
-#match in on $GOOD proto tcp from $GOOD_NET to $DEST_NET port 21 rdr-to 127.0.0.1 port 8021
+match in on $GOOD proto tcp from $GOOD_NET to $DEST_NET port 21 rdr-to 127.0.0.1 port 8021
diff --git a/sbin/pfctl/tests/files/pf0019.ok b/sbin/pfctl/tests/files/pf0019.ok
index 16c845aa2cd6..a5afc374d19f 100644
--- a/sbin/pfctl/tests/files/pf0019.ok
+++ b/sbin/pfctl/tests/files/pf0019.ok
@@ -2,3 +2,12 @@ EVIL = "lo0"
GOOD = "{ lo0, lo1000000 }"
GOOD_NET = "{ 127.0.0.0/24, 10.0.1.0/24 }"
DEST_NET = "{ 1.2.3.4/25, 2.4.6.8/30 }"
+match in on lo0 inet proto tcp from any to 1.2.3.4 port = 2222 rdr-to 10.0.0.10 port 22
+match in on lo0 inet proto tcp from 127.0.0.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo0 inet proto tcp from 127.0.0.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo0 inet proto tcp from 10.0.1.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo0 inet proto tcp from 10.0.1.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 127.0.0.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 127.0.0.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 10.0.1.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 10.0.1.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
diff --git a/sbin/pfctl/tests/files/pf0020.in b/sbin/pfctl/tests/files/pf0020.in
index b00125bbcdb8..c973785bc9c5 100644
--- a/sbin/pfctl/tests/files/pf0020.in
+++ b/sbin/pfctl/tests/files/pf0020.in
@@ -5,5 +5,5 @@ GOOD = "{ lo0, lo1000000 }"
GOOD_NET = "{ 127.0.0.0/24, 10.0.1.0/24 }"
DEST_NET = "{ 1.2.3.4/25, 2.4.6.8/30 }"
-#match out on $EVIL inet from $GOOD_NET to $DEST_NET nat-to $EVIL
-#match in on $GOOD proto tcp from $GOOD_NET to $DEST_NET port 21 rdr-to 127.0.0.1 port 8021
+match out on $EVIL inet from $GOOD_NET to $DEST_NET nat-to $EVIL
+match in on $GOOD proto tcp from $GOOD_NET to $DEST_NET port 21 rdr-to 127.0.0.1 port 8021
diff --git a/sbin/pfctl/tests/files/pf0020.ok b/sbin/pfctl/tests/files/pf0020.ok
index 16c845aa2cd6..bd2c6cf2055d 100644
--- a/sbin/pfctl/tests/files/pf0020.ok
+++ b/sbin/pfctl/tests/files/pf0020.ok
@@ -2,3 +2,15 @@ EVIL = "lo0"
GOOD = "{ lo0, lo1000000 }"
GOOD_NET = "{ 127.0.0.0/24, 10.0.1.0/24 }"
DEST_NET = "{ 1.2.3.4/25, 2.4.6.8/30 }"
+match out on lo0 inet from 127.0.0.0/24 to 1.2.3.0/25 nat-to 127.0.0.1
+match out on lo0 inet from 127.0.0.0/24 to 2.4.6.8/30 nat-to 127.0.0.1
+match out on lo0 inet from 10.0.1.0/24 to 1.2.3.0/25 nat-to 127.0.0.1
+match out on lo0 inet from 10.0.1.0/24 to 2.4.6.8/30 nat-to 127.0.0.1
+match in on lo0 inet proto tcp from 127.0.0.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo0 inet proto tcp from 127.0.0.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo0 inet proto tcp from 10.0.1.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo0 inet proto tcp from 10.0.1.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 127.0.0.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 127.0.0.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 10.0.1.0/24 to 1.2.3.0/25 port = ftp rdr-to 127.0.0.1 port 8021
+match in on lo1000000 inet proto tcp from 10.0.1.0/24 to 2.4.6.8/30 port = ftp rdr-to 127.0.0.1 port 8021
diff --git a/sbin/pfctl/tests/files/pf0048.in b/sbin/pfctl/tests/files/pf0048.in
index e97a819de945..a0dd143c8dd2 100644
--- a/sbin/pfctl/tests/files/pf0048.in
+++ b/sbin/pfctl/tests/files/pf0048.in
@@ -1,12 +1,12 @@
table < regress > { 1.2.3.4 !5.6.7.8 10/8 lo0 }
table <regress.1> const { ::1 fe80::/64 }
table <regress.a> { 1.2.3.4 !5.6.7.8 } { ::1 ::2 ::3 } file "/dev/null" const { 4.3.2.1 }
-#match out on lo0 inet from < regress.1> to <regress.2> nat-to lo0:0
-#match out on !lo0 inet from !<regress.1 > to <regress.2> nat-to lo0:0
-#match in on lo0 inet6 from <regress.1> to <regress.2> rdr-to lo0:0
-#match in on !lo0 inet6 from !< regress.1 > to <regress.2> rdr-to lo0:0
-#match in from { <regress.1> !<regress.2> } to any
-#match out from any to { !<regress.1>, <regress.2> }
+match out on lo0 inet from < regress.1> to <regress.2> nat-to lo0:0
+match out on !lo0 inet from !<regress.1 > to <regress.2> nat-to lo0:0
+match in on lo0 inet6 from <regress.1> to <regress.2> rdr-to lo0:0
+match in on !lo0 inet6 from !< regress.1 > to <regress.2> rdr-to lo0:0
+match in from { <regress.1> !<regress.2> } to any
+match out from any to { !<regress.1>, <regress.2> }
pass in from <regress> to any
pass out from any to <regress >
pass in from { <regress.1> <regress.2> } to any
diff --git a/sbin/pfctl/tests/files/pf0048.ok b/sbin/pfctl/tests/files/pf0048.ok
index f3536f566d35..89569fb4f8ba 100644
--- a/sbin/pfctl/tests/files/pf0048.ok
+++ b/sbin/pfctl/tests/files/pf0048.ok
@@ -1,6 +1,14 @@
table <regress> { 1.2.3.4 !5.6.7.8 10.0.0.0/8 ::1 fe80::1 127.0.0.1 }
table <regress.1> const { ::1 fe80::/64 }
table <regress.a> const { 1.2.3.4 !5.6.7.8 ::1 ::2 ::3 } file "/dev/null" { 4.3.2.1 }
+match out on lo0 inet from <regress.1> to <regress.2> nat-to 127.0.0.1
+match out on ! lo0 inet from ! <regress.1> to <regress.2> nat-to 127.0.0.1
+match in on lo0 inet6 from <regress.1> to <regress.2> rdr-to ::1
+match in on ! lo0 inet6 from ! <regress.1> to <regress.2> rdr-to ::1
+match in from <regress.1> to any
+match in from ! <regress.2> to any
+match out from any to ! <regress.1>
+match out from any to <regress.2>
pass in from <regress> to any flags S/SA keep state
pass out from any to <regress> flags S/SA keep state
pass in from <regress.1> to any flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf0069.in b/sbin/pfctl/tests/files/pf0069.in
index 1298954bbeda..85847b9bd6b2 100644
--- a/sbin/pfctl/tests/files/pf0069.in
+++ b/sbin/pfctl/tests/files/pf0069.in
@@ -1,3 +1,2 @@
-#match out on lo0 inet all tag regress nat-to lo0
+match out on lo0 inet all tag regress nat-to lo0
pass out quick on lo0 keep state tagged regress
-
diff --git a/sbin/pfctl/tests/files/pf0069.ok b/sbin/pfctl/tests/files/pf0069.ok
index 33e0519645fc..2bf34c04baa7 100644
--- a/sbin/pfctl/tests/files/pf0069.ok
+++ b/sbin/pfctl/tests/files/pf0069.ok
@@ -1 +1,2 @@
+match out on lo0 inet all tag regress nat-to 127.0.0.1
pass out quick on lo0 all flags S/SA keep state tagged regress
diff --git a/sbin/pfctl/tests/files/pf0070.in b/sbin/pfctl/tests/files/pf0070.in
index 8d5e34a13ff8..1ccec9302436 100644
--- a/sbin/pfctl/tests/files/pf0070.in
+++ b/sbin/pfctl/tests/files/pf0070.in
@@ -1,3 +1,2 @@
-#match out on lo0 from 10.0.0.0/8 to any nat-to lo0
+match out on lo0 from 10.0.0.0/8 to any nat-to lo0
block out on lo0 tagged regress
-
diff --git a/sbin/pfctl/tests/files/pf0070.ok b/sbin/pfctl/tests/files/pf0070.ok
index d30b70ff3e5a..cf79485b40c1 100644
--- a/sbin/pfctl/tests/files/pf0070.ok
+++ b/sbin/pfctl/tests/files/pf0070.ok
@@ -1 +1,2 @@
+match out on lo0 inet from 10.0.0.0/8 to any nat-to 127.0.0.1
block drop out on lo0 all tagged regress
diff --git a/sbin/pfctl/tests/files/pf0071.in b/sbin/pfctl/tests/files/pf0071.in
index 48976b61ed3d..8975a8ebc943 100644
--- a/sbin/pfctl/tests/files/pf0071.in
+++ b/sbin/pfctl/tests/files/pf0071.in
@@ -1,3 +1,2 @@
-#match in on lo0 proto tcp from 10.0.0.0/8 to port 80 rdr-to lo0
+match in on lo0 proto tcp from 10.0.0.0/8 to port 80 rdr-to lo0
block out on lo0 tagged regress
-
diff --git a/sbin/pfctl/tests/files/pf0071.ok b/sbin/pfctl/tests/files/pf0071.ok
index d30b70ff3e5a..2bae94fc8fac 100644
--- a/sbin/pfctl/tests/files/pf0071.ok
+++ b/sbin/pfctl/tests/files/pf0071.ok
@@ -1 +1,2 @@
+match in on lo0 inet proto tcp from 10.0.0.0/8 to any port = http rdr-to 127.0.0.1
block drop out on lo0 all tagged regress
diff --git a/sbin/pfctl/tests/files/pf0072.in b/sbin/pfctl/tests/files/pf0072.in
index fd037f31ef27..d23843b799d5 100644
--- a/sbin/pfctl/tests/files/pf0072.in
+++ b/sbin/pfctl/tests/files/pf0072.in
@@ -1,4 +1,3 @@
# test binat tagging
-#match on lo0 from 192.168.1.1 to any tag regress binat-to 10.0.0.1
+match on lo0 from 192.168.1.1 to any tag regress binat-to 10.0.0.1
block out on lo0 tagged regress
-
diff --git a/sbin/pfctl/tests/files/pf0072.ok b/sbin/pfctl/tests/files/pf0072.ok
index d30b70ff3e5a..02e676dadc06 100644
--- a/sbin/pfctl/tests/files/pf0072.ok
+++ b/sbin/pfctl/tests/files/pf0072.ok
@@ -1 +1,3 @@
+match out on lo0 inet from 192.168.1.1 to any tag regress nat-to 10.0.0.1 static-port
+match in on lo0 inet from any to 10.0.0.1 tag regress rdr-to 192.168.1.1
block drop out on lo0 all tagged regress
diff --git a/sbin/pfctl/tests/files/pf0084.in b/sbin/pfctl/tests/files/pf0084.in
index c0390df889e3..17140a786d73 100644
--- a/sbin/pfctl/tests/files/pf0084.in
+++ b/sbin/pfctl/tests/files/pf0084.in
@@ -1,9 +1,9 @@
-#match out on tun1000000 from 10.0.0.0/24 to any \
-# nat-to { 10.0.1.1, 10.0.1.2 } round-robin sticky-address
-#match in on tun1000000 from any to 10.0.1.1 \
-# rdr-to { 10.0.0.0/24 } sticky-address random
-#match in on tun1000000 from any to 10.0.1.2 \
-# rdr-to { 10.0.0.1, 10.0.0.2 } sticky-address
+match out on tun1000000 from 10.0.0.0/24 to any \
+ nat-to { 10.0.1.1, 10.0.1.2 } round-robin sticky-address
+match in on tun1000000 from any to 10.0.1.1 \
+ rdr-to { 10.0.0.0/24 } sticky-address random
+match in on tun1000000 from any to 10.0.1.2 \
+ rdr-to { 10.0.0.1, 10.0.0.2 } sticky-address
pass in proto tcp from any to any port 22 \
keep state (source-track)
diff --git a/sbin/pfctl/tests/files/pf0084.ok b/sbin/pfctl/tests/files/pf0084.ok
index 272fd6052023..1ca89e515a3d 100644
--- a/sbin/pfctl/tests/files/pf0084.ok
+++ b/sbin/pfctl/tests/files/pf0084.ok
@@ -1,3 +1,6 @@
+match out on tun1000000 inet from 10.0.0.0/24 to any nat-to { 10.0.1.1, 10.0.1.2 } round-robin sticky-address
+match in on tun1000000 inet from any to 10.0.1.1 rdr-to 10.0.0.0/24 random sticky-address
+match in on tun1000000 inet from any to 10.0.1.2 rdr-to { 10.0.0.1, 10.0.0.2 } round-robin sticky-address
pass in proto tcp from any to any port = ssh flags S/SA keep state (source-track global)
pass in proto tcp from any to any port = smtp flags S/SA keep state (source-track global)
pass in proto tcp from any to any port = http flags S/SA keep state (source-track rule, max-src-states 3, max-src-nodes 1000)
diff --git a/sbin/pfctl/tests/files/pf0088.in b/sbin/pfctl/tests/files/pf0088.in
index 4700b6916b7e..a85aa84a30bb 100644
--- a/sbin/pfctl/tests/files/pf0088.in
+++ b/sbin/pfctl/tests/files/pf0088.in
@@ -16,7 +16,7 @@ pass to 10.0.0.2 keep state
block from 10.0.0.3 to 10.0.0.2
pass to 10.0.0.2 modulate state
block from 10.0.0.3 to 10.0.0.2
-pass to 10.0.0.2 synproxy state
+pass in to 10.0.0.2 synproxy state
pass out proto tcp from 10.0.0.4 to 10.0.0.5 keep state
diff --git a/sbin/pfctl/tests/files/pf0088.ok b/sbin/pfctl/tests/files/pf0088.ok
index 47251a4503dd..801056a4ab46 100644
--- a/sbin/pfctl/tests/files/pf0088.ok
+++ b/sbin/pfctl/tests/files/pf0088.ok
@@ -11,7 +11,7 @@ pass inet from any to 10.0.0.2 flags S/SA keep state
block drop inet from 10.0.0.3 to 10.0.0.2
pass inet from any to 10.0.0.2 flags S/SA modulate state
block drop inet from 10.0.0.3 to 10.0.0.2
-pass inet from any to 10.0.0.2 flags S/SA synproxy state
+pass in inet from any to 10.0.0.2 flags S/SA synproxy state
pass out inet proto tcp from 10.0.0.4 to 10.0.0.5 flags S/SA keep state
pass out inet proto tcp from 10.0.0.4 to 10.0.0.5 port = http flags S/SA keep state
pass out all flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf0098.in b/sbin/pfctl/tests/files/pf0098.in
index b2b642be2026..c26f0fcfe4d3 100644
--- a/sbin/pfctl/tests/files/pf0098.in
+++ b/sbin/pfctl/tests/files/pf0098.in
@@ -1,4 +1,3 @@
# Test rule order processing should pass (require-order no longer required)
pass in on lo1000000 all
-#match out on lo0 inet6 all nat-to lo0
-
+match out on lo0 inet6 all nat-to lo0
diff --git a/sbin/pfctl/tests/files/pf0098.ok b/sbin/pfctl/tests/files/pf0098.ok
index 62016c91d60b..105bb46b4ae5 100644
--- a/sbin/pfctl/tests/files/pf0098.ok
+++ b/sbin/pfctl/tests/files/pf0098.ok
@@ -1 +1,2 @@
pass in on lo1000000 all flags S/SA keep state
+match out on lo0 inet6 all nat-to { ::1, fe80::1 } round-robin
diff --git a/sbin/pfctl/tests/files/pf0100.ok b/sbin/pfctl/tests/files/pf0100.ok
index 6d1740f308bc..9f4427379bc7 100644
--- a/sbin/pfctl/tests/files/pf0100.ok
+++ b/sbin/pfctl/tests/files/pf0100.ok
@@ -1,14 +1,14 @@
pass all flags S/SA keep state
-anchor "/b" all
-anchor "/3" all
+anchor "a/b" all
+anchor "1/2/3" all
anchor "relative" all {
pass in on lo0 all flags S/SA keep state label "TEST1"
}
-anchor "/*" all
-anchor "/*" all
+anchor "camield/*" all
+anchor "relayd/*" all
anchor "foo" in on lo0 all {
anchor "bar" in all {
- anchor "/3" all
+ anchor "/1/2/3" all
anchor "/relative" all
pass in on lo0 all flags S/SA keep state label "FOO"
}
diff --git a/sbin/pfctl/tests/files/pf0102.ok b/sbin/pfctl/tests/files/pf0102.ok
index 3233ca5a2643..1c76ec2725ba 100644
--- a/sbin/pfctl/tests/files/pf0102.ok
+++ b/sbin/pfctl/tests/files/pf0102.ok
@@ -1,8 +1,8 @@
pass inet from 1.1.1.1 to (self) flags S/SA keep state
-pass inet6 from 2002:: to (self)/32 flags S/SA keep state
+pass inet6 from 2002:: to (self) flags S/SA keep state
pass inet6 from 2002:: to (self) flags S/SA keep state
pass inet from 1.1.1.1 to (self) flags S/SA keep state
pass inet from 1.1.1.1 to (self) flags S/SA keep state
-pass inet6 from 2002:: to (self)/32 flags S/SA keep state
+pass inet6 from 2002:: to (self)/40 flags S/SA keep state
pass inet6 from 2002:: to (self)/40 flags S/SA keep state
pass inet from 1.1.1.1 to (self) flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf1002.in b/sbin/pfctl/tests/files/pf1002.in
index 5180e8395f9c..3fdde81be7de 100644
--- a/sbin/pfctl/tests/files/pf1002.in
+++ b/sbin/pfctl/tests/files/pf1002.in
@@ -1 +1,6 @@
set timeout interval 10
+set timeout sctp.first 11
+set timeout sctp.opening 12
+set timeout sctp.established 13
+set timeout sctp.closing 14
+set timeout sctp.closed 15
diff --git a/sbin/pfctl/tests/files/pf1002.ok b/sbin/pfctl/tests/files/pf1002.ok
index 5180e8395f9c..3fdde81be7de 100644
--- a/sbin/pfctl/tests/files/pf1002.ok
+++ b/sbin/pfctl/tests/files/pf1002.ok
@@ -1 +1,6 @@
set timeout interval 10
+set timeout sctp.first 11
+set timeout sctp.opening 12
+set timeout sctp.established 13
+set timeout sctp.closing 14
+set timeout sctp.closed 15
diff --git a/sbin/pfctl/tests/files/pf1010.in b/sbin/pfctl/tests/files/pf1010.in
new file mode 100644
index 000000000000..2baf4dc360af
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1010.in
@@ -0,0 +1,2 @@
+pass inet proto icmp icmp-type {unreach}
+pass in route-to (if0 127.0.0.1/8) sticky-address inet
diff --git a/sbin/pfctl/tests/files/pf1010.ok b/sbin/pfctl/tests/files/pf1010.ok
new file mode 100644
index 000000000000..b960dbfc50b8
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1010.ok
@@ -0,0 +1,2 @@
+pass inet proto icmp all icmp-type unreach keep state
+pass in route-to (if0 127.0.0.0/8) sticky-address inet all flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf1011.in b/sbin/pfctl/tests/files/pf1011.in
new file mode 100644
index 000000000000..84f0e7204e40
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1011.in
@@ -0,0 +1 @@
+scrub fragment no reassemble
diff --git a/sbin/pfctl/tests/files/pf1011.ok b/sbin/pfctl/tests/files/pf1011.ok
new file mode 100644
index 000000000000..48572b371d8d
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1011.ok
@@ -0,0 +1 @@
+scrub all fragment no reassemble
diff --git a/sbin/pfctl/tests/files/pf1012.in b/sbin/pfctl/tests/files/pf1012.in
new file mode 100644
index 000000000000..9083d1bf5396
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1012.in
@@ -0,0 +1 @@
+scrub
diff --git a/sbin/pfctl/tests/files/pf1012.ok b/sbin/pfctl/tests/files/pf1012.ok
new file mode 100644
index 000000000000..b7f1f454fb6a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1012.ok
@@ -0,0 +1 @@
+scrub all fragment reassemble
diff --git a/sbin/pfctl/tests/files/pf1013.in b/sbin/pfctl/tests/files/pf1013.in
new file mode 100644
index 000000000000..053804e1a35a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1013.in
@@ -0,0 +1 @@
+ether block out on igb0 ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1013.ok b/sbin/pfctl/tests/files/pf1013.ok
new file mode 100644
index 000000000000..7395f3fd6311
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1013.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1014.in b/sbin/pfctl/tests/files/pf1014.in
new file mode 100644
index 000000000000..8739034f1bda
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1014.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test"
diff --git a/sbin/pfctl/tests/files/pf1014.ok b/sbin/pfctl/tests/files/pf1014.ok
new file mode 100644
index 000000000000..d0086cb25e54
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1014.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test"
diff --git a/sbin/pfctl/tests/files/pf1015.in b/sbin/pfctl/tests/files/pf1015.in
new file mode 100644
index 000000000000..11c7a211ae8a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1015.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test" label "another label"
diff --git a/sbin/pfctl/tests/files/pf1015.ok b/sbin/pfctl/tests/files/pf1015.ok
new file mode 100644
index 000000000000..d3ea76f1875b
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1015.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test" label "another label"
diff --git a/sbin/pfctl/tests/files/pf1016.in b/sbin/pfctl/tests/files/pf1016.in
new file mode 100644
index 000000000000..a7b1f6bc0ca9
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1016.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1016.ok b/sbin/pfctl/tests/files/pf1016.ok
new file mode 100644
index 000000000000..f1d59c988730
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1016.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1017.in b/sbin/pfctl/tests/files/pf1017.in
new file mode 100644
index 000000000000..ad523337bdc5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1017.in
@@ -0,0 +1 @@
+ether block out on igb0 label "test" label "another test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1017.ok b/sbin/pfctl/tests/files/pf1017.ok
new file mode 100644
index 000000000000..0efdd55e27a0
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1017.ok
@@ -0,0 +1 @@
+ether block out on igb0 l3 all label "test" label "another test" ridentifier 12345678
diff --git a/sbin/pfctl/tests/files/pf1018.in b/sbin/pfctl/tests/files/pf1018.in
new file mode 100644
index 000000000000..90f0a3a0bab7
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1018.in
@@ -0,0 +1 @@
+pass from { 192.0.2.1 2001:db8::1 } to (pppoe0)
diff --git a/sbin/pfctl/tests/files/pf1018.ok b/sbin/pfctl/tests/files/pf1018.ok
new file mode 100644
index 000000000000..04950f0035b8
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1018.ok
@@ -0,0 +1,2 @@
+pass inet from 192.0.2.1 to (pppoe0) flags S/SA keep state
+pass inet6 from 2001:db8::1 to (pppoe0) flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf1019.in b/sbin/pfctl/tests/files/pf1019.in
new file mode 100644
index 000000000000..04a770768714
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1019.in
@@ -0,0 +1 @@
+pass in keep state (pflow)
diff --git a/sbin/pfctl/tests/files/pf1019.ok b/sbin/pfctl/tests/files/pf1019.ok
new file mode 100644
index 000000000000..e865d57da16c
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1019.ok
@@ -0,0 +1 @@
+pass in all flags S/SA keep state (pflow)
diff --git a/sbin/pfctl/tests/files/pf1020.in b/sbin/pfctl/tests/files/pf1020.in
new file mode 100644
index 000000000000..7f98df69bd04
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1020.in
@@ -0,0 +1,3 @@
+table <tabl1> file "./pf1020.include"
+
+block from <tabl1>
diff --git a/sbin/pfctl/tests/files/pf1020.include b/sbin/pfctl/tests/files/pf1020.include
new file mode 100644
index 000000000000..3fca07f64bfa
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1020.include
@@ -0,0 +1,4 @@
+; comment1
+# comment2
+1.0.0.1/32 ; comment1
+2.0.0.2/32 # comment2
diff --git a/sbin/pfctl/tests/files/pf1020.ok b/sbin/pfctl/tests/files/pf1020.ok
new file mode 100644
index 000000000000..16073b3d6987
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1020.ok
@@ -0,0 +1,2 @@
+table <tabl1> file "./pf1020.include"
+block drop from <tabl1> to any
diff --git a/sbin/pfctl/tests/files/pf1021.in b/sbin/pfctl/tests/files/pf1021.in
new file mode 100644
index 000000000000..841b024157c6
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1021.in
@@ -0,0 +1 @@
+nat on vtnet1 inet from ! (vtnet1) to any -> (vtnet1) endpoint-independent
diff --git a/sbin/pfctl/tests/files/pf1021.ok b/sbin/pfctl/tests/files/pf1021.ok
new file mode 100644
index 000000000000..3b5b84e2e11b
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1021.ok
@@ -0,0 +1 @@
+nat on vtnet1 inet from ! (vtnet1) to any -> (vtnet1) round-robin endpoint-independent
diff --git a/sbin/pfctl/tests/files/pf1022.in b/sbin/pfctl/tests/files/pf1022.in
new file mode 100644
index 000000000000..640eb1334100
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1022.in
@@ -0,0 +1 @@
+pass out on em0 from 192.0.2.1 to 198.51.100.1 received-on fxp0
diff --git a/sbin/pfctl/tests/files/pf1022.ok b/sbin/pfctl/tests/files/pf1022.ok
new file mode 100644
index 000000000000..2f7b4a5bd616
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1022.ok
@@ -0,0 +1 @@
+pass out on em0 inet from 192.0.2.1 to 198.51.100.1 received-on fxp0 flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf1023.in b/sbin/pfctl/tests/files/pf1023.in
new file mode 100644
index 000000000000..4855ae0f339e
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1023.in
@@ -0,0 +1,3 @@
+match log(matches) inet proto tcp
+match log(matches) inet from 192.0.2.0/24
+pass
diff --git a/sbin/pfctl/tests/files/pf1023.ok b/sbin/pfctl/tests/files/pf1023.ok
new file mode 100644
index 000000000000..63fa40113ecf
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1023.ok
@@ -0,0 +1,3 @@
+match log (matches) inet proto tcp all
+match log (matches) inet from 192.0.2.0/24 to any
+pass all flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf1024.in b/sbin/pfctl/tests/files/pf1024.in
new file mode 100644
index 000000000000..be518bb3bd53
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1024.in
@@ -0,0 +1 @@
+pass in inet af-to inet6 from 2001:db8::1
diff --git a/sbin/pfctl/tests/files/pf1024.ok b/sbin/pfctl/tests/files/pf1024.ok
new file mode 100644
index 000000000000..2d4ddb9d0ce7
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1024.ok
@@ -0,0 +1 @@
+pass in inet all flags S/SA keep state af-to inet6 from 2001:db8::1
diff --git a/sbin/pfctl/tests/files/pf1025.in b/sbin/pfctl/tests/files/pf1025.in
new file mode 100644
index 000000000000..d4ad821a6899
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1025.in
@@ -0,0 +1 @@
+pass in from 10.0.0.0/8 af-to inet6 from 2001:db8::1
diff --git a/sbin/pfctl/tests/files/pf1025.ok b/sbin/pfctl/tests/files/pf1025.ok
new file mode 100644
index 000000000000..8f48c987c6a0
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1025.ok
@@ -0,0 +1 @@
+pass in inet from 10.0.0.0/8 to any flags S/SA keep state af-to inet6 from 2001:db8::1
diff --git a/sbin/pfctl/tests/files/pf1026.in b/sbin/pfctl/tests/files/pf1026.in
new file mode 100644
index 000000000000..3691d0947b39
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1026.in
@@ -0,0 +1 @@
+pass in on epair2b route-to (epair0a 192.0.2.2) inet6 from any to 64:ff9b::/96 af-to inet from (epair0a)
diff --git a/sbin/pfctl/tests/files/pf1026.ok b/sbin/pfctl/tests/files/pf1026.ok
new file mode 100644
index 000000000000..323036f2b800
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1026.ok
@@ -0,0 +1 @@
+pass in on epair2b route-to (epair0a 192.0.2.2) inet6 from any to 64:ff9b::/96 flags S/SA keep state af-to inet from (epair0a) round-robin
diff --git a/sbin/pfctl/tests/files/pf1027.in b/sbin/pfctl/tests/files/pf1027.in
new file mode 100644
index 000000000000..3c5c24025e0a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1027.in
@@ -0,0 +1 @@
+pass in on epair2b reply-to (epair0a 2001:db8::1) inet6 from any to 64:ff9b::/96 af-to inet from (epair0a)
diff --git a/sbin/pfctl/tests/files/pf1027.ok b/sbin/pfctl/tests/files/pf1027.ok
new file mode 100644
index 000000000000..b50f1e216837
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1027.ok
@@ -0,0 +1 @@
+pass in on epair2b reply-to (epair0a 2001:db8::1) inet6 from any to 64:ff9b::/96 flags S/SA keep state af-to inet from (epair0a) round-robin
diff --git a/sbin/pfctl/tests/files/pf1028.in b/sbin/pfctl/tests/files/pf1028.in
new file mode 100644
index 000000000000..2386fcb52249
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1028.in
@@ -0,0 +1 @@
+rdr on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3
diff --git a/sbin/pfctl/tests/files/pf1028.ok b/sbin/pfctl/tests/files/pf1028.ok
new file mode 100644
index 000000000000..07be890f4e05
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1028.ok
@@ -0,0 +1 @@
+rdr on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3
diff --git a/sbin/pfctl/tests/files/pf1029.in b/sbin/pfctl/tests/files/pf1029.in
new file mode 100644
index 000000000000..73815839aadd
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1029.in
@@ -0,0 +1 @@
+rdr on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1002
diff --git a/sbin/pfctl/tests/files/pf1029.ok b/sbin/pfctl/tests/files/pf1029.ok
new file mode 100644
index 000000000000..6e9083bf856a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1029.ok
@@ -0,0 +1 @@
+rdr on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1002
diff --git a/sbin/pfctl/tests/files/pf1030.in b/sbin/pfctl/tests/files/pf1030.in
new file mode 100644
index 000000000000..b6f891998a71
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1030.in
@@ -0,0 +1 @@
+rdr on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 50001:65535
diff --git a/sbin/pfctl/tests/files/pf1030.ok b/sbin/pfctl/tests/files/pf1030.ok
new file mode 100644
index 000000000000..4f6b2eba2f39
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1030.ok
@@ -0,0 +1 @@
+rdr on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 50001:65535
diff --git a/sbin/pfctl/tests/files/pf1031.in b/sbin/pfctl/tests/files/pf1031.in
new file mode 100644
index 000000000000..7cad4ae64000
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1031.in
@@ -0,0 +1 @@
+rdr on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 port 1004:2004 -> 192.0.2.3 port 1004
diff --git a/sbin/pfctl/tests/files/pf1031.ok b/sbin/pfctl/tests/files/pf1031.ok
new file mode 100644
index 000000000000..8dd7fe027716
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1031.ok
@@ -0,0 +1 @@
+rdr on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 port 1004:2004 -> 192.0.2.3 port 1004
diff --git a/sbin/pfctl/tests/files/pf1032.in b/sbin/pfctl/tests/files/pf1032.in
new file mode 100644
index 000000000000..a2eec78da045
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1032.in
@@ -0,0 +1 @@
+rdr on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 port 1005:2005 -> 192.0.2.3 port 3004:*
diff --git a/sbin/pfctl/tests/files/pf1032.ok b/sbin/pfctl/tests/files/pf1032.ok
new file mode 100644
index 000000000000..3b3f124efc33
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1032.ok
@@ -0,0 +1 @@
+rdr on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 port 1005:2005 -> 192.0.2.3 port 3004:4004
diff --git a/sbin/pfctl/tests/files/pf1033.fail b/sbin/pfctl/tests/files/pf1033.fail
new file mode 100644
index 000000000000..d9fbfe4296e3
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1033.fail
@@ -0,0 +1 @@
+the 'static-port' option is only valid with nat rules
diff --git a/sbin/pfctl/tests/files/pf1033.in b/sbin/pfctl/tests/files/pf1033.in
new file mode 100644
index 000000000000..76f33e7e8f0e
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1033.in
@@ -0,0 +1 @@
+rdr on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 static-port
diff --git a/sbin/pfctl/tests/files/pf1034.fail b/sbin/pfctl/tests/files/pf1034.fail
new file mode 100644
index 000000000000..e407996a8fa3
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1034.fail
@@ -0,0 +1 @@
+the 'map-e-portset' option is only valid with nat rules
diff --git a/sbin/pfctl/tests/files/pf1034.in b/sbin/pfctl/tests/files/pf1034.in
new file mode 100644
index 000000000000..be847a8af241
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1034.in
@@ -0,0 +1 @@
+rdr on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 map-e-portset 6/8/0x34
diff --git a/sbin/pfctl/tests/files/pf1035.in b/sbin/pfctl/tests/files/pf1035.in
new file mode 100644
index 000000000000..9382ffedc8c9
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1035.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3
diff --git a/sbin/pfctl/tests/files/pf1035.ok b/sbin/pfctl/tests/files/pf1035.ok
new file mode 100644
index 000000000000..be573ef460f5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1035.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3
diff --git a/sbin/pfctl/tests/files/pf1036.in b/sbin/pfctl/tests/files/pf1036.in
new file mode 100644
index 000000000000..81718c908303
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1036.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 50001:65535
diff --git a/sbin/pfctl/tests/files/pf1036.ok b/sbin/pfctl/tests/files/pf1036.ok
new file mode 100644
index 000000000000..be573ef460f5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1036.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3
diff --git a/sbin/pfctl/tests/files/pf1037.in b/sbin/pfctl/tests/files/pf1037.in
new file mode 100644
index 000000000000..a30f6c0e7bbe
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1037.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1003
diff --git a/sbin/pfctl/tests/files/pf1037.ok b/sbin/pfctl/tests/files/pf1037.ok
new file mode 100644
index 000000000000..020e2de28dec
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1037.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1003
diff --git a/sbin/pfctl/tests/files/pf1038.in b/sbin/pfctl/tests/files/pf1038.in
new file mode 100644
index 000000000000..532060e56494
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1038.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1004:2004
diff --git a/sbin/pfctl/tests/files/pf1038.ok b/sbin/pfctl/tests/files/pf1038.ok
new file mode 100644
index 000000000000..a4021db7b1b2
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1038.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1004:2004
diff --git a/sbin/pfctl/tests/files/pf1039.in b/sbin/pfctl/tests/files/pf1039.in
new file mode 100644
index 000000000000..dba14b0625de
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1039.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 static-port
diff --git a/sbin/pfctl/tests/files/pf1039.ok b/sbin/pfctl/tests/files/pf1039.ok
new file mode 100644
index 000000000000..80cfbe742865
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1039.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 static-port
diff --git a/sbin/pfctl/tests/files/pf1040.fail b/sbin/pfctl/tests/files/pf1040.fail
new file mode 100644
index 000000000000..5b9afc22b441
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1040.fail
@@ -0,0 +1 @@
+the 'static-port' option can't be used when specifying a port range
diff --git a/sbin/pfctl/tests/files/pf1040.in b/sbin/pfctl/tests/files/pf1040.in
new file mode 100644
index 000000000000..38d7292a560a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1040.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1006 static-port
diff --git a/sbin/pfctl/tests/files/pf1040.ok b/sbin/pfctl/tests/files/pf1040.ok
new file mode 100644
index 000000000000..ffe2e023f77c
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1040.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 map-e-portset 6/8/52
diff --git a/sbin/pfctl/tests/files/pf1041.in b/sbin/pfctl/tests/files/pf1041.in
new file mode 100644
index 000000000000..4c384ac70e05
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1041.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 map-e-portset 6/8/0x34
diff --git a/sbin/pfctl/tests/files/pf1041.ok b/sbin/pfctl/tests/files/pf1041.ok
new file mode 100644
index 000000000000..ffe2e023f77c
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1041.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 map-e-portset 6/8/52
diff --git a/sbin/pfctl/tests/files/pf1042.fail b/sbin/pfctl/tests/files/pf1042.fail
new file mode 100644
index 000000000000..56e174a5ece5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1042.fail
@@ -0,0 +1 @@
+the 'map-e-portset' option can't be used 'static-port'
diff --git a/sbin/pfctl/tests/files/pf1042.in b/sbin/pfctl/tests/files/pf1042.in
new file mode 100644
index 000000000000..906f637b6a0a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1042.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 static-port map-e-portset 6/8/0x34
diff --git a/sbin/pfctl/tests/files/pf1043.fail b/sbin/pfctl/tests/files/pf1043.fail
new file mode 100644
index 000000000000..cdfab00916a2
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1043.fail
@@ -0,0 +1 @@
+the 'map-e-portset' option can't be used when specifying a port range
diff --git a/sbin/pfctl/tests/files/pf1043.in b/sbin/pfctl/tests/files/pf1043.in
new file mode 100644
index 000000000000..15428a9e54bc
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1043.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3 port 1007 map-e-portset 6/8/0x34
diff --git a/sbin/pfctl/tests/files/pf1044.in b/sbin/pfctl/tests/files/pf1044.in
new file mode 100644
index 000000000000..6a927b66b83f
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1044.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> <targets> sticky-address
diff --git a/sbin/pfctl/tests/files/pf1044.ok b/sbin/pfctl/tests/files/pf1044.ok
new file mode 100644
index 000000000000..a68b1daaa73a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1044.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> <targets> round-robin sticky-address
diff --git a/sbin/pfctl/tests/files/pf1045.in b/sbin/pfctl/tests/files/pf1045.in
new file mode 100644
index 000000000000..38f708ce19b8
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1045.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 bitmask
diff --git a/sbin/pfctl/tests/files/pf1045.ok b/sbin/pfctl/tests/files/pf1045.ok
new file mode 100644
index 000000000000..5388db7e58a4
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1045.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 bitmask
diff --git a/sbin/pfctl/tests/files/pf1046.fail b/sbin/pfctl/tests/files/pf1046.fail
new file mode 100644
index 000000000000..b152f9063241
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1046.fail
@@ -0,0 +1 @@
+tables are not supported by pool type
diff --git a/sbin/pfctl/tests/files/pf1046.in b/sbin/pfctl/tests/files/pf1046.in
new file mode 100644
index 000000000000..e4a9f79efd6f
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1046.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> <targets> bitmask
diff --git a/sbin/pfctl/tests/files/pf1047.fail b/sbin/pfctl/tests/files/pf1047.fail
new file mode 100644
index 000000000000..239b96b2fed4
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1047.fail
@@ -0,0 +1 @@
+interface \(vtnet1\) is not supported by pool type
diff --git a/sbin/pfctl/tests/files/pf1047.in b/sbin/pfctl/tests/files/pf1047.in
new file mode 100644
index 000000000000..369bfcb0fb26
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1047.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> (vtnet1) bitmask
diff --git a/sbin/pfctl/tests/files/pf1048.in b/sbin/pfctl/tests/files/pf1048.in
new file mode 100644
index 000000000000..01232a33b5d8
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1048.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 random
diff --git a/sbin/pfctl/tests/files/pf1048.ok b/sbin/pfctl/tests/files/pf1048.ok
new file mode 100644
index 000000000000..35e86fc676fc
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1048.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 random
diff --git a/sbin/pfctl/tests/files/pf1049.in b/sbin/pfctl/tests/files/pf1049.in
new file mode 100644
index 000000000000..3f2e5acf8265
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1049.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> { 192.0.2.3 }
diff --git a/sbin/pfctl/tests/files/pf1049.ok b/sbin/pfctl/tests/files/pf1049.ok
new file mode 100644
index 000000000000..be573ef460f5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1049.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 192.0.2.3
diff --git a/sbin/pfctl/tests/files/pf1050.in b/sbin/pfctl/tests/files/pf1050.in
new file mode 100644
index 000000000000..69ccaf445c3b
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1050.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> <targets>
diff --git a/sbin/pfctl/tests/files/pf1050.ok b/sbin/pfctl/tests/files/pf1050.ok
new file mode 100644
index 000000000000..24ca9b459bb7
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1050.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> <targets> round-robin
diff --git a/sbin/pfctl/tests/files/pf1051.in b/sbin/pfctl/tests/files/pf1051.in
new file mode 100644
index 000000000000..734da64a372c
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1051.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.1 203.0.113.2 }
diff --git a/sbin/pfctl/tests/files/pf1051.ok b/sbin/pfctl/tests/files/pf1051.ok
new file mode 100644
index 000000000000..86f23488be41
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1051.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.1, 203.0.113.2 } round-robin
diff --git a/sbin/pfctl/tests/files/pf1052.in b/sbin/pfctl/tests/files/pf1052.in
new file mode 100644
index 000000000000..2ea770f3c06e
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1052.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.1 <targets> }
diff --git a/sbin/pfctl/tests/files/pf1052.ok b/sbin/pfctl/tests/files/pf1052.ok
new file mode 100644
index 000000000000..b71d105eb77a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1052.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.1, <targets> } round-robin
diff --git a/sbin/pfctl/tests/files/pf1053.in b/sbin/pfctl/tests/files/pf1053.in
new file mode 100644
index 000000000000..f0cced0b64a2
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1053.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24
diff --git a/sbin/pfctl/tests/files/pf1053.ok b/sbin/pfctl/tests/files/pf1053.ok
new file mode 100644
index 000000000000..de321b8c738f
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1053.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24
diff --git a/sbin/pfctl/tests/files/pf1054.in b/sbin/pfctl/tests/files/pf1054.in
new file mode 100644
index 000000000000..9e66bb2a81d6
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1054.in
@@ -0,0 +1,3 @@
+# XXX: it causes just the 0th address to be used without cycling
+# Probably a bug
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 round-robin
diff --git a/sbin/pfctl/tests/files/pf1054.ok b/sbin/pfctl/tests/files/pf1054.ok
new file mode 100644
index 000000000000..3d7ab7974d87
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1054.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 round-robin
diff --git a/sbin/pfctl/tests/files/pf1055.in b/sbin/pfctl/tests/files/pf1055.in
new file mode 100644
index 000000000000..c116ef5fd43e
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1055.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 source-hash 0x42424242424242424242424242424242
diff --git a/sbin/pfctl/tests/files/pf1055.ok b/sbin/pfctl/tests/files/pf1055.ok
new file mode 100644
index 000000000000..468e47012169
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1055.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.0/24 source-hash 0x42424242424242424242424242424242
diff --git a/sbin/pfctl/tests/files/pf1056.in b/sbin/pfctl/tests/files/pf1056.in
new file mode 100644
index 000000000000..bd2af077fc3f
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1056.in
@@ -0,0 +1 @@
+pass in on vtnet0 inet6 from any to 64:ff9b::/96 af-to inet from 203.0.113.1 to 203.0.113.2
diff --git a/sbin/pfctl/tests/files/pf1056.ok b/sbin/pfctl/tests/files/pf1056.ok
new file mode 100644
index 000000000000..0397570dbce0
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1056.ok
@@ -0,0 +1 @@
+pass in on vtnet0 inet6 from any to 64:ff9b::/96 flags S/SA keep state af-to inet from 203.0.113.1 to 203.0.113.2
diff --git a/sbin/pfctl/tests/files/pf1057.in b/sbin/pfctl/tests/files/pf1057.in
new file mode 100644
index 000000000000..0e26976e5a0d
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1057.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> vlan1057
diff --git a/sbin/pfctl/tests/files/pf1057.ok b/sbin/pfctl/tests/files/pf1057.ok
new file mode 100644
index 000000000000..7626951e138c
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1057.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> 203.0.113.5
diff --git a/sbin/pfctl/tests/files/pf1058.in b/sbin/pfctl/tests/files/pf1058.in
new file mode 100644
index 000000000000..27c0ef1d69b3
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1058.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.1 vlan1058 }
diff --git a/sbin/pfctl/tests/files/pf1058.ok b/sbin/pfctl/tests/files/pf1058.ok
new file mode 100644
index 000000000000..b1d2b07a58b4
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1058.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.1, 203.0.113.5 } round-robin
diff --git a/sbin/pfctl/tests/files/pf1059.in b/sbin/pfctl/tests/files/pf1059.in
new file mode 100644
index 000000000000..92ed5c50656b
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1059.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> (vlan1059)
diff --git a/sbin/pfctl/tests/files/pf1059.ok b/sbin/pfctl/tests/files/pf1059.ok
new file mode 100644
index 000000000000..6b028f18ee60
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1059.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> (vlan1059) round-robin
diff --git a/sbin/pfctl/tests/files/pf1060.in b/sbin/pfctl/tests/files/pf1060.in
new file mode 100644
index 000000000000..85cdd19f2897
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1060.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.0 (vlan1060) }
diff --git a/sbin/pfctl/tests/files/pf1060.ok b/sbin/pfctl/tests/files/pf1060.ok
new file mode 100644
index 000000000000..3364b3cbdcc5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1060.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet proto tcp from 192.0.2.1 to 192.0.2.2 -> { 203.0.113.0, (vlan1060) } round-robin
diff --git a/sbin/pfctl/tests/files/pf1061.in b/sbin/pfctl/tests/files/pf1061.in
new file mode 100644
index 000000000000..32eb8272db8b
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1061.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 2001:db8::1 to 2001:db8::2 -> vlan1061:0
diff --git a/sbin/pfctl/tests/files/pf1061.ok b/sbin/pfctl/tests/files/pf1061.ok
new file mode 100644
index 000000000000..d2e6d969cb11
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1061.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet6 proto tcp from 2001:db8::1 to 2001:db8::2 -> 2001:db8::cb00:7105
diff --git a/sbin/pfctl/tests/files/pf1062.in b/sbin/pfctl/tests/files/pf1062.in
new file mode 100644
index 000000000000..4d6a0ecc2e92
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1062.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 2001:db8::1 to 2001:db8::2 -> { 2001:db8::3 vlan1062:0 }
diff --git a/sbin/pfctl/tests/files/pf1062.ok b/sbin/pfctl/tests/files/pf1062.ok
new file mode 100644
index 000000000000..cb5db62ded1d
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1062.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet6 proto tcp from 2001:db8::1 to 2001:db8::2 -> { 2001:db8::3, 2001:db8::cb00:7105 } round-robin
diff --git a/sbin/pfctl/tests/files/pf1063.in b/sbin/pfctl/tests/files/pf1063.in
new file mode 100644
index 000000000000..3d164538640d
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1063.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 2001:db8::1 to 2001:db8::2 -> (vlan1063)
diff --git a/sbin/pfctl/tests/files/pf1063.ok b/sbin/pfctl/tests/files/pf1063.ok
new file mode 100644
index 000000000000..13189e00cc8a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1063.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet6 proto tcp from 2001:db8::1 to 2001:db8::2 -> (vlan1063) round-robin
diff --git a/sbin/pfctl/tests/files/pf1064.in b/sbin/pfctl/tests/files/pf1064.in
new file mode 100644
index 000000000000..78d04135154f
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1064.in
@@ -0,0 +1 @@
+nat on vtnet0 proto tcp from 2001:db8::1 to 2001:db8::2 -> { fe80::2 (vlan1064) }
diff --git a/sbin/pfctl/tests/files/pf1064.ok b/sbin/pfctl/tests/files/pf1064.ok
new file mode 100644
index 000000000000..ed15d054ab34
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1064.ok
@@ -0,0 +1 @@
+nat on vtnet0 inet6 proto tcp from 2001:db8::1 to 2001:db8::2 -> { fe80::2, (vlan1064) } round-robin
diff --git a/sbin/pfctl/tests/files/pf1065.in b/sbin/pfctl/tests/files/pf1065.in
new file mode 100644
index 000000000000..690045befee6
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1065.in
@@ -0,0 +1 @@
+no nat on vtnet0 proto tcp from 2001:db8::1 to 2001:db8::2
diff --git a/sbin/pfctl/tests/files/pf1065.ok b/sbin/pfctl/tests/files/pf1065.ok
new file mode 100644
index 000000000000..651a2fa0ae09
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1065.ok
@@ -0,0 +1 @@
+no nat on vtnet0 inet6 proto tcp from 2001:db8::1 to 2001:db8::2
diff --git a/sbin/pfctl/tests/files/pf1066.in b/sbin/pfctl/tests/files/pf1066.in
new file mode 100644
index 000000000000..e81461c470ab
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1066.in
@@ -0,0 +1 @@
+no rdr on vtnet0 proto tcp from 2001:db8::1 to 2001:db8::2
diff --git a/sbin/pfctl/tests/files/pf1066.ok b/sbin/pfctl/tests/files/pf1066.ok
new file mode 100644
index 000000000000..5ff596fa0158
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1066.ok
@@ -0,0 +1 @@
+no rdr on vtnet0 inet6 proto tcp from 2001:db8::1 to 2001:db8::2
diff --git a/sbin/pfctl/tests/files/pf1067.fail b/sbin/pfctl/tests/files/pf1067.fail
new file mode 100644
index 000000000000..23ac1daad64f
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1067.fail
@@ -0,0 +1 @@
+route-to, reply-to and dup-to are not supported on block rules
diff --git a/sbin/pfctl/tests/files/pf1067.in b/sbin/pfctl/tests/files/pf1067.in
new file mode 100644
index 000000000000..47f3bf6285dd
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1067.in
@@ -0,0 +1 @@
+block in route-to (if0 127.0.0.1/8)
diff --git a/sbin/pfctl/tests/files/pf1068.in b/sbin/pfctl/tests/files/pf1068.in
new file mode 100644
index 000000000000..993cfa37f8f9
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1068.in
@@ -0,0 +1 @@
+pass in proto icmp max-pkt-rate 100/10
diff --git a/sbin/pfctl/tests/files/pf1068.ok b/sbin/pfctl/tests/files/pf1068.ok
new file mode 100644
index 000000000000..bd36043207f9
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1068.ok
@@ -0,0 +1 @@
+pass in proto icmp all max-pkt-rate 100/10 keep state
diff --git a/sbin/pfctl/tests/files/pf1069.in b/sbin/pfctl/tests/files/pf1069.in
new file mode 100644
index 000000000000..3a69158fff7e
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1069.in
@@ -0,0 +1 @@
+pass in proto icmp max-pkt-size 128
diff --git a/sbin/pfctl/tests/files/pf1069.ok b/sbin/pfctl/tests/files/pf1069.ok
new file mode 100644
index 000000000000..b79228266156
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1069.ok
@@ -0,0 +1 @@
+pass in proto icmp all max-pkt-size 128 keep state
diff --git a/sbin/pfctl/tests/files/pf1070.fail b/sbin/pfctl/tests/files/pf1070.fail
new file mode 100644
index 000000000000..60b56d9da2b9
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1070.fail
@@ -0,0 +1 @@
+pf1070.include:2: syntax error
diff --git a/sbin/pfctl/tests/files/pf1070.in b/sbin/pfctl/tests/files/pf1070.in
new file mode 100644
index 000000000000..42b874d4d6f4
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1070.in
@@ -0,0 +1,2 @@
+pass in
+include pf1070.include
diff --git a/sbin/pfctl/tests/files/pf1070.include b/sbin/pfctl/tests/files/pf1070.include
new file mode 100644
index 000000000000..09c3755dbe28
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1070.include
@@ -0,0 +1,2 @@
+block out
+invalidline
diff --git a/sbin/pfctl/tests/files/pf1071.in b/sbin/pfctl/tests/files/pf1071.in
new file mode 100644
index 000000000000..9e6c2abc0621
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1071.in
@@ -0,0 +1 @@
+pass inet from (lo0)/24
diff --git a/sbin/pfctl/tests/files/pf1071.ok b/sbin/pfctl/tests/files/pf1071.ok
new file mode 100644
index 000000000000..409b5dc4b068
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1071.ok
@@ -0,0 +1 @@
+pass inet from (lo0)/24 to any flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf1072.fail b/sbin/pfctl/tests/files/pf1072.fail
new file mode 100644
index 000000000000..06ef5ae457e5
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1072.fail
@@ -0,0 +1 @@
+invalid port range
diff --git a/sbin/pfctl/tests/files/pf1072.in b/sbin/pfctl/tests/files/pf1072.in
new file mode 100644
index 000000000000..e09e92388ce1
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1072.in
@@ -0,0 +1 @@
+pass in proto tcp from any port 500:100 to any
diff --git a/sbin/pfctl/tests/files/pf1073.in b/sbin/pfctl/tests/files/pf1073.in
new file mode 100644
index 000000000000..477995893ac3
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1073.in
@@ -0,0 +1 @@
+pass in on vtnet0 route-to ( vtnet1 2001:db8::1 ) prefer-ipv6-nexthop inet
diff --git a/sbin/pfctl/tests/files/pf1073.ok b/sbin/pfctl/tests/files/pf1073.ok
new file mode 100644
index 000000000000..f34867508c75
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1073.ok
@@ -0,0 +1 @@
+pass in on vtnet0 route-to (vtnet1 2001:db8::1) prefer-ipv6-nexthop inet all flags S/SA keep state
diff --git a/sbin/pfctl/tests/files/pf1074.fail b/sbin/pfctl/tests/files/pf1074.fail
new file mode 100644
index 000000000000..afe8ee3c458f
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1074.fail
@@ -0,0 +1 @@
+no routing address with matching address family found.
diff --git a/sbin/pfctl/tests/files/pf1074.in b/sbin/pfctl/tests/files/pf1074.in
new file mode 100644
index 000000000000..5d285bc5d6e8
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1074.in
@@ -0,0 +1 @@
+pass in on vtnet0 route-to ( vtnet1 2001:db8::1 ) inet
diff --git a/sbin/pfctl/tests/files/pf1075.in b/sbin/pfctl/tests/files/pf1075.in
new file mode 100644
index 000000000000..835a31a25c6a
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1075.in
@@ -0,0 +1 @@
+pass inet from (lo0)/24 once
diff --git a/sbin/pfctl/tests/files/pf1075.ok b/sbin/pfctl/tests/files/pf1075.ok
new file mode 100644
index 000000000000..2369c9410cda
--- /dev/null
+++ b/sbin/pfctl/tests/files/pf1075.ok
@@ -0,0 +1 @@
+pass inet from (lo0)/24 to any flags S/SA keep state once
diff --git a/sbin/pfctl/tests/macro.sh b/sbin/pfctl/tests/macro.sh
index 194e101d2f84..071c6cb4f426 100755
--- a/sbin/pfctl/tests/macro.sh
+++ b/sbin/pfctl/tests/macro.sh
@@ -1,9 +1,9 @@
-# $FreeBSD$
atf_test_case "space" cleanup
space_head()
{
atf_set descr "Test macros with spaces"
+ atf_set require.kmods "pf"
}
space_body()
diff --git a/sbin/pfctl/tests/pfctl_test.c b/sbin/pfctl/tests/pfctl_test.c
index 4f342a9b95e2..5f0aa7826bb4 100644
--- a/sbin/pfctl/tests/pfctl_test.c
+++ b/sbin/pfctl/tests/pfctl_test.c
@@ -30,8 +30,6 @@
* (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>
@@ -67,24 +65,6 @@ __FBSDID("$FreeBSD$");
* Copied from OpenBSD.
*/
-static bool
-check_pf_module_available(void)
-{
- int modid;
- struct module_stat stat;
-
- if ((modid = modfind("pf")) < 0) {
- warn("pf module not found");
- return false;
- }
- stat.version = sizeof(struct module_stat);
- if (modstat(modid, &stat) < 0) {
- warn("can't stat pf module id %d", modid);
- return false;
- }
- return (true);
-}
-
extern char **environ;
static struct sbuf *
@@ -121,27 +101,14 @@ read_file(const char *filename)
}
static void
-run_pfctl_test(const char *input_path, const char *expected_path,
- const atf_tc_t *tc)
+run_command_pipe(const char *argv[], struct sbuf **output)
{
- int status;
+ posix_spawn_file_actions_t action;
pid_t pid;
int pipefds[2];
- char input_files_path[PATH_MAX];
- struct sbuf *expected_output;
- struct sbuf *real_output;
- posix_spawn_file_actions_t action;
-
- if (!check_pf_module_available())
- atf_tc_skip("pf(4) is not loaded");
-
- /* The test inputs need to be able to use relative includes. */
- snprintf(input_files_path, sizeof(input_files_path), "%s/files",
- atf_tc_get_config_var(tc, "srcdir"));
- ATF_REQUIRE_ERRNO(0, chdir(input_files_path) == 0);
+ int status;
ATF_REQUIRE_ERRNO(0, pipe(pipefds) == 0);
- expected_output = read_file(expected_path);
posix_spawn_file_actions_init(&action);
posix_spawn_file_actions_addclose(&action, STDIN_FILENO);
@@ -149,27 +116,115 @@ run_pfctl_test(const char *input_path, const char *expected_path,
posix_spawn_file_actions_adddup2(&action, pipefds[0], STDOUT_FILENO);
posix_spawn_file_actions_adddup2(&action, pipefds[0], STDERR_FILENO);
- const char *argv[] = { "pfctl", "-o", "none", "-nvf", input_path,
- NULL };
- printf("Running %s %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3],
- argv[4]);
+ printf("Running ");
+ for (int i=0; argv[i] != NULL; i++)
+ printf("%s ", argv[i]);
+ printf("\n");
+
status = posix_spawnp(
- &pid, "pfctl", &action, NULL, __DECONST(char **, argv), environ);
+ &pid, argv[0], &action, NULL, __DECONST(char **, argv), environ);
ATF_REQUIRE_EQ_MSG(
status, 0, "posix_spawn failed: %s", strerror(errno));
posix_spawn_file_actions_destroy(&action);
close(pipefds[0]);
- real_output = read_fd(pipefds[1], 0);
- printf("---\n%s---\n", sbuf_data(real_output));
+ (*output) = read_fd(pipefds[1], 0);
+ printf("---\n%s---\n", sbuf_data(*output));
ATF_REQUIRE_EQ(waitpid(pid, &status, 0), pid);
ATF_REQUIRE_MSG(WIFEXITED(status),
- "pfctl returned non-zero! Output:\n %s", sbuf_data(real_output));
+ "%s returned non-zero! Output:\n %s", argv[0], sbuf_data(*output));
+ close(pipefds[1]);
+}
+
+static void
+run_command(const char *argv[])
+{
+ posix_spawn_file_actions_t action;
+ pid_t pid;
+ int status;
+
+ posix_spawn_file_actions_init(&action);
+ posix_spawn_file_actions_addopen(&action, STDOUT_FILENO, "/dev/null", O_WRONLY, 0);
+ posix_spawn_file_actions_addopen(&action, STDERR_FILENO, "/dev/null", O_WRONLY, 0);
+ posix_spawn_file_actions_addopen(&action, STDIN_FILENO, "/dev/zero", O_RDONLY, 0);
+
+ printf("Running ");
+ for (int i=0; argv[i] != NULL; i++)
+ printf("%s ", argv[i]);
+ printf("\n");
+
+ status = posix_spawnp(
+ &pid, argv[0], &action, NULL, __DECONST(char **, argv), environ);
+ posix_spawn_file_actions_destroy(&action);
+ waitpid(pid, &status, 0);
+}
+
+static void
+run_pfctl_test(const char *input_path, const char *output_path,
+ const atf_tc_t *tc, bool test_failure)
+{
+ char input_files_path[PATH_MAX];
+ struct sbuf *expected_output;
+ struct sbuf *real_output;
+
+ /* The test inputs need to be able to use relative includes. */
+ snprintf(input_files_path, sizeof(input_files_path), "%s/files",
+ atf_tc_get_config_var(tc, "srcdir"));
+ ATF_REQUIRE_ERRNO(0, chdir(input_files_path) == 0);
+ expected_output = read_file(output_path);
+
+ const char *argv[] = { "pfctl", "-o", "none", "-nvf", input_path,
+ NULL };
+ run_command_pipe(argv, &real_output);
+
+ if (test_failure) {
+ /*
+ * Error output contains additional strings like line number
+ * or "skipping rule due to errors", so use regexp to see
+ * if the expected error message is there somewhere.
+ */
+ ATF_CHECK_MATCH(sbuf_data(expected_output), sbuf_data(real_output));
+ sbuf_delete(expected_output);
+ } else {
+ ATF_CHECK_STREQ(sbuf_data(expected_output), sbuf_data(real_output));
+ sbuf_delete(expected_output);
+ }
- ATF_CHECK_STREQ(sbuf_data(expected_output), sbuf_data(real_output));
- sbuf_delete(expected_output);
sbuf_delete(real_output);
- close(pipefds[1]);
+}
+
+static void
+do_pf_test_iface_create(const char *number)
+{
+ struct sbuf *ifconfig_output;
+ char ifname[16] = {0};
+
+ snprintf(ifname, sizeof(ifname), "vlan%s", number);
+ const char *argv[] = { "ifconfig", ifname, "create", NULL};
+ run_command_pipe(argv, &ifconfig_output);
+ sbuf_delete(ifconfig_output);
+
+ const char *argv_inet[] = { "ifconfig", ifname, "inet", "203.0.113.5/30", NULL};
+ run_command_pipe(argv_inet, &ifconfig_output);
+ sbuf_delete(ifconfig_output);
+
+ const char *argv_inet6[] = { "ifconfig", ifname, "inet6", "2001:db8::203.0.113.5/126", NULL};
+ run_command_pipe(argv_inet6, &ifconfig_output);
+ sbuf_delete(ifconfig_output);
+
+ const char *argv_show[] = { "ifconfig", ifname, NULL};
+ run_command_pipe(argv_show, &ifconfig_output);
+ sbuf_delete(ifconfig_output);
+}
+
+static void
+do_pf_test_iface_remove(const char *number)
+{
+ char ifname[16] = {0};
+
+ snprintf(ifname, sizeof(ifname), "vlan%s", number);
+ const char *argv[] = { "ifconfig", ifname, "destroy", NULL};
+ run_command(argv);
}
static void
@@ -181,7 +236,21 @@ do_pf_test(const char *number, const atf_tc_t *tc)
atf_tc_get_config_var(tc, "srcdir"), number);
asprintf(&expected_path, "%s/files/pf%s.ok",
atf_tc_get_config_var(tc, "srcdir"), number);
- run_pfctl_test(input_path, expected_path, tc);
+ run_pfctl_test(input_path, expected_path, tc, false);
+ free(input_path);
+ free(expected_path);
+}
+
+static void
+do_pf_test_fail(const char *number, const atf_tc_t *tc)
+{
+ char *input_path;
+ char *expected_path;
+ asprintf(&input_path, "%s/files/pf%s.in",
+ atf_tc_get_config_var(tc, "srcdir"), number);
+ asprintf(&expected_path, "%s/files/pf%s.fail",
+ atf_tc_get_config_var(tc, "srcdir"), number);
+ run_pfctl_test(input_path, expected_path, tc, true);
free(input_path);
free(expected_path);
}
@@ -192,15 +261,17 @@ do_selfpf_test(const char *number, const atf_tc_t *tc)
char *expected_path;
asprintf(&expected_path, "%s/files/pf%s.ok",
atf_tc_get_config_var(tc, "srcdir"), number);
- run_pfctl_test(expected_path, expected_path, tc);
+ run_pfctl_test(expected_path, expected_path, tc, false);
free(expected_path);
}
+/* Standard tests perform the normal test and then the selfpf test */
#define PFCTL_TEST(number, descr) \
ATF_TC(pf##number); \
ATF_TC_HEAD(pf##number, tc) \
{ \
atf_tc_set_md_var(tc, "descr", descr); \
+ atf_tc_set_md_var(tc, "require.kmods", "pf"); \
} \
ATF_TC_BODY(pf##number, tc) \
{ \
@@ -210,21 +281,61 @@ do_selfpf_test(const char *number, const atf_tc_t *tc)
ATF_TC_HEAD(selfpf##number, tc) \
{ \
atf_tc_set_md_var(tc, "descr", "Self " descr); \
+ atf_tc_set_md_var(tc, "require.kmods", "pf"); \
} \
ATF_TC_BODY(selfpf##number, tc) \
{ \
do_selfpf_test(#number, tc); \
}
+/* Tests for failure perform only the normal test */
+#define PFCTL_TEST_FAIL(number, descr) \
+ ATF_TC(pf##number); \
+ ATF_TC_HEAD(pf##number, tc) \
+ { \
+ atf_tc_set_md_var(tc, "descr", descr); \
+ atf_tc_set_md_var(tc, "require.kmods", "pf"); \
+ } \
+ ATF_TC_BODY(pf##number, tc) \
+ { \
+ do_pf_test_fail(#number, tc); \
+ }
+/* Tests with interface perform only the normal test */
+#define PFCTL_TEST_IFACE(number, descr) \
+ ATF_TC_WITH_CLEANUP(pf##number); \
+ ATF_TC_HEAD(pf##number, tc) \
+ { \
+ atf_tc_set_md_var(tc, "descr", descr); \
+ atf_tc_set_md_var(tc, "execenv", "jail"); \
+ atf_tc_set_md_var(tc, "execenv.jail.params", "vnet"); \
+ atf_tc_set_md_var(tc, "require.kmods", "pf"); \
+ } \
+ ATF_TC_BODY(pf##number, tc) \
+ { \
+ do_pf_test_iface_create(#number); \
+ do_pf_test(#number, tc); \
+ } \
+ ATF_TC_CLEANUP(pf##number, tc) \
+ { \
+ do_pf_test_iface_remove(#number); \
+ }
#include "pfctl_test_list.inc"
#undef PFCTL_TEST
+#undef PFCTL_TEST_FAIL
+#undef PFCTL_TEST_IFACE
ATF_TP_ADD_TCS(tp)
{
#define PFCTL_TEST(number, descr) \
ATF_TP_ADD_TC(tp, pf##number); \
ATF_TP_ADD_TC(tp, selfpf##number);
+#define PFCTL_TEST_FAIL(number, descr) \
+ ATF_TP_ADD_TC(tp, pf##number);
+#define PFCTL_TEST_IFACE(number, descr) \
+ ATF_TP_ADD_TC(tp, pf##number);
#include "pfctl_test_list.inc"
#undef PFCTL_TEST
+#undef PFCTL_TEST_FAIL
+#undef PFCTL_TEST_IFACE
return atf_no_error();
}
diff --git a/sbin/pfctl/tests/pfctl_test_list.inc b/sbin/pfctl/tests/pfctl_test_list.inc
index aa3f625e905f..9dd4a590ad8f 100644
--- a/sbin/pfctl/tests/pfctl_test_list.inc
+++ b/sbin/pfctl/tests/pfctl_test_list.inc
@@ -29,8 +29,6 @@
* 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$
*/
/*
@@ -120,3 +118,69 @@ PFCTL_TEST(1006, "pfctl crashes with certain fairq configurations")
PFCTL_TEST(1007, "Basic ethernet rule")
PFCTL_TEST(1008, "Ethernet rule with mask length")
PFCTL_TEST(1009, "Ethernet rule with mask")
+PFCTL_TEST(1010, "POM_STICKYADDRESS test")
+PFCTL_TEST(1011, "Test disabling scrub fragment reassemble")
+PFCTL_TEST(1012, "Test scrub fragment reassemble is default")
+PFCTL_TEST(1013, "Ethernet rule with ridentifier")
+PFCTL_TEST(1014, "Ethernet rule with one label")
+PFCTL_TEST(1015, "Ethernet rule with several labels")
+PFCTL_TEST(1016, "Ethernet rule with ridentifier and one label")
+PFCTL_TEST(1017, "Ethernet rule with ridentifier and several labels")
+PFCTL_TEST(1018, "Test dynamic address mask")
+PFCTL_TEST(1019, "Test pflow option")
+PFCTL_TEST(1020, "Test hashmark and semicolon comment")
+PFCTL_TEST(1021, "Endpoint-independent")
+PFCTL_TEST(1022, "Test received-on")
+PFCTL_TEST(1023, "Test match log(matches)")
+PFCTL_TEST(1024, "nat64")
+PFCTL_TEST(1025, "nat64 with implicit address family")
+PFCTL_TEST(1026, "nat64 with route-to")
+PFCTL_TEST(1027, "nat64 with reply-to")
+PFCTL_TEST(1028, "RDR pool: For RDR rules no port specified means keep port")
+PFCTL_TEST(1029, "RDR pool: A single port is shown")
+PFCTL_TEST(1030, "RDR pool: The default values are shown for RDR rules")
+PFCTL_TEST(1031, "RDR pool: Multiple ports redirected to a single port")
+PFCTL_TEST(1032, "RDR pool: Multiple ports redirected to a port range")
+PFCTL_TEST_FAIL(1033, "RDR pool: static-port can't be used with RDR rules")
+PFCTL_TEST_FAIL(1034, "RDR pool: MAP-E port can't be used with RDR rules")
+PFCTL_TEST(1035, "NAT pool: For NAT rules no port specified means default values")
+PFCTL_TEST(1036, "NAT pool: Default port numbers are not shown, even if explicitly applied")
+PFCTL_TEST(1037, "NAT pool: Single port")
+PFCTL_TEST(1038, "NAT pool: Two ports")
+PFCTL_TEST(1039, "NAT pool: Static port")
+PFCTL_TEST_FAIL(1040, "NAT pool: Static port can't be used with port numbers")
+PFCTL_TEST(1041, "NAT pool: MAP-E is displayed using decimal system")
+PFCTL_TEST_FAIL(1042, "NAT pool: MAP-E port can't be used with static port")
+PFCTL_TEST_FAIL(1043, "NAT pool: MAP-E port can't be used with port numbers")
+PFCTL_TEST(1044, "pool: sticky-address is applied on top of round-robin")
+PFCTL_TEST(1045, "pool: bitmask is allowed for prefixes")
+PFCTL_TEST_FAIL(1046, "pool: bitmask is not allowed for tables")
+PFCTL_TEST_FAIL(1047, "pool: bitmask is not allowed for interfaces in brackets")
+PFCTL_TEST(1048, "pool: random is allowed for prefixes")
+PFCTL_TEST(1049, "pool: round-robin is not set for a single host, even if it looks like a table")
+PFCTL_TEST(1050, "pool: round-robin is set automatically for tables")
+PFCTL_TEST(1051, "pool: round-robin is set automatically for multiple targets")
+PFCTL_TEST(1052, "pool: hosts and table are allowed, round-robin is automatically set")
+PFCTL_TEST(1053, "pool: round-robin is not set automatically for prefixes")
+PFCTL_TEST(1054, "pool: round-robin is allowed for prefixes")
+PFCTL_TEST(1055, "pool: source hash")
+PFCTL_TEST(1056, "af-to: from and to")
+PFCTL_TEST_IFACE(1057, "Interface translation: IPv4 rule, interface without brackets is translated")
+PFCTL_TEST_IFACE(1058, "Interface translation: IPv4 rule, interface without brackets is translated, extra host, round-robin is applied")
+PFCTL_TEST_IFACE(1059, "Interface translation: IPv4 rule, interface with brackets is not translated, round-robin is applied")
+PFCTL_TEST_IFACE(1060, "Interface translation: IPv4 rule, interface with brackets is not translated, extra host, round-robin is applied")
+PFCTL_TEST_IFACE(1061, "Interface translation: IPv6 rule, interface without brackets is translated")
+PFCTL_TEST_IFACE(1062, "Interface translation: IPv6 rule, interface without brackets is translated, extra host, round-robin is applied")
+PFCTL_TEST_IFACE(1063, "Interface translation: IPv6 rule, interface with brackets is not translated, round-robin is applied")
+PFCTL_TEST_IFACE(1064, "Interface translation: IPv6 rule, interface with brackets is not translated, extra host, round robin is applied")
+PFCTL_TEST(1065, "no nat")
+PFCTL_TEST(1066, "no rdr")
+PFCTL_TEST_FAIL(1067, "route-to can't be used on block rules")
+PFCTL_TEST(1068, "max-pkt-rate")
+PFCTL_TEST(1069, "max-pkt-size")
+PFCTL_TEST_FAIL(1070, "include line number")
+PFCTL_TEST(1071, "mask length on (lo0)")
+PFCTL_TEST_FAIL(1072, "Invalid port range")
+PFCTL_TEST(1073, "Filter AF different than route-to AF, with prefer-ipv6-nexthop")
+PFCTL_TEST_FAIL(1074, "Filter AF different than route-to AF, without prefer-ipv6-nexthop")
+PFCTL_TEST(1075, "One shot rule")
diff --git a/sbin/pfilctl/Makefile b/sbin/pfilctl/Makefile
index d16051b967f0..d5efad642bfd 100644
--- a/sbin/pfilctl/Makefile
+++ b/sbin/pfilctl/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PROG= pfilctl
SRCS= pfilctl.c
diff --git a/sbin/pfilctl/pfilctl.8 b/sbin/pfilctl/pfilctl.8
index d0a50e489a03..4639a7f8e9de 100644
--- a/sbin/pfilctl/pfilctl.8
+++ b/sbin/pfilctl/pfilctl.8
@@ -21,8 +21,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd January 28, 2019
.Dt PFILCTL 8
.Os
diff --git a/sbin/pfilctl/pfilctl.c b/sbin/pfilctl/pfilctl.c
index 2a56009b35b8..1af2190072b6 100644
--- a/sbin/pfilctl/pfilctl.c
+++ b/sbin/pfilctl/pfilctl.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 2019 Gleb Smirnoff <glebius@FreeBSD.org>
*
@@ -25,9 +25,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/ioctl.h>
#include <net/if.h>
@@ -153,8 +150,8 @@ listhooks(int argc __unused, char *argv[] __unused)
u_int nhooks, i;
plh.pio_nhooks = 0;
- if (ioctl(dev, PFILIOC_LISTHEADS, &plh) != 0)
- err(1, "ioctl(PFILIOC_LISTHEADS)");
+ if (ioctl(dev, PFILIOC_LISTHOOKS, &plh) != 0)
+ err(1, "ioctl(PFILIOC_LISTHOOKS)");
retry:
plh.pio_hooks = calloc(plh.pio_nhooks, sizeof(struct pfilioc_hook));
if (plh.pio_hooks == NULL)
diff --git a/sbin/pflogd/Makefile b/sbin/pflogd/Makefile
index 423bfab8c8a2..7b4a636843e0 100644
--- a/sbin/pflogd/Makefile
+++ b/sbin/pflogd/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.PATH: ${SRCTOP}/contrib/pf/pflogd
PACKAGE=pf
diff --git a/sbin/pflogd/Makefile.depend b/sbin/pflogd/Makefile.depend
index 893e74eb908c..cf48f0c1690f 100644
--- a/sbin/pflogd/Makefile.depend
+++ b/sbin/pflogd/Makefile.depend
@@ -1,9 +1,8 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
+ include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
diff --git a/sbin/pflowctl/Makefile b/sbin/pflowctl/Makefile
new file mode 100644
index 000000000000..dd20f7b7a37a
--- /dev/null
+++ b/sbin/pflowctl/Makefile
@@ -0,0 +1,9 @@
+.include <src.opts.mk>
+
+PACKAGE=pf
+PROG= pflowctl
+MAN= pflowctl.8
+
+SRCS = pflowctl.c
+
+.include <bsd.prog.mk>
diff --git a/sbin/sconfig/Makefile.depend b/sbin/pflowctl/Makefile.depend
index c729e17c52db..6ef78fac5cbf 100644
--- a/sbin/sconfig/Makefile.depend
+++ b/sbin/pflowctl/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
@@ -6,6 +5,7 @@ DIRDEPS = \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
+ lib/libcompiler_rt \
.include <dirdeps.mk>
diff --git a/sbin/pflowctl/pflowctl.8 b/sbin/pflowctl/pflowctl.8
new file mode 100644
index 000000000000..407947613f6f
--- /dev/null
+++ b/sbin/pflowctl/pflowctl.8
@@ -0,0 +1,97 @@
+.\" $OpenBSD: pflow.4,v 1.19 2014/03/29 11:26:03 florian Exp $
+.\"
+.\" Copyright (c) 2008 Henning Brauer <henning@openbsd.org>
+.\" Copyright (c) 2008 Joerg Goltermann <jg@osn.de>
+.\"
+.\" Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+.\"
+.Dd $Mdocdate: January 25 2024 $
+.Dt PFLOWCTL 8
+.Os
+.Sh NAME
+.Nm pflowctl
+.Nd control pflow data export
+.Sh SYNOPSIS
+.Nm pflowctl
+.Bk -words
+.Op Fl v
+.Op Fl lc
+.Op Fl d Ar id
+.Op Fl s Ar id ...
+.Ek
+.Sh DESCRIPTION
+The
+.Nm
+utility creates, configures and deletes netflow accounting data export using the
+.Xr pflow 4
+subsystem.
+.Pp
+The
+.Nm
+utility provides several commands.
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl v
+Produce verbose output.
+.It Fl c
+Create a new
+.Xr pflow 4
+exporter.
+.It Fl d Ar id
+Remove an existing
+.Xr pflow 4
+exporter.
+The
+.Ar id
+may be either numeric or the full pflowX name.
+.It Fl l
+List all existing
+.Xr pflow 4
+exporters.
+.It Fl s Ar id ...
+Configure an existing
+.Xr pflow 4
+exporter.
+This takes the following keywords:
+.Pp
+.Bl -tag -width xxxxxxxxxxxx -compact
+.It Cm src
+set the source IP address (and optionally port).
+.It Cm dst
+set the destination IP address (and optionally port).
+.It Cm proto
+set the protocol version.
+Valid values are 5 and 10.
+.It Cm domain
+set the observation domain.
+.El
+.Pp
+Multiple keywords may be passed in the same command invocation.
+.Pp
+For example, the following command sets 10.0.0.1 as the source
+and 10.0.0.2:1234 as destination:
+.Bd -literal -offset indent
+# pflowctl -s pflow0 src 10.0.0.1 dst 10.0.0.2:1234
+.Ed
+.El
+.Sh SEE ALSO
+.Xr netintro 4 ,
+.Xr pf 4 ,
+.Xr pflow 4 ,
+.Xr udp 4 ,
+.Xr pf.conf 5
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Fx 15.0 .
diff --git a/sbin/pflowctl/pflowctl.c b/sbin/pflowctl/pflowctl.c
new file mode 100644
index 000000000000..b6561f7787c0
--- /dev/null
+++ b/sbin/pflowctl/pflowctl.c
@@ -0,0 +1,602 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Rubicon Communications, LLC (Netgate)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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>
+
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/pflow.h>
+
+#include <netlink/netlink.h>
+#include <netlink/netlink_generic.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_generic.h>
+#include <netlink/netlink_snl_route.h>
+
+static int get(int id);
+
+static bool verbose = false;
+
+extern char *__progname;
+
+static void
+usage(void)
+{
+ fprintf(stderr,
+"usage: %s [-lc] [-d id] [-s id ...] [-v]\n",
+ __progname);
+
+ exit(1);
+}
+
+static int
+pflow_to_id(const char *name)
+{
+ int ret, id;
+
+ ret = sscanf(name, "pflow%d", &id);
+ if (ret == 1)
+ return (id);
+
+ ret = sscanf(name, "%d", &id);
+ if (ret == 1)
+ return (id);
+
+ return (-1);
+}
+
+struct pflowctl_list {
+ int id;
+};
+#define _IN(_field) offsetof(struct genlmsghdr, _field)
+#define _OUT(_field) offsetof(struct pflowctl_list, _field)
+static struct snl_attr_parser ap_list[] = {
+ { .type = PFLOWNL_L_ID, .off = _OUT(id), .cb = snl_attr_get_int32 },
+};
+static struct snl_field_parser fp_list[] = {};
+#undef _IN
+#undef _OUT
+SNL_DECLARE_PARSER(list_parser, struct genlmsghdr, fp_list, ap_list);
+
+static int
+list(void)
+{
+ struct snl_state ss = {};
+ struct snl_errmsg_data e = {};
+ struct pflowctl_list l = {};
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ uint32_t seq_id;
+ int family_id;
+
+ snl_init(&ss, NETLINK_GENERIC);
+ family_id = snl_get_genl_family(&ss, PFLOWNL_FAMILY_NAME);
+ if (family_id == 0)
+ errx(1, "pflow.ko is not loaded.");
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, family_id, PFLOWNL_CMD_LIST);
+
+ hdr = snl_finalize_msg(&nw);
+ if (hdr == NULL)
+ return (ENOMEM);
+ seq_id = hdr->nlmsg_seq;
+
+ snl_send_message(&ss, hdr);
+
+ while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) {
+ if (! snl_parse_nlmsg(&ss, hdr, &list_parser, &l))
+ continue;
+
+ get(l.id);
+ }
+
+ if (e.error)
+ errc(1, e.error, "failed to list");
+
+ return (0);
+}
+
+struct pflowctl_create {
+ int id;
+};
+#define _IN(_field) offsetof(struct genlmsghsdr, _field)
+#define _OUT(_field) offsetof(struct pflowctl_create, _field)
+static struct snl_attr_parser ap_create[] = {
+ { .type = PFLOWNL_CREATE_ID, .off = _OUT(id), .cb = snl_attr_get_int32 },
+};
+static struct snl_field_parser pf_create[] = {};
+#undef _IN
+#undef _OUT
+SNL_DECLARE_PARSER(create_parser, struct genlmsghdr, pf_create, ap_create);
+
+static int
+create(void)
+{
+ struct snl_state ss = {};
+ struct snl_errmsg_data e = {};
+ struct pflowctl_create c = {};
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ uint32_t seq_id;
+ int family_id;
+
+ snl_init(&ss, NETLINK_GENERIC);
+ family_id = snl_get_genl_family(&ss, PFLOWNL_FAMILY_NAME);
+ if (family_id == 0)
+ errx(1, "pflow.ko is not loaded.");
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, family_id, PFLOWNL_CMD_CREATE);
+
+ hdr = snl_finalize_msg(&nw);
+ if (hdr == NULL)
+ return (ENOMEM);
+ seq_id = hdr->nlmsg_seq;
+
+ snl_send_message(&ss, hdr);
+
+ while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) {
+ if (! snl_parse_nlmsg(&ss, hdr, &create_parser, &c))
+ continue;
+
+ printf("pflow%d\n", c.id);
+ }
+
+ if (e.error)
+ errc(1, e.error, "failed to create");
+
+ return (0);
+}
+
+static int
+del(char *idstr)
+{
+ struct snl_state ss = {};
+ struct snl_errmsg_data e = {};
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ int family_id;
+ int id;
+
+ id = pflow_to_id(idstr);
+ if (id < 0)
+ return (EINVAL);
+
+ snl_init(&ss, NETLINK_GENERIC);
+ family_id = snl_get_genl_family(&ss, PFLOWNL_FAMILY_NAME);
+ if (family_id == 0)
+ errx(1, "pflow.ko is not loaded.");
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, family_id, PFLOWNL_CMD_DEL);
+
+ snl_add_msg_attr_s32(&nw, PFLOWNL_DEL_ID, id);
+
+ hdr = snl_finalize_msg(&nw);
+ if (hdr == NULL)
+ return (ENOMEM);
+
+ snl_send_message(&ss, hdr);
+ snl_read_reply_code(&ss, hdr->nlmsg_seq, &e);
+
+ if (e.error)
+ errc(1, e.error, "failed to delete");
+
+ return (0);
+}
+
+struct pflowctl_sockaddr {
+ union {
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage storage;
+ };
+};
+static bool
+pflowctl_post_sockaddr(struct snl_state* ss __unused, void *target)
+{
+ struct pflowctl_sockaddr *s = (struct pflowctl_sockaddr *)target;
+
+ if (s->storage.ss_family == AF_INET)
+ s->storage.ss_len = sizeof(struct sockaddr_in);
+ else if (s->storage.ss_family == AF_INET6)
+ s->storage.ss_len = sizeof(struct sockaddr_in6);
+ else
+ return (false);
+
+ return (true);
+}
+#define _OUT(_field) offsetof(struct pflowctl_sockaddr, _field)
+static struct snl_attr_parser nla_p_sockaddr[] = {
+ { .type = PFLOWNL_ADDR_FAMILY, .off = _OUT(in.sin_family), .cb = snl_attr_get_uint8 },
+ { .type = PFLOWNL_ADDR_PORT, .off = _OUT(in.sin_port), .cb = snl_attr_get_uint16 },
+ { .type = PFLOWNL_ADDR_IP, .off = _OUT(in.sin_addr), .cb = snl_attr_get_in_addr },
+ { .type = PFLOWNL_ADDR_IP6, .off = _OUT(in6.sin6_addr), .cb = snl_attr_get_in6_addr },
+};
+SNL_DECLARE_ATTR_PARSER_EXT(sockaddr_parser, 0, nla_p_sockaddr, pflowctl_post_sockaddr);
+#undef _OUT
+
+struct pflowctl_get {
+ int id;
+ int version;
+ struct pflowctl_sockaddr src;
+ struct pflowctl_sockaddr dst;
+ uint32_t obs_dom;
+ uint8_t so_status;
+};
+#define _IN(_field) offsetof(struct genlmsghdr, _field)
+#define _OUT(_field) offsetof(struct pflowctl_get, _field)
+static struct snl_attr_parser ap_get[] = {
+ { .type = PFLOWNL_GET_ID, .off = _OUT(id), .cb = snl_attr_get_int32 },
+ { .type = PFLOWNL_GET_VERSION, .off = _OUT(version), .cb = snl_attr_get_int16 },
+ { .type = PFLOWNL_GET_SRC, .off = _OUT(src), .arg = &sockaddr_parser, .cb = snl_attr_get_nested },
+ { .type = PFLOWNL_GET_DST, .off = _OUT(dst), .arg = &sockaddr_parser, .cb = snl_attr_get_nested },
+ { .type = PFLOWNL_GET_OBSERVATION_DOMAIN, .off = _OUT(obs_dom), .cb = snl_attr_get_uint32 },
+ { .type = PFLOWNL_GET_SOCKET_STATUS, .off = _OUT(so_status), .cb = snl_attr_get_uint8 },
+};
+static struct snl_field_parser fp_get[] = {};
+#undef _IN
+#undef _OUT
+SNL_DECLARE_PARSER(get_parser, struct genlmsghdr, fp_get, ap_get);
+
+static void
+print_sockaddr(const char *prefix, const struct sockaddr_storage *s)
+{
+ char buf[INET6_ADDRSTRLEN];
+ int error;
+
+ if (s->ss_family != AF_INET && s->ss_family != AF_INET6)
+ return;
+
+ if (s->ss_family == AF_INET ||
+ s->ss_family == AF_INET6) {
+ error = getnameinfo((const struct sockaddr *)s,
+ s->ss_len, buf, sizeof(buf), NULL, 0,
+ NI_NUMERICHOST);
+ if (error)
+ err(1, "sender: %s", gai_strerror(error));
+ }
+
+ printf("%s", prefix);
+ switch (s->ss_family) {
+ case AF_INET: {
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)s;
+ if (sin->sin_addr.s_addr != INADDR_ANY) {
+ printf("%s", buf);
+ if (sin->sin_port != 0)
+ printf(":%u", ntohs(sin->sin_port));
+ }
+ break;
+ }
+ case AF_INET6: {
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)s;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ printf("[%s]", buf);
+ if (sin6->sin6_port != 0)
+ printf(":%u", ntohs(sin6->sin6_port));
+ }
+ break;
+ }
+ }
+}
+
+static int
+get(int id)
+{
+ struct snl_state ss = {};
+ struct snl_errmsg_data e = {};
+ struct pflowctl_get g = {};
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ uint32_t seq_id;
+ int family_id;
+
+ snl_init(&ss, NETLINK_GENERIC);
+ family_id = snl_get_genl_family(&ss, PFLOWNL_FAMILY_NAME);
+ if (family_id == 0)
+ errx(1, "pflow.ko is not loaded.");
+
+ snl_init_writer(&ss, &nw);
+ hdr = snl_create_genl_msg_request(&nw, family_id, PFLOWNL_CMD_GET);
+ snl_add_msg_attr_s32(&nw, PFLOWNL_GET_ID, id);
+
+ hdr = snl_finalize_msg(&nw);
+ if (hdr == NULL)
+ return (ENOMEM);
+ seq_id = hdr->nlmsg_seq;
+
+ snl_send_message(&ss, hdr);
+
+ while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) {
+ if (! snl_parse_nlmsg(&ss, hdr, &get_parser, &g))
+ continue;
+
+ printf("pflow%d: version %d domain %u", g.id, g.version, g.obs_dom);
+ print_sockaddr(" src ", &g.src.storage);
+ print_sockaddr(" dst ", &g.dst.storage);
+ printf("\n");
+ if (verbose) {
+ printf("\tsocket: %s\n",
+ g.so_status ? "connected" : "disconnected");
+ }
+ }
+
+ if (e.error)
+ errc(1, e.error, "failed to get");
+
+ return (0);
+}
+
+struct pflowctl_set {
+ int id;
+ uint16_t version;
+ struct sockaddr_storage src;
+ struct sockaddr_storage dst;
+ uint32_t obs_dom;
+};
+static inline bool
+snl_add_msg_attr_sockaddr(struct snl_writer *nw, int attrtype, struct sockaddr_storage *s)
+{
+ int off = snl_add_msg_attr_nested(nw, attrtype);
+
+ snl_add_msg_attr_u8(nw, PFLOWNL_ADDR_FAMILY, s->ss_family);
+
+ switch (s->ss_family) {
+ case AF_INET: {
+ const struct sockaddr_in *in = (const struct sockaddr_in *)s;
+ snl_add_msg_attr_u16(nw, PFLOWNL_ADDR_PORT, in->sin_port);
+ snl_add_msg_attr_ip4(nw, PFLOWNL_ADDR_IP, &in->sin_addr);
+ break;
+ }
+ case AF_INET6: {
+ const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *)s;
+ snl_add_msg_attr_u16(nw, PFLOWNL_ADDR_PORT, in6->sin6_port);
+ snl_add_msg_attr_ip6(nw, PFLOWNL_ADDR_IP6, &in6->sin6_addr);
+ break;
+ }
+ default:
+ return (false);
+ }
+ snl_end_attr_nested(nw, off);
+
+ return (true);
+}
+
+static int
+do_set(struct pflowctl_set *s)
+{
+ struct snl_state ss = {};
+ struct snl_errmsg_data e = {};
+ struct snl_writer nw;
+ struct nlmsghdr *hdr;
+ int family_id;
+
+ snl_init(&ss, NETLINK_GENERIC);
+ family_id = snl_get_genl_family(&ss, PFLOWNL_FAMILY_NAME);
+ if (family_id == 0)
+ errx(1, "pflow.ko is not loaded.");
+
+ snl_init_writer(&ss, &nw);
+ snl_create_genl_msg_request(&nw, family_id, PFLOWNL_CMD_SET);
+
+ snl_add_msg_attr_s32(&nw, PFLOWNL_SET_ID, s->id);
+ if (s->version != 0)
+ snl_add_msg_attr_u16(&nw, PFLOWNL_SET_VERSION, s->version);
+ if (s->src.ss_len != 0)
+ snl_add_msg_attr_sockaddr(&nw, PFLOWNL_SET_SRC, &s->src);
+ if (s->dst.ss_len != 0)
+ snl_add_msg_attr_sockaddr(&nw, PFLOWNL_SET_DST, &s->dst);
+ if (s->obs_dom != 0)
+ snl_add_msg_attr_u32(&nw, PFLOWNL_SET_OBSERVATION_DOMAIN, s->obs_dom);
+
+ hdr = snl_finalize_msg(&nw);
+ if (hdr == NULL)
+ return (1);
+
+ snl_send_message(&ss, hdr);
+ snl_read_reply_code(&ss, hdr->nlmsg_seq, &e);
+
+ if (e.error)
+ errc(1, e.error, "failed to set");
+
+ return (0);
+}
+
+static void
+pflowctl_addr(const char *val, struct sockaddr_storage *ss)
+{
+ struct addrinfo *res0;
+ int error;
+ bool flag;
+ char *ip, *port;
+ char buf[sysconf(_SC_HOST_NAME_MAX) + 1 + sizeof(":65535")];
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_DGRAM, /*dummy*/
+ .ai_flags = AI_NUMERICHOST,
+ };
+
+ if (strlcpy(buf, val, sizeof(buf)) >= sizeof(buf))
+ errx(1, "%s bad value", val);
+
+ port = NULL;
+ flag = *buf == '[';
+
+ for (char *cp = buf; *cp; ++cp) {
+ if (*cp == ']' && *(cp + 1) == ':' && flag) {
+ *cp = '\0';
+ *(cp + 1) = '\0';
+ port = cp + 2;
+ break;
+ }
+ if (*cp == ']' && *(cp + 1) == '\0' && flag) {
+ *cp = '\0';
+ port = NULL;
+ break;
+ }
+ if (*cp == ':' && !flag) {
+ *cp = '\0';
+ port = cp + 1;
+ break;
+ }
+ }
+
+ ip = buf;
+ if (flag)
+ ip++;
+
+ if ((error = getaddrinfo(ip, port, &hints, &res0)) != 0)
+ errx(1, "error in parsing address string: %s",
+ gai_strerror(error));
+
+ memcpy(ss, res0->ai_addr, res0->ai_addr->sa_len);
+ freeaddrinfo(res0);
+}
+
+static int
+set(char *idstr, int argc, char *argv[])
+{
+ struct pflowctl_set s = {};
+
+ s.id = pflow_to_id(idstr);
+ if (s.id < 0)
+ return (EINVAL);
+
+ while (argc > 0) {
+ if (strcmp(argv[0], "src") == 0) {
+ if (argc < 2)
+ usage();
+
+ pflowctl_addr(argv[1], &s.src);
+
+ argc -= 2;
+ argv += 2;
+ } else if (strcmp(argv[0], "dst") == 0) {
+ if (argc < 2)
+ usage();
+
+ pflowctl_addr(argv[1], &s.dst);
+
+ argc -= 2;
+ argv += 2;
+ } else if (strcmp(argv[0], "proto") == 0) {
+ if (argc < 2)
+ usage();
+
+ s.version = strtol(argv[1], NULL, 10);
+
+ argc -= 2;
+ argv += 2;
+ } else if (strcmp(argv[0], "domain") == 0) {
+ if (argc < 2)
+ usage();
+
+ s.obs_dom = strtol(argv[1], NULL, 10);
+
+ argc -= 2;
+ argv += 2;
+ } else {
+ usage();
+ }
+ }
+
+ return (do_set(&s));
+}
+
+static const struct snl_hdr_parser *all_parsers[] = {
+ &list_parser,
+ &get_parser,
+};
+
+enum pflowctl_op_t {
+ OP_HELP,
+ OP_LIST,
+ OP_CREATE,
+ OP_DELETE,
+ OP_SET,
+};
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ enum pflowctl_op_t op = OP_HELP;
+ char **set_args = NULL;
+ size_t set_arg_count = 0;
+
+ SNL_VERIFY_PARSERS(all_parsers);
+
+ if (argc < 2)
+ usage();
+
+ while ((ch = getopt(argc, argv,
+ "lcd:s:v")) != -1) {
+ switch (ch) {
+ case 'l':
+ op = OP_LIST;
+ break;
+ case 'c':
+ op = OP_CREATE;
+ break;
+ case 'd':
+ op = OP_DELETE;
+ break;
+ case 's':
+ op = OP_SET;
+ set_arg_count = argc - optind;
+ set_args = argv + optind;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ }
+ }
+
+ switch (op) {
+ case OP_LIST:
+ return (list());
+ case OP_CREATE:
+ return (create());
+ case OP_DELETE:
+ return (del(optarg));
+ case OP_SET:
+ return (set(optarg, set_arg_count, set_args));
+ case OP_HELP:
+ usage();
+ break;
+ }
+
+ return (0);
+}
diff --git a/sbin/ping/Makefile b/sbin/ping/Makefile
index 23bac6d62d90..30c68cbaba52 100644
--- a/sbin/ping/Makefile
+++ b/sbin/ping/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=runtime
@@ -21,6 +18,7 @@ CFLAGS+= -DINET6 -DKAME_SCOPEID
SRCS+= ping6.c
LIBADD+= md
LINKS= ${BINDIR}/ping ${BINDIR}/ping6
+MLINKS= ping.8 ping6.8
.endif
.if ${MK_DYNAMICROOT} == "no"
diff --git a/sbin/ping/Makefile.depend b/sbin/ping/Makefile.depend
index c3985c1343dd..fb23b1474450 100644
--- a/sbin/ping/Makefile.depend
+++ b/sbin/ping/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
@@ -10,7 +9,7 @@ DIRDEPS = \
lib/libcapsicum \
lib/libcompiler_rt \
lib/libipsec \
- lib/libnv \
+ lib/libmd \
lib/msun \
diff --git a/sbin/ping/Makefile.depend.options b/sbin/ping/Makefile.depend.options
index a1c8f6278e92..5d5af2276e30 100644
--- a/sbin/ping/Makefile.depend.options
+++ b/sbin/ping/Makefile.depend.options
@@ -1,4 +1,3 @@
-# $FreeBSD$
# This file is not autogenerated - take care!
DIRDEPS_OPTIONS= CASPER
diff --git a/sbin/ping/main.c b/sbin/ping/main.c
index 11fa17b5ce2d..8a572cb3c914 100644
--- a/sbin/ping/main.c
+++ b/sbin/ping/main.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org>
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <sys/socket.h>
@@ -37,10 +34,13 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <err.h>
+#include <math.h>
+#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
#include <unistd.h>
#include "main.h"
@@ -61,115 +61,186 @@ __FBSDID("$FreeBSD$");
#error At least one of INET and INET6 is required
#endif
+/* various options */
+u_int options;
+
+char *hostname;
+
+/* counters */
+long nreceived; /* # of packets we got back */
+long nrepeats; /* number of duplicates */
+long ntransmitted; /* sequence # for outbound packets = #sent */
+long nrcvtimeout = 0; /* # of packets we got back after waittime */
+
+/* nonzero if we've been told to finish up */
+volatile sig_atomic_t seenint;
+volatile sig_atomic_t seeninfo;
+
+/* timing */
+int timing; /* flag to do timing */
+double tmin = 999999999.0; /* minimum round trip time */
+double tmax = 0.0; /* maximum round trip time */
+double tsum = 0.0; /* sum of all times, for doing average */
+double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
+
int
main(int argc, char *argv[])
{
-#if defined(INET) && defined(INET6)
+#if defined(INET)
struct in_addr a;
- struct in6_addr a6;
#endif
-#if defined(INET) || defined(INET6)
- struct addrinfo hints;
+#if defined(INET6)
+ struct in6_addr a6;
#endif
- int ch;
-#ifdef INET
- bool ipv4 = false;
+#if defined(INET) && defined(INET6)
+ struct addrinfo hints, *res, *ai;
+ const char *target;
+ int error;
#endif
-#ifdef INET6
- bool ipv6 = false;
+ int opt;
+#ifdef INET6
if (strcmp(getprogname(), "ping6") == 0)
- ipv6 = true;
+ return ping6(argc, argv);
#endif
- while ((ch = getopt(argc, argv, ":" OPTSTR)) != -1) {
- switch(ch) {
+ while ((opt = getopt(argc, argv, ":" OPTSTR)) != -1) {
+ switch (opt) {
#ifdef INET
case '4':
- ipv4 = true;
- break;
+ goto ping4;
#endif
#ifdef INET6
case '6':
- ipv6 = true;
- break;
+ goto ping6;
#endif
-#if defined(INET) && defined(INET6)
case 'S':
/*
* If -S is given with a numeric parameter,
* force use of the corresponding version.
*/
+#ifdef INET
if (inet_pton(AF_INET, optarg, &a) == 1)
- ipv4 = true;
- else if (inet_pton(AF_INET6, optarg, &a) == 1)
- ipv6 = true;
- break;
+ goto ping4;
+#endif
+#ifdef INET6
+ if (inet_pton(AF_INET6, optarg, &a6) == 1)
+ goto ping6;
#endif
+ break;
default:
break;
}
}
+ /*
+ * For IPv4, only one positional argument, the target, is allowed.
+ * For IPv6, multiple positional argument are allowed; the last
+ * one is the target, and preceding ones are intermediate hops.
+ * This nuance is lost here, but the only case where it matters is
+ * an error.
+ */
if (optind >= argc)
usage();
- optreset = 1;
- optind = 1;
#if defined(INET) && defined(INET6)
- if (ipv4 && ipv6)
- errx(1, "-4 and -6 cannot be used simultaneously");
-#endif
-
-#if defined(INET) && defined(INET6)
- if (inet_pton(AF_INET, argv[argc - 1], &a) == 1) {
- if (ipv6)
- errx(1, "IPv6 requested but IPv4 target address "
- "provided");
+ target = argv[argc - 1];
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_RAW;
+ if (feature_present("inet") && !feature_present("inet6"))
hints.ai_family = AF_INET;
- }
- else if (inet_pton(AF_INET6, argv[argc - 1], &a6) == 1) {
- if (ipv4)
- errx(1, "IPv4 requested but IPv6 target address "
- "provided");
+ else if (feature_present("inet6") && !feature_present("inet"))
hints.ai_family = AF_INET6;
- } else if (ipv6)
- hints.ai_family = AF_INET6;
- else if (ipv4)
- hints.ai_family = AF_INET;
- else {
- if (!feature_present("inet6"))
- hints.ai_family = AF_INET;
- else if (!feature_present("inet"))
- hints.ai_family = AF_INET6;
- else {
- struct addrinfo *res;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = SOCK_RAW;
- hints.ai_family = AF_UNSPEC;
- getaddrinfo(argv[argc - 1], NULL, &hints, &res);
- if (res != NULL) {
- hints.ai_family = res[0].ai_family;
- freeaddrinfo(res);
- }
+ else
+ hints.ai_family = AF_UNSPEC;
+ error = getaddrinfo(target, NULL, &hints, &res);
+ if (res == NULL)
+ errx(EX_NOHOST, "cannot resolve %s: %s",
+ target, gai_strerror(error));
+ for (ai = res; ai != NULL; ai = ai->ai_next) {
+ if (ai->ai_family == AF_INET) {
+ freeaddrinfo(res);
+ goto ping4;
+ }
+ if (ai->ai_family == AF_INET6) {
+ freeaddrinfo(res);
+ goto ping6;
}
}
-#elif defined(INET)
- hints.ai_family = AF_INET;
-#elif defined(INET6)
- hints.ai_family = AF_INET6;
+ freeaddrinfo(res);
+ errx(EX_NOHOST, "cannot resolve %s", target);
#endif
-
#ifdef INET
- if (hints.ai_family == AF_INET)
- return ping(argc, argv);
-#endif /* INET */
+ping4:
+ optreset = 1;
+ optind = 1;
+ return ping(argc, argv);
+#endif
#ifdef INET6
- if (hints.ai_family == AF_INET6)
- return ping6(argc, argv);
-#endif /* INET6 */
- errx(1, "Unknown host");
+ping6:
+ optreset = 1;
+ optind = 1;
+ return ping6(argc, argv);
+#endif
+}
+
+/*
+ * onsignal --
+ * Set the global bit that causes the main loop to quit.
+ */
+void
+onsignal(int sig)
+{
+ switch (sig) {
+ case SIGALRM:
+ case SIGINT:
+ /*
+ * When doing reverse DNS lookups, the seenint flag might not
+ * be noticed for a while. Just exit if we get a second SIGINT.
+ */
+ if (!(options & F_HOSTNAME) && seenint != 0)
+ _exit(nreceived ? 0 : 2);
+ seenint++;
+ break;
+ case SIGINFO:
+ seeninfo++;
+ break;
+ }
+}
+
+/*
+ * pr_summary --
+ * Print out summary statistics to the given output stream.
+ */
+void
+pr_summary(FILE * restrict stream)
+{
+ fprintf(stream, "\n--- %s ping statistics ---\n", hostname);
+ fprintf(stream, "%ld packets transmitted, ", ntransmitted);
+ fprintf(stream, "%ld packets received, ", nreceived);
+ if (nrepeats)
+ fprintf(stream, "+%ld duplicates, ", nrepeats);
+ if (ntransmitted) {
+ if (nreceived > ntransmitted)
+ fprintf(stream, "-- somebody's duplicating packets!");
+ else
+ fprintf(stream, "%.1f%% packet loss",
+ ((((double)ntransmitted - nreceived) * 100.0) /
+ ntransmitted));
+ }
+ if (nrcvtimeout)
+ fprintf(stream, ", %ld packets out of wait time", nrcvtimeout);
+ fputc('\n', stream);
+ if (nreceived && timing) {
+ /* Only display average to microseconds */
+ double num = nreceived + nrepeats;
+ double avg = tsum / num;
+ double stddev = sqrt(fmax(0, tsumsq / num - avg * avg));
+ fprintf(stream,
+ "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n",
+ tmin, avg, tmax, stddev);
+ }
+ fflush(stream);
}
void
@@ -180,48 +251,48 @@ usage(void)
#ifdef INET
"\tping [-4AaDdfHnoQqRrv] [-C pcp] [-c count] "
"[-G sweepmaxsize]\n"
- " [-g sweepminsize] [-h sweepincrsize] [-i wait] "
+ "\t [-g sweepminsize] [-h sweepincrsize] [-i wait] "
"[-l preload]\n"
- " [-M mask | time] [-m ttl] "
+ "\t [-M mask | time] [-m ttl] "
#ifdef IPSEC
"[-P policy] "
#endif
"[-p pattern] [-S src_addr] \n"
- " [-s packetsize] [-t timeout] [-W waittime] [-z tos] "
+ "\t [-s packetsize] [-t timeout] [-W waittime] [-z tos] "
"IPv4-host\n"
"\tping [-4AaDdfHLnoQqRrv] [-C pcp] [-c count] [-I iface] "
"[-i wait]\n"
- " [-l preload] [-M mask | time] [-m ttl] "
+ "\t [-l preload] [-M mask | time] [-m ttl] "
#ifdef IPSEC
"[-P policy] "
#endif
"[-p pattern]\n"
- " [-S src_addr] [-s packetsize] [-T ttl] [-t timeout] [-W waittime]\n"
- " [-z tos] IPv4-mcast-group\n"
+ "\t [-S src_addr] [-s packetsize] [-T ttl] [-t timeout] [-W waittime]\n"
+ "\t [-z tos] IPv4-mcast-group\n"
#endif /* INET */
#ifdef INET6
- "\tping [-6AaDd"
+ "\tping [-6AaDd"
#if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC)
- "E"
+ "E"
#endif
- "fHnNoOq"
+ "fHnNoOq"
#ifdef IPV6_USE_MIN_MTU
- "u"
+ "u"
#endif
- "vyY"
+ "vyY"
#if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC)
- "Z"
+ "Z"
#endif
"] "
- "[-b bufsiz] [-c count] [-e gateway]\n"
- " [-I interface] [-i wait] [-k addrtype] [-l preload] "
- "[-m hoplimit]\n"
- " [-p pattern]"
+ "[-b bufsiz] [-C pcp] [-c count] [-e gateway]\n"
+ "\t [-I interface] [-i wait] [-k addrtype] [-l preload] "
+ "[-m hoplimit]\n"
+ "\t [-p pattern]"
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
- " [-P policy]"
+ " [-P policy]"
#endif
- " [-S sourceaddr] [-s packetsize] [-t timeout]\n"
- " [-W waittime] [-z tclass] [IPv6-hops ...] IPv6-host\n"
+ " [-S sourceaddr] [-s packetsize] [-t timeout]\n"
+ "\t [-W waittime] [-z tclass] [IPv6-hops ...] IPv6-host\n"
#endif /* INET6 */
);
diff --git a/sbin/ping/main.h b/sbin/ping/main.h
index 51a368403bab..9a883b61a350 100644
--- a/sbin/ping/main.h
+++ b/sbin/ping/main.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 MAIN_H
@@ -51,6 +49,31 @@
#endif
#define PING6OPTS ".::6Aab:C:c:Dde:fHI:i:k:l:m:nNoOp:qS:s:t:uvyYW:z:" PING6ADDOPTS
+/* various options */
+extern u_int options;
+#define F_HOSTNAME 0x0004
+
+extern char *hostname;
+
+/* counters */
+extern long nreceived; /* # of packets we got back */
+extern long nrepeats; /* number of duplicates */
+extern long ntransmitted; /* sequence # for outbound packets = #sent */
+extern long nrcvtimeout; /* # of packets we got back after waittime */
+
+/* nonzero if we've been told to finish up */
+extern volatile sig_atomic_t seenint;
+extern volatile sig_atomic_t seeninfo;
+
+/* timing */
+extern int timing; /* flag to do timing */
+extern double tmin; /* minimum round trip time */
+extern double tmax; /* maximum round trip time */
+extern double tsum; /* sum of all times, for doing average */
+extern double tsumsq; /* sum of all times squared, for std. dev. */
+
+void onsignal(int);
+void pr_summary(FILE * __restrict);
void usage(void) __dead2;
#endif
diff --git a/sbin/ping/ping.8 b/sbin/ping/ping.8
index cd9c020382da..43dca1148e16 100644
--- a/sbin/ping/ping.8
+++ b/sbin/ping/ping.8
@@ -25,18 +25,15 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)ping.8 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD$
-.\"
-.Dd November 26, 2020
+.Dd September 15, 2023
.Dt PING 8
.Os
.Sh NAME
.Nm ping
.Nd send
-.Tn ICMP
+ICMP
or
-.Tn ICMPv6 ECHO_REQUEST
+ICMPv6 ECHO_REQUEST
packets to network hosts
.Sh SYNOPSIS
.Nm
@@ -82,6 +79,7 @@ packets to network hosts
.Op Fl 6AaDdEfHNnOoquvYyZ
.Op Fl .\& Ns Ar chars
.Op Fl b Ar bufsiz
+.Op Fl C Ar pcp
.Op Fl c Ar count
.Op Fl e Ar gateway
.Op Fl I Ar interface
@@ -101,19 +99,21 @@ packets to network hosts
The
.Nm
utility invoked with an IPv4 target
-.Ns ( Ar IPv4-host No or Ar IPv4-mcast-group Ns )
+.Ar ( IPv4-host
+or
+.Ar IPv4-mcast-group )
uses the
-.Tn ICMP
+ICMP
.No protocol Ap s mandatory
-.Tn ECHO_REQUEST
+ECHO_REQUEST
datagram to elicit an
-.Tn ICMP ECHO_RESPONSE
+ICMP ECHO_RESPONSE
from a host or gateway.
-.Tn ECHO_REQUEST
+ECHO_REQUEST
datagrams
.Pq Dq pings
have an IP and
-.Tn ICMP
+ICMP
header, followed by a
.Dq struct timeval
and then an arbitrary number of
@@ -121,24 +121,26 @@ and then an arbitrary number of
bytes used to fill out the packet.
.Pp
When invoked with an IPv6 target
-.Ns ( Ar IPv6-host Ns ) Ns ,
+.Ar ( IPv6-host ) ,
it uses the
-.Tn ICMPv6
+ICMPv6
protocol's mandatory
-.Tn ICMP6_ECHO_REQUEST
+ICMP6_ECHO_REQUEST
datagram to elicit an
-.Tn ICMP6_ECHO_REPLY
-.Ns .
-.Tn ICMP6_ECHO_REQUEST
+ICMP6_ECHO_REPLY.
+ICMP6_ECHO_REQUEST
datagrams have an IPv6 header and
-.Tn ICMPv6
+ICMPv6
header formatted as documented in RFC 2463.
.Pp
-When invoked with a hostname, the version to which the target is resolved first is used.
-In that case, the options and arguments used must be valid for the specific IP version, otherwise
+When invoked with a hostname, the version to which the target is resolved first
+is used.
+In that case, the options and arguments used must be valid for the specific IP
+version, otherwise
.Nm
exits with an error.
-If the target is resolved to both IPv4 and IPv6, the specific IP version can be requested by
+If the target is resolved to both IPv4 and IPv6, the specific IP version can be
+requested by
.Fl 4
or
.Fl 6
@@ -150,11 +152,11 @@ as
.Bl -tag -width indent
.It Fl .\& Ns Ar chars
By default, for every
-.Tn ECHO_REQUEST
+ECHO_REQUEST
sent, a period
.Dq .\&
is printed, while for every
-.Tn ECHO_REPLY
+ECHO_REPLY
received, a backspace is printed.
This option takes an optional string argument listing characters
that will be printed one by one in the provided order
@@ -167,7 +169,7 @@ ping -.0123456789 freebsd.org
.It Fl A
Audible.
Output a bell
-.Tn ( ASCII
+(ASCII
0x07)
character when no packet is received before the next packet
is transmitted.
@@ -177,7 +179,7 @@ if the maximum number of unreceived packets has increased.
.It Fl a
Audible.
Include a bell
-.Tn ( ASCII
+(ASCII
0x07)
character in the output when any packet is received.
.It Fl C Ar pcp
@@ -187,7 +189,7 @@ Add an 802.1p Ethernet Priority Code Point when sending a packet.
Stop after sending
(and receiving)
.Ar count
-.Tn ECHO_RESPONSE
+ECHO_RESPONSE
packets.
If this option is not specified,
.Nm
@@ -210,9 +212,9 @@ whichever is more.
Implies
.Fl .\&
to print a period for every
-.Tn ECHO_REQUEST
+ECHO_REQUEST
sent and a backspace for every
-.Tn ECHO_REPLY
+ECHO_REPLY
received.
This provides a rapid display of how many packets are being dropped.
Only the super-user may use this option.
@@ -228,14 +230,14 @@ option.
.It Fl I Ar iface
For an IPv4 target,
.Ar iface
-is an IP address indentifying an interface from which the packets will be sent.
+is an IP address identifying an interface from which the packets will be sent.
This flag applies only if the ping target is a multicast address.
.Pp
For an IPv6 target,
.Ar iface
-is a name of an interface (e.g. `em0') from which the packets will be sent.
-This flag applies if the ping target is a multicast address, or link-local/site-local
-unicast address.
+is a name of an interface (e.g., `em0') from which the packets will be sent.
+This flag applies if the ping target is a multicast address, or
+link-local/site-local unicast address.
.It Fl i Ar wait
Wait
.Ar wait
@@ -304,10 +306,10 @@ the sending node, and must be numeric.
.It Fl s Ar packetsize
Specify the number of data bytes to be sent.
The default is 56, which translates into 64
-.Tn ICMP
+ICMP
data bytes when combined
with the 8 bytes of
-.Tn ICMP
+ICMP
header data.
.Pp
For IPv4, only the super-user may specify values more than default.
@@ -321,9 +323,9 @@ Specify a timeout, in seconds, before ping exits regardless of how
many packets have been received.
.It Fl v
Verbose output.
-.Tn ICMP
+ICMP
packets other than
-.Tn ECHO_RESPONSE
+ECHO_RESPONSE
that are received are listed.
.It Fl W Ar waittime
Time in milliseconds to wait for a reply for each packet sent.
@@ -336,17 +338,17 @@ considered as replied when calculating statistics.
Use IPv4 regardless of how the target is resolved.
.It Fl G Ar sweepmaxsize
Specify the maximum size of
-.Tn ICMP
+ICMP
payload when sending sweeping pings.
This option is required for ping sweeps.
.It Fl g Ar sweepminsize
Specify the size of
-.Tn ICMP
+ICMP
payload to start with when sending sweeping pings.
The default value is 0.
.It Fl h Ar sweepincrsize
Specify the number of bytes to increment the size of
-.Tn ICMP
+ICMP
payload after
each sweep when sending sweeping pings.
The default value is 1.
@@ -396,9 +398,9 @@ messages.
.It Fl R
Record route.
Includes the
-.Tn RECORD_ROUTE
+RECORD_ROUTE
option in the
-.Tn ECHO_REQUEST
+ECHO_REQUEST
packet and displays
the route buffer on returned packets.
Note that the IP header is only large enough for nine such routes;
@@ -410,7 +412,7 @@ If more routes come back than should, such as due to an illegal spoofed
packet, ping will print the route list and then truncate it at the correct
spot.
Many hosts ignore or discard the
-.Tn RECORD_ROUTE
+RECORD_ROUTE
option.
.It Fl r
Bypass the normal routing tables and send directly to a host on an attached
@@ -575,21 +577,21 @@ during normal operations or from automated scripts.
.Sh ICMP PACKET DETAILS
An IP header without options is 20 bytes.
An
-.Tn ICMP
-.Tn ECHO_REQUEST
+ICMP
+ECHO_REQUEST
packet contains an additional 8 bytes worth of
-.Tn ICMP
+ICMP
header followed by an arbitrary amount of data.
When a
.Ar packetsize
is given, this indicated the size of this extra piece of data
(the default is 56).
Thus the amount of data received inside of an IP packet of type
-.Tn ICMP
-.Tn ECHO_REPLY
+ICMP
+ECHO_REPLY
will always be 8 bytes more than the requested data space
(the
-.Tn ICMP
+ICMP
header).
.Pp
If the data space is at least eight bytes large,
@@ -648,33 +650,29 @@ option of
.Nm .
.Sh IPv4 TTL DETAILS
The
-.Tn TTL
+TTL
value of an IP packet represents the maximum number of IP routers
that the packet can go through before being thrown away.
In current practice you can expect each router in the Internet to decrement
the
-.Tn TTL
+TTL
field by exactly one.
.Pp
The
-.Tn TCP/IP
+TCP/IP
specification recommends setting the
-.Tn TTL
+TTL
field for
-.Tn IP
-packets to 64, but many systems use smaller values
-.No ( Bx 4.3
-uses 30,
-.Bx 4.2
-used 15).
+IP
+packets to 64.
.Pp
-The maximum possible value of this field is 255, and most
+The maximum possible value of this field is 255, and some
.Ux
systems set
the
-.Tn TTL
+TTL
field of
-.Tn ICMP ECHO_REQUEST
+ICMP ECHO_REQUEST
packets to 255.
This is why you will find you can
.Dq ping
@@ -688,7 +686,7 @@ In normal operation
prints the ttl value from the packet it receives.
When a remote system receives a ping packet, it can do one of three things
with the
-.Tn TTL
+TTL
field in its response:
.Bl -bullet
.It
@@ -698,16 +696,16 @@ systems did before the
.Bx 4.3 tahoe
release.
In this case the
-.Tn TTL
+TTL
value in the received packet will be 255 minus the
number of routers in the round-trip path.
.It
-Set it to 255; this is what current
-.Bx
+Set it to 64; this is what current
+.Fx
systems do.
In this case the
-.Tn TTL
-value in the received packet will be 255 minus the
+TTL
+value in the received packet will be 64 minus the
number of routers in the path
.Em from
the remote system
@@ -718,9 +716,9 @@ host.
.It
Set it to some other value.
Some machines use the same value for
-.Tn ICMP
+ICMP
packets that they use for
-.Tn TCP
+TCP
packets, for example either 30 or 60.
Others may use completely wild values.
.El
@@ -739,9 +737,9 @@ An error occurred.
.El
.Sh EXAMPLES
The following will send ICMPv6 echo request to
-.Li dst.foo.com .
+.Li dst.example.com .
.Bd -literal -offset indent
-ping -6 -n dst.foo.com
+ping -6 -n dst.example.com
.Ed
.Pp
The following will probe hostnames for all nodes on the network link attached to
@@ -756,9 +754,9 @@ ping -6 -y ff02::1%wi0
.Ed
.Pp
The following will probe addresses assigned to the destination node,
-.Li dst.foo.com .
+.Li dst.example.com .
.Bd -literal -offset indent
-ping -6 -k agl dst.foo.com
+ping -6 -k agl dst.example.com
.Ed
.Sh SEE ALSO
.Xr netstat 1 ,
@@ -813,11 +811,11 @@ while at the US Army Ballistics
Research Laboratory.
.Sh BUGS
Many Hosts and Gateways ignore the IPv4
-.Tn RECORD_ROUTE
+RECORD_ROUTE
option.
.Pp
The maximum IP header length is too small for options like
-.Tn RECORD_ROUTE
+RECORD_ROUTE
to be completely useful.
.No There Ap s
not much that can be done about this, however.
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index cfef81f76099..d10e3c85c9bd 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* P I N G . C
*
@@ -89,7 +75,6 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
#include <errno.h>
-#include <math.h>
#include <netdb.h>
#include <stddef.h>
#include <signal.h>
@@ -129,10 +114,8 @@ struct tv32 {
};
/* various options */
-static int options;
#define F_FLOOD 0x0001
#define F_INTERVAL 0x0002
-#define F_NUMERIC 0x0004
#define F_PINGFILLED 0x0008
#define F_QUIET 0x0010
#define F_RROUTE 0x0020
@@ -180,7 +163,6 @@ static char BSPACE = '\b'; /* characters written for flood */
static const char *DOT = ".";
static size_t DOTlen = 1;
static size_t DOTidx = 0;
-static char *hostname;
static char *shostname;
static int ident; /* process id to identify our packets */
static int uid; /* cached uid for micro-optimization */
@@ -192,44 +174,24 @@ static int send_len;
/* counters */
static long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
static long npackets; /* max packets to transmit */
-static long nreceived; /* # of packets we got back */
-static long nrepeats; /* number of duplicates */
-static long ntransmitted; /* sequence # for outbound packets = #sent */
-static long snpackets; /* max packets to transmit in one sweep */
+static long snpackets; /* max packets to transmit in one sweep */
static long sntransmitted; /* # of packets we sent in this sweep */
static int sweepmax; /* max value of payload in sweep */
static int sweepmin = 0; /* start value of payload in sweep */
static int sweepincr = 1; /* payload increment in sweep */
static int interval = 1000; /* interval between packets, ms */
static int waittime = MAXWAIT; /* timeout for each packet */
-static long nrcvtimeout = 0; /* # of packets we got back after waittime */
-
-/* timing */
-static int timing; /* flag to do timing */
-static double tmin = 999999999.0; /* minimum round trip time */
-static double tmax = 0.0; /* maximum round trip time */
-static double tsum = 0.0; /* sum of all times, for doing average */
-static double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
-
-/* nonzero if we've been told to finish up */
-static volatile sig_atomic_t finish_up;
-static volatile sig_atomic_t siginfo_p;
static cap_channel_t *capdns;
static void fill(char *, char *);
static cap_channel_t *capdns_setup(void);
-static void check_status(void);
-static void finish(void) __dead2;
static void pinger(void);
static char *pr_addr(struct in_addr);
static char *pr_ntime(n_time);
static void pr_icmph(struct icmp *, struct ip *, const u_char *const);
-static void pr_iph(struct ip *);
+static void pr_iph(struct ip *, const u_char *);
static void pr_pack(char *, ssize_t, struct sockaddr_in *, struct timespec *);
-static void pr_retip(struct ip *, const u_char *);
-static void status(int);
-static void stopit(int);
int
ping(int argc, char *const *argv)
@@ -267,8 +229,6 @@ ping(int argc, char *const *argv)
#endif
cap_rights_t rights;
- options |= F_NUMERIC;
-
/*
* Do the stuff that we need root priv's for *first*, and
* then drop our setuid bit. Save error reporting for
@@ -353,47 +313,47 @@ ping(int argc, char *const *argv)
options |= F_DOT;
setbuf(stdout, (char *)NULL);
break;
- case 'G': /* Maximum packet size for ping sweep */
+ case 'G': /* Maximum payload size for ping sweep */
ltmp = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
- errx(EX_USAGE, "invalid packet size: `%s'",
+ errx(EX_USAGE, "invalid payload size: `%s'",
optarg);
}
sweepmax = (int)ltmp;
if (uid != 0 && sweepmax > DEFDATALEN) {
errc(EX_NOPERM, EPERM,
- "packet size too large: %d > %u",
+ "payload size too large: %d > %u",
sweepmax, DEFDATALEN);
}
options |= F_SWEEP;
break;
- case 'g': /* Minimum packet size for ping sweep */
- ltmp = strtonum(optarg, 1, INT_MAX, &errstr);
+ case 'g': /* Minimum payload size for ping sweep */
+ ltmp = strtonum(optarg, 0, INT_MAX, &errstr);
if (errstr != NULL) {
- errx(EX_USAGE, "invalid packet size: `%s'",
+ errx(EX_USAGE, "invalid payload size: `%s'",
optarg);
}
sweepmin = (int)ltmp;
if (uid != 0 && sweepmin > DEFDATALEN) {
errc(EX_NOPERM, EPERM,
- "packet size too large: %d > %u",
+ "payload size too large: %d > %u",
sweepmin, DEFDATALEN);
}
options |= F_SWEEP;
break;
case 'H':
- options &= ~F_NUMERIC;
+ options |= F_HOSTNAME;
break;
- case 'h': /* Packet size increment for ping sweep */
+ case 'h': /* Payload size increment for ping sweep */
ltmp = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr != NULL) {
- errx(EX_USAGE, "invalid packet size: `%s'",
+ errx(EX_USAGE, "invalid payload size: `%s'",
optarg);
}
sweepincr = (int)ltmp;
if (uid != 0 && sweepincr > DEFDATALEN) {
errc(EX_NOPERM, EPERM,
- "packet size too large: %d > %u",
+ "payload size too large: %d > %u",
sweepincr, DEFDATALEN);
}
options |= F_SWEEP;
@@ -455,7 +415,7 @@ ping(int argc, char *const *argv)
options |= F_TTL;
break;
case 'n':
- options |= F_NUMERIC;
+ options &= ~F_HOSTNAME;
break;
case 'o':
options |= F_ONCE;
@@ -885,22 +845,17 @@ ping(int argc, char *const *argv)
sigemptyset(&si_sa.sa_mask);
si_sa.sa_flags = 0;
-
- si_sa.sa_handler = stopit;
- if (sigaction(SIGINT, &si_sa, 0) == -1) {
+ si_sa.sa_handler = onsignal;
+ if (sigaction(SIGINT, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGINT");
- }
-
- si_sa.sa_handler = status;
- if (sigaction(SIGINFO, &si_sa, 0) == -1) {
- err(EX_OSERR, "sigaction");
- }
-
- if (alarmtimeout > 0) {
- si_sa.sa_handler = stopit;
+ seenint = 0;
+ if (sigaction(SIGINFO, &si_sa, 0) == -1)
+ err(EX_OSERR, "sigaction SIGINFO");
+ seeninfo = 0;
+ if (alarmtimeout > 0) {
if (sigaction(SIGALRM, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGALRM");
- }
+ }
bzero(&msg, sizeof(msg));
msg.msg_name = (caddr_t)&from;
@@ -932,13 +887,18 @@ ping(int argc, char *const *argv)
}
almost_done = 0;
- while (!finish_up) {
+ while (seenint == 0) {
struct timespec now, timeout;
fd_set rfds;
int n;
ssize_t cc;
- check_status();
+ /* signal handling */
+ if (seeninfo) {
+ pr_summary(stderr);
+ seeninfo = 0;
+ continue;
+ }
if ((unsigned)srecv >= FD_SETSIZE)
errx(EX_OSERR, "descriptor too large");
FD_ZERO(&rfds);
@@ -948,9 +908,10 @@ ping(int argc, char *const *argv)
timespecsub(&timeout, &now, &timeout);
if (timeout.tv_sec < 0)
timespecclear(&timeout);
+
n = pselect(srecv + 1, &rfds, NULL, NULL, &timeout, NULL);
if (n < 0)
- continue; /* Must be EINTR. */
+ continue; /* EINTR */
if (n == 1) {
struct timespec *tv = NULL;
#ifdef SO_TIMESTAMP
@@ -963,6 +924,9 @@ ping(int argc, char *const *argv)
warn("recvmsg");
continue;
}
+ /* If we have a 0 byte read from recvfrom continue */
+ if (cc == 0)
+ continue;
#ifdef SO_TIMESTAMP
if (cmsg != NULL &&
cmsg->cmsg_level == SOL_SOCKET &&
@@ -982,7 +946,7 @@ ping(int argc, char *const *argv)
(npackets && nreceived >= npackets))
break;
}
- if (n == 0 || options & F_FLOOD) {
+ if (n == 0 || (options & F_FLOOD)) {
if (sweepmax && sntransmitted == snpackets) {
if (datalen + sweepincr > sweepmax)
break;
@@ -998,14 +962,21 @@ ping(int argc, char *const *argv)
if (almost_done)
break;
almost_done = 1;
+ /*
+ * If we're not transmitting any more packets,
+ * change the timer to wait two round-trip times
+ * if we've received any packets or (waittime)
+ * milliseconds if we haven't.
+ */
intvl.tv_nsec = 0;
if (nreceived) {
intvl.tv_sec = 2 * tmax / 1000;
- if (!intvl.tv_sec)
+ if (intvl.tv_sec == 0)
intvl.tv_sec = 1;
} else {
intvl.tv_sec = waittime / 1000;
- intvl.tv_nsec = waittime % 1000 * 1000000;
+ intvl.tv_nsec =
+ waittime % 1000 * 1000000;
}
}
(void)clock_gettime(CLOCK_MONOTONIC, &last);
@@ -1016,28 +987,9 @@ ping(int argc, char *const *argv)
}
}
}
- finish();
- /* NOTREACHED */
- exit(0); /* Make the compiler happy */
-}
+ pr_summary(stdout);
-/*
- * stopit --
- * Set the global bit that causes the main loop to quit.
- * Do NOT call finish() from here, since finish() does far too much
- * to be called from a signal handler.
- */
-void
-stopit(int sig __unused)
-{
-
- /*
- * When doing reverse DNS lookups, the finish_up flag might not
- * be noticed for a while. Just exit if we get a second SIGINT.
- */
- if (!(options & F_NUMERIC) && finish_up)
- _exit(nreceived ? 0 : 2);
- finish_up = 1;
+ exit(nreceived ? 0 : 2);
}
/*
@@ -1144,8 +1096,10 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
struct icmp icp;
struct ip ip;
const u_char *icmp_data_raw;
+ ssize_t icmp_data_raw_len;
double triptime;
- int dupflag, hlen, i, j, recv_len;
+ int dupflag, i, j, recv_len;
+ int8_t hlen;
uint16_t seq;
static int old_rrlen;
static char old_rr[MAX_IPOPTLEN];
@@ -1155,15 +1109,27 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
const u_char *oicmp_raw;
/*
- * Get size of IP header of the received packet. The
- * information is contained in the lower four bits of the
- * first byte.
+ * Get size of IP header of the received packet.
+ * The header length is contained in the lower four bits of the first
+ * byte and represents the number of 4 byte octets the header takes up.
+ *
+ * The IHL minimum value is 5 (20 bytes) and its maximum value is 15
+ * (60 bytes).
*/
memcpy(&l, buf, sizeof(l));
hlen = (l & 0x0f) << 2;
- memcpy(&ip, buf, hlen);
- /* Check the IP header */
+ /* Reject IP packets with a short header */
+ if (hlen < (int8_t) sizeof(struct ip)) {
+ if (options & F_VERBOSE)
+ warn("IHL too short (%d bytes) from %s", hlen,
+ inet_ntoa(from->sin_addr));
+ return;
+ }
+
+ memcpy(&ip, buf, sizeof(struct ip));
+
+ /* Check packet has enough data to carry a valid ICMP header */
recv_len = cc;
if (cc < hlen + ICMP_MINLEN) {
if (options & F_VERBOSE)
@@ -1172,11 +1138,8 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
return;
}
-#ifndef icmp_data
- icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_ip);
-#else
+ icmp_data_raw_len = cc - (hlen + offsetof(struct icmp, icmp_data));
icmp_data_raw = buf + hlen + offsetof(struct icmp, icmp_data);
-#endif
/* Now the ICMP part */
cc -= hlen;
@@ -1200,8 +1163,14 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
tv1.tv_sec = ntohl(tv32.tv32_sec);
tv1.tv_nsec = ntohl(tv32.tv32_nsec);
timespecsub(tv, &tv1, tv);
- triptime = ((double)tv->tv_sec) * 1000.0 +
+ triptime = ((double)tv->tv_sec) * 1000.0 +
((double)tv->tv_nsec) / 1000000.0;
+ if (triptime < 0) {
+ warnx("time of day goes back (%.3f ms),"
+ " clamping time to 0",
+ triptime);
+ triptime = 0;
+ }
tsum += triptime;
tsumsq += triptime * triptime;
if (triptime < tmin)
@@ -1280,14 +1249,14 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
for (i = 0; i < datalen; ++i, ++cp) {
if ((i % 16) == 8)
(void)printf("\n\t");
- (void)printf("%2x ", *cp);
+ (void)printf(" %2x", *cp);
}
(void)printf("\ndp:");
cp = &outpack[ICMP_MINLEN];
for (i = 0; i < datalen; ++i, ++cp) {
if ((i % 16) == 8)
(void)printf("\n\t");
- (void)printf("%2x ", *cp);
+ (void)printf(" %2x", *cp);
}
break;
}
@@ -1304,12 +1273,45 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
* as root to avoid leaking information not normally
* available to those not running as root.
*/
+
+ /*
+ * If we don't have enough bytes for a quoted IP header and an
+ * ICMP header then stop.
+ */
+ if (icmp_data_raw_len <
+ (ssize_t)(sizeof(struct ip) + sizeof(struct icmp))) {
+ if (options & F_VERBOSE)
+ warnx("quoted data too short (%zd bytes) from %s",
+ icmp_data_raw_len, inet_ntoa(from->sin_addr));
+ return;
+ }
+
memcpy(&oip_header_len, icmp_data_raw, sizeof(oip_header_len));
oip_header_len = (oip_header_len & 0x0f) << 2;
- memcpy(&oip, icmp_data_raw, oip_header_len);
+
+ /* Reject IP packets with a short header */
+ if (oip_header_len < sizeof(struct ip)) {
+ if (options & F_VERBOSE)
+ warnx("inner IHL too short (%d bytes) from %s",
+ oip_header_len, inet_ntoa(from->sin_addr));
+ return;
+ }
+
+ /*
+ * Check against the actual IHL length, to protect against
+ * quoated packets carrying IP options.
+ */
+ if (icmp_data_raw_len <
+ (ssize_t)(oip_header_len + sizeof(struct icmp))) {
+ if (options & F_VERBOSE)
+ warnx("inner packet too short (%zd bytes) from %s",
+ icmp_data_raw_len, inet_ntoa(from->sin_addr));
+ return;
+ }
+
+ memcpy(&oip, icmp_data_raw, sizeof(struct ip));
oicmp_raw = icmp_data_raw + oip_header_len;
- memcpy(&oicmp, oicmp_raw, offsetof(struct icmp, icmp_id) +
- sizeof(oicmp.icmp_id));
+ memcpy(&oicmp, oicmp_raw, sizeof(struct icmp));
if (((options & F_VERBOSE) && uid == 0) ||
(!(options & F_QUIET2) &&
@@ -1319,7 +1321,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
(oicmp.icmp_id == ident))) {
(void)printf("%zd bytes from %s: ", cc,
pr_addr(from->sin_addr));
- pr_icmph(&icp, &oip, oicmp_raw);
+ pr_icmph(&icp, &oip, icmp_data_raw);
} else
return;
}
@@ -1356,7 +1358,7 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
(void)putchar('\n');
}
} else
- (void)printf("\t(truncated route)\n");
+ (void)printf("\t(truncated route)");
break;
case IPOPT_RR:
j = cp[IPOPT_OLEN]; /* get length */
@@ -1414,93 +1416,6 @@ pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
}
/*
- * status --
- * Print out statistics when SIGINFO is received.
- */
-
-static void
-status(int sig __unused)
-{
-
- siginfo_p = 1;
-}
-
-static void
-check_status(void)
-{
-
- if (siginfo_p) {
- siginfo_p = 0;
- (void)fprintf(stderr, "\r%ld/%ld packets received (%.1f%%)",
- nreceived, ntransmitted,
- ntransmitted ? nreceived * 100.0 / ntransmitted : 0.0);
- if (nreceived && timing)
- (void)fprintf(stderr, " %.3f min / %.3f avg / %.3f max",
- tmin, tsum / (nreceived + nrepeats), tmax);
- (void)fprintf(stderr, "\n");
- }
-}
-
-/*
- * finish --
- * Print out statistics, and give up.
- */
-static void
-finish(void)
-{
-
- (void)signal(SIGINT, SIG_IGN);
- (void)signal(SIGALRM, SIG_IGN);
- (void)putchar('\n');
- (void)fflush(stdout);
- (void)printf("--- %s ping statistics ---\n", hostname);
- (void)printf("%ld packets transmitted, ", ntransmitted);
- (void)printf("%ld packets received, ", nreceived);
- if (nrepeats)
- (void)printf("+%ld duplicates, ", nrepeats);
- if (ntransmitted) {
- if (nreceived > ntransmitted)
- (void)printf("-- somebody's printing up packets!");
- else
- (void)printf("%.1f%% packet loss",
- ((ntransmitted - nreceived) * 100.0) /
- ntransmitted);
- }
- if (nrcvtimeout)
- (void)printf(", %ld packets out of wait time", nrcvtimeout);
- (void)putchar('\n');
- if (nreceived && timing) {
- double n = nreceived + nrepeats;
- double avg = tsum / n;
- double vari = tsumsq / n - avg * avg;
- (void)printf(
- "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n",
- tmin, avg, tmax, sqrt(vari));
- }
-
- if (nreceived)
- exit(0);
- else
- exit(2);
-}
-
-#ifdef notdef
-static char *ttab[] = {
- "Echo Reply", /* ip + seq + udata */
- "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */
- "Source Quench", /* IP */
- "Redirect", /* redirect type, gateway, + IP */
- "Echo",
- "Time Exceeded", /* transit, frag reassem + IP */
- "Parameter Problem", /* pointer + IP */
- "Timestamp", /* id + seq + three timestamps */
- "Timestamp Reply", /* " */
- "Info Request", /* id + sq */
- "Info Reply" /* " */
-};
-#endif
-
-/*
* pr_icmph --
* Print a descriptive string about an ICMP header.
*/
@@ -1543,11 +1458,11 @@ pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw)
break;
}
/* Print returned IP header information */
- pr_retip(oip, oicmp_raw);
+ pr_iph(oip, oicmp_raw);
break;
case ICMP_SOURCEQUENCH:
(void)printf("Source Quench\n");
- pr_retip(oip, oicmp_raw);
+ pr_iph(oip, oicmp_raw);
break;
case ICMP_REDIRECT:
switch(icp->icmp_code) {
@@ -1568,7 +1483,7 @@ pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw)
break;
}
(void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr));
- pr_retip(oip, oicmp_raw);
+ pr_iph(oip, oicmp_raw);
break;
case ICMP_ECHO:
(void)printf("Echo Request\n");
@@ -1587,12 +1502,12 @@ pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw)
icp->icmp_code);
break;
}
- pr_retip(oip, oicmp_raw);
+ pr_iph(oip, oicmp_raw);
break;
case ICMP_PARAMPROB:
(void)printf("Parameter problem: pointer = 0x%02x\n",
icp->icmp_hun.ih_pptr);
- pr_retip(oip, oicmp_raw);
+ pr_iph(oip, oicmp_raw);
break;
case ICMP_TSTAMP:
(void)printf("Timestamp\n");
@@ -1632,31 +1547,39 @@ pr_icmph(struct icmp *icp, struct ip *oip, const u_char *const oicmp_raw)
* Print an IP header with options.
*/
static void
-pr_iph(struct ip *ip)
+pr_iph(struct ip *ip, const u_char *cp)
{
- struct in_addr ina;
- u_char *cp;
+ struct in_addr dst_ina, src_ina;
int hlen;
hlen = ip->ip_hl << 2;
- cp = (u_char *)ip + 20; /* point to options */
+ cp = cp + sizeof(struct ip); /* point to options */
- (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n");
+ memcpy(&src_ina, &ip->ip_src.s_addr, sizeof(src_ina));
+ memcpy(&dst_ina, &ip->ip_dst.s_addr, sizeof(dst_ina));
+
+ (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks %*s %*s",
+ (int)strlen(inet_ntoa(src_ina)), "Src",
+ (int)strlen(inet_ntoa(dst_ina)), "Dst");
+ if (hlen > (int)sizeof(struct ip))
+ (void)printf(" Opts");
+ (void)putchar('\n');
(void)printf(" %1x %1x %02x %04x %04x",
ip->ip_v, ip->ip_hl, ip->ip_tos, ntohs(ip->ip_len),
ntohs(ip->ip_id));
- (void)printf(" %1lx %04lx",
- (u_long) (ntohl(ip->ip_off) & 0xe000) >> 13,
- (u_long) ntohl(ip->ip_off) & 0x1fff);
+ (void)printf(" %1x %04x",
+ (ntohs(ip->ip_off) & 0xe000) >> 13,
+ ntohs(ip->ip_off) & 0x1fff);
(void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p,
ntohs(ip->ip_sum));
- memcpy(&ina, &ip->ip_src.s_addr, sizeof ina);
- (void)printf(" %s ", inet_ntoa(ina));
- memcpy(&ina, &ip->ip_dst.s_addr, sizeof ina);
- (void)printf(" %s ", inet_ntoa(ina));
+ (void)printf(" %s", inet_ntoa(src_ina));
+ (void)printf(" %s", inet_ntoa(dst_ina));
/* dump any option bytes */
- while (hlen-- > 20) {
- (void)printf("%02x", *cp++);
+ if (hlen > (int)sizeof(struct ip)) {
+ (void)printf(" ");
+ while (hlen-- > (int)sizeof(struct ip)) {
+ (void)printf("%02x", *cp++);
+ }
}
(void)putchar('\n');
}
@@ -1672,10 +1595,10 @@ pr_addr(struct in_addr ina)
struct hostent *hp;
static char buf[16 + 3 + MAXHOSTNAMELEN];
- if (options & F_NUMERIC)
+ if (!(options & F_HOSTNAME))
return inet_ntoa(ina);
- hp = cap_gethostbyaddr(capdns, (char *)&ina, 4, AF_INET);
+ hp = cap_gethostbyaddr(capdns, (char *)&ina, sizeof(ina), AF_INET);
if (hp == NULL)
return inet_ntoa(ina);
@@ -1685,23 +1608,6 @@ pr_addr(struct in_addr ina)
return(buf);
}
-/*
- * pr_retip --
- * Dump some info on a returned (via ICMP) IP packet.
- */
-static void
-pr_retip(struct ip *ip, const u_char *cp)
-{
- pr_iph(ip);
-
- if (ip->ip_p == 6)
- (void)printf("TCP: from port %u, to port %u (decimal)\n",
- (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
- else if (ip->ip_p == 17)
- (void)printf("UDP: from port %u, to port %u (decimal)\n",
- (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
-}
-
static char *
pr_ntime(n_time timestamp)
{
diff --git a/sbin/ping/ping.h b/sbin/ping/ping.h
index 36ce3c0b973d..34a15a2da5aa 100644
--- a/sbin/ping/ping.h
+++ b/sbin/ping/ping.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 PING_H
diff --git a/sbin/ping/ping6.c b/sbin/ping/ping6.c
index e780129c928d..356f0f72a6f8 100644
--- a/sbin/ping/ping6.c
+++ b/sbin/ping/ping6.c
@@ -65,21 +65,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
* measure round-trip-delays and packet loss across network paths.
@@ -126,7 +111,6 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <fcntl.h>
-#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -190,7 +174,6 @@ struct tv32 {
#define F_FQDN 0x1000
#define F_INTERFACE 0x2000
#define F_SRCADDR 0x4000
-#define F_HOSTNAME 0x10000
#define F_FQDNOLD 0x20000
#define F_NIGROUP 0x40000
#define F_SUPTYPES 0x80000
@@ -202,7 +185,6 @@ struct tv32 {
#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
#define F_WAITTIME 0x2000000
#define F_DOT 0x4000000
-static u_int options;
#define IN6LEN sizeof(struct in6_addr)
#define SA6LEN sizeof(struct sockaddr_in6)
@@ -231,7 +213,6 @@ static char BBELL = '\a'; /* characters written for AUDIBLE */
static const char *DOT = ".";
static size_t DOTlen = 1;
static size_t DOTidx = 0;
-static char *hostname;
static int ident; /* process id to identify our packets */
static u_int8_t nonce[8]; /* nonce field for node information */
static int hoplimit = -1; /* hoplimit */
@@ -243,20 +224,9 @@ static cap_channel_t *capdns;
/* counters */
static long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
static long npackets; /* max packets to transmit */
-static long nreceived; /* # of packets we got back */
-static long nrepeats; /* number of duplicates */
-static long ntransmitted; /* sequence # for outbound packets = #sent */
static long ntransmitfailures; /* number of transmit failures */
static int interval = 1000; /* interval between packets in ms */
static int waittime = MAXWAIT; /* timeout for each packet */
-static long nrcvtimeout = 0; /* # of packets we got back after waittime */
-
-/* timing */
-static int timing; /* flag to do timing */
-static double tmin = 999999999.0; /* minimum round trip time */
-static double tmax = 0.0; /* maximum round trip time */
-static double tsum = 0.0; /* sum of all times, for doing average */
-static double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
/* for node addresses */
static u_short naflags;
@@ -266,18 +236,11 @@ static struct msghdr smsghdr;
static struct iovec smsgiov;
static char *scmsg = 0;
-static volatile sig_atomic_t seenint;
-#ifdef SIGINFO
-static volatile sig_atomic_t seeninfo;
-#endif
-
static cap_channel_t *capdns_setup(void);
static void fill(char *, char *);
static int get_hoplim(struct msghdr *);
static int get_pathmtu(struct msghdr *);
static struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
-static void onsignal(int);
-static void onint(int);
static size_t pingerlen(void);
static int pinger(void);
static const char *pr_addr(struct sockaddr *, int);
@@ -295,7 +258,6 @@ static void pr_ip6opt(void *, size_t);
static void pr_rthdr(void *, size_t);
static int pr_bitrange(u_int32_t, int, int);
static void pr_retip(struct ip6_hdr *, u_char *);
-static void summary(void);
#ifdef IPSEC
#ifdef IPSEC_POLICY_IPSEC
static int setpolicy(int, char *);
@@ -580,7 +542,7 @@ ping6(int argc, char *argv[])
case 'W':
t = strtod(optarg, &e);
if (*e || e == optarg || t > (double)INT_MAX)
- err(EX_USAGE, "invalid timing interval: `%s'",
+ errx(EX_USAGE, "invalid timing interval: `%s'",
optarg);
options |= F_WAITTIME;
waittime = (int)t;
@@ -679,14 +641,15 @@ ping6(int argc, char *argv[])
error = cap_getaddrinfo(capdns, target, NULL, &hints, &res);
if (error)
- errx(1, "%s", gai_strerror(error));
+ errx(EX_NOHOST, "cannot resolve %s: %s",
+ target, gai_strerror(error));
if (res->ai_canonname)
hostname = strdup(res->ai_canonname);
else
hostname = target;
if (!res->ai_addr)
- errx(1, "cap_getaddrinfo failed");
+ errx(EX_NOHOST, "cannot resolve %s", target);
(void)memcpy(&dst, res->ai_addr, res->ai_addrlen);
@@ -737,7 +700,7 @@ ping6(int argc, char *argv[])
}
/*
- * let the kerel pass extension headers of incoming packets,
+ * let the kernel pass extension headers of incoming packets,
* for privileged socket options
*/
if ((options & F_VERBOSE) != 0) {
@@ -897,7 +860,7 @@ ping6(int argc, char *argv[])
}
#endif /*ICMP6_FILTER*/
- /* let the kerel pass extension headers of incoming packets */
+ /* let the kernel pass extension headers of incoming packets */
if ((options & F_VERBOSE) != 0) {
int opton = 1;
@@ -1144,7 +1107,7 @@ ping6(int argc, char *argv[])
if (caph_rights_limit(ssend, &rights_ssend) < 0)
err(1, "caph_rights_limit ssend setsockopt");
- printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
+ printf("PING(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
(unsigned long)(pingerlen() - 8));
printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
@@ -1165,11 +1128,9 @@ ping6(int argc, char *argv[])
if (sigaction(SIGINT, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGINT");
seenint = 0;
-#ifdef SIGINFO
if (sigaction(SIGINFO, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGINFO");
seeninfo = 0;
-#endif
if (alarmtimeout > 0) {
if (sigaction(SIGALRM, &si_sa, 0) == -1)
err(EX_OSERR, "sigaction SIGALRM");
@@ -1188,15 +1149,11 @@ ping6(int argc, char *argv[])
int n;
/* signal handling */
- if (seenint)
- onint(SIGINT);
-#ifdef SIGINFO
if (seeninfo) {
- summary();
+ pr_summary(stderr);
seeninfo = 0;
continue;
}
-#endif
FD_ZERO(&rfds);
FD_SET(srecv, &rfds);
clock_gettime(CLOCK_MONOTONIC, &now);
@@ -1260,12 +1217,12 @@ ping6(int argc, char *argv[])
if (almost_done)
break;
almost_done = 1;
- /*
- * If we're not transmitting any more packets,
- * change the timer to wait two round-trip times
- * if we've received any packets or (waittime)
- * milliseconds if we haven't.
- */
+ /*
+ * If we're not transmitting any more packets,
+ * change the timer to wait two round-trip times
+ * if we've received any packets or (waittime)
+ * milliseconds if we haven't.
+ */
intvl.tv_nsec = 0;
if (nreceived) {
intvl.tv_sec = 2 * tmax / 1000;
@@ -1274,7 +1231,7 @@ ping6(int argc, char *argv[])
} else {
intvl.tv_sec = waittime / 1000;
intvl.tv_nsec =
- waittime % 1000 * 1000000;
+ waittime % 1000 * 1000000;
}
}
clock_gettime(CLOCK_MONOTONIC, &last);
@@ -1290,7 +1247,7 @@ ping6(int argc, char *argv[])
si_sa.sa_handler = SIG_IGN;
sigaction(SIGINT, &si_sa, 0);
sigaction(SIGALRM, &si_sa, 0);
- summary();
+ pr_summary(stdout);
if(packet != NULL)
free(packet);
@@ -1303,23 +1260,6 @@ ping6(int argc, char *argv[])
exit(EX_OSERR);
}
-static void
-onsignal(int sig)
-{
-
- switch (sig) {
- case SIGINT:
- case SIGALRM:
- seenint++;
- break;
-#ifdef SIGINFO
- case SIGINFO:
- seeninfo++;
- break;
-#endif
- }
-}
-
/*
* pinger --
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
@@ -1471,7 +1411,7 @@ pinger(void)
ntransmitfailures++;
warn("sendmsg");
}
- (void)printf("ping6: wrote %s %d chars, ret=%d\n",
+ (void)printf("ping: wrote %s %d chars, ret=%d\n",
hostname, cc, i);
}
if (!(options & F_QUIET) && options & F_DOT)
@@ -1515,7 +1455,7 @@ mynireply(const struct icmp6_nodeinfo *nip)
*
* Return value:
* Pointer to an octet immediately following the ending zero octet
- * of the decoded label, or NULL if an error occured.
+ * of the decoded label, or NULL if an error occurred.
*/
static const char *
dnsdecode(const u_char *sp, const u_char *ep, const u_char *base, char *buf,
@@ -2167,7 +2107,7 @@ pr_nodeaddr(struct icmp6_nodeinfo *ni, int nilen)
/*
* In icmp-name-lookups 05 and later, TTL of each returned address
- * is contained in the resposne. We try to detect the version
+ * is contained in the response. We try to detect the version
* by the length of the data, but note that the detection algorithm
* is incomplete. We assume the latest draft by default.
*/
@@ -2307,59 +2247,6 @@ get_pathmtu(struct msghdr *mhdr)
return(0);
}
-/*
- * onint --
- * SIGINT handler.
- */
-/* ARGSUSED */
-static void
-onint(int notused __unused)
-{
- /*
- * When doing reverse DNS lookups, the seenint flag might not
- * be noticed for a while. Just exit if we get a second SIGINT.
- */
- if ((options & F_HOSTNAME) && seenint != 0)
- _exit(nreceived ? 0 : 2);
-}
-
-/*
- * summary --
- * Print out statistics.
- */
-static void
-summary(void)
-{
-
- (void)printf("\n--- %s ping6 statistics ---\n", hostname);
- (void)printf("%ld packets transmitted, ", ntransmitted);
- (void)printf("%ld packets received, ", nreceived);
- if (nrepeats)
- (void)printf("+%ld duplicates, ", nrepeats);
- if (ntransmitted) {
- if (nreceived > ntransmitted)
- (void)printf("-- somebody's duplicating packets!");
- else
- (void)printf("%.1f%% packet loss",
- ((((double)ntransmitted - nreceived) * 100.0) /
- ntransmitted));
- }
- if (nrcvtimeout)
- printf(", %ld packets out of wait time", nrcvtimeout);
- (void)putchar('\n');
- if (nreceived && timing) {
- /* Only display average to microseconds */
- double num = nreceived + nrepeats;
- double avg = tsum / num;
- double dev = sqrt(tsumsq / num - avg * avg);
- (void)printf(
- "round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n",
- tmin, avg, tmax, dev);
- (void)fflush(stdout);
- }
- (void)fflush(stdout);
-}
-
/*subject type*/
static const char *niqcode[] = {
"IPv6 address",
@@ -2642,7 +2529,7 @@ pr_addr(struct sockaddr *addr, int addrlen)
static char buf[NI_MAXHOST];
int flag = 0;
- if ((options & F_HOSTNAME) == 0)
+ if (!(options & F_HOSTNAME))
flag |= NI_NUMERICHOST;
if (cap_getnameinfo(capdns, addr, addrlen, buf, sizeof(buf), NULL, 0,
diff --git a/sbin/ping/ping6.h b/sbin/ping/ping6.h
index 5879b3684f2f..b0d75e6a4c65 100644
--- a/sbin/ping/ping6.h
+++ b/sbin/ping/ping6.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 PING6_H
diff --git a/sbin/ping/tests/Makefile b/sbin/ping/tests/Makefile
index c89d522a0dee..7d3ab02b9a86 100644
--- a/sbin/ping/tests/Makefile
+++ b/sbin/ping/tests/Makefile
@@ -1,14 +1,18 @@
-# $FreeBSD$
-
ATF_TESTS_C+= in_cksum_test
-SRCS.in_cksum_test= in_cksum_test.c ../utils.c
+.PATH: ${.CURDIR:H}
+SRCS.in_cksum_test= in_cksum_test.c utils.c
PACKAGE= tests
+ATF_TESTS_PYTEST+= test_ping.py
ATF_TESTS_SH+= ping_test
+# Exclusive because each injection test case uses the same IP addresses
+TEST_METADATA.ping_test+= is_exclusive="true"
+
${PACKAGE}FILES+= ping_c1_s56_t1.out
${PACKAGE}FILES+= ping_6_c1_s8_t1.out
${PACKAGE}FILES+= ping_c1_s56_t1_S127.out
${PACKAGE}FILES+= ping_c1_s8_t1_S1.out
+${PACKAGE}FILES+= injection.py
.include <bsd.test.mk>
diff --git a/sbin/gbde/Makefile.depend b/sbin/ping/tests/Makefile.depend
index 262aec4302c7..b372e6d58e9f 100644
--- a/sbin/gbde/Makefile.depend
+++ b/sbin/ping/tests/Makefile.depend
@@ -1,18 +1,11 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
- include \
- include/xlocale \
lib/${CSU_DIR} \
+ lib/atf/libatf-c \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
- lib/libgeom \
- lib/libmd \
- lib/libsbuf \
- lib/libutil \
+ sbin/ping \
.include <dirdeps.mk>
diff --git a/sbin/ping/tests/in_cksum_test.c b/sbin/ping/tests/in_cksum_test.c
index 597f6ac20722..ffdf8b4c63c5 100644
--- a/sbin/ping/tests/in_cksum_test.c
+++ b/sbin/ping/tests/in_cksum_test.c
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org>
* All rights reserved.
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <atf-c.h>
diff --git a/sbin/ping/tests/injection.py b/sbin/ping/tests/injection.py
new file mode 100644
index 000000000000..d46359a0c9f7
--- /dev/null
+++ b/sbin/ping/tests/injection.py
@@ -0,0 +1,83 @@
+#! /usr/bin/env python3
+# Used to inject various malformed packets
+
+import errno
+import logging
+import subprocess
+import sys
+
+logging.getLogger("scapy").setLevel(logging.CRITICAL)
+
+from scapy.all import IP, ICMP, IPOption
+import scapy.layers.all
+from scapy.layers.inet import ICMPEcho_am
+from scapy.layers.tuntap import TunTapInterface
+
+SRC_ADDR = "192.0.2.14"
+DST_ADDR = "192.0.2.15"
+
+mode = sys.argv[1]
+ip = None
+
+# fill opts with nop (0x01)
+opts = b''
+for x in range(40):
+ opts += b'\x01'
+
+
+# Create and configure a tun interface with an RFC5737 nonrouteable address
+create_proc = subprocess.run(
+ args=["ifconfig", "tun", "create"],
+ capture_output=True,
+ check=True,
+ text=True)
+iface = create_proc.stdout.strip()
+tun = TunTapInterface(iface)
+with open("tun.txt", "w") as f:
+ f.write(iface)
+subprocess.run(["ifconfig", tun.iface, "up"])
+subprocess.run(["ifconfig", tun.iface, SRC_ADDR, DST_ADDR])
+
+ping = subprocess.Popen(
+ args=["/sbin/ping", "-v", "-c1", "-t1", DST_ADDR],
+ text=True
+)
+# Wait for /sbin/ping to ping us
+echo_req = tun.recv()
+
+# Construct the response packet
+if mode == "opts":
+ # Sending reply with IP options
+ echo_reply = IP(
+ dst=SRC_ADDR,
+ src=DST_ADDR,
+ options=IPOption(opts)
+ )/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
+elif mode == "pip":
+ # packet in packet (inner has options)
+
+ inner = IP(
+ dst=SRC_ADDR,
+ src=DST_ADDR,
+ options=IPOption(opts)
+ )/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
+ outer = IP(
+ dst=SRC_ADDR,
+ src=DST_ADDR
+ )/ICMP(type=3, code=1) # host unreach
+
+ echo_reply = outer/inner
+elif mode == "reply":
+ # Sending normal echo reply
+ echo_reply = IP(
+ dst=SRC_ADDR,
+ src=DST_ADDR,
+ )/ICMP(type=0, code=0, id=echo_req.payload.id)/echo_req.payload.payload
+else:
+ print("unknown mode {}".format(mode))
+ exit(1)
+
+tun.send(echo_reply)
+outs, errs = ping.communicate()
+
+sys.exit(ping.returncode)
diff --git a/sbin/ping/tests/ping_6_c1_s8_t1.out b/sbin/ping/tests/ping_6_c1_s8_t1.out
index 81c56e6cf586..0d207e74bc3e 100644
--- a/sbin/ping/tests/ping_6_c1_s8_t1.out
+++ b/sbin/ping/tests/ping_6_c1_s8_t1.out
@@ -1,6 +1,6 @@
-PING6(56=40+8+8 bytes) ::1 --> ::1
+PING(56=40+8+8 bytes) ::1 --> ::1
16 bytes from ::1, icmp_seq=0 hlim= time= ms
---- localhost ping6 statistics ---
+--- localhost ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
diff --git a/sbin/ping/tests/ping_c1_s8_t1_S1.out b/sbin/ping/tests/ping_c1_s8_t1_S1.out
index 81c56e6cf586..0d207e74bc3e 100644
--- a/sbin/ping/tests/ping_c1_s8_t1_S1.out
+++ b/sbin/ping/tests/ping_c1_s8_t1_S1.out
@@ -1,6 +1,6 @@
-PING6(56=40+8+8 bytes) ::1 --> ::1
+PING(56=40+8+8 bytes) ::1 --> ::1
16 bytes from ::1, icmp_seq=0 hlim= time= ms
---- localhost ping6 statistics ---
+--- localhost ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
-round-trip min/avg/max/std-dev = /// ms
+round-trip min/avg/max/stddev = /// ms
diff --git a/sbin/ping/tests/ping_test.sh b/sbin/ping/tests/ping_test.sh
index 7f11af7e9818..5a12ace104d7 100644
--- a/sbin/ping/tests/ping_test.sh
+++ b/sbin/ping/tests/ping_test.sh
@@ -1,5 +1,5 @@
#
-# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org>
# All rights reserved.
@@ -25,126 +25,262 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
-require_ipv4() {
- if ! getaddrinfo -f inet localhost 1>/dev/null 2>&1; then
- atf_skip "IPv4 is not configured"
- fi
+require_ipv4()
+{
+ if ! getaddrinfo -f inet localhost 1>/dev/null 2>&1; then
+ atf_skip "IPv4 is not configured"
+ fi
}
-require_ipv6() {
- if ! getaddrinfo -f inet6 localhost 1>/dev/null 2>&1; then
- atf_skip "IPv6 is not configured"
- fi
+require_ipv6()
+{
+ if ! getaddrinfo -f inet6 localhost 1>/dev/null 2>&1; then
+ atf_skip "IPv6 is not configured"
+ fi
}
atf_test_case ping_c1_s56_t1
-ping_c1_s56_t1_head() {
- atf_set "descr" "Stop after receiving 1 ECHO_RESPONSE packet"
+ping_c1_s56_t1_head()
+{
+ atf_set "descr" "Stop after receiving 1 ECHO_RESPONSE packet"
}
-ping_c1_s56_t1_body() {
- require_ipv4
- atf_check -s exit:0 -o save:std.out -e empty \
- ping -4 -c 1 -s 56 -t 1 localhost
- check_ping_statistics std.out $(atf_get_srcdir)/ping_c1_s56_t1.out
+ping_c1_s56_t1_body()
+{
+ require_ipv4
+ atf_check -s exit:0 -o save:std.out -e empty \
+ ping -4 -c 1 -s 56 -t 1 localhost
+ check_ping_statistics std.out $(atf_get_srcdir)/ping_c1_s56_t1.out
}
atf_test_case ping_c1_s56_t1_S127
-ping_c1_s56_t1_S127_head() {
- atf_set "descr" "Check that ping -S 127.0.0.1 localhost succeeds"
+ping_c1_s56_t1_S127_head()
+{
+ atf_set "descr" "Check that ping -S 127.0.0.1 localhost succeeds"
}
-ping_c1_s56_t1_S127_body() {
- require_ipv4
- require_ipv6
- atf_check -s exit:0 -o save:std.out -e empty \
- ping -c 1 -s 56 -t 1 -S 127.0.0.1 localhost
- check_ping_statistics std.out $(atf_get_srcdir)/ping_c1_s56_t1_S127.out
+ping_c1_s56_t1_S127_body()
+{
+ require_ipv4
+ require_ipv6
+ atf_check -s exit:0 -o save:std.out -e empty \
+ ping -c 1 -s 56 -t 1 -S 127.0.0.1 localhost
+ check_ping_statistics std.out $(atf_get_srcdir)/ping_c1_s56_t1_S127.out
}
atf_test_case ping_6_c1_s8_t1
-ping_6_c1_s8_t1_head() {
- atf_set "descr" "Stop after receiving 1 ECHO_RESPONSE packet"
+ping_6_c1_s8_t1_head()
+{
+ atf_set "descr" "Stop after receiving 1 ECHO_RESPONSE packet"
}
-ping_6_c1_s8_t1_body() {
- require_ipv6
- atf_check -s exit:0 -o save:std.out -e empty \
- ping -6 -c 1 -s 8 -t 1 localhost
- check_ping_statistics std.out $(atf_get_srcdir)/ping_6_c1_s8_t1.out
+ping_6_c1_s8_t1_body()
+{
+ require_ipv6
+ atf_check -s exit:0 -o save:std.out -e empty \
+ ping -6 -c 1 -s 8 -t 1 localhost
+ check_ping_statistics std.out $(atf_get_srcdir)/ping_6_c1_s8_t1.out
}
atf_test_case ping_c1_s8_t1_S1
-ping_c1_s8_t1_S1_head() {
- atf_set "descr" "Check that ping -S ::1 localhost succeeds"
+ping_c1_s8_t1_S1_head()
+{
+ atf_set "descr" "Check that ping -S ::1 localhost succeeds"
}
-ping_c1_s8_t1_S1_body() {
- require_ipv4
- require_ipv6
- atf_check -s exit:0 -o save:std.out -e empty \
- ping -c 1 -s 8 -t 1 -S ::1 localhost
- check_ping_statistics std.out $(atf_get_srcdir)/ping_c1_s8_t1_S1.out
+ping_c1_s8_t1_S1_body()
+{
+ require_ipv4
+ require_ipv6
+ atf_check -s exit:0 -o save:std.out -e empty \
+ ping -c 1 -s 8 -t 1 -S ::1 localhost
+ check_ping_statistics std.out $(atf_get_srcdir)/ping_c1_s8_t1_S1.out
}
atf_test_case ping6_c1_s8_t1
-ping6_c1_s8_t1_head() {
- atf_set "descr" "Use IPv6 when invoked as ping6"
+ping6_c1_s8_t1_head()
+{
+ atf_set "descr" "Use IPv6 when invoked as ping6"
}
-ping6_c1_s8_t1_body() {
- require_ipv6
- atf_check -s exit:0 -o save:std.out -e empty \
- ping6 -c 1 -s 8 -t 1 localhost
- check_ping_statistics std.out $(atf_get_srcdir)/ping_6_c1_s8_t1.out
+ping6_c1_s8_t1_body()
+{
+ require_ipv6
+ atf_check -s exit:0 -o save:std.out -e empty \
+ ping6 -c 1 -s 8 -t 1 localhost
+ check_ping_statistics std.out $(atf_get_srcdir)/ping_6_c1_s8_t1.out
}
-ping_c1t6_head() {
- atf_set "descr" "-t6 is not interpreted as -t -6 by ping"
+atf_test_case ping_c1t6
+ping_c1t6_head()
+{
+ atf_set "descr" "-t6 is not interpreted as -t -6 by ping"
}
-ping_c1t6_body() {
- require_ipv4
- atf_check -s exit:0 -o ignore -e empty ping -c1 -t6 127.0.0.1
+ping_c1t6_body()
+{
+ require_ipv4
+ atf_check -s exit:0 -o ignore -e empty ping -c1 -t6 127.0.0.1
}
-ping6_c1t4_head() {
- atf_set "descr" "-t4 is not interpreted as -t -4 by ping6"
+atf_test_case ping_c1t4
+ping6_c1t4_head()
+{
+ atf_set "descr" "-t4 is not interpreted as -t -4 by ping6"
}
-ping6_c1t4_body() {
- require_ipv6
- atf_check -s exit:0 -o ignore -e empty ping6 -c1 -t4 ::1
+ping6_c1t4_body()
+{
+ require_ipv6
+ atf_check -s exit:0 -o ignore -e empty ping6 -c1 -t4 ::1
}
-ping_46_head() {
- atf_set "descr" "-4 and -6 may not be used together"
+atf_test_case ping_46
+ping_46_head()
+{
+ atf_set "descr" "-4 and -6 cannot be used simultaneously"
}
-ping_46_body() {
- atf_check -s exit:1 -e ignore ping -4 -6
+ping_46_body()
+{
+ require_ipv4
+ require_ipv6
+ atf_check -s exit:1 \
+ -e match:"illegal option -- 6" \
+ ping -4 -6 localhost
}
-ping6_46_head() {
- atf_set "descr" "-4 and -6 may not be used together"
+atf_test_case ping_64
+ping_64_head()
+{
+ atf_set "descr" "-4 and -6 cannot be used simultaneously"
}
-ping6_46_body() {
- atf_check -s exit:1 -e ignore ping6 -4 -6
+ping_64_body()
+{
+ require_ipv4
+ require_ipv6
+ atf_check -s exit:1 \
+ -e match:"illegal option -- 4" \
+ ping -6 -4 localhost
}
+atf_test_case ping6_4
+ping6_4_head()
+{
+ atf_set "descr" "ping6 does not accept -4"
+}
+ping6_4_body()
+{
+ require_ipv4
+ require_ipv6
+ atf_check -s exit:1 \
+ -e match:"illegal option -- 4" \
+ ping6 -4 localhost
+}
+
+atf_test_case ping_nohost
+ping_nohost_head()
+{
+ atf_set "descr" "ping a nonexistent host"
+}
+ping_nohost_body()
+{
+ atf_check -s exit:68 -e match:"cannot resolve" \
+ ping nonexistent.in-addr.arpa.
+}
+
+atf_test_case ping4_nohost
+ping4_nohost_head()
+{
+ atf_set "descr" "ping -4 a nonexistent host"
+}
+ping4_nohost_body()
+{
+ atf_check -s exit:68 -e match:"cannot resolve" \
+ ping -4 nonexistent.in-addr.arpa.
+}
+
+atf_test_case ping6_nohost
+ping6_nohost_head()
+{
+ atf_set "descr" "ping -6 a nonexistent host"
+}
+ping6_nohost_body()
+{
+ atf_check -s exit:68 -e match:"cannot resolve" \
+ ping -6 nonexistent.in-addr.arpa.
+}
+
+atf_test_case "inject_opts" "cleanup"
+inject_opts_head()
+{
+ atf_set "descr" "Inject an ECHO REPLY with IP options"
+ atf_set "require.user" "root"
+ atf_set "require.progs" "python3" "scapy"
+}
+inject_opts_body()
+{
+ atf_check -s exit:0 -o match:"wrong total length" -o match:"NOP" python3 $(atf_get_srcdir)/injection.py opts
+}
+inject_opts_cleanup()
+{
+ ifconfig `cat tun.txt` destroy
+}
+
+atf_test_case "inject_pip" "cleanup"
+inject_pip_head()
+{
+ atf_set "descr" "Inject an ICMP error with a quoted packet with IP options"
+ atf_set "require.user" "root"
+ atf_set "require.progs" "python3" "scapy"
+}
+inject_pip_body()
+{
+ atf_check -s exit:2 -o match:"Destination Host Unreachable" -o match:"(01){40}" python3 $(atf_get_srcdir)/injection.py pip
+}
+inject_pip_cleanup()
+{
+ ifconfig `cat tun.txt` destroy
+}
+
+# This is redundant with the ping_ tests, but it serves to ensure that scapy.py
+# is working correctly.
+atf_test_case "inject_reply" "cleanup"
+inject_reply_head()
+{
+ atf_set "descr" "Basic ping test with packet injection"
+ atf_set "require.user" "root"
+ atf_set "require.progs" "python3" "scapy"
+}
+inject_reply_body()
+{
+ atf_check -s exit:0 -o match:"1 packets transmitted, 1 packets received" python3 $(atf_get_srcdir)/injection.py reply
+}
+inject_reply_cleanup()
+{
+ ifconfig `cat tun.txt` destroy
+}
-atf_init_test_cases() {
- atf_add_test_case ping_c1_s56_t1
- atf_add_test_case ping_c1_s56_t1_S127
- atf_add_test_case ping_6_c1_s8_t1
- atf_add_test_case ping_c1_s8_t1_S1
- atf_add_test_case ping6_c1_s8_t1
- atf_add_test_case ping_c1t6
- atf_add_test_case ping6_c1t4
- atf_add_test_case ping_46
- atf_add_test_case ping6_46
+atf_init_test_cases()
+{
+ atf_add_test_case ping_c1_s56_t1
+ atf_add_test_case ping_c1_s56_t1_S127
+ atf_add_test_case ping_6_c1_s8_t1
+ atf_add_test_case ping_c1_s8_t1_S1
+ atf_add_test_case ping6_c1_s8_t1
+ atf_add_test_case ping_c1t6
+ atf_add_test_case ping6_c1t4
+ atf_add_test_case ping_46
+ atf_add_test_case ping_64
+ atf_add_test_case ping6_4
+ atf_add_test_case ping_nohost
+ atf_add_test_case ping4_nohost
+ atf_add_test_case ping6_nohost
+ atf_add_test_case inject_opts
+ atf_add_test_case inject_pip
+ atf_add_test_case inject_reply
}
-check_ping_statistics() {
- sed -e 's/0.[0-9]\{3\}//g' \
- -e 's/[1-9][0-9]*.[0-9]\{3\}//g' \
- -e 's/localhost ([0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{1,3\})/localhost/' \
- -e 's/from [0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{1,3\}/from/' \
- -e 's/ttl=[0-9][0-9]*/ttl=/' \
- -e 's/hlim=[0-9][0-9]*/hlim=/' \
- "$1" >"$1".filtered
- atf_check -s exit:0 diff -u "$1".filtered "$2"
+check_ping_statistics()
+{
+ sed -e 's/0.[0-9]\{3\}//g' \
+ -e 's/[1-9][0-9]*.[0-9]\{3\}//g' \
+ -e 's/localhost ([0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{1,3\})/localhost/' \
+ -e 's/from [0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{1,3\}/from/' \
+ -e 's/ttl=[0-9][0-9]*/ttl=/' \
+ -e 's/hlim=[0-9][0-9]*/hlim=/' \
+ "$1" >"$1".filtered
+ atf_check -s exit:0 diff -u "$1".filtered "$2"
}
diff --git a/sbin/ping/tests/test_ping.py b/sbin/ping/tests/test_ping.py
new file mode 100644
index 000000000000..3f9a3aecf924
--- /dev/null
+++ b/sbin/ping/tests/test_ping.py
@@ -0,0 +1,1458 @@
+import pytest
+
+import logging
+import os
+import re
+import subprocess
+
+from atf_python.sys.net.vnet import IfaceFactory
+from atf_python.sys.net.vnet import SingleVnetTestTemplate
+from atf_python.sys.net.tools import ToolsHelper
+from typing import List
+from typing import Optional
+
+logging.getLogger("scapy").setLevel(logging.CRITICAL)
+import scapy.all as sc
+
+
+def build_response_packet(echo, ip, icmp, oip_ihl, special):
+ icmp_id_seq_types = [0, 8, 13, 14, 15, 16, 17, 18, 37, 38]
+ oip = echo[sc.IP]
+ oicmp = echo[sc.ICMP]
+ load = echo[sc.ICMP].payload
+ oip[sc.IP].remove_payload()
+ oicmp[sc.ICMP].remove_payload()
+ oicmp.type = 8
+
+ # As if the original IP packet had these set
+ oip.ihl = None
+ oip.len = None
+ oip.id = 1
+ oip.flags = ip.flags
+ oip.chksum = None
+ oip.options = ip.options
+
+ # Inner packet (oip) options
+ if oip_ihl:
+ oip.ihl = oip_ihl
+
+ # Special options
+ if special == "no-payload":
+ load = ""
+ if special == "tcp":
+ oip.proto = "tcp"
+ tcp = sc.TCP(sport=1234, dport=5678)
+ return ip / icmp / oip / tcp
+ if special == "udp":
+ oip.proto = "udp"
+ udp = sc.UDP(sport=1234, dport=5678)
+ return ip / icmp / oip / udp
+ if special == "warp":
+ # Build a package with a timestamp of INT_MAX
+ # (time-warped package)
+ payload_no_timestamp = sc.bytes_hex(load)[16:]
+ load = b"\x7f" + (b"\xff" * 7) + sc.hex_bytes(payload_no_timestamp)
+ if special == "wrong":
+ # Build a package with a wrong last byte
+ payload_no_last_byte = sc.bytes_hex(load)[:-2]
+ load = (sc.hex_bytes(payload_no_last_byte)) + b"\x00"
+ if special == "not-mine":
+ # Modify the ICMP Identifier field
+ oicmp.id += 1
+
+ if icmp.type in icmp_id_seq_types:
+ pkt = ip / icmp / load
+ else:
+ del ip.options
+ pkt = ip / icmp / oip / oicmp / load
+ return pkt
+
+
+def generate_ip_options(opts):
+ if not opts:
+ return []
+
+ routers = [
+ "192.0.2.10",
+ "192.0.2.20",
+ "192.0.2.30",
+ "192.0.2.40",
+ "192.0.2.50",
+ "192.0.2.60",
+ "192.0.2.70",
+ "192.0.2.80",
+ "192.0.2.90",
+ ]
+ routers_zero = [0, 0, 0, 0, 0, 0, 0, 0, 0]
+ if opts == "EOL":
+ options = sc.IPOption_EOL()
+ elif opts == "NOP":
+ options = sc.IPOption_NOP()
+ elif opts == "NOP-40":
+ options = sc.IPOption_NOP() * 40
+ elif opts == "RR":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = sc.IPOption_RR(pointer=40, routers=routers)
+ elif opts == "RR-same":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = sc.IPOption_RR(pointer=3, routers=routers_zero)
+ elif opts == "RR-trunc":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = sc.IPOption_RR(length=7, routers=routers_zero)
+ elif opts == "LSRR":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = sc.IPOption_LSRR(routers=routers)
+ elif opts == "LSRR-trunc":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = sc.IPOption_LSRR(length=3, routers=routers_zero)
+ elif opts == "SSRR":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = sc.IPOption_SSRR(routers=routers)
+ elif opts == "SSRR-trunc":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = sc.IPOption_SSRR(length=3, routers=routers_zero)
+ elif opts == "unk":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = b"\x9f"
+ elif opts == "unk-40":
+ ToolsHelper.set_sysctl("net.inet.ip.process_options", 0)
+ options = b"\x9f" * 40
+ else:
+ options = []
+ return options
+
+
+def pinger(
+ # Required arguments
+ # Avoid setting defaults on these arguments,
+ # as we want to set them explicitly in the tests
+ iface: str,
+ /,
+ src: sc.scapy.fields.SourceIPField,
+ dst: sc.scapy.layers.inet.DestIPField,
+ icmp_type: sc.scapy.fields.ByteEnumField,
+ icmp_code: sc.scapy.fields.MultiEnumField,
+ # IP arguments
+ ihl: Optional[sc.scapy.fields.BitField] = None,
+ flags: Optional[sc.scapy.fields.FlagsField] = 0,
+ opts: Optional[str] = None,
+ oip_ihl: Optional[sc.scapy.fields.BitField] = None,
+ special: Optional[str] = None,
+ # ICMP arguments
+ # Match names with <netinet/ip_icmp.h>
+ icmp_pptr: sc.scapy.fields.ByteField = 0,
+ icmp_gwaddr: sc.scapy.fields.IPField = "0.0.0.0",
+ icmp_nextmtu: sc.scapy.fields.ShortField = 0,
+ icmp_otime: sc.scapy.layers.inet.ICMPTimeStampField = 0,
+ icmp_rtime: sc.scapy.layers.inet.ICMPTimeStampField = 0,
+ icmp_ttime: sc.scapy.layers.inet.ICMPTimeStampField = 0,
+ icmp_mask: sc.scapy.fields.IPField = "0.0.0.0",
+ request: Optional[str] = None,
+ # Miscellaneous arguments
+ count: int = 1,
+ dup: bool = False,
+ verbose: bool = True,
+) -> subprocess.CompletedProcess:
+ """P I N G E R
+
+ Echo reply faker
+
+ :param str iface: Interface to send packet to
+ :keyword src: Source packet IP
+ :type src: class:`scapy.fields.SourceIPField`
+ :keyword dst: Destination packet IP
+ :type dst: class:`scapy.layers.inet.DestIPField`
+ :keyword icmp_type: ICMP type
+ :type icmp_type: class:`scapy.fields.ByteEnumField`
+ :keyword icmp_code: ICMP code
+ :type icmp_code: class:`scapy.fields.MultiEnumField`
+
+ :keyword ihl: Internet Header Length, defaults to None
+ :type ihl: class:`scapy.fields.BitField`, optional
+ :keyword flags: IP flags - one of `DF`, `MF` or `evil`, defaults to 0
+ :type flags: class:`scapy.fields.FlagsField`, optional
+ :keyword opts: Include IP options - one of `EOL`, `NOP`, `NOP-40`, `unk`,
+ `unk-40`, `RR`, `RR-same`, `RR-trunc`, `LSRR`, `LSRR-trunc`, `SSRR` or
+ `SSRR-trunc`, defaults to None
+ :type opts: str, optional
+ :keyword oip_ihl: Inner packet's Internet Header Length, defaults to None
+ :type oip_ihl: class:`scapy.fields.BitField`, optional
+ :keyword special: Send a special packet - one of `no-payload`, `not-mine`,
+ `tcp`, `udp`, `wrong` or `warp`, defaults to None
+ :type special: str, optional
+ :keyword icmp_pptr: ICMP pointer, defaults to 0
+ :type icmp_pptr: class:`scapy.fields.ByteField`
+ :keyword icmp_gwaddr: ICMP gateway IP address, defaults to "0.0.0.0"
+ :type icmp_gwaddr: class:`scapy.fields.IPField`
+ :keyword icmp_nextmtu: ICMP next MTU, defaults to 0
+ :type icmp_nextmtu: class:`scapy.fields.ShortField`
+ :keyword icmp_otime: ICMP originate timestamp, defaults to 0
+ :type icmp_otime: class:`scapy.layers.inet.ICMPTimeStampField`
+ :keyword icmp_rtime: ICMP receive timestamp, defaults to 0
+ :type icmp_rtime: class:`scapy.layers.inet.ICMPTimeStampField`
+ :keyword icmp_ttime: ICMP transmit timestamp, defaults to 0
+ :type icmp_ttime: class:`scapy.layers.inet.ICMPTimeStampField`
+ :keyword icmp_mask: ICMP address mask, defaults to "0.0.0.0"
+ :type icmp_mask: class:`scapy.fields.IPField`
+ :keyword request: Request type - one of `mask` or `timestamp`,
+ defaults to None
+ :type request: str, optional
+ :keyword count: Number of packets to send, defaults to 1
+ :type count: int
+ :keyword dup: Duplicate packets, defaults to `False`
+ :type dup: bool
+ :keyword verbose: Turn on/off verbosity, defaults to `True`
+ :type verbose: bool
+
+ :return: A class:`subprocess.CompletedProcess` with the output from the
+ ping utility
+ :rtype: class:`subprocess.CompletedProcess`
+ """
+ tun = sc.TunTapInterface(iface)
+ subprocess.run(["ifconfig", tun.iface, "up"], check=True)
+ subprocess.run(["ifconfig", tun.iface, src, dst], check=True)
+ ip_opts = generate_ip_options(opts)
+ ip = sc.IP(ihl=ihl, flags=flags, src=dst, dst=src, options=ip_opts)
+ command = [
+ "/sbin/ping",
+ "-c",
+ str(count),
+ "-t",
+ str(count),
+ ]
+ if verbose:
+ command += ["-v"]
+ if request == "mask":
+ command += ["-Mm"]
+ if request == "timestamp":
+ command += ["-Mt"]
+ if special:
+ command += ["-p1"]
+ if opts in [
+ "RR",
+ "RR-same",
+ "RR-trunc",
+ "LSRR",
+ "LSRR-trunc",
+ "SSRR",
+ "SSRR-trunc",
+ ]:
+ command += ["-R"]
+ command += [dst]
+ with subprocess.Popen(
+ args=command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
+ ) as ping:
+ for dummy in range(count):
+ echo = tun.recv()
+ icmp = sc.ICMP(
+ type=icmp_type,
+ code=icmp_code,
+ id=echo[sc.ICMP].id,
+ seq=echo[sc.ICMP].seq,
+ ts_ori=icmp_otime,
+ ts_rx=icmp_rtime,
+ ts_tx=icmp_ttime,
+ gw=icmp_gwaddr,
+ ptr=icmp_pptr,
+ addr_mask=icmp_mask,
+ nexthopmtu=icmp_nextmtu,
+ )
+ pkt = build_response_packet(echo, ip, icmp, oip_ihl, special)
+ tun.send(pkt)
+ if dup is True:
+ tun.send(pkt)
+ stdout, stderr = ping.communicate()
+ return subprocess.CompletedProcess(
+ ping.args, ping.returncode, stdout, stderr
+ )
+
+
+def redact(output):
+ """Redact some elements of ping's output"""
+ pattern_replacements = [
+ (r"localhost \([0-9]{1,3}(\.[0-9]{1,3}){3}\)", "localhost"),
+ (r"from [0-9]{1,3}(\.[0-9]{1,3}){3}", "from"),
+ ("hlim=[0-9]*", "hlim="),
+ ("ttl=[0-9]*", "ttl="),
+ ("time=[0-9.-]*", "time="),
+ ("cp: .*", "cp: xx xx xx xx xx xx xx xx"),
+ ("dp: .*", "dp: xx xx xx xx xx xx xx xx"),
+ (r"\(-[0-9\.]+[0-9]+ ms\)", "(- ms)"),
+ (r"[0-9\.]+/[0-9.]+", "/"),
+ ]
+ for pattern, repl in pattern_replacements:
+ output = re.sub(pattern, repl, output)
+ return output
+
+
+class TestPing(SingleVnetTestTemplate):
+ IPV6_PREFIXES: List[str] = ["2001:db8::1/64"]
+ IPV4_PREFIXES: List[str] = ["192.0.2.1/24"]
+
+ # Each param in testdata contains a dictionary with the command,
+ # and the expected outcome (returncode, redacted stdout, and stderr)
+ testdata = [
+ pytest.param(
+ {
+ "args": "ping -4 -c1 -s56 -t1 localhost",
+ "returncode": 0,
+ "stdout": """\
+PING localhost: 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+
+--- localhost ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_4_c1_s56_t1_localhost",
+ ),
+ pytest.param(
+ {
+ "args": "ping -6 -c1 -s8 -t1 localhost",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) ::1 --> ::1
+16 bytes from ::1, icmp_seq=0 hlim= time= ms
+
+--- localhost ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_6_c1_s8_t1_localhost",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c1 192.0.2.1",
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.1 (192.0.2.1): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+
+--- 192.0.2.1 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_A_c1_192_0_2_1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c1 192.0.2.2",
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_A_c1_192_0_2_2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c1 2001:db8::1",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
+
+--- 2001:db8::1 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_A_c1_2001_db8__1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c1 2001:db8::2",
+ "returncode": 2,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+
+--- 2001:db8::2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_A_c1_2001_db8__2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c3 192.0.2.1",
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.1 (192.0.2.1): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+64 bytes from: icmp_seq=1 ttl= time= ms
+64 bytes from: icmp_seq=2 ttl= time= ms
+
+--- 192.0.2.1 ping statistics ---
+3 packets transmitted, 3 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_A_3_192_0.2.1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c3 192.0.2.2",
+ "returncode": 2,
+ "stdout": """\
+\x07\x07PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+3 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_A_c3_192_0_2_2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c3 2001:db8::1",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
+16 bytes from 2001:db8::1, icmp_seq=1 hlim= time= ms
+16 bytes from 2001:db8::1, icmp_seq=2 hlim= time= ms
+
+--- 2001:db8::1 ping statistics ---
+3 packets transmitted, 3 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_A_c3_2001_db8__1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -A -c3 2001:db8::2",
+ "returncode": 2,
+ "stdout": """\
+\x07\x07PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+
+--- 2001:db8::2 ping statistics ---
+3 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_A_c3_2001_db8__2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c1 192.0.2.1",
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.1 (192.0.2.1): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+
+--- 192.0.2.1 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_c1_192_0_2_1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c1 192.0.2.2",
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_c1_192_0_2_2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c1 2001:db8::1",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
+
+--- 2001:db8::1 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_c1_2001_db8__1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c1 2001:db8::2",
+ "returncode": 2,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+
+--- 2001:db8::2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_c1_2001_db8__2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c1 -S127.0.0.1 -s56 -t1 localhost",
+ "returncode": 0,
+ "stdout": """\
+PING localhost from: 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+
+--- localhost ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_c1_S127_0_0_1_s56_t1_localhost",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c1 -S::1 -s8 -t1 localhost",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) ::1 --> ::1
+16 bytes from ::1, icmp_seq=0 hlim= time= ms
+
+--- localhost ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_c1_S__1_s8_t1_localhost",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c3 192.0.2.1",
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.1 (192.0.2.1): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+64 bytes from: icmp_seq=1 ttl= time= ms
+64 bytes from: icmp_seq=2 ttl= time= ms
+
+--- 192.0.2.1 ping statistics ---
+3 packets transmitted, 3 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_c3_192_0_2_1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c3 192.0.2.2",
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+3 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_c3_192_0_2_2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c3 2001:db8::1",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+16 bytes from 2001:db8::1, icmp_seq=0 hlim= time= ms
+16 bytes from 2001:db8::1, icmp_seq=1 hlim= time= ms
+16 bytes from 2001:db8::1, icmp_seq=2 hlim= time= ms
+
+--- 2001:db8::1 ping statistics ---
+3 packets transmitted, 3 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_c3_2001_db8__1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -c3 2001:db8::2",
+ "returncode": 2,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+
+--- 2001:db8::2 ping statistics ---
+3 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_c3_2001_db8__2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c1 192.0.2.1",
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.1 (192.0.2.1): 56 data bytes
+
+--- 192.0.2.1 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_q_c1_192_0_2_1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c1 192.0.2.2",
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_q_c1_192_0_2_2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c1 2001:db8::1",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+
+--- 2001:db8::1 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_q_c1_2001_db8__1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c1 2001:db8::2",
+ "returncode": 2,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+
+--- 2001:db8::2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_q_c1_2001_db8__2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c3 192.0.2.1",
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.1 (192.0.2.1): 56 data bytes
+
+--- 192.0.2.1 ping statistics ---
+3 packets transmitted, 3 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_q_c3_192_0_2_1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c3 192.0.2.2",
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+3 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_q_c3_192_0_2_2",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c3 2001:db8::1",
+ "returncode": 0,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::1
+
+--- 2001:db8::1 ping statistics ---
+3 packets transmitted, 3 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ },
+ id="_q_c3_2001_db8__1",
+ ),
+ pytest.param(
+ {
+ "args": "ping -q -c3 2001:db8::2",
+ "returncode": 2,
+ "stdout": """\
+PING(56=40+8+8 bytes) 2001:db8::1 --> 2001:db8::2
+
+--- 2001:db8::2 ping statistics ---
+3 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ },
+ id="_q_c3_2001_db8__2",
+ ),
+ ]
+
+ @pytest.mark.parametrize("expected", testdata)
+ @pytest.mark.require_user("root")
+ @pytest.mark.require_user("unprivileged")
+ def test_ping(self, expected):
+ """Test ping"""
+ ping = subprocess.run(
+ expected["args"].split(),
+ capture_output=True,
+ timeout=15,
+ text=True,
+ )
+ assert ping.returncode == expected["returncode"]
+ assert redact(ping.stdout) == expected["stdout"]
+ assert ping.stderr == expected["stderr"]
+
+ # Each param in ping46_testdata contains a dictionary with the arguments
+ # and the expected outcome (returncode, redacted stdout, and stderr)
+ # common to `ping -4` and `ping -6`
+ ping46_testdata = [
+ pytest.param(
+ {
+ "args": "-Wx localhost",
+ "returncode": os.EX_USAGE,
+ "stdout": "",
+ "stderr": "ping: invalid timing interval: `x'\n",
+ },
+ id="_Wx_localhost",
+ ),
+ ]
+
+ @pytest.mark.parametrize("expected", ping46_testdata)
+ @pytest.mark.require_user("root")
+ @pytest.mark.require_user("unprivileged")
+ def test_ping_46(self, expected):
+ """Test ping -4/ping -6"""
+ for version in [4, 6]:
+ ping = subprocess.run(
+ ["ping", f"-{version}"] + expected["args"].split(),
+ capture_output=True,
+ timeout=15,
+ text=True,
+ )
+ assert ping.returncode == expected["returncode"]
+ assert redact(ping.stdout) == expected["stdout"]
+ assert ping.stderr == expected["stderr"]
+
+ # Each param in pinger_testdata contains a dictionary with the keywords to
+ # `pinger()` and a dictionary with the expected outcome (returncode,
+ # stdout, stderr, and if ping's output is redacted)
+ pinger_testdata = [
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "EOL",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+wrong total length 88 instead of 84
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_EOL",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "LSRR",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+LSRR: 192.0.2.10
+ 192.0.2.20
+ 192.0.2.30
+ 192.0.2.40
+ 192.0.2.50
+ 192.0.2.60
+ 192.0.2.70
+ 192.0.2.80
+ 192.0.2.90
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_LSRR",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "LSRR-trunc",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+LSRR: (truncated route)
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_LSRR_trunc",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "SSRR",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+SSRR: 192.0.2.10
+ 192.0.2.20
+ 192.0.2.30
+ 192.0.2.40
+ 192.0.2.50
+ 192.0.2.60
+ 192.0.2.70
+ 192.0.2.80
+ 192.0.2.90
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_SSRR",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "SSRR-trunc",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+SSRR: (truncated route)
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_SSRR_trunc",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "RR",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+RR: 192.0.2.10
+ 192.0.2.20
+ 192.0.2.30
+ 192.0.2.40
+ 192.0.2.50
+ 192.0.2.60
+ 192.0.2.70
+ 192.0.2.80
+ 192.0.2.90
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_RR",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "RR-same",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms (same route)
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_RR_same",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "RR-trunc",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+RR: (truncated route)
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_RR_trunc",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "NOP",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+wrong total length 88 instead of 84
+NOP
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_NOP",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "ihl": 0x4,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "", # "IHL too short" message not shown
+ "redacted": False,
+ },
+ id="_IHL_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "special": "no-payload",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": """\
+ping: quoted data too short (28 bytes) from 192.0.2.2
+""",
+ "redacted": False,
+ },
+ id="_quoted_data_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "oip_ihl": 0x4,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "", # "inner IHL too short" message not shown
+ "redacted": False,
+ },
+ id="_inner_IHL_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "oip_ihl": 0xF,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": """\
+ping: inner packet too short (84 bytes) from 192.0.2.2
+""",
+ "redacted": False,
+ },
+ id="_inner_packet_too_short",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "oip_ihl": 0xF,
+ "special": "no-payload",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ "redacted": False,
+ },
+ id="_max_inner_packet_ihl_without_payload",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "NOP-40",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+wrong total length 124 instead of 84
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+NOP
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_NOP_40",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "opts": "unk",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+wrong total length 88 instead of 84
+unknown option 9f
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_opts_unk",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "opts": "NOP-40",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+132 bytes from 192.0.2.2: Destination Host Unreachable
+Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Opts
+ 4 f 00 007c 0001 0 0000 40 01 d868 192.0.2.1 192.0.2.2 01010101010101010101010101010101010101010101010101010101010101010101010101010101
+
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ "redacted": False,
+ },
+ id="_3_1_opts_NOP_40",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "flags": "DF",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+92 bytes from 192.0.2.2: Destination Host Unreachable
+Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
+ 4 5 00 0054 0001 2 0000 40 01 b6a4 192.0.2.1 192.0.2.2
+
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ "redacted": False,
+ },
+ id="_3_1_flags_DF",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "special": "tcp",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": """\
+ping: quoted data too short (40 bytes) from 192.0.2.2
+""",
+ "redacted": False,
+ },
+ id="_3_1_special_tcp",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "special": "udp",
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": """\
+ping: quoted data too short (28 bytes) from 192.0.2.2
+""",
+ "redacted": False,
+ },
+ id="_3_1_special_udp",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "verbose": False,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+92 bytes from 192.0.2.2: Destination Host Unreachable
+Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
+ 4 5 00 0054 0001 0 0000 40 01 f6a4 192.0.2.1 192.0.2.2
+
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ "redacted": False,
+ },
+ id="_3_1_verbose_false",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 3,
+ "icmp_code": 1,
+ "special": "not-mine",
+ "verbose": False,
+ },
+ {
+ "returncode": 2,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 0 packets received, 100.0% packet loss
+""",
+ "stderr": "",
+ "redacted": False,
+ },
+ id="_3_1_special_not_mine_verbose_false",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "special": "warp",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": """\
+ping: time of day goes back (- ms), clamping time to 0
+""",
+ "redacted": True,
+ },
+ id="_0_0_special_warp",
+ ),
+ pytest.param(
+ {
+ "src": "192.0.2.1",
+ "dst": "192.0.2.2",
+ "icmp_type": 0,
+ "icmp_code": 0,
+ "special": "wrong",
+ },
+ {
+ "returncode": 0,
+ "stdout": """\
+PATTERN: 0x01
+PING 192.0.2.2 (192.0.2.2): 56 data bytes
+64 bytes from: icmp_seq=0 ttl= time= ms
+wrong data byte #55 should be 0x1 but was 0x0
+cp: xx xx xx xx xx xx xx xx
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0
+dp: xx xx xx xx xx xx xx xx
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
+
+--- 192.0.2.2 ping statistics ---
+1 packets transmitted, 1 packets received, 0.0% packet loss
+round-trip min/avg/max/stddev = /// ms
+""",
+ "stderr": "",
+ "redacted": True,
+ },
+ id="_0_0_special_wrong",
+ ),
+ ]
+
+ @pytest.mark.parametrize("pinger_kargs, expected", pinger_testdata)
+ @pytest.mark.require_progs(["scapy"])
+ @pytest.mark.require_user("root")
+ def test_pinger(self, pinger_kargs, expected):
+ """Test ping using pinger(), a reply faker"""
+ iface = IfaceFactory().create_iface("", "tun")[0].name
+ ping = pinger(iface, **pinger_kargs)
+ assert ping.returncode == expected["returncode"]
+ if expected["redacted"]:
+ assert redact(ping.stdout) == expected["stdout"]
+ assert redact(ping.stderr) == expected["stderr"]
+ else:
+ assert ping.stdout == expected["stdout"]
+ assert ping.stderr == expected["stderr"]
diff --git a/sbin/ping/utils.c b/sbin/ping/utils.c
index 1df233995bf0..e723f690be2b 100644
--- a/sbin/ping/utils.c
+++ b/sbin/ping/utils.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <string.h>
#include "utils.h"
diff --git a/sbin/ping/utils.h b/sbin/ping/utils.h
index cb56e587a368..758cac3c9ec1 100644
--- a/sbin/ping/utils.h
+++ b/sbin/ping/utils.h
@@ -1,5 +1,5 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (C) 2019 Jan Sucan <jansucan@FreeBSD.org>
* All rights reserved.
@@ -24,8 +24,6 @@
* 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 UTILS_H
diff --git a/sbin/ping6/Makefile.depend.options b/sbin/ping6/Makefile.depend.options
deleted file mode 100644
index a1c8f6278e92..000000000000
--- a/sbin/ping6/Makefile.depend.options
+++ /dev/null
@@ -1,8 +0,0 @@
-# $FreeBSD$
-# This file is not autogenerated - take care!
-
-DIRDEPS_OPTIONS= CASPER
-
-DIRDEPS.CASPER.yes= lib/libcasper/services/cap_dns
-
-.include <dirdeps-options.mk>
diff --git a/sbin/quotacheck/Makefile b/sbin/quotacheck/Makefile
index 10bdeb7a9e54..edaac8679459 100644
--- a/sbin/quotacheck/Makefile
+++ b/sbin/quotacheck/Makefile
@@ -1,6 +1,3 @@
-# $FreeBSD$
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-
PACKAGE=quotacheck
PROG= quotacheck
SRCS= quotacheck.c preen.c fsutil.c utilities.c
diff --git a/sbin/quotacheck/Makefile.depend b/sbin/quotacheck/Makefile.depend
index 991757ecadc0..2e61386bc0cc 100644
--- a/sbin/quotacheck/Makefile.depend
+++ b/sbin/quotacheck/Makefile.depend
@@ -1,13 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libufs \
lib/libutil \
diff --git a/sbin/quotacheck/preen.c b/sbin/quotacheck/preen.c
index 26cfa4513fd6..b7bd79a462d7 100644
--- a/sbin/quotacheck/preen.c
+++ b/sbin/quotacheck/preen.c
@@ -29,18 +29,9 @@
* 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/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)preen.c 8.5 (Berkeley) 4/28/95";
-#else
-__RCSID("$NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $");
-#endif
-#endif /* not lint */
+/* $NetBSD: preen.c,v 1.18 1998/07/26 20:02:36 mycroft Exp $ */
#include <sys/param.h>
#include <sys/stat.h>
diff --git a/sbin/quotacheck/quotacheck.8 b/sbin/quotacheck/quotacheck.8
index 2f039b8404a2..cd1b60e51060 100644
--- a/sbin/quotacheck/quotacheck.8
+++ b/sbin/quotacheck/quotacheck.8
@@ -28,9 +28,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)quotacheck.8 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
.Dd January 25, 2007
.Dt QUOTACHECK 8
.Os
diff --git a/sbin/quotacheck/quotacheck.c b/sbin/quotacheck/quotacheck.c
index 9a01be11d9d0..1871d2efc25a 100644
--- a/sbin/quotacheck/quotacheck.c
+++ b/sbin/quotacheck/quotacheck.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1990, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)quotacheck.c 8.3 (Berkeley) 1/29/94";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* Fix up / report on disk quotas & usage
*/
@@ -91,10 +77,6 @@ union {
long dev_bsize = 1;
ino_t maxino;
-union dinode {
- struct ufs1_dinode dp1;
- struct ufs2_dinode dp2;
-};
#define DIP(dp, field) \
((sblock.fs_magic == FS_UFS1_MAGIC) ? \
(dp)->dp1.field : (dp)->dp2.field)
@@ -321,7 +303,7 @@ chkquota(char *specname, struct quotafile *qfu, struct quotafile *qfg)
}
}
sync();
- if ((ret = sbget(fi, &fs, STDSB)) != 0) {
+ if ((ret = sbget(fi, &fs, UFS_STDSB, UFS_NOCSUM)) != 0) {
switch (ret) {
case ENOENT:
warn("Cannot find file system superblock");
diff --git a/sbin/quotacheck/quotacheck.h b/sbin/quotacheck/quotacheck.h
index 2699e4707fe9..041a879c3024 100644
--- a/sbin/quotacheck/quotacheck.h
+++ b/sbin/quotacheck/quotacheck.h
@@ -30,8 +30,6 @@
* 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$
*/
extern char *blockcheck(char *);
diff --git a/sbin/rcorder/Makefile b/sbin/rcorder/Makefile
index 7bab197ed4ab..a57786a83381 100644
--- a/sbin/rcorder/Makefile
+++ b/sbin/rcorder/Makefile
@@ -1,5 +1,4 @@
# $NetBSD: Makefile,v 1.1 1999/11/23 05:28:20 mrg Exp $
-# $FreeBSD$
PACKAGE=rc
PROG= rcorder
diff --git a/sbin/rcorder/Makefile.depend b/sbin/rcorder/Makefile.depend
index 991757ecadc0..678747db6f2c 100644
--- a/sbin/rcorder/Makefile.depend
+++ b/sbin/rcorder/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/rcorder/ealloc.c b/sbin/rcorder/ealloc.c
index eae8bb67d69a..9d6f20f77137 100644
--- a/sbin/rcorder/ealloc.c
+++ b/sbin/rcorder/ealloc.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $NetBSD: ealloc.c,v 1.1.1.1 1999/11/19 04:30:56 mrg Exp $ */
/*-
diff --git a/sbin/rcorder/ealloc.h b/sbin/rcorder/ealloc.h
index 093ebc3dadc8..f1c81fb2fd18 100644
--- a/sbin/rcorder/ealloc.h
+++ b/sbin/rcorder/ealloc.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $NetBSD: ealloc.h,v 1.1.1.1 1999/11/19 04:30:56 mrg Exp $ */
void *emalloc(size_t len);
diff --git a/sbin/rcorder/hash.c b/sbin/rcorder/hash.c
index 3dcb77054960..a40e52529d06 100644
--- a/sbin/rcorder/hash.c
+++ b/sbin/rcorder/hash.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $NetBSD: hash.c,v 1.1.1.1 1999/11/19 04:30:56 mrg Exp $ */
/*-
@@ -41,19 +40,6 @@
* SUCH DAMAGE.
*/
-#ifdef MAKE_BOOTSTRAP
-static char rcsid[] = "$NetBSD: hash.c,v 1.1.1.1 1999/11/19 04:30:56 mrg Exp $";
-#else
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)hash.c 8.1 (Berkeley) 6/6/93";
-#else
-__RCSID("$NetBSD: hash.c,v 1.1.1.1 1999/11/19 04:30:56 mrg Exp $");
-#endif
-#endif /* not lint */
-#endif
-
#include <sys/types.h>
#include <stdlib.h>
diff --git a/sbin/rcorder/hash.h b/sbin/rcorder/hash.h
index d190633861a0..d1f096a3c017 100644
--- a/sbin/rcorder/hash.h
+++ b/sbin/rcorder/hash.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $NetBSD: hash.h,v 1.1.1.1 1999/11/19 04:30:56 mrg Exp $ */
/*-
@@ -39,8 +38,6 @@
* 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: @(#)hash.h 8.1 (Berkeley) 6/6/93
*/
/* hash.h --
diff --git a/sbin/rcorder/rcorder-visualize.sh b/sbin/rcorder/rcorder-visualize.sh
index ab0632f76e56..cf59f7989ed2 100755
--- a/sbin/rcorder/rcorder-visualize.sh
+++ b/sbin/rcorder/rcorder-visualize.sh
@@ -24,7 +24,6 @@
# (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$
#
# Simple script to show the dependency graph for rc scripts.
# Output is in the dot(1) language and can be rendered using
diff --git a/sbin/rcorder/rcorder.8 b/sbin/rcorder/rcorder.8
index 6b29359f3c20..cc94ca6992d5 100644
--- a/sbin/rcorder/rcorder.8
+++ b/sbin/rcorder/rcorder.8
@@ -29,9 +29,7 @@
.\" (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 September 8, 2020
+.Dd June 10, 2023
.Dt RCORDER 8
.Os
.Sh NAME
@@ -153,8 +151,10 @@ in use:
.It Sy firstboot , nojail , nojailvnet , nostart
Used by
.Xr rc 8 .
-.It Sy resume
+.It Sy suspend , resume
Used by
+.Nm /etc/rc.suspend
+and
.Nm /etc/rc.resume
(see
.Xr acpiconf 8 )
@@ -170,7 +170,7 @@ $ rcorder /etc/rc.d/* /usr/local/etc/rc.d/*
.Ed
.Pp
Count the number of services in the base system, which specify the
-.Sy shutdown
+.Sy nostart
keyword, while skipping those with
.Sy firstboot
and
@@ -224,7 +224,7 @@ If a file has an item in
or in
.Ql BEFORE
that could not be provided,
-this missing provider and the requirement will be drawn bold red as well.
+this missing provider and the requirement will be drawn in bold red as well.
.Sh SEE ALSO
.Xr acpiconf 8 ,
.Xr rc 8 ,
diff --git a/sbin/rcorder/rcorder.c b/sbin/rcorder/rcorder.c
index a8d4f4fdc3e1..3d2a67c82a5a 100644
--- a/sbin/rcorder/rcorder.c
+++ b/sbin/rcorder/rcorder.c
@@ -3,7 +3,7 @@
#endif
/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ * SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1998, 1999 Matthew R. Green
* All rights reserved.
@@ -40,8 +40,6 @@
*/
#include <sys/types.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/stat.h>
#include <err.h>
@@ -982,9 +980,11 @@ do_file(filenode *fnode, strnodelist *stack_ptr)
fnode->last->next = fnode->next;
}
- if (fnode->issues_count)
- warnx("`%s' was seen in circular dependencies for %d times.",
- fnode->filename, fnode->issues_count);
+ if (fnode->issues_count) {
+ warnx("`%s' was seen in circular dependencies %d time%s.",
+ fnode->filename, fnode->issues_count,
+ fnode->issues_count > 1 ? "s" : "");
+ }
DPRINTF((stderr, "nuking %s\n", fnode->filename));
}
diff --git a/sbin/rcorder/sprite.h b/sbin/rcorder/sprite.h
index e311ee6e0f66..8ca07f7aa6d8 100644
--- a/sbin/rcorder/sprite.h
+++ b/sbin/rcorder/sprite.h
@@ -38,9 +38,6 @@
* 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: @(#)sprite.h 8.1 (Berkeley) 6/6/93
- * $FreeBSD$
*/
/*
diff --git a/sbin/reboot/Makefile b/sbin/reboot/Makefile
index 87c47307d59c..27805d307794 100644
--- a/sbin/reboot/Makefile
+++ b/sbin/reboot/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
PACKAGE=runtime
PROG= reboot
MAN= reboot.8 nextboot.8
@@ -15,9 +12,9 @@ MAN+= boot_i386.8
MLINKS+= boot_i386.8 boot.8
.endif
-LINKS= ${BINDIR}/reboot ${BINDIR}/halt ${BINDIR}/reboot ${BINDIR}/fastboot \
- ${BINDIR}/reboot ${BINDIR}/fasthalt
-
-SCRIPTS= nextboot.sh
+LINKS= ${BINDIR}/reboot ${BINDIR}/halt \
+ ${BINDIR}/reboot ${BINDIR}/fastboot \
+ ${BINDIR}/reboot ${BINDIR}/fasthalt \
+ ${BINDIR}/reboot ${BINDIR}/nextboot
.include <bsd.prog.mk>
diff --git a/sbin/reboot/Makefile.depend b/sbin/reboot/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/reboot/Makefile.depend
+++ b/sbin/reboot/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/reboot/boot_i386.8 b/sbin/reboot/boot_i386.8
index a78bd34a6a7c..26dd588fb437 100644
--- a/sbin/reboot/boot_i386.8
+++ b/sbin/reboot/boot_i386.8
@@ -32,11 +32,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)boot_i386.8 8.2 (Berkeley) 4/19/94
-.\"
-.\" $FreeBSD$
-.\"
-.Dd July 11, 2020
+.Dd April 7, 2025
.Dt BOOT 8 i386
.Os
.Sh NAME
@@ -49,14 +45,14 @@ An automatic consistency check of the file systems will be performed,
and unless this fails, the system will resume multi-user operations.
.Pp
.Sy Cold starts .
-Most i386 PCs attempt to boot first from floppy disk drive 0 (sometimes
+Legacy i386 PCs attempt to boot first from floppy disk drive 0 (sometimes
known as drive A:) and, failing that, from hard disk drive 0 (sometimes
known as drive C:, or as drive 0x80 to the BIOS).
Some BIOSes allow
you to change this default sequence, and may also include a CD-ROM
drive as a boot device.
.Pp
-Some newer PCs boot using UEFI firmware, not BIOS.
+Contemporary PCs boot using UEFI firmware, not BIOS.
That process is described
in
.Xr uefi 8 .
@@ -246,7 +242,7 @@ the root password must be entered.
.It Fl S Ns Ar speed
set the speed of the serial console to
.Ar speed .
-The default is 9600 unless it has been overridden by setting
+The default is 115200 unless it has been overridden by setting
.Va BOOT_COMCONSOLE_SPEED
in
.Xr make.conf 5
diff --git a/sbin/reboot/nextboot.8 b/sbin/reboot/nextboot.8
index b09e99e4fb4f..188063dbfd3b 100644
--- a/sbin/reboot/nextboot.8
+++ b/sbin/reboot/nextboot.8
@@ -22,8 +22,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd March 29, 2022
.Dt NEXTBOOT 8
.Os
diff --git a/sbin/reboot/nextboot.sh b/sbin/reboot/nextboot.sh
deleted file mode 100644
index 2350c42516bf..000000000000
--- a/sbin/reboot/nextboot.sh
+++ /dev/null
@@ -1,133 +0,0 @@
-#! /bin/sh
-#
-# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
-#
-# Copyright (c) 2002 Gordon Tetlow. All rights reserved.
-# Copyright (c) 2012 Sandvine Incorporated. 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$
-
-append="NO"
-delete="NO"
-kenv=
-force="NO"
-nextboot_file="/boot/nextboot.conf"
-zfs=
-
-add_kenv()
-{
- local var value
-
- var=$1
- # strip literal quotes if passed in
- value=${2%\"*}
- value=${value#*\"}
-
- if [ -n "${kenv}" ]; then
- kenv="${kenv}
-"
- fi
- kenv="${kenv}${var}=\"${value}\""
-}
-
-display_usage() {
- cat <<-EOF
- Usage: nextboot [-af] [-e variable=value] [-k kernel] [-o options]
- nextboot -D
- EOF
-}
-
-while getopts "aDe:fk:o:" argument ; do
- case "${argument}" in
- a)
- append="YES"
- ;;
- D)
- delete="YES"
- ;;
- e)
- var=${OPTARG%%=*}
- value=${OPTARG#*=}
- if [ -z "$var" -o -z "$value" ]; then
- display_usage
- exit 1
- fi
- add_kenv "$var" "$value"
- ;;
- f)
- force="YES"
- ;;
- k)
- kernel="${OPTARG}"
- add_kenv kernel "$kernel"
- ;;
- o)
- add_kenv kernel_options "${OPTARG}"
- ;;
- *)
- display_usage
- exit 1
- ;;
- esac
-done
-
-if [ ${delete} = "YES" ]; then
- rm -f ${nextboot_file}
- exit 0
-fi
-
-if [ -z "${kenv}" ]; then
- display_usage
- exit 1
-fi
-
-if [ -n "${kernel}" -a ${force} = "NO" -a ! -d /boot/${kernel} ]; then
- echo "Error: /boot/${kernel} doesn't exist. Use -f to override."
- exit 1
-fi
-
-zfs=$(df -Tn "/boot/" 2>/dev/null | while read _fs _type _other ; do
- [ "zfs" = "${_type}" ] || continue
- echo "${_fs%%/*}"
-done)
-
-set -e
-
-nextboot_tmp=$(mktemp $(dirname ${nextboot_file})/nextboot.XXXXXX)
-
-if [ -n "${zfs}" ]; then
- zfsbootcfg -z ${zfs} -n freebsd:nvstore -k nextboot_enable -v YES
- cat >> ${nextboot_tmp} << EOF
-$kenv
-EOF
-else
-cat >> ${nextboot_tmp} << EOF
-nextboot_enable="YES"
-$kenv
-EOF
-fi
-
-fsync ${nextboot_tmp}
-
-mv ${nextboot_tmp} ${nextboot_file}
diff --git a/sbin/reboot/reboot.8 b/sbin/reboot/reboot.8
index 5fee3ece7c67..1bbc39d52be4 100644
--- a/sbin/reboot/reboot.8
+++ b/sbin/reboot/reboot.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)reboot.8 8.1 (Berkeley) 6/9/93
-.\" $FreeBSD$
-.\"
-.Dd December 20, 2017
+.Dd April 12, 2025
.Dt REBOOT 8
.Os
.Sh NAME
@@ -39,17 +36,25 @@
.Nd stopping and restarting the system
.Sh SYNOPSIS
.Nm halt
-.Op Fl lNnpq
+.Op Fl DflNnpq
+.Op Fl e Ar variable=value
.Op Fl k Ar kernel
+.Op Fl o Ar options
.Nm
-.Op Fl cdlNnpqr
+.Op Fl cDdflNnpqr
+.Op Fl e Ar variable=value
.Op Fl k Ar kernel
+.Op Fl o Ar options
.Nm fasthalt
-.Op Fl lNnpq
+.Op Fl DflNnpq
+.Op Fl e Ar variable=value
.Op Fl k Ar kernel
+.Op Fl o Ar options
.Nm fastboot
-.Op Fl dlNnpq
+.Op Fl dDflNnpq
+.Op Fl e Ar variable=value
.Op Fl k Ar kernel
+.Op Fl o Ar options
.Sh DESCRIPTION
The
.Nm halt
@@ -80,23 +85,56 @@ driver implements the power cycle functionality and only on hardware
with a BMC that supports power cycling.
Unlike power off, the amount of hardware that supports power cycling
is small.
+.It Fl D
+Delete existing
+.Nm nextboot
+configuration and exit.
.It Fl d
The system is requested to create a crash dump.
This option is
supported only when rebooting, and it has no effect unless a dump
device has previously been specified with
.Xr dumpon 8 .
-.It Fl k Ar kernel
-Boot the specified
-.Ar kernel
+.It Fl e Ar variable=value
+Sets
+.Va variable
+to
+.Va value
+in the loader's and kernel's environment.
+If
+.Va value
+is not already enclosed in double quotes, they will be added before writing to the
+.Nm nextboot
+configuration.
+Care should be taken if
+.Va value
+contains any characters that are special to the shell or loader's configuration
+parsing code.
+.It Fl f
+Force reboot.
+Normally,
+.Nm
+checks for the presence of the next kernel,
+and absence of the
+.Pa /var/run/noshutdown
+file.
+Without this flag, reboot is denied if one of the conditions failed.
+.It Fl k Ar kname
+Boot the specified kernel
+.Ar kname
on the next system boot.
-If the kernel boots successfully, the
+This is a one-shot option, the
.Em default
-kernel will be booted on successive boots, this is a one-shot option.
-If the boot fails, the system will continue attempting to boot
-.Ar kernel
-until the boot process is interrupted and a valid kernel booted.
-This may change in the future.
+kernel will be booted on successive boots.
+No
+.Nm reboot
+or
+.Nm halt
+will be performed if
+.Em /boot/kname/kernel
+does not exist unless the
+.Fl f
+flag is specified.
.It Fl l
The halt or reboot is
.Em not
@@ -121,6 +159,9 @@ This can happen when devices have been disconnected, such as with
.It Fl n
The file system cache is not flushed.
This option should probably not be used.
+.It Fl o Ar options
+This option
+allows the passing of kernel flags for the next boot.
.It Fl p
The system will turn off the power if it can.
If the power down action fails, the system
@@ -143,7 +184,7 @@ After changing vfs.root.mountfrom with
.Nm Fl r
can be used to change the root filesystem while preserving kernel state.
This requires the
-.Xr tmpfs 5
+.Xr tmpfs 4
kernel module to be loaded because
.Xr init 8
needs a place to store itself after the old root is unmounted, but
@@ -181,6 +222,7 @@ reboot -r
.Ed
.Sh SEE ALSO
.Xr kenv 1 ,
+.Xr reboot 2 ,
.Xr getutxent 3 ,
.Xr ipmi 4 ,
.Xr boot 8 ,
diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c
index 118ac304024c..f6065e80fb66 100644
--- a/sbin/reboot/reboot.c
+++ b/sbin/reboot/reboot.c
@@ -29,85 +29,258 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1986, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)reboot.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
#include <sys/boottrace.h>
+#include <sys/mount.h>
#include <sys/reboot.h>
+#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/time.h>
+#include <sys/wait.h>
-#include <signal.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
+#include <paths.h>
#include <pwd.h>
-#include <syslog.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
#include <unistd.h>
#include <utmpx.h>
-static void usage(void);
-static u_int get_pageins(void);
+extern char **environ;
+
+#define PATH_NEXTBOOT "/boot/nextboot.conf"
+
+static void usage(void) __dead2;
+static uint64_t get_pageins(void);
+
+static bool dohalt;
+static bool donextboot;
+
+#define E(...) do { \
+ if (force) { \
+ warn( __VA_ARGS__ ); \
+ return; \
+ } \
+ err(1, __VA_ARGS__); \
+ } while (0) \
+
+static void
+zfsbootcfg(const char *pool, bool force)
+{
+ const char * const av[] = {
+ "zfsbootcfg",
+ "-z",
+ pool,
+ "-n",
+ "freebsd:nvstore",
+ "-k",
+ "nextboot_enable",
+ "-v",
+ "YES",
+ NULL
+ };
+ int rv, status;
+ pid_t p;
+
+ rv = posix_spawnp(&p, av[0], NULL, NULL, __DECONST(char **, av),
+ environ);
+ if (rv == -1)
+ E("system zfsbootcfg");
+ if (waitpid(p, &status, WEXITED) < 0) {
+ if (errno == EINTR)
+ return;
+ E("waitpid zfsbootcfg");
+ }
+ if (WIFEXITED(status)) {
+ int e = WEXITSTATUS(status);
+
+ if (e == 0)
+ return;
+ if (e == 127)
+ E("zfsbootcfg not found in path");
+ E("zfsbootcfg returned %d", e);
+ }
+ if (WIFSIGNALED(status))
+ E("zfsbootcfg died with signal %d", WTERMSIG(status));
+ E("zfsbootcfg unexpected status %d", status);
+}
+
+static void
+write_nextboot(const char *fn, const char *env, bool force)
+{
+ char tmp[PATH_MAX];
+ FILE *fp;
+ struct statfs sfs;
+ int tmpfd;
+ bool supported = false;
+ bool zfs = false;
+
+ if (statfs("/boot", &sfs) != 0)
+ err(1, "statfs /boot");
+ if (strcmp(sfs.f_fstypename, "ufs") == 0) {
+ /*
+ * Only UFS supports the full nextboot protocol.
+ */
+ supported = true;
+ } else if (strcmp(sfs.f_fstypename, "zfs") == 0) {
+ zfs = true;
+ }
+
+ if (zfs) {
+ char *slash;
+
+ slash = strchr(sfs.f_mntfromname, '/');
+ if (slash != NULL)
+ *slash = '\0';
+ zfsbootcfg(sfs.f_mntfromname, force);
+ }
+
+ if (strlcpy(tmp, fn, sizeof(tmp)) >= sizeof(tmp))
+ E("Path too long %s", fn);
+ if (strlcat(tmp, ".XXXXXX", sizeof(tmp)) >= sizeof(tmp))
+ E("Path too long %s", fn);
+ tmpfd = mkstemp(tmp);
+ if (tmpfd == -1)
+ E("mkstemp %s", tmp);
+
+ fp = fdopen(tmpfd, "w");
+ if (fp == NULL)
+ E("fdopen %s", tmp);
+
+ if (fprintf(fp, "%s%s",
+ supported ? "nextboot_enable=\"YES\"\n" : "",
+ env != NULL ? env : "") < 0) {
+ int e;
+
+ e = errno;
+ if (unlink(tmp))
+ warn("unlink %s", tmp);
+ errno = e;
+ E("Can't write %s", tmp);
+ }
+ if (fsync(fileno(fp)) != 0)
+ E("Can't fsync %s", fn);
+ if (rename(tmp, fn) != 0) {
+ int e;
+
+ e = errno;
+ if (unlink(tmp))
+ warn("unlink %s", tmp);
+ errno = e;
+ E("Can't rename %s to %s", tmp, fn);
+ }
+ fclose(fp);
+}
+
+static char *
+split_kv(char *raw)
+{
+ char *eq;
+ int len;
-static int dohalt;
+ eq = strchr(raw, '=');
+ if (eq == NULL)
+ errx(1, "No = in environment string %s", raw);
+ *eq++ = '\0';
+ len = strlen(eq);
+ if (len == 0)
+ errx(1, "Invalid null value %s=", raw);
+ if (eq[0] == '"') {
+ if (len < 2 || eq[len - 1] != '"')
+ errx(1, "Invalid string '%s'", eq);
+ eq[len - 1] = '\0';
+ return (eq + 1);
+ }
+ return (eq);
+}
+
+static void
+add_env(char **env, const char *key, const char *value)
+{
+ char *oldenv;
+
+ oldenv = *env;
+ asprintf(env, "%s%s=\"%s\"\n", oldenv != NULL ? oldenv : "", key, value);
+ if (env == NULL)
+ errx(1, "No memory to build env array");
+ free(oldenv);
+}
+
+/*
+ * Different options are valid for different programs.
+ */
+#define GETOPT_REBOOT "cDde:fk:lNno:pqr"
+#define GETOPT_NEXTBOOT "De:fk:o:"
int
main(int argc, char *argv[])
{
struct utmpx utx;
const struct passwd *pw;
- int ch, howto, i, fd, lflag, nflag, qflag, sverrno, Nflag;
- u_int pageins;
- const char *user, *kernel = NULL;
+ struct stat st;
+ int ch, howto = 0, i, sverrno;
+ bool Dflag, fflag, lflag, Nflag, nflag, qflag;
+ uint64_t pageins;
+ const char *user, *kernel = NULL, *getopts = GETOPT_REBOOT;
+ char *env = NULL, *v;
if (strstr(getprogname(), "halt") != NULL) {
- dohalt = 1;
+ dohalt = true;
howto = RB_HALT;
- } else
+ } else if (strcmp(getprogname(), "nextboot") == 0) {
+ donextboot = true;
+ getopts = GETOPT_NEXTBOOT; /* Note: reboot's extra opts return '?' */
+ } else {
+ /* reboot */
howto = 0;
- lflag = nflag = qflag = Nflag = 0;
- while ((ch = getopt(argc, argv, "cdk:lNnpqr")) != -1)
+ }
+ Dflag = fflag = lflag = Nflag = nflag = qflag = false;
+ while ((ch = getopt(argc, argv, getopts)) != -1) {
switch(ch) {
case 'c':
howto |= RB_POWERCYCLE;
break;
+ case 'D':
+ Dflag = true;
+ break;
case 'd':
howto |= RB_DUMP;
break;
+ case 'e':
+ v = split_kv(optarg);
+ add_env(&env, optarg, v);
+ break;
+ case 'f':
+ fflag = true;
+ break;
case 'k':
kernel = optarg;
break;
case 'l':
- lflag = 1;
+ lflag = true;
break;
case 'n':
- nflag = 1;
+ nflag = true;
howto |= RB_NOSYNC;
break;
case 'N':
- nflag = 1;
- Nflag = 1;
+ nflag = true;
+ Nflag = true;
+ break;
+ case 'o':
+ add_env(&env, "kernel_options", optarg);
break;
case 'p':
howto |= RB_POWEROFF;
break;
case 'q':
- qflag = 1;
+ qflag = true;
break;
case 'r':
howto |= RB_REROOT;
@@ -116,11 +289,20 @@ main(int argc, char *argv[])
default:
usage();
}
+ }
+
argc -= optind;
argv += optind;
if (argc != 0)
usage();
+ if (!donextboot && !fflag && stat(_PATH_NOSHUTDOWN, &st) == 0) {
+ errx(1, "Reboot cannot be done, " _PATH_NOSHUTDOWN
+ " is present");
+ }
+
+ if (Dflag && ((howto & ~RB_HALT) != 0 || kernel != NULL))
+ errx(1, "cannot delete existing nextboot config and do anything else");
if ((howto & (RB_DUMP | RB_HALT)) == (RB_DUMP | RB_HALT))
errx(1, "cannot dump (-d) when halting; must reboot instead");
if (Nflag && (howto & RB_NOSYNC) != 0)
@@ -129,7 +311,31 @@ main(int argc, char *argv[])
errx(1, "-c and -p cannot be used together");
if ((howto & RB_REROOT) != 0 && howto != RB_REROOT)
errx(1, "-r cannot be used with -c, -d, -n, or -p");
- if (geteuid()) {
+ if ((howto & RB_REROOT) != 0 && kernel != NULL)
+ errx(1, "-r and -k cannot be used together, there is no next kernel");
+
+ if (Dflag) {
+ struct stat sb;
+
+ /*
+ * Break the rule about stat then doing
+ * something. When we're booting, there's no
+ * race. When we're a read-only root, though, the
+ * read-only error takes priority over the file not
+ * there error in unlink. So stat it first and exit
+ * with success if it isn't there. Otherwise, let
+ * unlink sort error reporting. POSIX-1.2024 suggests
+ * ENOENT should be preferred to EROFS for unlink,
+ * but FreeBSD historically has preferred EROFS.
+ */
+ if (stat(PATH_NEXTBOOT, &sb) != 0 && errno == ENOENT)
+ exit(0);
+ if (unlink(PATH_NEXTBOOT) != 0)
+ warn("unlink " PATH_NEXTBOOT);
+ exit(0);
+ }
+
+ if (!donextboot && geteuid() != 0) {
errno = EPERM;
err(1, NULL);
}
@@ -140,17 +346,27 @@ main(int argc, char *argv[])
}
if (kernel != NULL) {
- fd = open("/boot/nextboot.conf", O_WRONLY | O_CREAT | O_TRUNC,
- 0444);
- if (fd > -1) {
- (void)write(fd, "nextboot_enable=\"YES\"\n", 22);
- (void)write(fd, "kernel=\"", 8L);
- (void)write(fd, kernel, strlen(kernel));
- (void)write(fd, "\"\n", 2);
- close(fd);
+ if (!fflag) {
+ char *k;
+ struct stat sb;
+
+ asprintf(&k, "/boot/%s/kernel", kernel);
+ if (k == NULL)
+ errx(1, "No memory to check %s", kernel);
+ if (stat(k, &sb) != 0)
+ err(1, "stat %s", k);
+ if (!S_ISREG(sb.st_mode))
+ errx(1, "%s is not a file", k);
+ free(k);
}
+ add_env(&env, "kernel", kernel);
}
+ if (env != NULL)
+ write_nextboot(PATH_NEXTBOOT, env, fflag);
+ if (donextboot)
+ exit (0);
+
/* Log the reboot. */
if (!lflag) {
if ((user = getlogin()) == NULL)
@@ -274,17 +490,17 @@ usage(void)
exit(1);
}
-static u_int
+static uint64_t
get_pageins(void)
{
- u_int pageins;
+ uint64_t pageins;
size_t len;
len = sizeof(pageins);
if (sysctlbyname("vm.stats.vm.v_swappgsin", &pageins, &len, NULL, 0)
!= 0) {
- warnx("v_swappgsin");
+ warn("v_swappgsin");
return (0);
}
- return pageins;
+ return (pageins);
}
diff --git a/sbin/recoverdisk/Makefile b/sbin/recoverdisk/Makefile
index 2094ad29d54b..41bc736ecc6e 100644
--- a/sbin/recoverdisk/Makefile
+++ b/sbin/recoverdisk/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=runtime
PROG= recoverdisk
diff --git a/sbin/recoverdisk/Makefile.depend b/sbin/recoverdisk/Makefile.depend
index 6cfaab1c3644..9add648af17b 100644
--- a/sbin/recoverdisk/Makefile.depend
+++ b/sbin/recoverdisk/Makefile.depend
@@ -1,13 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/msun \
.include <dirdeps.mk>
diff --git a/sbin/recoverdisk/recoverdisk.1 b/sbin/recoverdisk/recoverdisk.1
index 4b838332ec19..76085f3ceb41 100644
--- a/sbin/recoverdisk/recoverdisk.1
+++ b/sbin/recoverdisk/recoverdisk.1
@@ -22,17 +22,16 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
.Dd April 3, 2020
.Dt RECOVERDISK 1
.Os
.Sh NAME
.Nm recoverdisk
-.Nd recover data from hard disk or optical media
+.Nd recover data from disk-like devices.
.Sh SYNOPSIS
.Nm
.Op Fl b Ar bigsize
+.Op Fl i Ar interval
.Op Fl r Ar readlist
.Op Fl s Ar interval
.Op Fl u Ar pattern
@@ -43,79 +42,109 @@
.Sh DESCRIPTION
The
.Nm
-utility reads data from the
+utility reads all data from the
.Ar source
-file until all blocks could be successfully read.
+and retries read operations until they succeed.
If
.Ar destination
-was specified all data is being written to that file.
-It starts reading in multiples of the sector size.
-Whenever a block fails, it is put to the end of the working queue and will be
-read again, possibly with a smaller read size.
+is specified all data read be written there.
+.Pp
+The internal work-list can be saved and loaded so that
+.Nm
+sessions can be resumed, for instance when a marginal
+source hard-disk shuts down.
.Pp
-By default it uses block sizes of roughly 1 MB, 32kB, and the native
-sector size (usually 512 bytes).
-These figures are adjusted slightly, for devices whose sectorsize is not a
-power of 2, e.g., audio CDs with a sector size of 2352 bytes.
+The work-list is initialized with a single item which covers the entire
+.Ar source
+and
+.Nm
+always chips away at the first item on the work-list.
+
+When a read succeeds, that part of the current chunk is eliminated
+from the work-list.
+
+When a read fails, that part of the item is appended to the worklist
+as a separate item, and will be retried in due order.
+If
+.Ar destination
+is specified, the corresponding range is filled with '_UNREAD_'.
+.Pp
+The first pass attempts to read everything in "big-size" chunks,
+the second pass reads in "medium-size" chunks and third and subsequent
+passes read in "small-size" chunks.
+This three stage process is an attempt to optimize the case where only
+a few bad blocks exist on
+.Ar source .
+If too many read-errors are encountered,
+.Nm
+will fall back to smaller sizes sooner.
+.Pp
+The three sizes default to 128kB (or less if the sector size does
+not divide 128kB cleanly, for instance audio CD media), and the
+reported
+.Dv DIOCGSTRIPESIZE
+and
+.Dv DIOCGSECTORSIZE
+respectively.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl b Ar bigsize
-The size of reads attempted first.
-The middle pass is roughly the logarithmic average of the bigsize and
-the sectorsize.
-.It Fl r Ar readlist
-Read the list of blocks and block sizes to read from the specified file.
-.It Fl s Ar interval
-How often we should update the writelist file while things go OK.
-The default is 60 and the unit is "progress messages" so if things
-go well, this is the same as once per minute.
+The size of reads attempted in first pass.
+.It Fl m Ar mediumsize
+The size of reads attempted in second pass.
+.It Fl s Ar smallsize
+The size of reads attempted in third and subsequent passes.
+.It Fl r Ar work-list-file
+Read the work-list from a file.
+.It Fl w Ar work-list-file
+Write the work-list to a file when a read succeed, but at most once
+every minute.
+.It Fl l Ar log-file
+Each successful read is logged with timestamp, offset and length.
+.It Fl t Ar totalsize
+How many bytes should be recovered.
+The default is what
+.Dv DIOCGMEDIASIZE
+reports for character and block devices or
+.Dv st_size
+if
+.Ar source
+is a regular file.
+.It Fl i Ar pause
+.Xr sleep 3
+this long between reads. This reduces the load on the
+.Ar source
+device and the system in general.
+.It Fl p Ar pause
+.Xr sleep 3
+this long whenever a read fails.
+This makes the
+.Ar source
+device look less sick to the operating system.
.It Fl u Ar pattern
-By default blocks which encounter read errors will be filled with
-the pattern
+By default blocks which cannot be read are filled with the pattern
.Ql _UNREAD_
in the output file.
-This option can be
-used to specify another pattern.
-Nothing gets written if the string is empty.
+This option can be used to specify a different pattern.
+If the pattern is the empty string, nothing is written.
.It Fl v
-Enables nicer status report using ANSI escapes and UTF-8.
-.It Fl w Ar writelist
-Write the list of remaining blocks to read to the specified file if
-.Nm
-is aborted via
-.Dv SIGINT .
+Produce a detailed progress report with ANSI escapes and UTF-8.
.El
.Pp
-The
-.Fl r
-and
-.Fl w
-options can be specified together.
-Especially, they can point to the same file, which will be updated on abort.
-.Sh OUTPUT
-The
.Nm
-utility
-prints several columns, detailing the progress
-.Bl -tag -width remaining
-.It Va start
-Starting offset of the current block.
-.It Va size
-Read size of the current block.
-.It Va len
-Length of the current block.
-.It Va state
-Is increased for every failed read.
-.It Va done
-Number of bytes already read.
-.It Va remaining
-Number of bytes remaining.
-.It Va "% done"
-Percent complete.
-.El
+can be aborted with
+.Dv SIGINT ,
+but with a sick
+.Ar source
+it may take up to several minutes before the current read operation
+returns from the kernel.
+.Pp
.Sh EXAMPLES
.Bd -literal
+# check if all sectors can be read on a USB stick:
+recoverdisk /dev/da0
+
# recover data from failing hard drive ada3
recoverdisk /dev/ada3 /data/disk.img
@@ -131,10 +160,72 @@ recoverdisk -r worklist -w worklist /dev/cd0 /data/cd.iso
# recover a single file from the unreadable media
recoverdisk /cdrom/file.avi file.avi
-# If the disk hangs the system on read-errors try:
-recoverdisk -b 0 /dev/ada3 /somewhere
-
.Ed
+.Sh PRACTICAL ADVICE
+In Datamuseum.dk
+.Nm
+has been used to recover all sorts of data-media for two decades,
+here are some things we have learned:
+.Bl -bullet
+.It
+Interacting with failing hardware has a tendency to crash machines,
+so it is always a good idea to use the
+.Fl -w work-list-file
+so that it is possible to continue.
+.It
+When attempting to recover hard to read data from failing hard disks,
+it pays to pamper the drive as much as possible:
+.It
+It is generally best to keep the drive in it's usual physical orientation,
+but it can also help to try other orientations.
+.It
+Insulate the drive from external vibrations.
+.It
+Keep the drive cool with a fan.
+.It
+If possible, power the drive from a laboratory power supply.
+.It
+Do not lose patience: Let
+.Nm
+run as long as possible.
+.It
+(S)ATA controllers do not handle failing disks well, if this
+is a problem, use a USB-(S)ATA adapter instead.
+.It
+The
+.Nm
+source code is deliberately written to be easily portable to
+older versions of
+.Fx
+and to other operating systems.
+.It
+If you need to read ST-506, RLL or ESDI drives
+.Fx 3.5.1
+is a good compromise.
+.It
+Sometimes forcing the disk to step between reads helps.
+Since
+.Nm
+process the work-list in the order it is read, this
+can be accomplished by sorting the work-list with
+something like:
+.Dl % sort +0.5
+.It
+By default the
+.Xr CAM
+layer will retry failing read operations, but that
+will get stuck on the bad sectors for long time
+and delay recovering what actually can be read from
+a rapidly failing drive.
+In that situation, set the appropriate
+.Dl kern.cam.*.retry_count
+sysctl to zero.
+.It
+For floppies and un-zoned hard disks (ST-506 to
+early IDE) set
+.Fl b Ar bigsize
+to the size of a track.
+.El
.Sh SEE ALSO
.Xr dd 1 ,
.Xr ada 4 ,
@@ -145,7 +236,8 @@ recoverdisk -b 0 /dev/ada3 /somewhere
The
.Nm
utility first appeared in
-.Fx 7.0 .
+.Fx 7.0
+because Somebodyâ„¢ forgot to make a backup copy.
.Sh AUTHORS
.An -nosplit
The original implementation was done by
@@ -153,34 +245,29 @@ The original implementation was done by
with minor improvements from
.An Ulrich Sp\(:orlein Aq Mt uqs@FreeBSD.org .
.Pp
-This manual page was written by
+This manual page was originally written by
.An Ulrich Sp\(:orlein .
.Sh BUGS
-Reading from media where the sectorsize is not a power of 2 will make all
-1 MB reads fail.
-This is due to the DMA reads being split up into blocks of at most 128kB.
-These reads then fail if the sectorsize is not a divisor of 128kB.
-When reading a full raw audio CD, this leads to roughly 700 error messages
-flying by.
-This is harmless and can be avoided by setting
-.Fl b
-to no more than 128kB.
+If a failing device causes the machine to crash, there is
+a risk that a chunk might have been successfully read
+and removed from the work-list, but not yet flushed to
+the
+.Ar destination .
.Pp
.Nm
-needs to know about read errors as fast as possible, i.e., retries by lower
-layers will usually slow down the operation.
-When using
-.Xr cam 4
-attached drives, you may want to set kern.cam.XX.retry_count to zero, e.g.:
-.Bd -literal
-# sysctl kern.cam.ada.retry_count=0
-# sysctl kern.cam.cd.retry_count=0
-# sysctl kern.cam.da.retry_count=0
-.Ed
-.\".Pp
-.\"When reading from optical media, a bug in the GEOM framework will
-.\"prevent it from seeing that the media has been removed.
-.\"The device can still be opened, but all reads will fail.
-.\"This is usually harmless, but will send
-.\".Nm
-.\"into an infinite loop.
+calls
+.Xr fdatasync 3
+on the destination before writing the work-list to a
+temporary file, and calls it again on the temporary
+file before renaming it to the specified
+.Fl w Ar work-file-list
+filename.
+But even then things dont always work out.
+.Pp
+.Nm
+should have an option for reconstructing the work-list
+from the
+.Ar destination
+by enumerating the
+.Fl u Ar pattern
+filled ranges.
diff --git a/sbin/recoverdisk/recoverdisk.c b/sbin/recoverdisk/recoverdisk.c
index 35d7adc7a5c3..5971f78738ac 100644
--- a/sbin/recoverdisk/recoverdisk.c
+++ b/sbin/recoverdisk/recoverdisk.c
@@ -7,9 +7,8 @@
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
- *
- * $FreeBSD$
*/
+
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/disk.h>
@@ -29,18 +28,15 @@
#include <time.h>
#include <unistd.h>
-/* Safe printf into a fixed-size buffer */
-#define bprintf(buf, fmt, ...) \
- do { \
- int ibprintf; \
- ibprintf = snprintf(buf, sizeof buf, fmt, __VA_ARGS__); \
- assert(ibprintf >= 0 && ibprintf < (int)sizeof buf); \
- } while (0)
+/*
+ * This is a compromise between speed and wasted effort
+ */
+#define COMPROMISE_SIZE (128<<10)
struct lump {
- off_t start;
- off_t len;
- int state;
+ uint64_t start;
+ uint64_t len;
+ unsigned pass;
TAILQ_ENTRY(lump) list;
};
@@ -48,25 +44,34 @@ struct period {
time_t t0;
time_t t1;
char str[20];
- off_t bytes_read;
+ uint64_t bytes_read;
TAILQ_ENTRY(period) list;
};
TAILQ_HEAD(period_head, period);
static volatile sig_atomic_t aborting = 0;
static int verbose = 0;
-static size_t bigsize = 1024 * 1024;
-static size_t medsize;
-static size_t minsize = 512;
-static off_t tot_size;
-static off_t done_size;
+static uint64_t big_read;
+static uint64_t medium_read;
+static uint64_t small_read;
+static uint64_t total_size;
+static uint64_t done_size;
+static uint64_t wasted_size;
static char *input;
-static char *wworklist = NULL;
-static char *rworklist = NULL;
+static char *write_worklist_file = NULL;
+static char *read_worklist_file = NULL;
static const char *unreadable_pattern = "_UNREAD_";
-static const int write_errors_are_fatal = 1;
-static int fdr, fdw;
-
+static int write_errors_are_fatal = 1;
+static int read_fd, write_fd;
+static FILE *log_file = NULL;
+static char *work_buf;
+static char *pattern_buf;
+static double error_pause;
+static double interval;
+
+static unsigned nlumps;
+static double n_reads, n_good_reads;
+static time_t t_first;
static TAILQ_HEAD(, lump) lumps = TAILQ_HEAD_INITIALIZER(lumps);
static struct period_head minute = TAILQ_HEAD_INITIALIZER(minute);
static struct period_head quarter = TAILQ_HEAD_INITIALIZER(quarter);
@@ -76,7 +81,8 @@ static struct period_head day = TAILQ_HEAD_INITIALIZER(quarter);
/**********************************************************************/
static void
-report_good_read2(time_t now, size_t bytes, struct period_head *ph, time_t dt)
+account_good_read_period(time_t now, uint64_t bytes,
+ struct period_head *ph, time_t dt)
{
struct period *pp;
const char *fmt;
@@ -84,7 +90,7 @@ report_good_read2(time_t now, size_t bytes, struct period_head *ph, time_t dt)
pp = TAILQ_FIRST(ph);
if (pp == NULL || pp->t1 < now) {
- pp = calloc(sizeof *pp, 1L);
+ pp = calloc(1UL, sizeof(*pp));
assert(pp != NULL);
pp->t0 = (now / dt) * dt;
pp->t1 = (now / dt + 1) * dt;
@@ -100,13 +106,13 @@ report_good_read2(time_t now, size_t bytes, struct period_head *ph, time_t dt)
}
static void
-report_good_read(time_t now, size_t bytes)
+account_good_read(time_t now, uint64_t bytes)
{
- report_good_read2(now, bytes, &minute, 60L);
- report_good_read2(now, bytes, &quarter, 900L);
- report_good_read2(now, bytes, &hour, 3600L);
- report_good_read2(now, bytes, &day, 86400L);
+ account_good_read_period(now, bytes, &minute, 60L);
+ account_good_read_period(now, bytes, &quarter, 900L);
+ account_good_read_period(now, bytes, &hour, 3600L);
+ account_good_read_period(now, bytes, &day, 86400L);
}
static void
@@ -116,20 +122,18 @@ report_one_period(const char *period, struct period_head *ph)
int n;
n = 0;
- printf("%s \xe2\x94\x82", period);
+ printf("%s ", period);
TAILQ_FOREACH(pp, ph, list) {
- if (n == 3) {
+ if (++n == 4) {
TAILQ_REMOVE(ph, pp, list);
free(pp);
break;
}
- if (n++)
- printf(" \xe2\x94\x82");
- printf(" %s %14jd", pp->str, pp->bytes_read);
+ printf("\xe2\x94\x82 %s %14ju ",
+ pp->str, (uintmax_t)pp->bytes_read);
}
for (; n < 3; n++) {
- printf(" \xe2\x94\x82");
- printf(" %5s %14s", "", "");
+ printf("\xe2\x94\x82 %5s %14s ", "", "");
}
printf("\x1b[K\n");
}
@@ -148,27 +152,23 @@ report_periods(void)
static void
set_verbose(void)
{
- struct winsize wsz;
- if (!isatty(STDIN_FILENO) || ioctl(STDIN_FILENO, TIOCGWINSZ, &wsz))
- return;
verbose = 1;
}
static void
-report_header(int eol)
+report_header(const char *term)
{
- printf("%13s %7s %13s %5s %13s %13s %9s",
+ printf("%13s %7s %13s %5s %13s %13s %9s%s",
"start",
"size",
"block-len",
"pass",
"done",
"remaining",
- "% done");
- if (eol)
- printf("\x1b[K");
- putchar('\n');
+ "% done",
+ term
+ );
}
#define REPORTWID 79
@@ -188,20 +188,20 @@ report_hline(const char *how)
printf("\x1b[K\n");
}
-static off_t hist[REPORTWID];
-static off_t last_done = -1;
+static uint64_t hist[REPORTWID];
+static uint64_t prev_done = ~0UL;
static void
-report_histogram(const struct lump *lp)
+report_histogram(uint64_t start)
{
- off_t j, bucket, fp, fe, k, now;
+ uint64_t j, bucket, fp, fe, k, now;
double a;
struct lump *lp2;
- bucket = tot_size / REPORTWID;
- if (tot_size > bucket * REPORTWID)
+ bucket = total_size / REPORTWID;
+ if (total_size > bucket * REPORTWID)
bucket += 1;
- if (done_size != last_done) {
+ if (done_size != prev_done) {
memset(hist, 0, sizeof hist);
TAILQ_FOREACH(lp2, &lumps, list) {
fp = lp2->start;
@@ -215,9 +215,9 @@ report_histogram(const struct lump *lp)
fp += k;
}
}
- last_done = done_size;
+ prev_done = done_size;
}
- now = lp->start / bucket;
+ now = start / bucket;
for (j = 0; j < REPORTWID; j++) {
a = round(8 * (double)hist[j] / bucket);
assert (a >= 0 && a < 9);
@@ -230,7 +230,7 @@ report_histogram(const struct lump *lp)
} else {
putchar(0xe2);
putchar(0x96);
- putchar(0x80 + (int)a);
+ putchar(0x80 + (char)a);
}
if (j == now)
printf("\x1b[0m");
@@ -239,34 +239,40 @@ report_histogram(const struct lump *lp)
}
static void
-report(const struct lump *lp, size_t sz)
+report(uint64_t sz)
{
struct winsize wsz;
+ const struct lump *lp = TAILQ_FIRST(&lumps);
int j;
-
- assert(lp != NULL);
+ unsigned pass = 0;
+ uintmax_t start = 0, length = 0;
+ time_t t_now = time(NULL);
+
+ if (lp != NULL) {
+ pass = lp->pass;
+ start = lp->start;
+ length = lp->len;
+ }
if (verbose) {
printf("\x1b[H%s\x1b[K\n", input);
- report_header(1);
- } else {
- putchar('\r');
+ report_header("\x1b[K\n");
}
- printf("%13jd %7zu %13jd %5d %13jd %13jd %9.4f",
- (intmax_t)lp->start,
- sz,
- (intmax_t)lp->len,
- lp->state,
- (intmax_t)done_size,
- (intmax_t)(tot_size - done_size),
- 100*(double)done_size/(double)tot_size
+ printf("%13ju %7ju %13ju %5u %13ju %13ju %9.4f",
+ start,
+ (uintmax_t)sz,
+ length,
+ pass,
+ (uintmax_t)done_size,
+ (uintmax_t)(total_size - done_size),
+ 100*(double)done_size/(double)total_size
);
if (verbose) {
printf("\x1b[K\n");
report_hline(NULL);
- report_histogram(lp);
+ report_histogram(start);
if (TAILQ_EMPTY(&minute)) {
report_hline(NULL);
} else {
@@ -274,27 +280,36 @@ report(const struct lump *lp, size_t sz)
report_periods();
report_hline("\xe2\x94\xb4");
}
+ printf("Missing: %u", nlumps);
+ printf(" Success: %.0f/%.0f =", n_good_reads, n_reads);
+ printf(" %.4f%%", 100 * n_good_reads / n_reads);
+ printf(" Duration: %.3fs", (t_now - t_first) / n_reads);
+ printf("\x1b[K\n");
+ report_hline(NULL);
j = ioctl(STDIN_FILENO, TIOCGWINSZ, &wsz);
if (!j)
printf("\x1b[%d;1H", wsz.ws_row);
+ } else {
+ printf("\n");
}
- fflush(stdout);
}
/**********************************************************************/
static void
-new_lump(off_t start, off_t len, int state)
+new_lump(uint64_t start, uint64_t len, unsigned pass)
{
struct lump *lp;
+ assert(len > 0);
lp = malloc(sizeof *lp);
if (lp == NULL)
err(1, "Malloc failed");
lp->start = start;
lp->len = len;
- lp->state = state;
+ lp->pass = pass;
TAILQ_INSERT_TAIL(&lumps, lp, list);
+ nlumps += 1;
}
/**********************************************************************
@@ -308,98 +323,100 @@ save_worklist(void)
struct lump *llp;
char buf[PATH_MAX];
- if (fdw >= 0 && fdatasync(fdw))
+ if (write_fd >= 0 && fdatasync(write_fd))
err(1, "Write error, probably disk full");
- if (wworklist != NULL) {
- bprintf(buf, "%s.tmp", wworklist);
- (void)fprintf(stderr, "\nSaving worklist ...");
- (void)fflush(stderr);
+ if (write_worklist_file != NULL) {
+ snprintf(buf, sizeof(buf), "%s.tmp", write_worklist_file);
+ fprintf(stderr, "\nSaving worklist ...");
file = fopen(buf, "w");
if (file == NULL)
err(1, "Error opening file %s", buf);
- TAILQ_FOREACH(llp, &lumps, list)
- fprintf(file, "%jd %jd %d\n",
- (intmax_t)llp->start, (intmax_t)llp->len,
- llp->state);
- (void)fflush(file);
+ TAILQ_FOREACH(llp, &lumps, list) {
+ assert (llp->len > 0);
+ fprintf(file, "%ju %ju %u\n",
+ (uintmax_t)llp->start,
+ (uintmax_t)llp->len,
+ llp->pass);
+ }
+ fflush(file);
if (ferror(file) || fdatasync(fileno(file)) || fclose(file))
err(1, "Error writing file %s", buf);
- if (rename(buf, wworklist))
- err(1, "Error renaming %s to %s", buf, wworklist);
- (void)fprintf(stderr, " done.\n");
+ if (rename(buf, write_worklist_file))
+ err(1, "Error renaming %s to %s",
+ buf, write_worklist_file);
+ fprintf(stderr, " done.\n");
}
}
/* Read the worklist if -r was given */
-static off_t
-read_worklist(off_t t)
+static uint64_t
+read_worklist(void)
{
- off_t s, l, d;
- int state, lines;
+ uintmax_t start, length;
+ uint64_t missing = 0;
+ unsigned pass, lines;
FILE *file;
- (void)fprintf(stderr, "Reading worklist ...");
- (void)fflush(stderr);
- file = fopen(rworklist, "r");
+ fprintf(stderr, "Reading worklist ...");
+ file = fopen(read_worklist_file, "r");
if (file == NULL)
- err(1, "Error opening file %s", rworklist);
+ err(1, "Error opening file %s", read_worklist_file);
lines = 0;
- d = t;
for (;;) {
++lines;
- if (3 != fscanf(file, "%jd %jd %d\n", &s, &l, &state)) {
+ if (3 != fscanf(file, "%ju %ju %u\n", &start, &length, &pass)) {
if (!feof(file))
- err(1, "Error parsing file %s at line %d",
- rworklist, lines);
+ err(1, "Error parsing file %s at line %u",
+ read_worklist_file, lines);
else
break;
}
- new_lump(s, l, state);
- d -= l;
+ if (length > 0) {
+ new_lump(start, length, pass);
+ missing += length;
+ }
}
if (fclose(file))
- err(1, "Error closing file %s", rworklist);
- (void)fprintf(stderr, " done.\n");
+ err(1, "Error closing file %s", read_worklist_file);
+ fprintf(stderr, " done.\n");
/*
- * Return the number of bytes already read
- * (at least not in worklist).
+ * Return the number of bytes outstanding
*/
- return (d);
+ return (missing);
}
/**********************************************************************/
static void
-write_buf(int fd, const void *buf, ssize_t len, off_t where)
+write_buf(int fd, const void *buf, uint64_t length, uint64_t where)
{
- ssize_t i;
+ int64_t i;
- i = pwrite(fd, buf, len, where);
- if (i == len)
+ i = pwrite(fd, buf, length, (off_t)where);
+ if (i > 0 && (uint64_t)i == length)
return;
- printf("\nWrite error at %jd/%zu\n\t%s\n",
- where, i, strerror(errno));
+ printf("\nWrite error at %ju/%ju: %jd (%s)\n",
+ (uintmax_t)where,
+ (uintmax_t)length,
+ (intmax_t)i, strerror(errno));
save_worklist();
if (write_errors_are_fatal)
exit(3);
}
static void
-fill_buf(char *buf, ssize_t len, const char *pattern)
+fill_buf(char *buf, int64_t len, const char *pattern)
{
- ssize_t sz = strlen(pattern);
- ssize_t i, j;
+ int64_t sz = strlen(pattern);
+ int64_t i;
for (i = 0; i < len; i += sz) {
- j = len - i;
- if (j > sz)
- j = sz;
- memcpy(buf + i, pattern, j);
+ memcpy(buf + i, pattern, MIN(len - i, sz));
}
}
@@ -408,45 +425,356 @@ fill_buf(char *buf, ssize_t len, const char *pattern)
static void
usage(void)
{
- (void)fprintf(stderr, "usage: recoverdisk [-b bigsize] [-r readlist] "
+ fprintf(stderr, "usage: recoverdisk "
+ "[-b big_read] [-i interval ] [-r readlist] "
"[-s interval] [-w writelist] source [destination]\n");
/* XXX update */
exit(1);
}
static void
-sighandler(__unused int sig)
+sighandler(int sig)
{
+ (void)sig;
aborting = 1;
}
+/**********************************************************************/
+
+static int64_t
+attempt_one_lump(time_t t_now)
+{
+ struct lump *lp;
+ uint64_t sz;
+ int64_t retval;
+ int error;
+
+ lp = TAILQ_FIRST(&lumps);
+ if (lp == NULL)
+ return(0);
+
+ if (lp->pass == 0) {
+ sz = MIN(lp->len, big_read);
+ } else if (lp->pass == 1) {
+ sz = MIN(lp->len, medium_read);
+ } else {
+ sz = MIN(lp->len, small_read);
+ }
+
+ assert(sz != 0);
+
+ n_reads += 1;
+ retval = pread(read_fd, work_buf, sz, lp->start);
+
+#if 0 /* enable this when testing */
+ if (!(random() & 0xf)) {
+ retval = -1;
+ errno = EIO;
+ usleep(20000);
+ } else {
+ usleep(2000);
+ }
+#endif
+
+ error = errno;
+ if (retval > 0) {
+ n_good_reads += 1;
+ sz = retval;
+ done_size += sz;
+ if (write_fd >= 0) {
+ write_buf(write_fd, work_buf, sz, lp->start);
+ }
+ if (log_file != NULL) {
+ fprintf(log_file, "%jd %ju %ju\n",
+ (intmax_t)t_now,
+ (uintmax_t)lp->start,
+ (uintmax_t)sz
+ );
+ fflush(log_file);
+ }
+ } else {
+ wasted_size += sz;
+ printf("%14ju %7ju read error %d: (%s)",
+ (uintmax_t)lp->start,
+ (uintmax_t)sz, error, strerror(error));
+ if (error_pause > 1) {
+ printf(" (Pausing %g s)", error_pause);
+ }
+ printf("\n");
+
+ if (write_fd >= 0 && pattern_buf != NULL) {
+ write_buf(write_fd, pattern_buf, sz, lp->start);
+ }
+ new_lump(lp->start, sz, lp->pass + 1);
+ retval = -sz;
+ }
+ lp->start += sz;
+ lp->len -= sz;
+ if (lp->len == 0) {
+ TAILQ_REMOVE(&lumps, lp, list);
+ nlumps -= 1;
+ free(lp);
+ }
+ errno = error;
+ return (retval);
+}
+
+
+/**********************************************************************/
+
+static void
+determine_total_size(void)
+{
+ struct stat sb;
+ int error;
+
+ if (total_size != 0)
+ return;
+
+ error = fstat(read_fd, &sb);
+ if (error < 0)
+ err(1, "fstat failed");
+
+ if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
+#ifdef DIOCGMEDIASIZE
+ off_t mediasize;
+ error = ioctl(read_fd, DIOCGMEDIASIZE, &mediasize);
+ if (error == 0 && mediasize > 0) {
+ total_size = mediasize;
+ printf("# Got total_size from DIOCGMEDIASIZE: %ju\n",
+ (uintmax_t)total_size);
+ return;
+ }
+#endif
+ } else if (S_ISREG(sb.st_mode) && sb.st_size > 0) {
+ total_size = sb.st_size;
+ printf("# Got total_size from stat(2): %ju\n",
+ (uintmax_t)total_size);
+ return;
+ } else {
+ errx(1, "Input must be device or regular file");
+ }
+ fprintf(stderr, "Specify total size with -t option\n");
+ exit(1);
+}
+
+static void
+determine_read_sizes(void)
+{
+ int error;
+ u_int sectorsize;
+ off_t stripesize;
+
+#ifdef DIOCGSECTORSIZE
+ if (small_read == 0) {
+ error = ioctl(read_fd, DIOCGSECTORSIZE, &sectorsize);
+ if (error >= 0 && sectorsize > 0) {
+ small_read = sectorsize;
+ printf("# Got small_read from DIOCGSECTORSIZE: %ju\n",
+ (uintmax_t)small_read
+ );
+ }
+ }
+#endif
+
+ if (small_read == 0) {
+ small_read = 512;
+ printf("# Defaulting small_read to %ju\n", (uintmax_t)small_read);
+ }
+
+ if (medium_read && (medium_read % small_read)) {
+ errx(1,
+ "medium_read (%ju) is not a multiple of small_read (%ju)\n",
+ (uintmax_t)medium_read, (uintmax_t)small_read
+ );
+ }
+
+ if (big_read != 0 && (big_read % small_read)) {
+ errx(1,
+ "big_read (%ju) is not a multiple of small_read (%ju)\n",
+ (uintmax_t)big_read, (uintmax_t)small_read
+ );
+ }
+
+#ifdef DIOCGSTRIPESIZE
+ if (medium_read == 0) {
+ error = ioctl(read_fd, DIOCGSTRIPESIZE, &stripesize);
+ if (error < 0 || stripesize <= 0) {
+ // nope
+ } else if ((uint64_t)stripesize < small_read) {
+ // nope
+ } else if (stripesize % small_read) {
+ // nope
+ } else if (stripesize <= COMPROMISE_SIZE) {
+ medium_read = stripesize;
+ printf("# Got medium_read from DIOCGSTRIPESIZE: %ju\n",
+ (uintmax_t)medium_read
+ );
+ }
+ }
+#endif
+
+#if defined(DIOCGFWSECTORS) && defined(DIOCGFWHEADS)
+ if (medium_read == 0) {
+ u_int fwsectors = 0, fwheads = 0;
+ error = ioctl(read_fd, DIOCGFWSECTORS, &fwsectors);
+ if (error)
+ fwsectors = 0;
+ error = ioctl(read_fd, DIOCGFWHEADS, &fwheads);
+ if (error)
+ fwheads = 0;
+ if (fwsectors * fwheads * small_read <= COMPROMISE_SIZE) {
+ medium_read = fwsectors * fwheads * small_read;
+ printf(
+ "# Got medium_read from DIOCGFW{SECTORS*HEADS}: %ju\n",
+ (uintmax_t)medium_read
+ );
+ } else if (fwsectors * small_read <= COMPROMISE_SIZE) {
+ medium_read = fwsectors * small_read;
+ printf(
+ "# Got medium_read from DIOCGFWSECTORS: %ju\n",
+ (uintmax_t)medium_read
+ );
+ }
+ }
+#endif
+
+ if (big_read == 0 && medium_read != 0) {
+ if (medium_read * 2 > COMPROMISE_SIZE) {
+ big_read = medium_read;
+ medium_read = 0;
+ } else {
+ big_read = COMPROMISE_SIZE;
+ big_read -= big_read % medium_read;
+ }
+ printf("# Got big_read from medium_read: %ju\n",
+ (uintmax_t)big_read
+ );
+ }
+
+ if (big_read == 0) {
+ big_read = COMPROMISE_SIZE;
+ big_read -= big_read % small_read;
+ printf("# Defaulting big_read to %ju\n",
+ (uintmax_t)big_read
+ );
+ }
+
+ if (medium_read >= big_read)
+ medium_read = 0;
+
+ if (medium_read == 0) {
+ /*
+ * We do not want to go directly to single sectors, but
+ * we also dont want to waste time doing multi-sector
+ * reads with high failure probability.
+ */
+ uint64_t h = big_read;
+ uint64_t l = small_read;
+ while (h > l) {
+ h >>= 2;
+ l <<= 1;
+ }
+ medium_read = h;
+ printf("# Got medium_read from small_read & big_read: %ju\n",
+ (uintmax_t)medium_read
+ );
+ }
+ printf("# Bigsize = %ju, medium_read = %ju, small_read = %ju\n",
+ (uintmax_t)big_read, (uintmax_t)medium_read, (uintmax_t)small_read);
+
+ assert(0 < small_read);
+
+ assert(0 < medium_read);
+ assert(medium_read >= small_read);
+ assert(medium_read <= big_read);
+ assert(medium_read % small_read == 0);
+
+ assert(0 < big_read);
+ assert(big_read >= medium_read);
+ assert(big_read % small_read == 0);
+}
+
+/**********************************************************************/
+
+static void
+monitor_read_sizes(uint64_t failed_size)
+{
+
+ if (failed_size == big_read && medium_read != small_read) {
+ if (n_reads < n_good_reads + 3)
+ return;
+ fprintf(
+ stderr,
+ "Too many failures for big reads."
+ " (%.0f bad of %.0f)"
+ " Shifting to medium_reads.\n",
+ n_reads - n_good_reads, n_reads
+ );
+ big_read = medium_read;
+ medium_read = small_read;
+ wasted_size = 0;
+ return;
+ }
+
+ if (big_read > small_read && wasted_size / small_read > 200) {
+ fprintf(
+ stderr,
+ "Too much wasted effort."
+ " (%.0f bad of %.0f)"
+ " Shifting to small_reads.\n",
+ n_reads - n_good_reads, n_reads
+ );
+ big_read = small_read;
+ medium_read = small_read;
+ return;
+ }
+}
+
+/**********************************************************************/
+
int
main(int argc, char * const argv[])
{
int ch;
- size_t sz, j;
+ int64_t sz;
int error;
- char *buf;
- u_int sectorsize;
- off_t stripesize;
- time_t t1, t2;
- struct stat sb;
- u_int n, snapshot = 60;
- static struct lump *lp;
+ time_t t_now, t_report, t_save;
+ time_t snapshot = 60, unsaved;
+ setbuf(stdout, NULL);
+ setbuf(stderr, NULL);
- while ((ch = getopt(argc, argv, "b:r:w:s:u:v")) != -1) {
+ while ((ch = getopt(argc, argv, "b:i:l:p:m:r:w:s:t:u:v")) != -1) {
switch (ch) {
case 'b':
- bigsize = strtoul(optarg, NULL, 0);
+ big_read = strtoul(optarg, NULL, 0);
+ break;
+ case 'i':
+ interval = strtod(optarg, NULL);
+ break;
+ case 'l':
+ log_file = fopen(optarg, "a");
+ if (log_file == NULL) {
+ err(1, "Could not open logfile for append");
+ }
+ break;
+ case 'p':
+ error_pause = strtod(optarg, NULL);
+ break;
+ case 'm':
+ medium_read = strtoul(optarg, NULL, 0);
break;
case 'r':
- rworklist = strdup(optarg);
- if (rworklist == NULL)
+ read_worklist_file = strdup(optarg);
+ if (read_worklist_file == NULL)
err(1, "Cannot allocate enough memory");
break;
case 's':
- snapshot = strtoul(optarg, NULL, 0);
+ small_read = strtoul(optarg, NULL, 0);
+ break;
+ case 't':
+ total_size = strtoul(optarg, NULL, 0);
break;
case 'u':
unreadable_pattern = optarg;
@@ -455,8 +783,8 @@ main(int argc, char * const argv[])
set_verbose();
break;
case 'w':
- wworklist = strdup(optarg);
- if (wworklist == NULL)
+ write_worklist_file = strdup(optarg);
+ if (write_worklist_file == NULL)
err(1, "Cannot allocate enough memory");
break;
default:
@@ -471,149 +799,111 @@ main(int argc, char * const argv[])
usage();
input = argv[0];
- fdr = open(argv[0], O_RDONLY);
- if (fdr < 0)
+ read_fd = open(argv[0], O_RDONLY);
+ if (read_fd < 0)
err(1, "Cannot open read descriptor %s", argv[0]);
- error = fstat(fdr, &sb);
- if (error < 0)
- err(1, "fstat failed");
- if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode)) {
- error = ioctl(fdr, DIOCGSECTORSIZE, &sectorsize);
- if (error < 0)
- err(1, "DIOCGSECTORSIZE failed");
+ determine_total_size();
- error = ioctl(fdr, DIOCGSTRIPESIZE, &stripesize);
- if (error == 0 && stripesize > sectorsize)
- sectorsize = stripesize;
+ determine_read_sizes();
- minsize = sectorsize;
- bigsize = rounddown(bigsize, sectorsize);
+ work_buf = malloc(big_read);
+ assert (work_buf != NULL);
- error = ioctl(fdr, DIOCGMEDIASIZE, &tot_size);
- if (error < 0)
- err(1, "DIOCGMEDIASIZE failed");
+ if (argc > 1) {
+ write_fd = open(argv[1], O_WRONLY | O_CREAT, DEFFILEMODE);
+ if (write_fd < 0)
+ err(1, "Cannot open write descriptor %s", argv[1]);
+ if (ftruncate(write_fd, (off_t)total_size) < 0)
+ err(1, "Cannot truncate output %s to %ju bytes",
+ argv[1], (uintmax_t)total_size);
} else {
- tot_size = sb.st_size;
+ write_fd = -1;
}
- if (bigsize < minsize)
- bigsize = minsize;
-
- for (ch = 0; (bigsize >> ch) > minsize; ch++)
- continue;
- medsize = bigsize >> (ch / 2);
- medsize = rounddown(medsize, minsize);
-
- fprintf(stderr, "Bigsize = %zu, medsize = %zu, minsize = %zu\n",
- bigsize, medsize, minsize);
-
- buf = malloc(bigsize);
- if (buf == NULL)
- err(1, "Cannot allocate %zu bytes buffer", bigsize);
+ if (strlen(unreadable_pattern)) {
+ pattern_buf = malloc(big_read);
+ assert(pattern_buf != NULL);
+ fill_buf(pattern_buf, big_read, unreadable_pattern);
+ }
- if (argc > 1) {
- fdw = open(argv[1], O_WRONLY | O_CREAT, DEFFILEMODE);
- if (fdw < 0)
- err(1, "Cannot open write descriptor %s", argv[1]);
- if (ftruncate(fdw, tot_size) < 0)
- err(1, "Cannot truncate output %s to %jd bytes",
- argv[1], (intmax_t)tot_size);
- } else
- fdw = -1;
-
- if (rworklist != NULL) {
- done_size = read_worklist(tot_size);
+ if (read_worklist_file != NULL) {
+ done_size = total_size - read_worklist();
} else {
- new_lump(0, tot_size, 0);
+ new_lump(0UL, total_size, 0UL);
done_size = 0;
}
- if (wworklist != NULL)
+ if (write_worklist_file != NULL)
signal(SIGINT, sighandler);
- t1 = time(NULL);
sz = 0;
if (!verbose)
- report_header(0);
+ report_header("\n");
else
printf("\x1b[2J");
- n = 0;
- for (;;) {
- lp = TAILQ_FIRST(&lumps);
- if (lp == NULL)
- break;
- while (lp->len > 0) {
- if (lp->state == 0)
- sz = MIN(lp->len, (off_t)bigsize);
- else if (lp->state == 1)
- sz = MIN(lp->len, (off_t)medsize);
- else
- sz = MIN(lp->len, (off_t)minsize);
- assert(sz != 0);
-
- t2 = time(NULL);
- if (t1 != t2 || lp->len < (off_t)bigsize) {
- t1 = t2;
- if (++n == snapshot) {
- save_worklist();
- n = 0;
- }
- report(lp, sz);
- }
+ t_first = time(NULL);
+ t_report = t_first;
+ t_save = t_first;
+ unsaved = 0;
+ while (!aborting) {
+ if (interval > 0) {
+ usleep((unsigned long)(1e6 * interval));
+ }
+ t_now = time(NULL);
+ sz = attempt_one_lump(t_now);
+ error = errno;
- j = pread(fdr, buf, sz, lp->start);
-#if 0
-if (!(random() & 0xf)) {
- j = -1;
- errno = EIO;
-}
-#endif
- if (j == sz) {
- done_size += sz;
- if (fdw >= 0)
- write_buf(fdw, buf, sz, lp->start);
- lp->start += sz;
- lp->len -= sz;
- if (verbose && lp->state > 2)
- report_good_read(t2, sz);
- continue;
- }
- error = errno;
-
- printf("%jd %zu %d read error (%s)\n",
- lp->start, sz, lp->state, strerror(error));
- if (verbose)
- report(lp, sz);
- if (fdw >= 0 && strlen(unreadable_pattern)) {
- fill_buf(buf, sz, unreadable_pattern);
- write_buf(fdw, buf, sz, lp->start);
+ if (sz == 0) {
+ break;
+ }
+
+ if (sz > 0) {
+ unsaved += 1;
+ }
+ if (unsaved && (t_save + snapshot) < t_now) {
+ save_worklist();
+ unsaved = 0;
+ t_save = t_now;
+ if (!verbose) {
+ report_header("\n");
+ t_report = t_now;
}
- new_lump(lp->start, sz, lp->state + 1);
- lp->start += sz;
- lp->len -= sz;
- if (error == EINVAL) {
- printf("Try with -b 131072 or lower ?\n");
- aborting = 1;
- break;
+ }
+ if (sz > 0) {
+ if (verbose) {
+ account_good_read(t_now, sz);
}
- if (error == ENXIO) {
- printf("Input device probably detached...\n");
- aborting = 1;
- break;
+ if (t_report != t_now) {
+ report(sz);
+ t_report = t_now;
}
+ continue;
}
- if (aborting)
- save_worklist();
- if (aborting || !TAILQ_NEXT(lp, list))
- report(lp, sz);
- if (aborting)
+
+ monitor_read_sizes(-sz);
+
+ if (error == EINVAL) {
+ printf("Try with -b 131072 or lower ?\n");
+ aborting = 1;
break;
- assert(lp->len == 0);
- TAILQ_REMOVE(&lumps, lp, list);
- free(lp);
+ }
+ if (error == ENXIO) {
+ printf("Input device probably detached...\n");
+ aborting = 1;
+ break;
+ }
+ report(-sz);
+ t_report = t_now;
+ if (error_pause > 0) {
+ usleep((unsigned long)(1e6 * error_pause));
+ }
}
+ save_worklist();
+ free(work_buf);
+ if (pattern_buf != NULL)
+ free(pattern_buf);
printf("%s", aborting ? "Aborted\n" : "Completed\n");
- free(buf);
- return (0);
+ report(0UL);
+ return (0); // XXX
}
diff --git a/sbin/resolvconf/Makefile b/sbin/resolvconf/Makefile
index 6d7586090da0..328153a2b0ba 100644
--- a/sbin/resolvconf/Makefile
+++ b/sbin/resolvconf/Makefile
@@ -1,6 +1,4 @@
-# $FreeBSD$
-
-PACKAGE=runtime
+PACKAGE=resolvconf
DIST= ${SRCTOP}/contrib/openresolv
.PATH: ${DIST}
diff --git a/sbin/resolvconf/Makefile.depend b/sbin/resolvconf/Makefile.depend
index f80275d86ab1..11aba52f82cf 100644
--- a/sbin/resolvconf/Makefile.depend
+++ b/sbin/resolvconf/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/restore/Makefile b/sbin/restore/Makefile
index d6c1e6202693..99fc7e190bfd 100644
--- a/sbin/restore/Makefile
+++ b/sbin/restore/Makefile
@@ -1,9 +1,6 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
.PATH: ${.CURDIR:H}/dump
-PACKAGE=runtime
+PACKAGE=ufs
PROG= restore
LINKS= ${BINDIR}/restore ${BINDIR}/rrestore
MAN= restore.8
diff --git a/sbin/restore/Makefile.depend b/sbin/restore/Makefile.depend
index 4bd09984c29d..528bba446e46 100644
--- a/sbin/restore/Makefile.depend
+++ b/sbin/restore/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/protocols \
include/xlocale \
diff --git a/sbin/restore/dirs.c b/sbin/restore/dirs.c
index a8120fda8b6e..16fdecba6c18 100644
--- a/sbin/restore/dirs.c
+++ b/sbin/restore/dirs.c
@@ -34,14 +34,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)dirs.c 8.7 (Berkeley) 5/1/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
@@ -646,6 +638,11 @@ setdirmodes(int flags)
}
cp = myname(ep);
if (!Nflag) {
+ if (myuid != 0)
+ (void) chown(cp, myuid, node.gid);
+ else
+ (void) chown(cp, node.uid, node.gid);
+ (void) chmod(cp, node.mode);
if (node.extsize > 0) {
if (bufsize >= node.extsize) {
set_extattr(-1, cp, buf, node.extsize, SXA_FILE);
@@ -654,11 +651,6 @@ setdirmodes(int flags)
"extended attributes for ", cp);
}
}
- if (myuid != 0)
- (void) chown(cp, myuid, node.gid);
- else
- (void) chown(cp, node.uid, node.gid);
- (void) chmod(cp, node.mode);
utimensat(AT_FDCWD, cp, node.ctimep, 0);
utimensat(AT_FDCWD, cp, node.mtimep, 0);
(void) chflags(cp, node.flags);
diff --git a/sbin/restore/extern.h b/sbin/restore/extern.h
index c33034c48c5e..0b2f85d878c3 100644
--- a/sbin/restore/extern.h
+++ b/sbin/restore/extern.h
@@ -27,9 +27,6 @@
* 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.
- *
- * @(#)extern.h 8.2 (Berkeley) 1/7/94
- * $FreeBSD$
*/
struct entry *addentry(char *, ino_t, int);
diff --git a/sbin/restore/interactive.c b/sbin/restore/interactive.c
index 15b1fb45bb04..ea7fc0f18b64 100644
--- a/sbin/restore/interactive.c
+++ b/sbin/restore/interactive.c
@@ -29,15 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)interactive.c 8.5 (Berkeley) 5/1/95";
-#endif
-#endif /* not lint */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/stat.h>
diff --git a/sbin/restore/main.c b/sbin/restore/main.c
index 7b9a5359d57d..f94b37503d18 100644
--- a/sbin/restore/main.c
+++ b/sbin/restore/main.c
@@ -29,21 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1983, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/4/95";
-#endif
-#endif /* not lint */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/stat.h>
diff --git a/sbin/restore/restore.8 b/sbin/restore/restore.8
index ffaa491b4fd7..b7b96a1a0d2a 100644
--- a/sbin/restore/restore.8
+++ b/sbin/restore/restore.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)restore.8 8.4 (Berkeley) 5/1/95
-.\" $FreeBSD$
-.\"
.Dd October 12, 2006
.Dt RESTORE 8
.Os
diff --git a/sbin/restore/restore.c b/sbin/restore/restore.c
index 7c9056ee16d9..1a5e16174b2c 100644
--- a/sbin/restore/restore.c
+++ b/sbin/restore/restore.c
@@ -29,15 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)restore.c 8.3 (Berkeley) 9/13/94";
-#endif
-#endif /* not lint */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <limits.h>
diff --git a/sbin/restore/restore.h b/sbin/restore/restore.h
index 2e6ff623dc3a..407816993196 100644
--- a/sbin/restore/restore.h
+++ b/sbin/restore/restore.h
@@ -32,9 +32,6 @@
* 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.
- *
- * @(#)restore.h 8.3 (Berkeley) 9/13/94
- * $FreeBSD$
*/
/*
@@ -60,7 +57,7 @@ extern long volno; /* current volume being read */
extern long ntrec; /* number of TP_BSIZE records per tape block */
extern time_t dumptime; /* time that this dump begins */
extern time_t dumpdate; /* time that this dump was made */
-extern char command; /* opration being performed */
+extern char command; /* operation being performed */
extern FILE *terminal; /* file descriptor for the terminal input */
extern int Bcvt; /* need byte swapping on inodes and dirs */
extern int oldinofmt; /* reading tape with FreeBSD 1 format inodes */
@@ -74,7 +71,7 @@ struct entry {
char e_type; /* type of this entry, see below */
short e_flags; /* status flags, see below */
ino_t e_ino; /* inode number in previous file sys */
- long e_index; /* unique index (for dumpped table) */
+ long e_index; /* unique index (for dumped table) */
struct entry *e_parent; /* pointer to parent directory (..) */
struct entry *e_sibling; /* next element in this directory (.) */
struct entry *e_links; /* hard links to this inode */
diff --git a/sbin/restore/symtab.c b/sbin/restore/symtab.c
index 49ed39dd2022..3ae6bf20c7be 100644
--- a/sbin/restore/symtab.c
+++ b/sbin/restore/symtab.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)symtab.c 8.3 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
/*
* These routines maintain the symbol table which tracks the state
* of the file system being restored. They provide lookup by either
diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c
index 1c8c2402b9fc..5b7cde10c670 100644
--- a/sbin/restore/tape.c
+++ b/sbin/restore/tape.c
@@ -34,18 +34,10 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)tape.c 8.9 (Berkeley) 5/1/95";
-#endif
-#endif /* not lint */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/file.h>
#include <sys/mtio.h>
+#include <sys/queue.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/extattr.h>
@@ -628,10 +620,10 @@ extractfile(char *name)
return (GOOD);
}
if (linkit(lnkbuf, name, SYMLINK) == GOOD) {
- if (extsize > 0)
- set_extattr(-1, name, buf, extsize, SXA_LINK);
(void) lchown(name, uid, gid);
(void) lchmod(name, mode);
+ if (extsize > 0)
+ set_extattr(-1, name, buf, extsize, SXA_LINK);
(void) utimensat(AT_FDCWD, name, ctimep,
AT_SYMLINK_NOFOLLOW);
(void) utimensat(AT_FDCWD, name, mtimep,
@@ -655,6 +647,8 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
+ (void) chown(name, uid, gid);
+ (void) chmod(name, mode);
if (extsize == 0) {
skipfile();
} else {
@@ -662,8 +656,6 @@ extractfile(char *name)
getfile(xtrnull, xtrattr, xtrnull);
set_extattr(-1, name, buf, extsize, SXA_FILE);
}
- (void) chown(name, uid, gid);
- (void) chmod(name, mode);
(void) utimensat(AT_FDCWD, name, ctimep, 0);
(void) utimensat(AT_FDCWD, name, mtimep, 0);
(void) chflags(name, flags);
@@ -685,6 +677,8 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
+ (void) chown(name, uid, gid);
+ (void) chmod(name, mode);
if (extsize == 0) {
skipfile();
} else {
@@ -692,8 +686,6 @@ extractfile(char *name)
getfile(xtrnull, xtrattr, xtrnull);
set_extattr(-1, name, buf, extsize, SXA_FILE);
}
- (void) chown(name, uid, gid);
- (void) chmod(name, mode);
(void) utimensat(AT_FDCWD, name, ctimep, 0);
(void) utimensat(AT_FDCWD, name, mtimep, 0);
(void) chflags(name, flags);
@@ -714,12 +706,12 @@ extractfile(char *name)
skipfile();
return (FAIL);
}
+ (void) fchown(ofile, uid, gid);
+ (void) fchmod(ofile, mode);
buf = setupextattr(extsize);
getfile(xtrfile, xtrattr, xtrskip);
if (extsize > 0)
set_extattr(ofile, name, buf, extsize, SXA_FD);
- (void) fchown(ofile, uid, gid);
- (void) fchmod(ofile, mode);
(void) futimens(ofile, ctimep);
(void) futimens(ofile, mtimep);
(void) fchflags(ofile, flags);
diff --git a/sbin/restore/utilities.c b/sbin/restore/utilities.c
index a53d42f9e600..c4d4fb1ea42f 100644
--- a/sbin/restore/utilities.c
+++ b/sbin/restore/utilities.c
@@ -29,14 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)utilities.c 8.5 (Berkeley) 4/28/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/stat.h>
diff --git a/sbin/route/Makefile b/sbin/route/Makefile
index e65030f805bb..43b9c0d8d821 100644
--- a/sbin/route/Makefile
+++ b/sbin/route/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
.include <src.opts.mk>
PACKAGE=runtime
@@ -19,6 +16,17 @@ CFLAGS+= -DINET6
.endif
CFLAGS+= -I.
+.if ${MK_NETLINK_SUPPORT} != "no"
+SRCS+= route_netlink.c
+.else
+CFLAGS+=-DWITHOUT_NETLINK
+.endif
+
+.if ${MK_JAIL} != "no" && !defined(RESCUE)
+CFLAGS+= -DJAIL
+LIBADD+= jail
+.endif
+
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests
diff --git a/sbin/route/Makefile.depend b/sbin/route/Makefile.depend
index d5ed563ecfc8..672ec75190c6 100644
--- a/sbin/route/Makefile.depend
+++ b/sbin/route/Makefile.depend
@@ -1,14 +1,13 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
+ lib/libjail \
.include <dirdeps.mk>
diff --git a/sbin/route/keywords b/sbin/route/keywords
index 82edc46690d1..cbd8799ffb6b 100644
--- a/sbin/route/keywords
+++ b/sbin/route/keywords
@@ -1,5 +1,3 @@
-# @(#)keywords 8.2 (Berkeley) 3/19/94
-# $FreeBSD$
4
6
diff --git a/sbin/route/route.8 b/sbin/route/route.8
index 161189e7a9d8..572781ef59c8 100644
--- a/sbin/route/route.8
+++ b/sbin/route/route.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)route.8 8.3 (Berkeley) 3/19/94
-.\" $FreeBSD$
-.\"
-.Dd December 15, 2021
+.Dd November 12, 2024
.Dt ROUTE 8
.Os
.Sh NAME
@@ -36,6 +33,7 @@
.Nd manually manipulate the routing tables
.Sh SYNOPSIS
.Nm
+.Op Fl j Ar jail
.Op Fl dnqtv
.Ar command
.Oo
@@ -91,6 +89,8 @@ Suppress all output from the
and
.Cm flush
commands.
+.It Fl j Ar jail
+Run inside a jail.
.El
.Pp
The
@@ -134,7 +134,7 @@ The flush command has the syntax:
.Bd -ragged -offset indent -compact
.Nm
.Op Fl n
-.Cm flush Oc Oo Ar family Oc Op Fl fib Ar number
+.Cm flush Oo Ar family Oc Op Fl fib Ar number
.Ed
.Pp
If the
@@ -228,10 +228,10 @@ is interpreted as
.Fl host Li 128.32.0.130 ;
.Fl net Li 128.32
is interpreted as
-.Li 128.32.0.0;
+.Li 128.32.0.0 ;
.Fl net Li 128.32.130
is interpreted as
-.Li 128.32.130.0;
+.Li 128.32.130.0 ;
and
.Li 192.168.64/20
is interpreted as
@@ -265,9 +265,7 @@ if the local or remote addresses change.
The optional
.Fl netmask
modifier is intended
-to achieve the effect of an
-.Tn OSI
-.Tn ESIS
+to achieve the effect of an OSI ESIS
redirect with the netmask option,
or to manually add subnet routes with
netmasks different from that of the implied network interface
@@ -378,9 +376,7 @@ In a
or
.Cm add
command where the destination and gateway are not sufficient to specify
-the route (as in the
-.Tn ISO
-case where several interfaces may have the
+the route (as in the ISO case where several interfaces may have the
same address), the
.Fl ifp
or
@@ -405,6 +401,72 @@ and
.Dv RTM_CHANGE .
As such, only the super-user may modify
the routing tables.
+.Pp
+.Fx provides support for scalable multipath routing.
+It is activated by default, but can be turned off by setting the
+.Va net.route.multipath
+.Xr sysctl 8
+MIB to 0.
+.Pp
+There are multiple route lookup algorithms available.
+They can be configured by setting
+.Va net.route.algo.inet.algo
+for IPv4 and
+.Va net.route.algo.inet6.algo
+for IPv6
+.Xr sysctl 8
+MIBs.
+.Pp
+A list of available algorithms can be obtained by accessing the
+following
+.Xr sysctl 8
+MIBs
+.Va net.route.algo.inet.algo_list
+for IPv4 and
+.Va net.route.algo.inet6.algo_list
+for IPv6.
+.Pp
+The following algorithms are available:
+.Bl -tag -width radix_lockless
+.It radix
+Base system radix backend.
+.It bsearch
+Lockless binary search in a special IP array, tailored for a small FIB
+with <16 routes.
+This algorithm is only available for IPv4.
+.It radix_lockless
+Lockless immutable radix, re-created on every rtable change,
+tailored for a small FIB with <1000 routes.
+.It dpdk_lpm
+DPDK DIR24-8-based lookups, lockless datastructure, optimized
+for large FIBs.
+DIR24-8 relies on a large flat lookup table (64 MB with IPv4) which is
+directly indexed by the more significant portion of the lookup key.
+In order to use the dpdk_lpm algorithm one or both of the
+following kernel modules must be loaded via
+.Xr loader.conf 5 :
+.Bl -tag -width dpdk_lpm6.ko -compact
+.It dpdk_lpm4.ko
+DPDK implementation for IPv4.
+.It dpdk_lpm6.ko
+DPDK implementation for IPv6.
+.El
+.It dxr
+IPv4 only, lockless, compressed lookup structure
+(below 2.5 Bytes per IPv4 prefix for large BGP FIBs)
+which easily fits into modern CPU cache hierarchies,
+lookup throughput scales linearly with CPU cores.
+Loadable as a kernel module at runtime or via
+.Xr loader.conf 5 :
+.Bl -tag -width fib_dxr.ko -compact
+.It fib_dxr.ko
+.El
+.El
+.Pp
+The algorithms are selected automatically based on the size of the routing
+table of the system.
+They can be changed, but not every algorithm performs best for every
+FIB size.
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
@@ -438,9 +500,8 @@ Remove all routes from the routing table:
.Pp
.Dl route flush
.Pp
-List all routing tables:
-.Pp
-.Dl netstat -r
+The routing table can be listed with
+.Xr netstat 1 .
.Sh DIAGNOSTICS
.Bl -diag
.It "add [host \&| network ] %s: gateway %s flags %x"
@@ -480,10 +541,10 @@ same route as the one being changed.
The next-hop gateway should be reachable through a different route.
.El
.Sh SEE ALSO
-.\".Xr esis 4 ,
.Xr netstat 1 ,
.Xr netintro 4 ,
.Xr route 4 ,
+.Xr loader.conf 5 ,
.Xr arp 8 ,
.Xr routed 8
.Sh HISTORY
@@ -491,17 +552,3 @@ The
.Nm
utility appeared in
.Bx 4.2 .
-.Sh BUGS
-The first paragraph may have slightly exaggerated
-.Xr routed 8 Ns 's
-abilities.
-.Pp
-Currently, routes with the
-.Dv RTF_BLACKHOLE
-flag set need to have the gateway set to an instance of the
-.Xr lo 4
-driver, using the
-.Fl iface
-option, for the flag to have any effect; unless IP fast forwarding
-is enabled, in which case the meaning of the flag will always
-be honored.
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 5f33cecb1b20..f37d23d25c2c 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -29,25 +29,13 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1983, 1989, 1991, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
-#endif
-#endif /* not lint */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
+#ifdef JAIL
+#include <sys/jail.h>
+#endif
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/queue.h>
@@ -63,6 +51,9 @@ __FBSDID("$FreeBSD$");
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#ifdef JAIL
+#include <jail.h>
+#endif
#include <paths.h>
#include <signal.h>
#include <stdbool.h>
@@ -90,31 +81,45 @@ static struct keytab {
{0, 0}
};
+int verbose, debugonly;
+#ifdef JAIL
+char * jail_name;
+#endif
static struct sockaddr_storage so[RTAX_MAX];
static int pid, rtm_addrs;
-static int s;
-static int nflag, af, qflag, tflag;
-static int verbose, aflen;
-static int locking, lockrest, debugonly;
+static int nflag, af, aflen, qflag, tflag;
+static int locking, lockrest;
static struct rt_metrics rt_metrics;
static u_long rtm_inits;
static uid_t uid;
static int defaultfib;
static int numfibs;
-static char domain[MAXHOSTNAMELEN + 1];
-static bool domain_initialized;
-static int rtm_seq;
+static char domain_storage[MAXHOSTNAMELEN + 1];
+static const char *domain;
static char rt_line[NI_MAXHOST];
static char net_line[MAXHOSTNAMELEN + 1];
+#ifdef WITHOUT_NETLINK
+static int s;
+static int rtm_seq;
+
static struct {
struct rt_msghdr m_rtm;
char m_space[512];
} m_rtmsg;
+static int rtmsg_rtsock(int, int, int);
+static int flushroutes_fib_rtsock(int);
+static void monitor_rtsock(void);
+#else
+int rtmsg_nl(int, int, int, int, struct sockaddr_storage *, struct rt_metrics *);
+int flushroutes_fib_nl(int, int);
+void monitor_nl(int);
+#endif
+
static TAILQ_HEAD(fibl_head_t, fibl) fibl_head;
-static void printb(int, const char *);
+void printb(int, const char *);
static void flushroutes(int argc, char *argv[]);
static int flushroutes_fib(int);
static int getaddr(int, char *, int);
@@ -127,7 +132,7 @@ static int inet6_makenetandmask(struct sockaddr_in6 *, const char *);
#endif
static void interfaces(void);
static void monitor(int, char*[]);
-static const char *netname(struct sockaddr *);
+const char *netname(struct sockaddr *);
static void newroute(int, char **);
static int newroute_fib(int, char *, int);
static void pmsg_addrs(char *, int, size_t);
@@ -135,7 +140,7 @@ static void pmsg_common(struct rt_msghdr *, size_t);
static int prefixlen(const char *);
static void print_getmsg(struct rt_msghdr *, int, int);
static void print_rtmsg(struct rt_msghdr *, size_t);
-static const char *routename(struct sockaddr *);
+const char *routename(struct sockaddr *);
static int rtmsg(int, int, int);
static void set_metric(char *, int);
static int set_sofib(int);
@@ -161,7 +166,7 @@ usage(const char *cp)
{
if (cp != NULL)
warnx("bad keyword: %s", cp);
- errx(EX_USAGE, "usage: route [-46dnqtv] command [[modifiers] args]");
+ errx(EX_USAGE, "usage: route [-j jail] [-46dnqtv] command [[modifiers] args]");
/* NOTREACHED */
}
@@ -169,12 +174,15 @@ int
main(int argc, char **argv)
{
int ch;
+#ifdef JAIL
+ int jid;
+#endif
size_t len;
if (argc < 2)
usage(NULL);
- while ((ch = getopt(argc, argv, "46nqdtv")) != -1)
+ while ((ch = getopt(argc, argv, "46nqdtvj:")) != -1)
switch(ch) {
case '4':
#ifdef INET
@@ -207,6 +215,15 @@ main(int argc, char **argv)
case 'd':
debugonly = 1;
break;
+ case 'j':
+#ifdef JAIL
+ if (optarg == NULL)
+ usage(NULL);
+ jail_name = optarg;
+#else
+ errx(1, "Jail support is not compiled in");
+#endif
+ break;
case '?':
default:
usage(NULL);
@@ -216,12 +233,25 @@ main(int argc, char **argv)
pid = getpid();
uid = geteuid();
+
+#ifdef JAIL
+ if (jail_name != NULL) {
+ jid = jail_getid(jail_name);
+ if (jid == -1)
+ errx(1, "Jail not found");
+ if (jail_attach(jid) != 0)
+ errx(1, "Cannot attach to jail");
+ }
+#endif
+
+#ifdef WITHOUT_NETLINK
if (tflag)
s = open(_PATH_DEVNULL, O_WRONLY, 0);
else
s = socket(PF_ROUTE, SOCK_RAW, 0);
if (s < 0)
err(EX_OSERR, "socket");
+#endif
len = sizeof(numfibs);
if (sysctlbyname("net.fibs", (void *)&numfibs, &len, NULL, 0) == -1)
@@ -264,10 +294,14 @@ static int
set_sofib(int fib)
{
+#ifdef WITHOUT_NETLINK
if (fib < 0)
return (0);
return (setsockopt(s, SOL_SOCKET, SO_SETFIB, (void *)&fib,
sizeof(fib)));
+#else
+ return (0);
+#endif
}
static int
@@ -395,7 +429,9 @@ flushroutes(int argc, char *argv[])
if (uid != 0 && !debugonly && !tflag)
errx(EX_NOPERM, "must be root to alter routing table");
+#ifdef WITHOUT_NETLINK
shutdown(s, SHUT_RD); /* Don't want to read back our messages */
+#endif
TAILQ_INIT(&fibl_head);
while (argc > 1) {
@@ -442,6 +478,17 @@ flushroutes(int argc, char *argv[])
static int
flushroutes_fib(int fib)
{
+#ifdef WITHOUT_NETLINK
+ return (flushroutes_fib_rtsock(fib));
+#else
+ return (flushroutes_fib_nl(fib, af));
+#endif
+}
+
+#ifdef WITHOUT_NETLINK
+static int
+flushroutes_fib_rtsock(int fib)
+{
struct rt_msghdr *rtm;
size_t needed;
char *buf, *next, *lim;
@@ -525,22 +572,25 @@ retry:
free(buf);
return (error);
}
+#endif
-static const char *
+const char *
routename(struct sockaddr *sa)
{
struct sockaddr_dl *sdl;
const char *cp;
int n;
- if (!domain_initialized) {
- domain_initialized = true;
- if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
- (cp = strchr(domain, '.'))) {
- domain[MAXHOSTNAMELEN] = '\0';
- (void)strcpy(domain, cp + 1);
- } else
- domain[0] = '\0';
+ if (domain == NULL) {
+ if (gethostname(domain_storage,
+ sizeof(domain_storage) - 1) == 0 &&
+ (cp = strchr(domain_storage, '.')) != NULL) {
+ domain_storage[sizeof(domain_storage) - 1] = '\0';
+ domain = cp + 1;
+ } else {
+ domain_storage[0] = '\0';
+ domain = domain_storage;
+ }
}
/* If the address is zero-filled, use "default". */
@@ -645,7 +695,7 @@ routename(struct sockaddr *sa)
* Return the name of the network whose address is given.
* The address is assumed to be that of a net, not a host.
*/
-static const char *
+const char *
netname(struct sockaddr *sa)
{
struct sockaddr_dl *sdl;
@@ -810,8 +860,10 @@ newroute(int argc, char **argv)
warn("sigaction SIGALRM");
cmd = argv[0];
+#ifdef WITHOUT_NETLINK
if (*cmd != 'g' && *cmd != 's')
shutdown(s, SHUT_RD); /* Don't want to read back our messages */
+#endif
while (--argc > 0) {
if (**(++argv)== '-') {
switch (key = keyword(1 + *argv)) {
@@ -1279,6 +1331,9 @@ getaddr(int idx, char *str, int nrflags)
q = strchr(str,'/');
if (q != NULL && idx == RTAX_DST) {
/* A.B.C.D/NUM */
+ struct sockaddr_in *mask;
+ uint32_t mask_bits;
+
*q = '\0';
if (inet_aton(str, &sin->sin_addr) == 0)
errx(EX_NOHOST, "bad address: %s", str);
@@ -1288,6 +1343,20 @@ getaddr(int idx, char *str, int nrflags)
errx(EX_NOHOST, "bad mask length: %s", q + 1);
inet_makemask((struct sockaddr_in *)&so[RTAX_NETMASK],masklen);
+
+ /*
+ * Check for bogus destination such as "10/8"; heuristic is
+ * that there are bits set in the host part, and no dot
+ * is present.
+ */
+ mask = ((struct sockaddr_in *) &so[RTAX_NETMASK]);
+ mask_bits = ntohl(mask->sin_addr.s_addr);
+ if ((ntohl(sin->sin_addr.s_addr) & ~mask_bits) != 0 &&
+ strchr(str, '.') == NULL)
+ errx(EX_NOHOST,
+ "malformed address, bits set after mask;"
+ " %s means %s",
+ str, inet_ntoa(sin->sin_addr));
return (0);
}
if (inet_aton(str, &sin->sin_addr) != 0)
@@ -1398,8 +1467,8 @@ retry2:
static void
monitor(int argc, char *argv[])
{
- int n, fib, error;
- char msg[2048], *endptr;
+ int fib, error;
+ char *endptr;
fib = defaultfib;
while (argc > 1) {
@@ -1435,6 +1504,19 @@ monitor(int argc, char *argv[])
interfaces();
exit(0);
}
+#ifdef WITHOUT_NETLINK
+ monitor_rtsock();
+#else
+ monitor_nl(fib);
+#endif
+}
+
+#ifdef WITHOUT_NETLINK
+static void
+monitor_rtsock(void)
+{
+ char msg[2048];
+ int n;
#ifdef SO_RERROR
n = 1;
@@ -1454,25 +1536,12 @@ monitor(int argc, char *argv[])
print_rtmsg((struct rt_msghdr *)(void *)msg, n);
}
}
+#endif
static int
rtmsg(int cmd, int flags, int fib)
{
- int rlen;
- char *cp = m_rtmsg.m_space;
- int l;
-
-#define NEXTADDR(w, u) \
- if (rtm_addrs & (w)) { \
- l = SA_SIZE(&(u)); \
- memmove(cp, (char *)&(u), l); \
- cp += l; \
- if (verbose) \
- sodump((struct sockaddr *)&(u), #w); \
- }
-
errno = 0;
- memset(&m_rtmsg, 0, sizeof(m_rtmsg));
if (cmd == 'a')
cmd = RTM_ADD;
else if (cmd == 'c')
@@ -1488,6 +1557,33 @@ rtmsg(int cmd, int flags, int fib)
cmd = RTM_DELETE;
flags |= RTF_PINNED;
}
+#ifdef WITHOUT_NETLINK
+ return (rtmsg_rtsock(cmd, flags, fib));
+#else
+ errno = rtmsg_nl(cmd, flags, fib, rtm_addrs, so, &rt_metrics);
+ return (errno == 0 ? 0 : -1);
+#endif
+}
+
+#ifdef WITHOUT_NETLINK
+static int
+rtmsg_rtsock(int cmd, int flags, int fib)
+{
+ int rlen;
+ char *cp = m_rtmsg.m_space;
+ int l;
+
+ memset(&m_rtmsg, 0, sizeof(m_rtmsg));
+
+#define NEXTADDR(w, u) \
+ if (rtm_addrs & (w)) { \
+ l = SA_SIZE(&(u)); \
+ memmove(cp, (char *)&(u), l); \
+ cp += l; \
+ if (verbose) \
+ sodump((struct sockaddr *)&(u), #w); \
+ }
+
#define rtm m_rtmsg.m_rtm
rtm.rtm_type = cmd;
rtm.rtm_flags = flags;
@@ -1545,6 +1641,7 @@ rtmsg(int cmd, int flags, int fib)
#undef rtm
return (0);
}
+#endif
static const char *const msgtypes[] = {
"",
@@ -1566,12 +1663,13 @@ static const char *const msgtypes[] = {
"RTM_DELMADDR: multicast group membership removed from iface",
"RTM_IFANNOUNCE: interface arrival/departure",
"RTM_IEEE80211: IEEE 802.11 wireless event",
+ "RTM_IPFWLOG: IPFW log",
};
static const char metricnames[] =
"\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire"
"\1mtu";
-static const char routeflags[] =
+const char routeflags[] =
"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE"
"\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3"
@@ -1812,7 +1910,7 @@ pmsg_addrs(char *cp, int addrs, size_t len)
(void)fflush(stdout);
}
-static void
+void
printb(int b, const char *str)
{
int i;
diff --git a/sbin/route/route_netlink.c b/sbin/route/route_netlink.c
new file mode 100644
index 000000000000..ba22a2ec1e22
--- /dev/null
+++ b/sbin/route/route_netlink.c
@@ -0,0 +1,914 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <errno.h>
+
+#include <sys/bitcount.h>
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <netlink/netlink.h>
+#include <netlink/netlink_route.h>
+#include <netlink/netlink_snl.h>
+#include <netlink/netlink_snl_route.h>
+#include <netlink/netlink_snl_route_compat.h>
+#include <netlink/netlink_snl_route_parsers.h>
+
+const char *routename(struct sockaddr *);
+const char *netname(struct sockaddr *);
+void printb(int, const char *);
+extern const char routeflags[];
+extern int verbose, debugonly;
+
+int rtmsg_nl(int cmd, int rtm_flags, int fib, int rtm_addrs, struct sockaddr_storage *so,
+ struct rt_metrics *rt_metrics);
+int flushroutes_fib_nl(int fib, int af);
+void monitor_nl(int fib);
+
+struct nl_helper;
+struct snl_msg_info;
+static void print_getmsg(struct nl_helper *h, struct nlmsghdr *hdr,
+ struct sockaddr *dst);
+static void print_nlmsg(struct nl_helper *h, struct nlmsghdr *hdr,
+ struct snl_msg_info *cinfo);
+
+#define s6_addr32 __u6_addr.__u6_addr32
+#define bitcount32(x) __bitcount32((uint32_t)(x))
+static int
+inet6_get_plen(const struct in6_addr *addr)
+{
+
+ return (bitcount32(addr->s6_addr32[0]) + bitcount32(addr->s6_addr32[1]) +
+ bitcount32(addr->s6_addr32[2]) + bitcount32(addr->s6_addr32[3]));
+}
+
+static void
+ip6_writemask(struct in6_addr *addr6, uint8_t mask)
+{
+ uint32_t *cp;
+
+ for (cp = (uint32_t *)addr6; mask >= 32; mask -= 32)
+ *cp++ = 0xFFFFFFFF;
+ if (mask > 0)
+ *cp = htonl(mask ? ~((1 << (32 - mask)) - 1) : 0);
+}
+
+static struct sockaddr *
+get_netmask(struct snl_state *ss, int family, int plen)
+{
+ if (family == AF_INET) {
+ if (plen == 32)
+ return (NULL);
+
+ struct sockaddr_in *sin = snl_allocz(ss, sizeof(*sin));
+
+ sin->sin_len = sizeof(*sin);
+ sin->sin_family = family;
+ sin->sin_addr.s_addr = htonl(plen ? ~((1 << (32 - plen)) - 1) : 0);
+
+ return (struct sockaddr *)sin;
+ } else if (family == AF_INET6) {
+ if (plen == 128)
+ return (NULL);
+
+ struct sockaddr_in6 *sin6 = snl_allocz(ss, sizeof(*sin6));
+
+ sin6->sin6_len = sizeof(*sin6);
+ sin6->sin6_family = family;
+ ip6_writemask(&sin6->sin6_addr, plen);
+
+ return (struct sockaddr *)sin6;
+ }
+ return (NULL);
+}
+
+static void
+nl_init_socket(struct snl_state *ss)
+{
+ if (snl_init(ss, NETLINK_ROUTE))
+ return;
+
+ if (modfind("netlink") == -1 && errno == ENOENT) {
+ /* Try to load */
+ if (kldload("netlink") == -1)
+ err(1, "netlink is not loaded and load attempt failed");
+ if (snl_init(ss, NETLINK_ROUTE))
+ return;
+ }
+
+ err(1, "unable to open netlink socket");
+}
+
+struct nl_helper {
+ struct snl_state ss_cmd;
+};
+
+static void
+nl_helper_init(struct nl_helper *h)
+{
+ nl_init_socket(&h->ss_cmd);
+}
+
+static void
+nl_helper_free(struct nl_helper *h)
+{
+ snl_free(&h->ss_cmd);
+}
+
+static struct sockaddr *
+get_addr(struct sockaddr_storage *so, int rtm_addrs, int addr_type)
+{
+ struct sockaddr *sa = NULL;
+
+ if (rtm_addrs & (1 << addr_type))
+ sa = (struct sockaddr *)&so[addr_type];
+ return (sa);
+}
+
+static int
+rtmsg_nl_int(struct nl_helper *h, int cmd, int rtm_flags, int fib, int rtm_addrs,
+ struct sockaddr_storage *so, struct rt_metrics *rt_metrics)
+{
+ struct snl_state *ss = &h->ss_cmd;
+ struct snl_writer nw;
+ int nl_type = 0, nl_flags = 0;
+
+ snl_init_writer(ss, &nw);
+
+ switch (cmd) {
+ case RTSOCK_RTM_ADD:
+ nl_type = RTM_NEWROUTE;
+ nl_flags = NLM_F_CREATE | NLM_F_APPEND; /* Do append by default */
+ break;
+ case RTSOCK_RTM_CHANGE:
+ nl_type = RTM_NEWROUTE;
+ nl_flags = NLM_F_REPLACE;
+ break;
+ case RTSOCK_RTM_DELETE:
+ nl_type = RTM_DELROUTE;
+ break;
+ case RTSOCK_RTM_GET:
+ nl_type = RTM_GETROUTE;
+ break;
+ default:
+ exit(1);
+ }
+
+ struct sockaddr *dst = get_addr(so, rtm_addrs, RTAX_DST);
+ struct sockaddr *mask = get_addr(so, rtm_addrs, RTAX_NETMASK);
+ struct sockaddr *gw = get_addr(so, rtm_addrs, RTAX_GATEWAY);
+
+ if (dst == NULL)
+ return (EINVAL);
+
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, nl_type);
+ hdr->nlmsg_flags |= nl_flags;
+
+ int plen = 0;
+ int rtm_type = RTN_UNICAST;
+
+ switch (dst->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *mask4 = (struct sockaddr_in *)mask;
+
+ if ((rtm_flags & RTF_HOST) == 0 && mask4 != NULL)
+ plen = bitcount32(mask4->sin_addr.s_addr);
+ else
+ plen = 32;
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask;
+
+ if ((rtm_flags & RTF_HOST) == 0 && mask6 != NULL)
+ plen = inet6_get_plen(&mask6->sin6_addr);
+ else
+ plen = 128;
+ break;
+ }
+ default:
+ return (ENOTSUP);
+ }
+
+ if (rtm_flags & RTF_REJECT)
+ rtm_type = RTN_PROHIBIT;
+ else if (rtm_flags & RTF_BLACKHOLE)
+ rtm_type = RTN_BLACKHOLE;
+
+ struct rtmsg *rtm = snl_reserve_msg_object(&nw, struct rtmsg);
+ rtm->rtm_family = dst->sa_family;
+ rtm->rtm_protocol = RTPROT_STATIC;
+ rtm->rtm_type = rtm_type;
+ rtm->rtm_dst_len = plen;
+
+ /* Request exact prefix match if mask is set */
+ if ((cmd == RTSOCK_RTM_GET) && (mask != NULL))
+ rtm->rtm_flags = RTM_F_PREFIX;
+
+ snl_add_msg_attr_ip(&nw, RTA_DST, dst);
+ snl_add_msg_attr_u32(&nw, RTA_TABLE, fib);
+
+ uint32_t rta_oif = 0;
+
+ if (gw != NULL) {
+ if (rtm_flags & RTF_GATEWAY) {
+ if (gw->sa_family == dst->sa_family)
+ snl_add_msg_attr_ip(&nw, RTA_GATEWAY, gw);
+ else
+ snl_add_msg_attr_ipvia(&nw, RTA_VIA, gw);
+ if (gw->sa_family == AF_INET6) {
+ struct sockaddr_in6 *gw6 = (struct sockaddr_in6 *)gw;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&gw6->sin6_addr))
+ rta_oif = gw6->sin6_scope_id;
+ }
+ } else {
+ /* Should be AF_LINK */
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)gw;
+ if (sdl->sdl_index != 0)
+ rta_oif = sdl->sdl_index;
+ }
+ }
+
+ if (dst->sa_family == AF_INET6 && rta_oif == 0) {
+ struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
+ rta_oif = dst6->sin6_scope_id;
+ }
+
+ if (rta_oif != 0)
+ snl_add_msg_attr_u32(&nw, RTA_OIF, rta_oif);
+ if (rtm_flags != 0)
+ snl_add_msg_attr_u32(&nw, NL_RTA_RTFLAGS, rtm_flags);
+
+ if (rt_metrics->rmx_mtu > 0) {
+ int off = snl_add_msg_attr_nested(&nw, RTA_METRICS);
+ snl_add_msg_attr_u32(&nw, RTAX_MTU, rt_metrics->rmx_mtu);
+ snl_end_attr_nested(&nw, off);
+ }
+
+ if (rt_metrics->rmx_weight > 0)
+ snl_add_msg_attr_u32(&nw, NL_RTA_WEIGHT, rt_metrics->rmx_weight);
+
+ if ((hdr = snl_finalize_msg(&nw)) && snl_send_message(ss, hdr)) {
+ struct snl_errmsg_data e = {};
+
+ hdr = snl_read_reply(ss, hdr->nlmsg_seq);
+ if (nl_type == NL_RTM_GETROUTE) {
+ if (hdr->nlmsg_type == NL_RTM_NEWROUTE) {
+ print_getmsg(h, hdr, dst);
+ return (0);
+ }
+ }
+
+ if (snl_parse_errmsg(ss, hdr, &e)) {
+ switch (e.error) {
+ case (ESRCH):
+ warnx("route has not been found");
+ break;
+ default:
+ if (e.error == 0)
+ break;
+ warnc(e.error, "message indicates error");
+ }
+
+ return (e.error);
+ }
+ }
+
+ return (EINVAL);
+}
+
+int
+rtmsg_nl(int cmd, int rtm_flags, int fib, int rtm_addrs,
+ struct sockaddr_storage *so, struct rt_metrics *rt_metrics)
+{
+ struct nl_helper h = {};
+
+ nl_helper_init(&h);
+ int error = rtmsg_nl_int(&h, cmd, rtm_flags, fib, rtm_addrs, so, rt_metrics);
+ nl_helper_free(&h);
+
+ return (error);
+}
+
+static void
+get_ifdata(struct nl_helper *h, uint32_t ifindex, struct snl_parsed_link_simple *link)
+{
+ struct snl_state *ss = &h->ss_cmd;
+ struct snl_writer nw;
+
+ snl_init_writer(ss, &nw);
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, NL_RTM_GETLINK);
+ struct ifinfomsg *ifmsg = snl_reserve_msg_object(&nw, struct ifinfomsg);
+ if (ifmsg != NULL)
+ ifmsg->ifi_index = ifindex;
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
+ return;
+
+ hdr = snl_read_reply(ss, hdr->nlmsg_seq);
+
+ if (hdr != NULL && hdr->nlmsg_type == RTM_NEWLINK) {
+ snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser_simple, link);
+ }
+
+ if (link->ifla_ifname == NULL) {
+ char ifname[16];
+
+ snprintf(ifname, sizeof(ifname), "if#%u", ifindex);
+ int len = strlen(ifname);
+ char *buf = snl_allocz(ss, len + 1);
+ strlcpy(buf, ifname, len + 1);
+ link->ifla_ifname = buf;
+ }
+}
+
+static void
+print_getmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct sockaddr *dst)
+{
+ struct snl_state *ss = &h->ss_cmd;
+ struct timespec ts;
+ struct snl_parsed_route r = { .rtax_weight = RT_DEFAULT_WEIGHT };
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &r))
+ return;
+
+ struct snl_parsed_link_simple link = {};
+ get_ifdata(h, r.rta_oif, &link);
+
+ if (r.rtax_mtu == 0)
+ r.rtax_mtu = link.ifla_mtu;
+ r.rta_rtflags |= (RTF_UP | RTF_DONE);
+
+ (void)printf(" route to: %s\n", routename(dst));
+
+ if (r.rta_dst)
+ (void)printf("destination: %s\n", routename(r.rta_dst));
+ struct sockaddr *mask = get_netmask(ss, r.rtm_family, r.rtm_dst_len);
+ if (mask)
+ (void)printf(" mask: %s\n", routename(mask));
+ if (r.rta_gw && (r.rta_rtflags & RTF_GATEWAY))
+ (void)printf(" gateway: %s\n", routename(r.rta_gw));
+ (void)printf(" fib: %u\n", (unsigned int)r.rta_table);
+ if (link.ifla_ifname)
+ (void)printf(" interface: %s\n", link.ifla_ifname);
+ (void)printf(" flags: ");
+ printb(r.rta_rtflags, routeflags);
+
+ struct rt_metrics rmx = {
+ .rmx_mtu = r.rtax_mtu,
+ .rmx_weight = r.rtax_weight,
+ .rmx_expire = r.rta_expire,
+ };
+
+ printf("\n%9s %9s %9s %9s %9s %10s %9s\n", "recvpipe",
+ "sendpipe", "ssthresh", "rtt,msec", "mtu ", "weight", "expire");
+ printf("%8lu ", rmx.rmx_recvpipe);
+ printf("%8lu ", rmx.rmx_sendpipe);
+ printf("%8lu ", rmx.rmx_ssthresh);
+ printf("%8lu ", 0UL);
+ printf("%8lu ", rmx.rmx_mtu);
+ printf("%8lu ", rmx.rmx_weight);
+ if (rmx.rmx_expire > 0)
+ clock_gettime(CLOCK_REALTIME_FAST, &ts);
+ else
+ ts.tv_sec = 0;
+ printf("%8ld \n", (long)(rmx.rmx_expire - ts.tv_sec));
+}
+
+static void
+print_prefix(struct nl_helper *h, char *buf, int bufsize, struct sockaddr *sa, int plen)
+{
+ int sz = 0;
+
+ if (sa == NULL) {
+ snprintf(buf, bufsize, "<NULL>");
+ return;
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+ char abuf[INET_ADDRSTRLEN];
+
+ inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf));
+ sz = snprintf(buf, bufsize, "%s", abuf);
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ char abuf[INET6_ADDRSTRLEN];
+ char *ifname = NULL;
+
+ inet_ntop(AF_INET6, &sin6->sin6_addr, abuf, sizeof(abuf));
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ struct snl_parsed_link_simple link = {};
+
+ if (sin6->sin6_scope_id != 0) {
+ get_ifdata(h, sin6->sin6_scope_id, &link);
+ ifname = link.ifla_ifname;
+ }
+ }
+ if (ifname == NULL)
+ sz = snprintf(buf, bufsize, "%s", abuf);
+ else
+ sz = snprintf(buf, bufsize, "%s%%%s", abuf, ifname);
+ break;
+ }
+ default:
+ snprintf(buf, bufsize, "unknown_af#%d", sa->sa_family);
+ plen = -1;
+ }
+
+ if (plen >= 0)
+ snprintf(buf + sz, bufsize - sz, "/%d", plen);
+}
+
+static int
+print_line_prefix(struct nlmsghdr *hdr, struct snl_msg_info *cinfo,
+ const char *cmd, const char *name)
+{
+ struct timespec tp;
+ struct tm tm;
+ char buf[32];
+
+ clock_gettime(CLOCK_REALTIME, &tp);
+ localtime_r(&tp.tv_sec, &tm);
+
+ strftime(buf, sizeof(buf), "%T", &tm);
+ int len = printf("%s.%03ld PID %4u %s %s ", buf, tp.tv_nsec / 1000000,
+ cinfo->process_id, cmd, name);
+
+ return (len);
+}
+
+static const char *
+get_action_name(struct nlmsghdr *hdr, int new_cmd)
+{
+ if (hdr->nlmsg_type == new_cmd) {
+ //return ((hdr->nlmsg_flags & NLM_F_REPLACE) ? "replace" : "add");
+ return ("add/repl");
+ } else
+ return ("delete");
+}
+
+static void
+print_nlmsg_route_nhop(struct nl_helper *h, struct snl_parsed_route *r,
+ struct rta_mpath_nh *nh, bool first)
+{
+ // gw 10.0.0.1 ifp vtnet0 mtu 1500 table inet.0
+ if (nh->gw != NULL) {
+ char gwbuf[128];
+ print_prefix(h, gwbuf, sizeof(gwbuf), nh->gw, -1);
+ printf("gw %s ", gwbuf);
+ }
+
+ if (nh->ifindex != 0) {
+ struct snl_parsed_link_simple link = {};
+
+ get_ifdata(h, nh->ifindex, &link);
+ if (nh->rtax_mtu == 0)
+ nh->rtax_mtu = link.ifla_mtu;
+ printf("iface %s ", link.ifla_ifname);
+ if (nh->rtax_mtu != 0)
+ printf("mtu %d ", nh->rtax_mtu);
+ }
+
+ if (first) {
+ switch (r->rtm_family) {
+ case AF_INET:
+ printf("table inet.%d", r->rta_table);
+ break;
+ case AF_INET6:
+ printf("table inet6.%d", r->rta_table);
+ break;
+ }
+ }
+
+ printf("\n");
+}
+
+static void
+print_nlmsg_route(struct nl_helper *h, struct nlmsghdr *hdr,
+ struct snl_msg_info *cinfo)
+{
+ struct snl_parsed_route r = { .rtax_weight = RT_DEFAULT_WEIGHT };
+ struct snl_state *ss = &h->ss_cmd;
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_route_parser, &r))
+ return;
+
+ // 20:19:41.333 add route 10.0.0.0/24 gw 10.0.0.1 ifp vtnet0 mtu 1500 table inet.0
+
+ const char *cmd = get_action_name(hdr, RTM_NEWROUTE);
+ int len = print_line_prefix(hdr, cinfo, cmd, "route");
+
+ char buf[128];
+ print_prefix(h, buf, sizeof(buf), r.rta_dst, r.rtm_dst_len);
+ len += strlen(buf) + 1;
+ printf("%s ", buf);
+
+ switch (r.rtm_type) {
+ case RTN_BLACKHOLE:
+ printf("blackhole\n");
+ return;
+ case RTN_UNREACHABLE:
+ printf("unreach(reject)\n");
+ return;
+ case RTN_PROHIBIT:
+ printf("prohibit(reject)\n");
+ return;
+ }
+
+ if (r.rta_multipath.num_nhops != 0) {
+ bool first = true;
+
+ memset(buf, ' ', sizeof(buf));
+ buf[len] = '\0';
+
+ for (uint32_t i = 0; i < r.rta_multipath.num_nhops; i++) {
+ struct rta_mpath_nh *nh = r.rta_multipath.nhops[i];
+
+ if (!first)
+ printf("%s", buf);
+ print_nlmsg_route_nhop(h, &r, nh, first);
+ first = false;
+ }
+ } else {
+ struct rta_mpath_nh nh = {
+ .gw = r.rta_gw,
+ .ifindex = r.rta_oif,
+ .rtax_mtu = r.rtax_mtu,
+ };
+
+ print_nlmsg_route_nhop(h, &r, &nh, true);
+ }
+}
+
+static const char *operstate[] = {
+ "UNKNOWN", /* 0, IF_OPER_UNKNOWN */
+ "NOTPRESENT", /* 1, IF_OPER_NOTPRESENT */
+ "DOWN", /* 2, IF_OPER_DOWN */
+ "LLDOWN", /* 3, IF_OPER_LOWERLAYERDOWN */
+ "TESTING", /* 4, IF_OPER_TESTING */
+ "DORMANT", /* 5, IF_OPER_DORMANT */
+ "UP", /* 6, IF_OPER_UP */
+};
+
+static void
+print_nlmsg_link(struct nl_helper *h, struct nlmsghdr *hdr,
+ struct snl_msg_info *cinfo)
+{
+ struct snl_parsed_link l = {};
+ struct snl_state *ss = &h->ss_cmd;
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_link_parser, &l))
+ return;
+
+ // 20:19:41.333 add iface#3 vtnet0 admin UP oper UP mtu 1500 table inet.0
+ const char *cmd = get_action_name(hdr, RTM_NEWLINK);
+ print_line_prefix(hdr, cinfo, cmd, "iface");
+
+ printf("iface#%u %s ", l.ifi_index, l.ifla_ifname);
+ printf("admin %s ", (l.ifi_flags & IFF_UP) ? "UP" : "DOWN");
+ if (l.ifla_operstate < nitems(operstate))
+ printf("oper %s ", operstate[l.ifla_operstate]);
+ if (l.ifla_mtu > 0)
+ printf("mtu %u ", l.ifla_mtu);
+
+ printf("\n");
+}
+
+static void
+print_nlmsg_addr(struct nl_helper *h, struct nlmsghdr *hdr,
+ struct snl_msg_info *cinfo)
+{
+ struct snl_parsed_addr attrs = {};
+ struct snl_state *ss = &h->ss_cmd;
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_addr_parser, &attrs))
+ return;
+
+ // add addr 192.168.1.1/24 iface vtnet0
+ const char *cmd = get_action_name(hdr, RTM_NEWADDR);
+ print_line_prefix(hdr, cinfo, cmd, "addr");
+
+ char buf[128];
+ struct sockaddr *addr = attrs.ifa_local ? attrs.ifa_local : attrs.ifa_address;
+ print_prefix(h, buf, sizeof(buf), addr, attrs.ifa_prefixlen);
+ printf("%s ", buf);
+
+ struct snl_parsed_link_simple link = {};
+ get_ifdata(h, attrs.ifa_index, &link);
+
+ if (link.ifi_flags & IFF_POINTOPOINT) {
+ char buf[64];
+ print_prefix(h, buf, sizeof(buf), attrs.ifa_address, -1);
+ printf("-> %s ", buf);
+ }
+
+ printf("iface %s ", link.ifla_ifname);
+
+ printf("\n");
+}
+
+static const char *nudstate[] = {
+ "INCOMPLETE", /* 0x01(0) */
+ "REACHABLE", /* 0x02(1) */
+ "STALE", /* 0x04(2) */
+ "DELAY", /* 0x08(3) */
+ "PROBE", /* 0x10(4) */
+ "FAILED", /* 0x20(5) */
+};
+
+#define NUD_INCOMPLETE 0x01 /* No lladdr, address resolution in progress */
+#define NUD_REACHABLE 0x02 /* reachable & recently resolved */
+#define NUD_STALE 0x04 /* has lladdr but it's stale */
+#define NUD_DELAY 0x08 /* has lladdr, is stale, probes delayed */
+#define NUD_PROBE 0x10 /* has lladdr, is stale, probes sent */
+#define NUD_FAILED 0x20 /* unused */
+
+
+static void
+print_nlmsg_neigh(struct nl_helper *h, struct nlmsghdr *hdr,
+ struct snl_msg_info *cinfo)
+{
+ struct snl_parsed_neigh attrs = {};
+ struct snl_state *ss = &h->ss_cmd;
+
+ if (!snl_parse_nlmsg(ss, hdr, &snl_rtm_neigh_parser, &attrs))
+ return;
+
+ // add addr 192.168.1.1 state %s lladdr %s iface vtnet0
+ const char *cmd = get_action_name(hdr, RTM_NEWNEIGH);
+ print_line_prefix(hdr, cinfo, cmd, "neigh");
+
+ char buf[128];
+ print_prefix(h, buf, sizeof(buf), attrs.nda_dst, -1);
+ printf("%s ", buf);
+
+ struct snl_parsed_link_simple link = {};
+ get_ifdata(h, attrs.nda_ifindex, &link);
+
+ for (unsigned int i = 0; i < nitems(nudstate); i++) {
+ if ((1 << i) & attrs.ndm_state) {
+ printf("state %s ", nudstate[i]);
+ break;
+ }
+ }
+
+ if (attrs.nda_lladdr != NULL) {
+ int if_type = link.ifi_type;
+
+ if ((if_type == IFT_ETHER || if_type == IFT_L2VLAN || if_type == IFT_BRIDGE) &&
+ NLA_DATA_LEN(attrs.nda_lladdr) == ETHER_ADDR_LEN) {
+ struct ether_addr *ll;
+
+ ll = (struct ether_addr *)NLA_DATA(attrs.nda_lladdr);
+ printf("lladdr %s ", ether_ntoa(ll));
+ } else {
+ struct sockaddr_dl sdl = {
+ .sdl_len = sizeof(sdl),
+ .sdl_family = AF_LINK,
+ .sdl_index = attrs.nda_ifindex,
+ .sdl_type = if_type,
+ .sdl_alen = NLA_DATA_LEN(attrs.nda_lladdr),
+ };
+ if (sdl.sdl_alen < sizeof(sdl.sdl_data)) {
+ void *ll = NLA_DATA(attrs.nda_lladdr);
+
+ memcpy(sdl.sdl_data, ll, sdl.sdl_alen);
+ printf("lladdr %s ", link_ntoa(&sdl));
+ }
+ }
+ }
+
+ if (link.ifla_ifname != NULL)
+ printf("iface %s ", link.ifla_ifname);
+ printf("\n");
+}
+
+static void
+print_nlmsg_generic(struct nl_helper *h, struct nlmsghdr *hdr, struct snl_msg_info *cinfo)
+{
+ const char *cmd = get_action_name(hdr, 0);
+ print_line_prefix(hdr, cinfo, cmd, "unknown message");
+ printf(" type %u\n", hdr->nlmsg_type);
+}
+
+static void
+print_nlmsg(struct nl_helper *h, struct nlmsghdr *hdr, struct snl_msg_info *cinfo)
+{
+ switch (hdr->nlmsg_type) {
+ case RTM_NEWLINK:
+ case RTM_DELLINK:
+ print_nlmsg_link(h, hdr, cinfo);
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ print_nlmsg_addr(h, hdr, cinfo);
+ break;
+ case RTM_NEWROUTE:
+ case RTM_DELROUTE:
+ print_nlmsg_route(h, hdr, cinfo);
+ break;
+ case RTM_NEWNEIGH:
+ case RTM_DELNEIGH:
+ print_nlmsg_neigh(h, hdr, cinfo);
+ break;
+ default:
+ print_nlmsg_generic(h, hdr, cinfo);
+ }
+
+ fflush(stdout);
+ snl_clear_lb(&h->ss_cmd);
+}
+
+void
+monitor_nl(int fib)
+{
+ struct snl_state ss_event = {};
+ struct nl_helper h;
+
+ nl_init_socket(&ss_event);
+ nl_helper_init(&h);
+
+ int groups[] = {
+ RTNLGRP_LINK,
+ RTNLGRP_NEIGH,
+ RTNLGRP_NEXTHOP,
+#ifdef INET
+ RTNLGRP_IPV4_IFADDR,
+ RTNLGRP_IPV4_ROUTE,
+#endif
+#ifdef INET6
+ RTNLGRP_IPV6_IFADDR,
+ RTNLGRP_IPV6_ROUTE,
+#endif
+ };
+
+ int optval = 1;
+ socklen_t optlen = sizeof(optval);
+ setsockopt(ss_event.fd, SOL_NETLINK, NETLINK_MSG_INFO, &optval, optlen);
+
+ for (unsigned int i = 0; i < nitems(groups); i++) {
+ int error;
+ int optval = groups[i];
+ socklen_t optlen = sizeof(optval);
+ error = setsockopt(ss_event.fd, SOL_NETLINK,
+ NETLINK_ADD_MEMBERSHIP, &optval, optlen);
+ if (error != 0)
+ warn("Unable to subscribe to group %d", optval);
+ }
+
+ struct snl_msg_info attrs = {};
+ struct nlmsghdr *hdr;
+ while ((hdr = snl_read_message_dbg(&ss_event, &attrs)) != NULL)
+ {
+ print_nlmsg(&h, hdr, &attrs);
+ snl_clear_lb(&h.ss_cmd);
+ snl_clear_lb(&ss_event);
+ }
+
+ snl_free(&ss_event);
+ nl_helper_free(&h);
+ exit(0);
+}
+
+static void
+print_flushed_route(struct snl_parsed_route *r, struct sockaddr *gw)
+{
+ struct sockaddr *sa = r->rta_dst;
+
+ printf("%-20.20s ", r->rta_rtflags & RTF_HOST ?
+ routename(sa) : netname(sa));
+ sa = gw;
+ printf("%-20.20s ", routename(sa));
+ printf("-fib %-3d ", r->rta_table);
+ printf("done\n");
+}
+
+static int
+flushroute_one(struct nl_helper *h, struct snl_parsed_route *r)
+{
+ struct snl_state *ss = &h->ss_cmd;
+ struct snl_errmsg_data e = {};
+ struct snl_writer nw;
+
+ snl_init_writer(ss, &nw);
+
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, NL_RTM_DELROUTE);
+ struct rtmsg *rtm = snl_reserve_msg_object(&nw, struct rtmsg);
+ rtm->rtm_family = r->rtm_family;
+ rtm->rtm_dst_len = r->rtm_dst_len;
+
+ snl_add_msg_attr_u32(&nw, RTA_TABLE, r->rta_table);
+ snl_add_msg_attr_ip(&nw, RTA_DST, r->rta_dst);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(ss, hdr))
+ return (ENOMEM);
+
+ if (!snl_read_reply_code(ss, hdr->nlmsg_seq, &e)) {
+ return (e.error);
+ if (e.error == EPERM)
+ errc(1, e.error, "RTM_DELROUTE failed:");
+ else
+ warnc(e.error, "RTM_DELROUTE failed:");
+ return (true);
+ };
+
+ if (verbose) {
+ struct snl_msg_info attrs = {};
+ print_nlmsg(h, hdr, &attrs);
+ }
+ else {
+ if (r->rta_multipath.num_nhops != 0) {
+ for (uint32_t i = 0; i < r->rta_multipath.num_nhops; i++) {
+ struct rta_mpath_nh *nh = r->rta_multipath.nhops[i];
+
+ print_flushed_route(r, nh->gw);
+ }
+
+ } else
+ print_flushed_route(r, r->rta_gw);
+ }
+
+ return (0);
+}
+
+int
+flushroutes_fib_nl(int fib, int af)
+{
+ struct snl_state ss = {};
+ struct snl_writer nw;
+ struct nl_helper h = {};
+
+ nl_init_socket(&ss);
+ snl_init_writer(&ss, &nw);
+
+ struct nlmsghdr *hdr = snl_create_msg_request(&nw, NL_RTM_GETROUTE);
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ struct rtmsg *rtm = snl_reserve_msg_object(&nw, struct rtmsg);
+ rtm->rtm_family = af;
+ snl_add_msg_attr_u32(&nw, RTA_TABLE, fib);
+
+ if (! (hdr = snl_finalize_msg(&nw)) || !snl_send_message(&ss, hdr)) {
+ snl_free(&ss);
+ return (EINVAL);
+ }
+
+ struct snl_errmsg_data e = {};
+ uint32_t nlm_seq = hdr->nlmsg_seq;
+
+ nl_helper_init(&h);
+
+ while ((hdr = snl_read_reply_multi(&ss, nlm_seq, &e)) != NULL) {
+ struct snl_parsed_route r = { .rtax_weight = RT_DEFAULT_WEIGHT };
+ int error;
+
+ if (!snl_parse_nlmsg(&ss, hdr, &snl_rtm_route_parser, &r))
+ continue;
+ if (verbose) {
+ struct snl_msg_info attrs = {};
+ print_nlmsg(&h, hdr, &attrs);
+ }
+ if (r.rta_table != (uint32_t)fib || r.rtm_family != af)
+ continue;
+ if ((r.rta_rtflags & RTF_GATEWAY) == 0)
+ continue;
+ if (debugonly)
+ continue;
+
+ if ((error = flushroute_one(&h, &r)) != 0) {
+ if (error == EPERM)
+ errc(1, error, "RTM_DELROUTE failed:");
+ else
+ warnc(error, "RTM_DELROUTE failed:");
+ }
+ snl_clear_lb(&h.ss_cmd);
+ }
+
+ snl_free(&ss);
+ nl_helper_free(&h);
+
+ return (e.error);
+}
+
diff --git a/sbin/route/tests/Makefile b/sbin/route/tests/Makefile
index eb278981f8cd..9d634d7c48b8 100644
--- a/sbin/route/tests/Makefile
+++ b/sbin/route/tests/Makefile
@@ -1,11 +1,9 @@
-# $FreeBSD$
-
PACKAGE= tests
-ATF_TESTS_SH+= \
- basic
+ATF_TESTS_SH+= basic
+# Tests reuse jail names and so cannot run in parallel.
+TEST_METADATA.basic+= is_exclusive=true
-${PACKAGE}FILES+= \
- utils.subr
+${PACKAGE}FILES+= utils.subr
.include <bsd.test.mk>
diff --git a/sbin/route/tests/Makefile.depend b/sbin/route/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/sbin/route/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/route/tests/basic.sh b/sbin/route/tests/basic.sh
index 370a96a25892..2e2ab9dba97f 100644
--- a/sbin/route/tests/basic.sh
+++ b/sbin/route/tests/basic.sh
@@ -1,5 +1,5 @@
#-
-# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2020 Ahsan Barkati
#
@@ -24,7 +24,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
. $(atf_get_srcdir)/utils.subr
@@ -118,8 +117,66 @@ basic_v6_cleanup()
vnet_cleanup
}
+atf_test_case "interface_route_v4" "cleanup"
+interface_route_v4_head()
+{
+ atf_set descr 'add interface route for v4'
+ atf_set require.user root
+ atf_set require.progs jail jq
+}
+
+interface_route_v4_body()
+{
+ epair=$(vnet_mkepair)
+ ifconfig ${epair}a up
+ vnet_mkjail alcatraz ${epair}b
+
+ # add interface route
+ jexec alcatraz route add "192.0.2.1" -iface ${epair}b
+ gateway=$(check_route "alcatraz" "192.0.2.1")
+
+ if [ -z "${gateway}" ]; then
+ atf_fail "Failed to add interface route."
+ fi
+}
+
+interface_route_v4_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_test_case "interface_route_v6" "cleanup"
+interface_route_v6_head()
+{
+ atf_set descr 'add interface route for v6'
+ atf_set require.user root
+ atf_set require.progs jail jq
+}
+
+interface_route_v6_body()
+{
+ epair=$(vnet_mkepair)
+ ifconfig ${epair}a up
+ vnet_mkjail alcatraz ${epair}b
+
+ # add interface route
+ jexec alcatraz route add -6 "2001:db8:cc4b::1" -iface ${epair}b
+ gateway=$(check_route "alcatraz" "2001:db8:cc4b::1")
+
+ if [ -z "${gateway}" ]; then
+ atf_fail "Failed to add interface route."
+ fi
+}
+
+interface_route_v6_cleanup()
+{
+ vnet_cleanup
+}
+
atf_init_test_cases()
{
atf_add_test_case "basic_v4"
atf_add_test_case "basic_v6"
+ atf_add_test_case "interface_route_v4"
+ atf_add_test_case "interface_route_v6"
}
diff --git a/sbin/route/tests/utils.subr b/sbin/route/tests/utils.subr
index fda9980eb78d..51c15a6ef9f6 100644
--- a/sbin/route/tests/utils.subr
+++ b/sbin/route/tests/utils.subr
@@ -1,5 +1,5 @@
#-
-# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2020 Ahsan Barkati
#
@@ -24,7 +24,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
#
. $(atf_get_srcdir)/../../sys/common/vnet.subr
diff --git a/sbin/routed/Makefile b/sbin/routed/Makefile
index c01ab4178443..b88bf17efffc 100644
--- a/sbin/routed/Makefile
+++ b/sbin/routed/Makefile
@@ -1,7 +1,6 @@
# Make `routed` for FreeBSD
-# $FreeBSD$
-PACKAGE=runtime
+PACKAGE=rip
PROG= routed
MAN= routed.8
SRCS= if.c input.c main.c output.c parms.c radix.c rdisc.c table.c trace.c
diff --git a/sbin/routed/Makefile.depend b/sbin/routed/Makefile.depend
index c369ae60fd72..e85de6035de9 100644
--- a/sbin/routed/Makefile.depend
+++ b/sbin/routed/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/protocols \
diff --git a/sbin/routed/Makefile.inc b/sbin/routed/Makefile.inc
index 265f86d1ed55..e09337e43724 100644
--- a/sbin/routed/Makefile.inc
+++ b/sbin/routed/Makefile.inc
@@ -1,3 +1,3 @@
-# $FreeBSD$
+PACKAGE= rip
.include "../Makefile.inc"
diff --git a/sbin/routed/defs.h b/sbin/routed/defs.h
index 9b0218163d3b..81f3131f2676 100644
--- a/sbin/routed/defs.h
+++ b/sbin/routed/defs.h
@@ -27,10 +27,6 @@
* 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.
- *
- * @(#)defs.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
*/
@@ -88,9 +84,6 @@
#define RIPVERSION RIPv2
#include <protocols/routed.h>
-#ifndef __RCSID
-#define __RCSID(_s) static const char rcsid[] UNUSED = _s
-#endif
#ifndef __COPYRIGHT
#define __COPYRIGHT(_s) static const char copyright[] UNUSED = _s
#endif
diff --git a/sbin/routed/if.c b/sbin/routed/if.c
index da451e69e4d8..72894942fe05 100644
--- a/sbin/routed/if.c
+++ b/sbin/routed/if.c
@@ -27,17 +27,12 @@
* 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 <stdint.h>
#include "defs.h"
#include "pathnames.h"
-
-__RCSID("$FreeBSD$");
-
struct ifhead ifnet = LIST_HEAD_INITIALIZER(ifnet); /* all interfaces */
struct ifhead remote_if = LIST_HEAD_INITIALIZER(remote_if); /* remote interfaces */
diff --git a/sbin/routed/input.c b/sbin/routed/input.c
index ef1c025e8f81..238933d29e6b 100644
--- a/sbin/routed/input.c
+++ b/sbin/routed/input.c
@@ -27,14 +27,9 @@
* 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 "defs.h"
-
-__RCSID("$FreeBSD$");
-
static void input(struct sockaddr_in *, struct interface *, struct interface *,
struct rip *, int);
static void input_route(naddr, naddr, struct rt_spare *, struct netinfo *);
diff --git a/sbin/routed/main.c b/sbin/routed/main.c
index d3b6a4484689..49be52ccbdf4 100644
--- a/sbin/routed/main.c
+++ b/sbin/routed/main.c
@@ -27,8 +27,6 @@
* 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 "defs.h"
@@ -37,11 +35,6 @@
#include <fcntl.h>
#include <sys/file.h>
-__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993 "
- "The Regents of the University of California."
- " All rights reserved.");
-__RCSID("$FreeBSD$");
-
pid_t mypid;
naddr myaddr; /* system address */
diff --git a/sbin/routed/output.c b/sbin/routed/output.c
index af4085ac02da..726fab2c11b5 100644
--- a/sbin/routed/output.c
+++ b/sbin/routed/output.c
@@ -27,15 +27,10 @@
* 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 "defs.h"
-__RCSID("$FreeBSD$");
-
-
u_int update_seqno;
diff --git a/sbin/routed/parms.c b/sbin/routed/parms.c
index c05951700581..59f141c76c66 100644
--- a/sbin/routed/parms.c
+++ b/sbin/routed/parms.c
@@ -27,17 +27,12 @@
* 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 "defs.h"
#include "pathnames.h"
#include <sys/stat.h>
-__RCSID("$FreeBSD$");
-
-
static struct parm *parms;
struct intnet *intnets;
struct r1net *r1nets;
diff --git a/sbin/routed/pathnames.h b/sbin/routed/pathnames.h
index 5a31fa7e86bc..f5b8bd31b4d5 100644
--- a/sbin/routed/pathnames.h
+++ b/sbin/routed/pathnames.h
@@ -27,10 +27,6 @@
* 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.
- *
- * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
*/
#include <paths.h>
diff --git a/sbin/routed/radix.c b/sbin/routed/radix.c
index 2372b8c68581..ad5b1df1f572 100644
--- a/sbin/routed/radix.c
+++ b/sbin/routed/radix.c
@@ -27,10 +27,6 @@
* 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.
- *
- * @(#)radix.c 8.4 (Berkeley) 11/2/94
- *
- * $FreeBSD$
*/
/*
@@ -38,9 +34,6 @@
*/
#include "defs.h"
-
-__RCSID("$FreeBSD$");
-
#define log(x, msg) syslog(x, msg)
#define panic(s) {log(LOG_ERR,s); exit(1);}
#define min(a,b) (((a)<(b))?(a):(b))
diff --git a/sbin/routed/radix.h b/sbin/routed/radix.h
index 4bbd70359331..35f7dcf7e08c 100644
--- a/sbin/routed/radix.h
+++ b/sbin/routed/radix.h
@@ -27,10 +27,6 @@
* 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.
- *
- * @(#)radix.h 8.2 (Berkeley) 10/31/94
- *
- * $FreeBSD$
*/
#ifndef __RADIX_H_
diff --git a/sbin/routed/rdisc.c b/sbin/routed/rdisc.c
index 3494f061b64b..2dfcc15768d8 100644
--- a/sbin/routed/rdisc.c
+++ b/sbin/routed/rdisc.c
@@ -27,17 +27,12 @@
* 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 "defs.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
-
-__RCSID("$FreeBSD$");
-
/* router advertisement ICMP packet */
struct icmp_ad {
u_int8_t icmp_type; /* type of message */
diff --git a/sbin/routed/routed.8 b/sbin/routed/routed.8
index 6988e916fa78..334c828b943e 100644
--- a/sbin/routed/routed.8
+++ b/sbin/routed/routed.8
@@ -27,16 +27,20 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD$
-.\"
-.Dd June 27, 2022
+.Dd May 20, 2025
.Dt ROUTED 8
.Os
.Sh NAME
.Nm routed ,
.Nm rdisc
.Nd network RIP and router discovery routing daemon
+.Sh DEPRECATION NOTICE
+The
+.Nm routed
+and
+.Nm rdisc
+utilities are deprecated and will be removed in
+.Fx 16.0 .
.Sh SYNOPSIS
.Nm
.Op Fl isqdghmpAtv
diff --git a/sbin/routed/rtquery/Makefile b/sbin/routed/rtquery/Makefile
index a9893a988537..bd81c590a1ae 100644
--- a/sbin/routed/rtquery/Makefile
+++ b/sbin/routed/rtquery/Makefile
@@ -1,6 +1,5 @@
# Make `routed` tools for BSD/OS
# $Revision: 1.6 $
-# $FreeBSD$
PACKAGE=runtime
PROG= rtquery
diff --git a/sbin/routed/rtquery/Makefile.depend b/sbin/routed/rtquery/Makefile.depend
index c369ae60fd72..e85de6035de9 100644
--- a/sbin/routed/rtquery/Makefile.depend
+++ b/sbin/routed/rtquery/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/protocols \
diff --git a/sbin/routed/rtquery/rtquery.8 b/sbin/routed/rtquery/rtquery.8
index 4f16e88d5c09..ff46a3414dcf 100644
--- a/sbin/routed/rtquery/rtquery.8
+++ b/sbin/routed/rtquery/rtquery.8
@@ -1,12 +1,16 @@
.\" $Revision: 2.27 $
-.\" $FreeBSD$
.\"
-.Dd June 1, 1996
+.Dd May 20, 2025
.Dt RTQUERY 8
.Os
.Sh NAME
.Nm rtquery
.Nd query routing daemons for their routing tables
+.Sh DEPRECATION NOTICE
+The
+.Nm
+utility is deprecated and will be removed in
+.Fx 16.0 .
.Sh SYNOPSIS
.Nm
.Op Fl np1
diff --git a/sbin/routed/rtquery/rtquery.c b/sbin/routed/rtquery/rtquery.c
index 883c51fabc68..67a635545624 100644
--- a/sbin/routed/rtquery/rtquery.c
+++ b/sbin/routed/rtquery/rtquery.c
@@ -27,11 +27,8 @@
* 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/cdefs.h>
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
@@ -52,24 +49,6 @@
#endif
#define UNUSED __attribute__((unused))
-#ifndef __RCSID
-#define __RCSID(_s) static const char rcsid[] UNUSED = _s
-#endif
-#ifndef __COPYRIGHT
-#define __COPYRIGHT(_s) static const char copyright[] UNUSED = _s
-#endif
-__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\n"
- "The Regents of the University of California."
- " All rights reserved.\n");
-#ifdef __NetBSD__
-__RCSID("$NetBSD$");
-#elif defined(__FreeBSD__)
-__RCSID("$FreeBSD$");
-#else
-__RCSID("$Revision: 2.26 $");
-#ident "$Revision: 2.26 $"
-#endif
-
#ifndef sgi
#define _HAVE_SIN_LEN
#endif
@@ -131,7 +110,7 @@ static void query_loop(char *argv[], int) __attribute((__noreturn__));
static int getnet(char *, struct netinfo *);
static u_int std_mask(u_int);
static int parse_quote(char **, const char *, char *, char *, int);
-static void usage(void);
+static void usage(void) __dead2;
int
diff --git a/sbin/routed/table.c b/sbin/routed/table.c
index 648a1d1a6b25..b43c8bb873a5 100644
--- a/sbin/routed/table.c
+++ b/sbin/routed/table.c
@@ -27,14 +27,9 @@
* 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 "defs.h"
-
-__RCSID("$FreeBSD$");
-
static struct rt_spare *rts_better(struct rt_entry *);
static struct rt_spare rts_empty = {0,0,0,HOPCNT_INFINITY,0,0,0};
static void set_need_flash(void);
diff --git a/sbin/routed/trace.c b/sbin/routed/trace.c
index 98c29218fb89..59929b130b1a 100644
--- a/sbin/routed/trace.c
+++ b/sbin/routed/trace.c
@@ -27,8 +27,6 @@
* 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$
*/
#define RIPCMDS
@@ -38,9 +36,6 @@
#include <sys/signal.h>
#include <fcntl.h>
-__RCSID("$FreeBSD$");
-
-
int tracelevel, new_tracelevel;
FILE *ftrace; /* output trace file */
diff --git a/sbin/rtsol/Makefile b/sbin/rtsol/Makefile
index ee22f5756b64..30041076e0d9 100644
--- a/sbin/rtsol/Makefile
+++ b/sbin/rtsol/Makefile
@@ -12,7 +12,6 @@
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE.
#
-# $FreeBSD$
.PATH: ${SRCTOP}/usr.sbin/rtsold
diff --git a/sbin/rtsol/Makefile.depend b/sbin/rtsol/Makefile.depend
index d897c480ee77..2326fec704fd 100644
--- a/sbin/rtsol/Makefile.depend
+++ b/sbin/rtsol/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/rtsol/Makefile.depend.options b/sbin/rtsol/Makefile.depend.options
index c20f954f5bc4..a0449df3a893 100644
--- a/sbin/rtsol/Makefile.depend.options
+++ b/sbin/rtsol/Makefile.depend.options
@@ -1,4 +1,3 @@
-# $FreeBSD$
# This file is not autogenerated - take care!
DIRDEPS_OPTIONS= CASPER
diff --git a/sbin/savecore/Makefile b/sbin/savecore/Makefile
index bcc59a01b795..7e194a62deb1 100644
--- a/sbin/savecore/Makefile
+++ b/sbin/savecore/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PACKAGE=runtime
CONFS= minfree
VAR_CRASH= /var/crash
@@ -20,4 +18,7 @@ CFLAGS+= -DWITH_CASPER
LIBADD+= casper cap_fileargs cap_syslog
.endif
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
.include <bsd.prog.mk>
diff --git a/sbin/savecore/Makefile.depend b/sbin/savecore/Makefile.depend
index 9252d37765d2..eec802016aec 100644
--- a/sbin/savecore/Makefile.depend
+++ b/sbin/savecore/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
@@ -8,10 +7,9 @@ DIRDEPS = \
lib/libc \
lib/libcapsicum \
lib/libcompiler_rt \
- lib/libnv \
- lib/libutil \
- lib/libxo \
+ lib/libxo/libxo \
lib/libz \
+ lib/libzstd \
.include <dirdeps.mk>
diff --git a/sbin/savecore/Makefile.depend.options b/sbin/savecore/Makefile.depend.options
index 171e8ef8fb8a..20f5a17299f5 100644
--- a/sbin/savecore/Makefile.depend.options
+++ b/sbin/savecore/Makefile.depend.options
@@ -1,4 +1,3 @@
-# $FreeBSD$
# This file is not autogenerated - take care!
DIRDEPS_OPTIONS= CASPER
diff --git a/sbin/savecore/savecore.8 b/sbin/savecore/savecore.8
index b1e0c38c6b44..1fb79c51f98d 100644
--- a/sbin/savecore/savecore.8
+++ b/sbin/savecore/savecore.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" From: @(#)savecore.8 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
-.Dd April 4, 2022
+.Dd July 16, 2025
.Dt SAVECORE 8
.Os
.Sh NAME
@@ -72,7 +69,7 @@ Generate output via
.Xr libxo 3
in a selection of different human and machine readable formats.
See
-.Xr xo_parse_args 3
+.Xr xo_options 7
for details on command line arguments.
.It Fl C
Check to see if a dump exists,
@@ -196,7 +193,7 @@ is meant to be called near the end of the initialization file
.Xr zstd 1 ,
.Xr getbootfile 3 ,
.Xr libxo 3 ,
-.Xr xo_parse_args 3 ,
+.Xr xo_options 7 ,
.Xr mem 4 ,
.Xr textdump 4 ,
.Xr tar 5 ,
diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c
index 9f1f04422a55..2f3ad3adc7ab 100644
--- a/sbin/savecore/savecore.c
+++ b/sbin/savecore/savecore.c
@@ -62,9 +62,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/kerneldump.h>
@@ -104,6 +101,9 @@ __FBSDID("$FreeBSD$");
#define STATUS_GOOD 1
#define STATUS_UNKNOWN 2
+#define LOG_OPTIONS LOG_PERROR
+#define LOG_FACILITY LOG_DAEMON
+
static cap_channel_t *capsyslog;
static fileargs_t *capfa;
static bool checkfor, compress, uncompress, clear, force, keep; /* flags */
@@ -338,7 +338,8 @@ write_header_info(xo_handle_t *xostdout, const struct kerneldumpheader *kdh,
printheader(xoinfo, kdh, device, bounds, status);
xo_close_container_h(xoinfo, "crashdump");
xo_flush_h(xoinfo);
- xo_finish_h(xoinfo);
+ if (xo_finish_h(xoinfo) < 0)
+ xo_err(EXIT_FAILURE, "stdout");
fclose(info);
return (0);
@@ -436,7 +437,7 @@ check_space(const char *savedir, int savedirfd, off_t dumpsize, int bounds)
if (fstatfs(savedirfd, &fsbuf) < 0) {
logmsg(LOG_ERR, "%s: %m", savedir);
- exit(1);
+ exit(EXIT_FAILURE);
}
spacefree = ((off_t) fsbuf.f_bavail * fsbuf.f_bsize) / 1024;
totfree = ((off_t) fsbuf.f_bfree * fsbuf.f_bsize) / 1024;
@@ -1126,7 +1127,7 @@ DoFile(const char *savedir, int savedirfd, const char *device)
if (checkfor) {
printf("A dump exists on %s\n", device);
close(fddev);
- exit(0);
+ exit(EXIT_SUCCESS);
}
if (kdhl.panicstring[0] != '\0')
@@ -1278,7 +1279,8 @@ nuke:
"error while clearing the dump header: %m");
}
xo_close_container_h(xostdout, "crashdump");
- xo_finish_h(xostdout);
+ if (xo_finish_h(xostdout) < 0)
+ xo_err(EXIT_FAILURE, "stdout");
free(dumpkey);
free(temp);
close(fddev);
@@ -1303,7 +1305,7 @@ devify(int argc, char **argv)
devs = malloc(argc * sizeof(*argv));
if (devs == NULL) {
logmsg(LOG_ERR, "malloc(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
for (i = 0; i < argc; i++) {
if (strncmp(argv[i], _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
@@ -1314,16 +1316,16 @@ devify(int argc, char **argv)
fullpath = malloc(PATH_MAX);
if (fullpath == NULL) {
logmsg(LOG_ERR, "malloc(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
l = snprintf(fullpath, PATH_MAX, "%s%s", _PATH_DEV,
argv[i]);
if (l < 0) {
logmsg(LOG_ERR, "snprintf(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
} else if (l >= PATH_MAX) {
logmsg(LOG_ERR, "device name too long");
- exit(1);
+ exit(EXIT_FAILURE);
}
devs[i] = fullpath;
}
@@ -1348,7 +1350,7 @@ enum_dumpdevs(int *argcp)
argv = malloc(n * sizeof(*argv));
if (argv == NULL) {
logmsg(LOG_ERR, "malloc(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
for (;;) {
fsp = getfsent();
@@ -1362,13 +1364,13 @@ enum_dumpdevs(int *argcp)
argv = realloc(argv, n * sizeof(*argv));
if (argv == NULL) {
logmsg(LOG_ERR, "realloc(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
}
argv[argc] = strdup(fsp->fs_spec);
if (argv[argc] == NULL) {
logmsg(LOG_ERR, "strdup(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
argc++;
}
@@ -1385,7 +1387,7 @@ init_caps(int argc, char **argv)
capcas = cap_init();
if (capcas == NULL) {
logmsg(LOG_ERR, "cap_init(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
/*
* The fileargs capability does not currently provide a way to limit
@@ -1396,20 +1398,21 @@ init_caps(int argc, char **argv)
0, &rights, FA_OPEN);
if (capfa == NULL) {
logmsg(LOG_ERR, "fileargs_init(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
caph_cache_catpages();
caph_cache_tzdata();
if (caph_enter_casper() != 0) {
logmsg(LOG_ERR, "caph_enter_casper(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
capsyslog = cap_service_open(capcas, "system.syslog");
if (capsyslog == NULL) {
logmsg(LOG_ERR, "cap_service_open(system.syslog): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
cap_close(capcas);
+ cap_openlog(capsyslog, "savecore", LOG_OPTIONS, LOG_FACILITY);
}
static void
@@ -1420,7 +1423,7 @@ usage(void)
" savecore -C [-v] [device ...]",
" savecore -L [-fvZz] [-m maxdumps] [directory]",
" savecore [-fkuvz] [-m maxdumps] [directory [device ...]]");
- exit(1);
+ exit(EXIT_FAILURE);
}
int
@@ -1437,12 +1440,12 @@ main(int argc, char **argv)
savedir = ".";
comp_desired = KERNELDUMP_COMP_NONE;
- openlog("savecore", LOG_PERROR, LOG_DAEMON);
+ openlog("savecore", LOG_OPTIONS, LOG_FACILITY);
signal(SIGINFO, infohandler);
argc = xo_parse_args(argc, argv);
if (argc < 0)
- exit(1);
+ exit(EXIT_FAILURE);
while ((ch = getopt(argc, argv, "CcfkLm:uvZz")) != -1)
switch(ch) {
@@ -1465,7 +1468,7 @@ main(int argc, char **argv)
maxdumps = atoi(optarg);
if (maxdumps <= 0) {
logmsg(LOG_ERR, "Invalid maxdump value");
- exit(1);
+ exit(EXIT_FAILURE);
}
break;
case 'u':
@@ -1505,7 +1508,7 @@ main(int argc, char **argv)
error = chdir(argv[0]);
if (error) {
logmsg(LOG_ERR, "chdir(%s): %m", argv[0]);
- exit(1);
+ exit(EXIT_FAILURE);
}
savedir = argv[0];
argc--;
@@ -1527,7 +1530,7 @@ main(int argc, char **argv)
savedirfd = open(savedir, O_RDONLY | O_DIRECTORY);
if (savedirfd < 0) {
logmsg(LOG_ERR, "open(%s): %m", savedir);
- exit(1);
+ exit(EXIT_FAILURE);
}
(void)cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, CAP_FSTATAT,
CAP_FSTATFS, CAP_PREAD, CAP_SYMLINKAT, CAP_FTRUNCATE, CAP_UNLINKAT,
@@ -1537,7 +1540,7 @@ main(int argc, char **argv)
CAP_RENAMEAT_TARGET);
if (caph_rights_limit(savedirfd, &rights) < 0) {
logmsg(LOG_ERR, "cap_rights_limit(): %m");
- exit(1);
+ exit(EXIT_FAILURE);
}
/* Enter capability mode. */
@@ -1550,7 +1553,7 @@ main(int argc, char **argv)
if (checkfor) {
if (verbose)
printf("No dump exists\n");
- exit(1);
+ exit(EXIT_FAILURE);
}
if (verbose)
logmsg(LOG_WARNING, "no dumps found");
@@ -1559,14 +1562,14 @@ main(int argc, char **argv)
if (verbose)
logmsg(LOG_WARNING,
"unsaved dumps found but not saved");
- exit(1);
+ exit(EXIT_FAILURE);
} else if (verbose)
logmsg(LOG_WARNING, "no unsaved dumps found");
} else if (verbose) {
logmsg(LOG_NOTICE, "%d cores saved in %s\n", nsaved, savedir);
}
- return (0);
+ exit(EXIT_SUCCESS);
}
static void
diff --git a/sbin/savecore/tests/Makefile b/sbin/savecore/tests/Makefile
new file mode 100644
index 000000000000..7ec3c9aeedcc
--- /dev/null
+++ b/sbin/savecore/tests/Makefile
@@ -0,0 +1,6 @@
+ATF_TESTS_SH= livedump_test log_test
+
+# The test fails if any kernel modules are loaded while the test is running.
+TEST_METADATA.livedump_test+= is_exclusive=true
+
+.include <bsd.test.mk>
diff --git a/sbin/savecore/tests/livedump_test.sh b/sbin/savecore/tests/livedump_test.sh
new file mode 100644
index 000000000000..382b090235ee
--- /dev/null
+++ b/sbin/savecore/tests/livedump_test.sh
@@ -0,0 +1,54 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024 Mark Johnston <markj@FreeBSD.org>
+#
+
+atf_test_case livedump_kldstat
+livedump_kldstat_head()
+{
+ atf_set "descr" "Test livedump integrity"
+ atf_set "require.progs" kgdb
+ atf_set "require.user" root
+}
+livedump_kldstat_body()
+{
+ atf_check -e match:"savecore .*- livedump" savecore -L .
+
+ kernel=$(sysctl -n kern.bootfile)
+
+ if ! [ -f /usr/lib/debug/${kernel}.debug ]; then
+ atf_skip "No debug symbols for the running kernel"
+ fi
+
+ # Implement kldstat using gdb script.
+ cat >./kldstat.gdb <<'__EOF__'
+printf "Id Refs Address Size Name\n"
+set $_lf = linker_files.tqh_first
+while ($_lf)
+ printf "%2d %4d %p %8x %s\n", $_lf->id, $_lf->refs, $_lf->address, $_lf->size, $_lf->filename
+ set $_lf = $_lf->link.tqe_next
+end
+__EOF__
+
+ # Ignore stderr since kgdb prints some warnings about inaccessible
+ # source files.
+ #
+ # Use a script to source the main gdb script, otherwise kgdb prints
+ # a bunch of line noise that is annoying to filter out.
+ echo "source ./kldstat.gdb" > ./script.gdb
+ atf_check -o save:out -e ignore \
+ kgdb -q ${kernel} ./livecore.0 < ./script.gdb
+
+ # Get rid of gunk printed by kgdb.
+ sed -i '' -n -e 's/^(kgdb) //' -e '/^Id Refs /,$p' out
+
+ # The output of kgdb should match the output of kldstat.
+ atf_check -o save:kldstat kldstat
+ atf_check diff kldstat out
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case livedump_kldstat
+}
diff --git a/sbin/savecore/tests/log_test.sh b/sbin/savecore/tests/log_test.sh
new file mode 100644
index 000000000000..9b006a2f2644
--- /dev/null
+++ b/sbin/savecore/tests/log_test.sh
@@ -0,0 +1,25 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2025 Stéphane Rochoy <stephane.rochoy@stormshield.eu>
+#
+
+atf_test_case log_perror
+log_perror_head()
+{
+ atf_set "descr" "Test LOG_PERROR behavior"
+}
+log_perror_body()
+{
+ atf_check -s exit:1 \
+ -o ignore \
+ -e save:savecore.err \
+ savecore -vC /dev/missing
+ grep -qE 'savecore [0-9]+ - - /dev/missing: No such file or directory' savecore.err \
+ || atf_fail "missing/invalid error output"
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case log_perror
+}
diff --git a/sbin/sconfig/Makefile b/sbin/sconfig/Makefile
deleted file mode 100644
index 8617eaf4b1cc..000000000000
--- a/sbin/sconfig/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# Cronyx Id: sbin.sconfig.Makefile,v 1.1.4.1 2003/02/17 12:51:24 rik Exp $
-# $FreeBSD$
-
-PACKAGE=utilities
-PROG= sconfig
-MAN= sconfig.8
-WARNS?= 2
-CFLAGS+= -I${SRCTOP}/sys/dev/cp
-
-.include <bsd.prog.mk>
diff --git a/sbin/sconfig/sconfig.8 b/sbin/sconfig/sconfig.8
deleted file mode 100644
index a55bf911e3dd..000000000000
--- a/sbin/sconfig/sconfig.8
+++ /dev/null
@@ -1,608 +0,0 @@
-.\" Copyright (c) 2002-2004 Roman Kurakin <rik@cronyx.ru>
-.\" Copyright (c) 2002-2004 Cronyx Engineering
-.\" All rights reserved.
-.\"
-.\" This software is distributed with NO WARRANTIES, not even the implied
-.\" warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-.\"
-.\" Authors grant any other persons or organisations a permission to use,
-.\" modify and redistribute this software in source and binary forms,
-.\" as long as this message is kept with the software, all derivative
-.\" works or modified versions.
-.\"
-.\" $FreeBSD$
-.Dd October 3, 2016
-.Dt SCONFIG 8 i386
-.Os
-.Sh NAME
-.Nm sconfig
-.Nd "channel configuration utility for Cronyx adapters"
-.Sh SYNOPSIS
-.Nm
-.Op Fl aimsxeftuc
-.Op Ar device
-.Op Ar data_rate_options
-.Op Ar protocol_options ...
-.Op Ar interface_options ...
-.Sh DESCRIPTION
-The
-.Nm
-utility is used for configuring the channel options of the Cronyx
-adapters.
-In asynchronous mode, all parameters should be set using the standard
-.Xr stty 1
-utility.
-With
-.Nm ,
-it is only possible to set some of them (see below).
-.Pp
-Some of the options can be set only on free channels,
-that is when the corresponding network interface is in the
-.Cm down
-state in the synchronous mode,
-and the terminal device
-.Pa /dev/tty*
-is closed in asynchronous mode.
-.Pp
-Other channel options can be changed
-.Dq "on the fly" .
-Generally, the channel options are set up during the operating system startup,
-for example, from the
-.Pa /etc/rc
-script.
-.Pp
-Note that not all options make sense in every particular case,
-and an attempt to set some of them may hung up the channel
-or the whole adapter.
-.\"--------------------------------------------------------------
-.Ss "Information Options"
-Only one of these options can be specified.
-If information option is specified,
-.Nm
-will show the corresponding information and will ignore all other options,
-except
-.Ar device .
-See also the description of the
-.Ar device
-argument.
-.Bl -tag -width indent
-.It <none>
-This will show settings of the channel.
-.It Fl a
-Print all settings of the channel.
-.It Fl i
-Print interface settings, equal to the output of the
-.Xr ifconfig 8
-utility.
-.It Fl m
-Print modem signal status.
-The description of all signals can be found in any modem documentation.
-Only LE signal should be described.
-If this signal is ON then the channel is busy.
-If it is OFF then the channel is free.
-.It Fl s
-Print brief channel statistics.
-This is the generic statistics,
-see also the
-.Fl x , e , f , t ,
-and
-.Fl u
-options.
-For a description of the output, see below.
-.Pp
-This statistics is very useful if something goes wrong.
-For example, if all interrupt counters are zero then the device
-was configured to use an interrupt that was not registered in the
-BIOS for use with the ISA bus.
-.It Fl x
-Print full channel statistics.
-This options prints additional counters,
-but with less precision than with the
-.Fl s
-option.
-.It Fl e
-Print brief E1/G703 statistics.
-If this option is selected, the
-statistics accumulated over the last 15 minutes is printed.
-For a description of the output, see below.
-.It Fl f
-Print full E1/G703 statistics.
-This option shows all E1/G703 statistics that the
-.Fl e
-option shows,
-plus total statistics for the whole period of time and statistics for
-last 24 hours (if available).
-For a description of the output, see below.
-.It Fl t
-Print brief E3/T3/STS-1 statistics.
-If this option is selected, the
-statistics accumulated over the last 15 minutes is printed.
-For a description of the output, see below.
-.It Fl u
-Print full E3/T3/STS-1 statistics.
-This option shows all E3/T3/STS-1 statistics that the
-.Fl t
-option shows,
-plus total statistics for the whole period of time and statistics for
-last 24 hours (if available).
-For a description of the output, see below.
-.It Fl c
-Cleans all kind of statistics.
-.El
-.\"--------------------------------------------------------------
-.Ss "Device Selection"
-The device is selected using the name of the network interface,
-as shown by
-.Xr ifconfig 8 .
-The channel number depends on the order the drivers were loaded into the system.
-Sometimes people confuse channel number and adapter number because of the
-same spelling.
-The adapter number appears in the kernel context, while the channel number
-is in the configuration context.
-.Bl -tag -width indent
-.It <none>
-If the device name is omitted,
-.Nm
-will print information about all channels of all Cronyx adapters
-available in the system.
-If some settings need to be made, the device name must be specified.
-.It Li cx Ns Ar ##
-This is the channel name for the Sigma family of Cronyx adapters.
-(ISA bus.)
-.It Li ct Ns Ar ##
-This is the channel name for the Tau family of Cronyx adapters.
-(ISA bus.)
-.It Li cp Ns Ar ##
-This is the channel name for the Tau-PCI family of Cronyx adapters.
-(PCI bus.)
-.It Li ce Ns Ar ##
-This is the channel name for the Tau32-PCI family of Cronyx adapters.
-(PCI bus.)
-.El
-.\"--------------------------------------------------------------
-.Ss "Data Rate Options"
-.Bl -tag -width indent
-.It Ar value
-A non-zero value will set the data rate to a given value
-in asynchronous mode,
-and will set the data rate and internal clock source of synchronization
-in synchronous mode.
-A zero value is equivalent to specifying the
-.Cm extclock
-option.
-The transmitted data (TxD) are synchronized using the internal on-board timing
-generator, the internally generated timing signal is driven on the TXCOUT pin,
-and the signal on the TXCIN pin is ignored.
-This mode is used for direct
-terminal-to-terminal communication, e.g., when connecting two computers together
-in synchronous mode with a relatively short cable.
-This method should also be
-used for testing channels with an external loopback connector.
-.It Cm extclock
-Set the external timing clock source for synchronous channels.
-External clock mode is the most commonly used method for connecting
-external modem hardware.
-In this mode,
-the external timing signal is received on the TXCIN pin of the connector,
-and it is used as a synchronization clock for transmitting data (TxD).
-.Pp
-Note: in
-.Cm extclock
-mode, the device cannot determine the value of the external timing clock
-since it does not have the built-in clock gauge.
-.El
-.\"--------------------------------------------------------------
-.Ss "Protocol Options"
-Note: these option can only be used on a free channel, and they require
-specifying the device name.
-.Bl -tag -width indent
-.It Cm async
-(Only for Sigma family.)
-Select the asynchronous protocol (or mode).
-In this mode, Cronyx adapters behave as normal serial devices,
-and standard serial communications utilities can be used to
-work with them.
-All asynchronous settings should be set using the standard
-serial communications configuration utilities, e.g.,
-.Xr stty 1 .
-With
-.Nm ,
-it is only possible to set some of them.
-.It Cm cisco
-Select the Cisco HDLC synchronous protocol.
-.It Cm fr
-Select the Frame Relay synchronous protocol
-.Tn ( ANSI
-T1.617 Annex D).
-.It Cm ppp
-Select the synchronous PPP protocol.
-.It Sm Cm keepalive No = Bro Cm on , off Brc Sm
-Turn on/off transmission of keepalive messages.
-This option is used only for synchronous PPP.
-If this option is
-.Cm on ,
-PPP will periodically send ECHO-REQUEST messages.
-If it will not receive any ECHO-REPLY messages for
-some (definite) period of time it will break the connection.
-It is used for tracking the line state.
-.It Cm idle
-This mode is reported when using Netgraph.
-An actual protocol depends on the type of a connected Netgraph node,
-and it cannot be changed with
-.Nm .
-.El
-.\"--------------------------------------------------------------
-.Ss "Interface Options"
-Not all of these options can be set on a busy channel, and not all of them
-are applicable to all kinds of adapters/channels.
-For all dual-state options,
-.Cm off
-is the default value.
-None of these options can be used in the asynchronous mode,
-except for the
-.Cm debug
-option.
-.Bl -tag -width indent
-.It Sm Cm port No = Bro Cm rs232 , v35 , rs449 Brc Sm
-Set the port type for old Sigma models.
-.It Sm Cm cfg No = Bro Cm A , B , C Brc Sm
-Set the configuration for the adapter.
-This option can be used only with Tau/E1
-and Tau/G703 adapters, and only if all channels are free.
-.Bl -tag -width ".Cm cfg Ns = Ns Cm A"
-.It Cm cfg Ns = Ns Cm A
-Two independent E1/G703 channels.
-This is the default setting.
-.It Cm cfg Ns = Ns Cm B
-(Only for ISA models.)
-For Tau/G703 this means one G703 channel and one digital channel.
-For Tau/E1, the first physical channel is divided into two subchannels.
-One of them goes to the first logical channel, another one goes to the
-second physical channel.
-Second (logical) channel is the digital channel.
-.It Cm cfg Ns = Ns Cm C
-(Only for E1 models.)
-In this mode, first
-physical channel consists of three data flows.
-Two of them go to the two (logical) channels.
-The last one goes to the second physical channel.
-On newer models (Tau32-PCI, Tau-PCI/2E1 and Tau-PCI/4E1),
-this programs the hardware to use a single source of synchronization
-and pass all unused (in both channels) timeslots from
-one channel to another.
-.El
-.Pp
-For a detailed description of available configuration modes,
-see the adapter documentation.
-This option cannot be set on a busy channel.
-.It Sm Cm loop No = Bro Cm on , off Brc Sm
-Turn on/off internal loopback.
-This mode is useful for debugging.
-When this mode is
-.Cm on ,
-some data should be sent.
-If no interrupts are generated, chances are that
-the corresponding IRQ configuration entry in the BIOS
-was not switched from
-.Dq Li "PCI/ISA PNP"
-to
-.Dq Li "Legacy ISA" .
-.It Sm Cm rloop No = Bro Cm on , off Brc Sm
-(Only for Tau32-PCI and Tau-PCI/E3.)
-Turn on/off remote loopback feature.
-This mode is also useful for debugging.
-.It Sm Cm dpll No = Bro Cm on , off Brc Sm
-Turn on/off digital phase locked loop mode (DPLL).
-When enabled, the receiver
-timing clock signal is derived from the received data.
-Must be used with the NRZI
-encoding to avoid the synchronization loss.
-.It Sm Cm nrzi No = Bro Cm on , off Brc Sm
-Turn on/off NRZI encoding.
-If
-.Cm off ,
-NRZ encoding is used.
-.Bl -tag -width "NRZI"
-.It NRZ
-The zero bit is transmitted by the zero signal level,
-the one bit is transmitted by the positive signal level.
-.It NRZI
-The zero bit is transmitted by the change of the signal
-level, the one bit is by the constant signal level.
-Commonly used with the
-.Cm dpll Ns = Ns Cm on
-option.
-.El
-.It Sm Cm invclk No = Bro Cm on , off Brc Sm
-(Tau and Tau-PCI only.)
-Invert both the transmit and receive clock signals.
-.It Sm Cm invrclk No = Bro Cm on , off Brc Sm
-(Tau-PCI only.)
-Invert the receive clock signals.
-.It Sm Cm invtclk No = Bro Cm on , off Brc Sm
-(Tau-PCI only.)
-Invert the transmit clock signals.
-.It Sm Cm higain No = Bro Cm on , off Brc Sm
-(E1 only.)
-In off state the sensitivity is -12 dB.
-Turn on/off increasing the E1 receiver's non-linear sensitivity to -30dB.
-This allows increasing of the line distance.
-.It Sm Cm cablen No = Bro Cm on , off Brc Sm
-(Tau-PCI/T3 and Tau-PCI/STS-1 only.)
-Turn on/off adjusting of the transmit signal for a long cable T3/STS-1.
-.It Sm Cm monitor No = Bro Cm on , off Brc Sm
-(Tau32-PCI, Tau-PCI/2E1 and Tau-PCI/4E1 only.)
-Turn on/off increasing of the E1 receiver's linear sensitivity to -30dB.
-This can be used for the interception purposes.
-.It Sm Cm phony No = Bro Cm on , off Brc Sm
-(Tau32-PCI and Tau-PCI E1 family only.)
-Turn on/off the so-called
-.Dq phony
-mode.
-This mode allows
-receiving raw CEPT frames from the E1 line.
-Raw frames can be accessed, for example, with the raw protocol.
-Packets would come at a rate of 500 frames per second
-with length
-.No 16* Ns Ar N
-(for Tau-PCI/E1 model), where
-.Ar N
-is the number of timeslots.
-For
-Tau-PCI/2E1 and Tau-PCI/4E1,
-.Ar N
-should be equal to 32 regardless of the number of
-used timeslots.
-.It Sm Cm unfram No = Bro Cm on , off Brc Sm
-(Tau32-PCI, Tau-PCI/2E1 and Tau-PCI/4E1 only.)
-Turn on/off unframed mode.
-.Bl -tag -width ".Cm unfram Ns = Ns Cm off"
-.It Cm unfram Ns = Ns Cm on
-Switch channel to the unframed G.703 mode.
-.It Cm unfram Ns = Ns Cm off
-Switch channel to the framed E1 (G.704) mode.
-.El
-.It Sm Cm scrambler No = Bro Cm on , off Brc Sm
-(Tau32-PCI, Tau-PCI/G.703, Tau-PCI/2E1, and
-Tau-PCI/4E1 in unframed mode only.)
-Turn on/off scrambling of the G.703 data.
-.It Sm Cm use16 No = Bro Cm on , off Brc Sm
-(Tau32-PCI and Tau-PCI E1 family only.)
-Turn on/off the usage of the 16th timeslot for data transmission.
-Normally, the 16th timeslot is used for signalling information
-(multiframing CAS).
-.It Sm Cm crc4 No = Bro Cm on , off Brc Sm
-(E1 only.)
-Turn on/off CRC4 superframe mode.
-.It Sm Cm syn No = Bro Cm int , rcv , rcv0 , rcv1 , rcv2 , rcv3 Brc Sm
-.Bl -tag -width ".Cm rcv3"
-.It Cm int
-Use an internal clock generator for G703 transmitter
-(clock master).
-.It Cm rcv
-Use the G703 receiver data clock as the transmit clock
-(clock slave).
-.It Cm rcv0 , rcv1 , rcv2 , rcv3
-Use the G703 receiver clock of the other channel
-(E1 models only).
-.El
-.It Cm dir Ns = Ns Ar number
-(Tau32-PCI, Tau-PCI/2E1 and Tau-PCI/4E1 only.)
-Bind a logical channel to a physical channel.
-Using this parameter it is possible, for example, to split
-physical E1 channel into several logical channels.
-.It Cm ts Ns = Ns Ar interval
-(E1 only.)
-Set up the list of timeslots for use by the channel.
-The timeslots are numbered from 1 to 31,
-and are separated by a comma or a minus sign,
-giving an interval.
-Example:
-.Dq Li ts=1-3,5,17 .
-.It Cm pass Ns = Ns Ar interval
-(Tau/E1 only.)
-Set up the list of timeslots, translated to the E1 subchannel in
-.Cm cfg Ns = Ns Cm B
-and
-.Cm cfg Ns = Ns Cm C
-configurations.
-.It Sm Cm debug No = Bro Cm 0 , 1 , 2 Brc Sm
-Turn on/off debug messages.
-.Bl -tag -width 2n
-.It Cm 0
-Turn debug messages off.
-.It Cm 1
-Turn debug messages on, equivalent to the
-.Cm debug
-option of the
-.Xr ifconfig 8
-utility.
-.It Cm 2
-High intensive debug messages, for developers only.
-.El
-.El
-.\"--------------------------------------------------------------
-.Sh EXAMPLES
-Set up channel 1 for use with the HDSL modem or any other
-synchronous leased-line modem, and PPP/HDLC protocol (for Sigma):
-.Bd -literal -offset indent
-sconfig cx1 ppp extclock
-ifconfig cx1 158.250.244.2 158.250.244.1 up
-.Ed
-.Pp
-Set up channel 0 of Tau/E1 for use with the Cisco protocol
-over the E1 link, with a single virtual connection.
-The DLCI number is detected automatically.
-Use timeslots 1-10:
-.Bd -literal -offset indent
-sconfig ct0 cisco ts=1-10
-ifconfig ct0 158.250.244.2 158.250.244.1 up
-.Ed
-.Pp
-Set up channel 0 for the synchronous null-modem link to the nearby computer,
-internal clock source, 256000 bits/sec, protocol Cisco/HDLC (for Tau):
-.Bd -literal -offset indent
-sconfig ct0 cisco 256000
-ifconfig ct0 200.1.1.1 200.1.1.2 up
-.Ed
-.Pp
-Set up channel 1 for the leased line link using the data-only
-null-modem cable (or modems like Zelax+ M115).
-Synchronous DPLL mode, 128000
-bits/sec, protocol PPP/HDLC, NRZI encoding (for Sigma):
-.Bd -literal -offset indent
-sconfig cx1 ppp 128000 nrzi=on dpll=on
-ifconfig cx1 158.250.244.2 158.250.244.1 up
-.Ed
-.\"--------------------------------------------------------------
-.Sh DIAGNOSTICS
-This section contains a description of abbreviations used by
-.Nm
-while displaying various statistics.
-For a description of options related to
-statistics, please see above.
-.\"--------------------------------------------------------------
-.Ss Statistics
-When running, the driver gathers statistics about the channels, which
-can be accessed using the
-.Nm
-utility,
-or through the
-.Xr ioctl 2
-call
-.Dv SERIAL_GETSTAT .
-.Pp
-.Bl -tag -width indent -compact
-.It Va Rintr
-Total number of receive interrupts.
-.It Va Tintr
-Total number of transmit interrupts.
-.It Va Mintr
-Total number of modem interrupts.
-.It Va Ibytes
-Total bytes received.
-.It Va Ipkts
-Total packets received (for HDLC mode).
-.It Va Ierrs
-Number of receive errors.
-.It Va Obytes
-Total bytes transmitted.
-.It Va Opkts
-Total packets transmitted (for HDLC mode).
-.It Va Oerrs
-Number of transmit errors.
-.El
-.\"--------------------------------------------------------------
-.Ss E1/G.703 Statistics
-For E1 and G.703 channels, the SNMP-compatible statistics data are gathered
-(see RFC 1406).
-It can be accessed using the
-.Nm
-utility,
-or through the
-.Xr ioctl 2
-call
-.Dv SERIAL_GETESTAT .
-.Bl -tag -width ".Va RCRC Pq Va rcrce"
-.It Va Unav Pq Va uas
-Unavailable seconds: receiving all ones, loss of carrier, or loss of
-signal.
-.It Va Degr Pq Va dm
-Degraded minutes: having error rate more than 10E-6, not counting unavailable
-and severely errored seconds.
-.It Va Bpv Pq Va bpv
-HDB3 bipolar violation errors.
-.It Va Fsyn Pq Va fse
-Frame synchronization errors (E1 only).
-.It Va CRC Pq Va crce
-CRC4 errors (E1).
-.It Va RCRC Pq Va rcrce
-Remote CRC4 errors: E-bit counter (E1).
-.It Va Err Pq Va es
-Errored seconds: any framing errors, or out of frame sync, or any slip events.
-.It Va Lerr Pq Va les
-Line errored seconds: any BPV.
-.It Va Sev Pq Va ses
-Severely errored seconds: 832 or more framing errors, or 2048 or more bipolar
-violations.
-.It Va Bur Pq Va bes
-Bursty errored seconds: more than 1 framing error, but not severely errored.
-.It Va Oof Pq Va oofs
-Severely errored framing seconds: out of frame sync.
-.It Va Slp Pq Va css
-Controlled slip seconds: any slip buffer overflow or underflow.
-.El
-.\"--------------------------------------------------------------
-.Ss E1/G.703 Status
-The
-.Nm
-utility also prints the E1/G.703 channel status.
-The status can have the
-following values (non-exclusive):
-.Pp
-.Bl -tag -width ".Li FARLOMF" -compact
-.It Li Ok
-The channel is in a valid state, synchronized.
-.It Li LOS
-Loss of sync.
-.It Li AIS
-Receiving unframed all ones (E1 only).
-.It Li LOF
-Loss of framing (E1 only).
-.It Li LOMF
-Loss of multiframing (E1 only).
-.It Li FARLOF
-Receiving remote alarm (E1 only).
-.It Li AIS16
-Receiving all ones in the timeslot 16 (E1 only).
-.It Li FARLOMF
-Receiving distant multiframe alarm (E1 only).
-.It Li TSTREQ
-Receiving test request code (G.703 only).
-.It Li TSTERR
-Test error (G.703 only).
-.El
-.\"--------------------------------------------------------------
-.Sh SEE ALSO
-.Xr stty 1 ,
-.Xr ioctl 2 ,
-.Xr ifconfig 8 ,
-.Xr route 8 ,
-.\"--------------------------------------------------------------
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Fx 5.2 .
-The
-.Nm
-utility is a replacement for the
-.Nm cxconfig
-and
-.Nm ctconfig
-utilities that were used in the past with
-.Fx
-drivers.
-Those two utilities and
-.Nm
-are not compatible,
-and therefore all scripts using them have to be rewritten.
-Moreover,
-.Tn Linux
-and
-.Fx
-versions of the
-.Nm
-utility are not fully compatible.
-.\"--------------------------------------------------------------
-.Sh AUTHORS
-.An Cronyx Engineering Aq Mt info@cronyx.ru
-.Pp
-.Pa http://www.cronyx.ru
-.\"--------------------------------------------------------------
-.Sh BUGS
-All software produced by Cronyx Engineering is thoroughly tested.
-But as created by a man, it can contain some bugs.
-If you have caught one, try to localize it and send an email with the
-description of the bug, and all operations that you have done.
-We will try to reproduce the error and fix it.
diff --git a/sbin/sconfig/sconfig.c b/sbin/sconfig/sconfig.c
deleted file mode 100644
index 48363036e412..000000000000
--- a/sbin/sconfig/sconfig.c
+++ /dev/null
@@ -1,1212 +0,0 @@
-/*
- * Channel configuration utility for Cronyx serial adapters.
- *
- * Copyright (C) 1997-2002 Cronyx Engineering.
- * Author: Serge Vakulenko, <vak@cronyx.ru>
- *
- * Copyright (C) 1999-2005 Cronyx Engineering.
- * Author: Roman Kurakin, <rik@cronyx.ru>
- *
- * This software is distributed with NO WARRANTIES, not even the implied
- * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Authors grant any other persons or organisations permission to use
- * or modify this software as long as this message is kept with the software,
- * all derivative works or modified versions.
- *
- * Cronyx Id: sconfig.c,v 1.4.2.2 2005/11/09 13:01:35 rik Exp $
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include "cserial.h"
-
-#define MAXCHAN 128
-
-int vflag, eflag, sflag, mflag, cflag, fflag, iflag, aflag, xflag;
-int tflag, uflag;
-char mask[64];
-int adapter_type; /* 0-sigma, 1-tau, 2-taupci, 3-tau32 */
-char chan_name[16];
-
-static void
-usage (void)
-{
- printf(
-"Serial Adapter Configuration Utility\n"
-"Copyright (C) 1998-2005 Cronyx Engineering.\n"
-"See also man sconfig (8)\n"
-"Usage:\n"
-"\tsconfig [-aimsxeftuc] [device [parameters ...]]\n"
-"\n"
-"Options:\n"
-"\t<no options>\t\t -- print channel options\n"
-"\t-a\t\t\t -- print all settings of the channel\n"
-"\t-i\t\t\t -- print network interface status\n"
-"\t-m\t\t\t -- print modem signal status\n"
-"\t-s\t\t\t -- print channel statistics\n"
-"\t-x\t\t\t -- print extended channel statistics\n"
-"\t-e\t\t\t -- print short E1/G703 statistics\n"
-"\t-f\t\t\t -- print full E1/G703 statistics\n"
-"\t-t\t\t\t -- print short E3/T3/STS-1 statistics\n"
-"\t-u\t\t\t -- print full E3/T3/STS-1 statistics\n"
-"\t-c\t\t\t -- clear statistics\n"
-"\nParameters:\n"
-"\t<number>\t\t -- baud rate, internal clock\n"
-"\textclock\t\t -- external clock (default)\n"
-"\nProtocol options:\n"
-"\tasync\t\t\t -- asynchronous protocol\n"
-#ifdef __linux__
-"\tsync\t\t\t -- synchronous protocol\n"
-#endif
-"\tcisco\t\t\t -- Cisco/HDLC protocol\n"
-"\tfr\t\t\t -- Frame Relay protocol\n"
-#ifdef __linux__
-"\t dlci<number>\t -- Add new DLCI\n"
-#endif
-"\tppp\t\t\t -- PPP protocol\n"
-#ifdef __linux__
-"\trbrg\t\t\t -- Remote bridge\n"
-"\traw\t\t\t -- raw HDLC protocol\n"
-"\tpacket\t\t\t -- packetized HDLC protocol\n"
-"\tidle\t\t\t -- no protocol\n"
-#else
-"\t keepalive={on,of}\t -- Enable/disable keepalive\n"
-#endif
-"\nInterface options:\n"
-"\tport={rs232,v35,rs449}\t -- port type (for old models of Sigma)\n"
-"\tcfg={A,B,C}\t\t -- adapter configuration\n"
-"\tloop={on,off}\t\t -- internal loopback\n"
-"\trloop={on,off}\t\t -- remote loopback\n"
-"\tdpll={on,off}\t\t -- DPLL mode\n"
-"\tnrzi={on,off}\t\t -- NRZI encoding\n"
-"\tinvclk={on,off}\t\t -- invert receive and transmit clock\n"
-"\tinvrclk={on,off}\t -- invert receive clock\n"
-"\tinvtclk={on,off}\t -- invert transmit clock\n"
-"\thigain={on,off}\t\t -- E1 high non linear input sensitivity \n\t\t\t\t (long line)\n"
-"\tmonitor={on,off}\t -- E1 high linear input sensitivity \n\t\t\t\t (interception mode)\n"
-"\tphony={on,off}\t\t -- E1 telepnony mode\n"
-"\tunfram={on,off}\t\t -- E1 unframed mode\n"
-"\tscrambler={on,off}\t -- G.703 scrambling mode\n"
-"\tuse16={on,off}\t\t -- E1 timeslot 16 usage\n"
-"\tcrc4={on,off}\t\t -- E1 CRC4 mode\n"
-#ifdef __linux__
-"\tami={on,off}\t\t -- E1 AMI or HDB3 line code\n"
-"\tmtu={size}\t\t -- set MTU in bytes\n"
-#endif
-"\tsyn={int,rcv,rcvX}\t -- G.703 transmit clock\n"
-"\tts=...\t\t\t -- E1 timeslots\n"
-"\tpass=...\t\t -- E1 subchannel timeslots\n"
-"\tdir=<num>\t\t -- connect channel to link<num>\n"
-/*"\trqken={size}\t\t -- set receive queue length in packets\n"*/
-/*"\tcablen={on,off}\t\t -- T3/STS-1 high transmitter output for long cable\n"*/
-"\tdebug={0,1,2}\t\t -- enable/disable debug messages\n"
- );
- exit (0);
-}
-
-static unsigned long
-scan_timeslots (char *s)
-{
- char *e;
- long v;
- int i;
- unsigned long ts, lastv;
-
- ts = lastv = 0;
- for (;;) {
- v = strtol (s, &e, 10);
- if (e == s)
- break;
- if (*e == '-') {
- lastv = v;
- s = e+1;
- continue;
- }
- if (*e == ',')
- ++e;
-
- if (lastv)
- for (i=lastv; i<v; ++i)
- ts |= 1L << i;
- ts |= 1L << v;
-
- lastv = 0;
- s = e;
- }
- return ts;
-}
-
-static int
-ppp_ok (void)
-{
-#ifdef __linux__
- int s, p;
- struct ifreq ifr;
- char pttyname[32];
- char *p1, *p2;
- int i, j;
- int ppp_disc = N_PPP;
-
- /*
- * Open a socket for doing the ioctl operations.
- */
- s = socket (AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- fprintf (stderr, "Error opening socket.\n");
- return 0;
- }
- strncpy (ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name));
- if (ioctl (s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0) {
- /* Ok. */
- close (s);
- return 1;
- }
- close (s);
-
- /* open pseudo-tty and try to set PPP discipline */
- sprintf (pttyname, "/dev/ptyXX");
- p1 = &pttyname[8];
- p2 = &pttyname[9];
- for (i=0; i<16; i++) {
- struct stat stb;
-
- *p1 = "pqrstuvwxyzabcde"[i];
- *p2 = '0';
- if (stat (pttyname, &stb) < 0)
- continue;
- for (j=0; j<16; j++) {
- *p2 = "0123456789abcdef"[j];
- p = open (pttyname, 2);
- if (p > 0) {
- if (ioctl (p, TIOCSETD, &ppp_disc) < 0) {
- fprintf (stderr, "No PPP discipline in kernel.\n");
- close (p);
- return 0;
- }
- close (p);
- return 1;
- }
- }
- }
- fprintf (stderr, "Cannot get pseudo-tty.\n");
- return 0;
-#else
- return 1;
-#endif
-}
-
-static char *
-format_timeslots (unsigned long s)
-{
- static char buf [100];
- char *p = buf;
- int i;
-
- for (i=1; i<32; ++i)
- if ((s >> i) & 1) {
- int prev = (i > 1) & (s >> (i-1));
- int next = (i < 31) & (s >> (i+1));
-
- if (prev) {
- if (next)
- continue;
- *p++ = '-';
- } else if (p > buf)
- *p++ = ',';
-
- if (i >= 10)
- *p++ = '0' + i / 10;
- *p++ = '0' + i % 10;
- }
- *p = 0;
- return buf;
-}
-
-static void
-print_modems (int fd, int need_header)
-{
- int status;
-
- if (ioctl (fd, TIOCMGET, &status) < 0) {
- perror ("getting modem status");
- return;
- }
- if (need_header)
- printf ("Channel\tLE\tDTR\tDSR\tRTS\tCTS\tCD\n");
- printf ("%s\t%s\t%s\t%s\t%s\t%s\t%s\n", chan_name,
- status & TIOCM_LE ? "On" : "-",
- status & TIOCM_DTR ? "On" : "-",
- status & TIOCM_DSR ? "On" : "-",
- status & TIOCM_RTS ? "On" : "-",
- status & TIOCM_CTS ? "On" : "-",
- status & TIOCM_CD ? "On" : "-");
-}
-
-static void
-#ifdef __linux__
-print_ifconfig (int fd)
-#else
-print_ifconfig (int fd __unused)
-#endif
-{
- char buf [64];
-#ifdef __linux__
- char protocol [8];
-
- if (ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0 &&
- strcmp (protocol, "fr") == 0)
- sprintf (buf, "ifconfig %sd16 2>/dev/null", chan_name);
- else
-#endif
- sprintf (buf, "ifconfig %s 2>/dev/null", chan_name);
- system (buf);
-}
-
-static void
-set_debug_ifconfig (int on)
-{
- char buf [64];
- sprintf (buf, "ifconfig %s %sdebug 2>/dev/null", chan_name,
- on ? "" : "-");
- system (buf);
-}
-
-static char *
-format_long (unsigned long val)
-{
- static char s[32];
- int l;
- l = sprintf (s, "%lu", val);
- if (l>7 && !sflag) {
- s[3] = s[2];
- s[2] = s[1];
- s[1] = '.';
- s[4] = 'e';
- sprintf (s + 5, "%02d", l-1);
- }
- return s;
-}
-
-static void
-print_stats (int fd, int need_header)
-{
- struct serial_statistics st;
- unsigned long sarr [9];
- int i;
-
- if (ioctl (fd, SERIAL_GETSTAT, &st) < 0) {
- perror ("getting statistics");
- return;
- }
- if (need_header) {
- if (sflag) {
- printf (" ------------Receive----------- "
- "------------Transmit----------\n");
- printf ("Channel Interrupts Packets Errors "
- "Interrupts Packets Errors\n");
- }
- else {
- printf (" --------Receive--------------- "
- "--------Transmit-------------- Modem\n");
- printf ("Channel Intrs Bytes Packets Errors "
- "Intrs Bytes Packets Errors Intrs\n");
- }
- }
-
- sarr [0] = st.rintr;
- sarr [1] = st.ibytes;
- sarr [2] = st.ipkts;
- sarr [3] = st.ierrs;
- sarr [4] = st.tintr;
- sarr [5] = st.obytes;
- sarr [6] = st.opkts;
- sarr [7] = st.oerrs;
- sarr [8] = st.mintr;
- printf ("%s", chan_name);
- if (sflag) {
- printf ("\t%-12lu%-12lu%-12lu%-12lu%-12lu%-12lu", sarr[0],
- sarr[2], sarr[3], sarr[4], sarr[6], sarr[7]);
- } else {
- for (i = 0; i < 9; i++)
- printf ("\t%s", format_long (sarr [i]));
- printf ("\n");
- }
-}
-
-static void
-clear_stats (int fd)
-{
- if (ioctl (fd, SERIAL_CLRSTAT, 0) < 0) {
- perror ("clearing statistics");
- exit (-1);
- }
-}
-
-static char *
-format_e1_status (unsigned long status)
-{
- static char buf [80];
-
- if (status == 0)
- return "n/a";
- if (status & E1_NOALARM)
- return "Ok";
- buf[0] = 0;
- if (status & E1_LOS) strcat (buf, ",LOS");
- if (status & E1_AIS) strcat (buf, ",AIS");
- if (status & E1_LOF) strcat (buf, ",LOF");
- if (status & E1_LOMF) strcat (buf, ",LOMF");
- if (status & E1_CRC4E) strcat (buf, ",CRC4E");
- if (status & E1_FARLOF) strcat (buf, ",FARLOF");
- if (status & E1_AIS16) strcat (buf, ",AIS16");
- if (status & E1_FARLOMF) strcat (buf, ",FARLOMF");
-/* if (status & E1_TSTREQ) strcat (buf, ",TSTREQ");*/
-/* if (status & E1_TSTERR) strcat (buf, ",TSTERR");*/
- if (buf[0] == ',')
- return buf+1;
- return "Unknown";
-}
-
-static void
-print_frac (int leftalign, unsigned long numerator, unsigned long divider)
-{
- int n;
-
- if (numerator < 1 || divider < 1) {
- printf (leftalign ? "/- " : " -");
- return;
- }
- n = (int) (0.5 + 1000.0 * numerator / divider);
- if (n < 1000) {
- printf (leftalign ? "/.%-3d" : " .%03d", n);
- return;
- }
- putchar (leftalign ? '/' : ' ');
-
- if (n >= 1000000) n = (n+500) / 1000 * 1000;
- else if (n >= 100000) n = (n+50) / 100 * 100;
- else if (n >= 10000) n = (n+5) / 10 * 10;
-
- switch (n) {
- case 1000: printf (".999"); return;
- case 10000: n = 9990; break;
- case 100000: n = 99900; break;
- case 1000000: n = 999000; break;
- }
- if (n < 10000) printf ("%d.%d", n/1000, n/10%100);
- else if (n < 100000) printf ("%d.%d", n/1000, n/100%10);
- else if (n < 1000000) printf ("%d.", n/1000);
- else printf ("%d", n/1000);
-}
-
-static void
-print_e1_stats (int fd, int need_header)
-{
- struct e1_statistics st;
- int i, maxi;
-
- if (need_header)
- printf ("Chan\t Unav/Degr Bpv/Fsyn CRC/RCRC Err/Lerr Sev/Bur Oof/Slp Status\n");
-
- if (ioctl (fd, SERIAL_GETESTAT, &st) < 0)
- return;
- printf ("%s\t", chan_name);
-
- /* Unavailable seconds, degraded minutes */
- print_frac (0, st.currnt.uas, st.cursec);
- print_frac (1, 60 * st.currnt.dm, st.cursec);
-
- /* Bipolar violations, frame sync errors */
- print_frac (0, st.currnt.bpv, st.cursec);
- print_frac (1, st.currnt.fse, st.cursec);
-
- /* CRC errors, remote CRC errors (E-bit) */
- print_frac (0, st.currnt.crce, st.cursec);
- print_frac (1, st.currnt.rcrce, st.cursec);
-
- /* Errored seconds, line errored seconds */
- print_frac (0, st.currnt.es, st.cursec);
- print_frac (1, st.currnt.les, st.cursec);
-
- /* Severely errored seconds, bursty errored seconds */
- print_frac (0, st.currnt.ses, st.cursec);
- print_frac (1, st.currnt.bes, st.cursec);
-
- /* Out of frame seconds, controlled slip seconds */
- print_frac (0, st.currnt.oofs, st.cursec);
- print_frac (1, st.currnt.css, st.cursec);
-
- printf (" %s\n", format_e1_status (st.status));
-
- if (fflag) {
- /* Print total statistics. */
- printf ("\t");
- print_frac (0, st.total.uas, st.totsec);
- print_frac (1, 60 * st.total.dm, st.totsec);
-
- print_frac (0, st.total.bpv, st.totsec);
- print_frac (1, st.total.fse, st.totsec);
-
- print_frac (0, st.total.crce, st.totsec);
- print_frac (1, st.total.rcrce, st.totsec);
-
- print_frac (0, st.total.es, st.totsec);
- print_frac (1, st.total.les, st.totsec);
-
- print_frac (0, st.total.ses, st.totsec);
- print_frac (1, st.total.bes, st.totsec);
-
- print_frac (0, st.total.oofs, st.totsec);
- print_frac (1, st.total.css, st.totsec);
-
- printf (" -- Total\n");
-
- /* Print 24-hour history. */
- maxi = (st.totsec - st.cursec) / 900;
- if (maxi > 48)
- maxi = 48;
- for (i=0; i<maxi; ++i) {
- printf (" ");
- print_frac (0, st.interval[i].uas, 15*60);
- print_frac (1, 60 * st.interval[i].dm, 15*60);
-
- print_frac (0, st.interval[i].bpv, 15*60);
- print_frac (1, st.interval[i].fse, 15*60);
-
- print_frac (0, st.interval[i].crce, 15*60);
- print_frac (1, st.interval[i].rcrce, 15*60);
-
- print_frac (0, st.interval[i].es, 15*60);
- print_frac (1, st.interval[i].les, 15*60);
-
- print_frac (0, st.interval[i].ses, 15*60);
- print_frac (1, st.interval[i].bes, 15*60);
-
- print_frac (0, st.interval[i].oofs, 15*60);
- print_frac (1, st.interval[i].css, 15*60);
-
- if (i < 3)
- printf (" -- %dm\n", (i+1)*15);
- else
- printf (" -- %dh %dm\n", (i+1)/4, (i+1)%4*15);
- }
- }
-}
-
-static char *
-format_e3_status (unsigned long status)
-{
- static char buf [80];
-
- buf[0] = 0;
- if (status & E3_LOS) strcat (buf, ",LOS");
- if (status & E3_TXE) strcat (buf, ",XMIT");
- if (buf[0] == ',')
- return buf+1;
- return "Ok";
-}
-
-static char *
-format_e3_cv (unsigned long cv, unsigned long baud, unsigned long atime)
-{
- static char buf[80];
-
- if (!cv || !baud || !atime)
- sprintf (buf, " - ");
- else
- sprintf (buf, "%10lu (%.1e)", cv, (double)cv/baud/atime);
- return buf;
-}
-
-static void
-print_e3_stats (int fd, int need_header)
-{
- struct e3_statistics st;
- int i, maxi;
- long baud;
-
- if (need_header)
- printf ("Chan\t--Code Violations---\t\t\t\t\t ----Status----\n");
-
- if (ioctl (fd, SERIAL_GETE3STAT, &st) < 0 ||
- ioctl (fd, SERIAL_GETBAUD, &baud) < 0)
- return;
-
- if (!st.cursec)
- st.cursec = 1;
-
- printf ("%s\t%s\t\t\t\t\t", chan_name,
- format_e3_cv (st.ccv, baud, st.cursec));
-
- printf (" %s\n", format_e3_status (st.status));
-
-
- if (uflag) {
- /* Print total statistics. */
- printf ("\t%s\t\t\t\t\t",
- format_e3_cv (st.tcv, baud, st.totsec));
- printf (" -- Total\n");
-
- /* Print 24-hour history. */
- maxi = (st.totsec - st.cursec) / 900;
- if (maxi > 48)
- maxi = 48;
- for (i=0; i<maxi; ++i) {
- printf ("\t%s\t\t\t\t\t",
- format_e3_cv (st.icv[i], baud, 15*60));
- if (i < 3)
- printf (" -- %2dm\n", (i+1)*15);
- else
- printf (" -- %2dh %2dm\n", (i+1)/4, (i+1)%4*15);
- }
- }
-}
-
-static void
-print_chan (int fd)
-{
- char protocol [8];
- char cfg;
- int loop, dpll, nrzi, invclk, clk, higain, phony, use16, crc4;
- int level, keepalive, debug, port, invrclk, invtclk, unfram, monitor;
- int cable, dir, scrambler, ami, mtu;
- int cablen, rloop, rqlen;
- long baud, timeslots, subchan;
- int protocol_valid, baud_valid, loop_valid, use16_valid, crc4_valid;
- int dpll_valid, nrzi_valid, invclk_valid, clk_valid, phony_valid;
- int timeslots_valid, subchan_valid, higain_valid, level_valid;
- int keepalive_valid, debug_valid, cfg_valid, port_valid;
- int invrclk_valid, invtclk_valid, unfram_valid, monitor_valid;
- int cable_valid, dir_valid, scrambler_valid, ami_valid, mtu_valid;
- int cablen_valid, rloop_valid, rqlen_valid;
-
- protocol_valid = ioctl (fd, SERIAL_GETPROTO, &protocol) >= 0;
- cfg_valid = ioctl (fd, SERIAL_GETCFG, &cfg) >= 0;
- baud_valid = ioctl (fd, SERIAL_GETBAUD, &baud) >= 0;
- loop_valid = ioctl (fd, SERIAL_GETLOOP, &loop) >= 0;
- dpll_valid = ioctl (fd, SERIAL_GETDPLL, &dpll) >= 0;
- nrzi_valid = ioctl (fd, SERIAL_GETNRZI, &nrzi) >= 0;
- invclk_valid = ioctl (fd, SERIAL_GETINVCLK, &invclk) >= 0;
- invrclk_valid = ioctl (fd, SERIAL_GETINVRCLK, &invrclk) >= 0;
- invtclk_valid = ioctl (fd, SERIAL_GETINVTCLK, &invtclk) >= 0;
- clk_valid = ioctl (fd, SERIAL_GETCLK, &clk) >= 0;
- timeslots_valid = ioctl (fd, SERIAL_GETTIMESLOTS, &timeslots) >= 0;
- subchan_valid = ioctl (fd, SERIAL_GETSUBCHAN, &subchan) >= 0;
- higain_valid = ioctl (fd, SERIAL_GETHIGAIN, &higain) >= 0;
- phony_valid = ioctl (fd, SERIAL_GETPHONY, &phony) >= 0;
- unfram_valid = ioctl (fd, SERIAL_GETUNFRAM, &unfram) >= 0;
- monitor_valid = ioctl (fd, SERIAL_GETMONITOR, &monitor) >= 0;
- use16_valid = ioctl (fd, SERIAL_GETUSE16, &use16) >= 0;
- crc4_valid = ioctl (fd, SERIAL_GETCRC4, &crc4) >= 0;
- ami_valid = ioctl (fd, SERIAL_GETLCODE, &ami) >= 0;
- level_valid = ioctl (fd, SERIAL_GETLEVEL, &level) >= 0;
- keepalive_valid = ioctl (fd, SERIAL_GETKEEPALIVE, &keepalive) >= 0;
- debug_valid = ioctl (fd, SERIAL_GETDEBUG, &debug) >= 0;
- port_valid = ioctl (fd, SERIAL_GETPORT, &port) >= 0;
- cable_valid = ioctl (fd, SERIAL_GETCABLE, &cable) >= 0;
- dir_valid = ioctl (fd, SERIAL_GETDIR, &dir) >= 0;
- scrambler_valid = ioctl (fd, SERIAL_GETSCRAMBLER, &scrambler) >= 0;
- cablen_valid = ioctl (fd, SERIAL_GETCABLEN, &cablen) >= 0;
- rloop_valid = ioctl (fd, SERIAL_GETRLOOP, &rloop) >= 0;
- mtu_valid = ioctl (fd, SERIAL_GETMTU, &mtu) >= 0;
- rqlen_valid = ioctl (fd, SERIAL_GETRQLEN, &rqlen) >= 0;
-
- printf ("%s", chan_name);
- if (port_valid)
- switch (port) {
- case 0: printf (" (rs232)"); break;
- case 1: printf (" (v35)"); break;
- case 2: printf (" (rs530)"); break;
- }
- else if (cable_valid)
- switch (cable) {
- case 0: printf (" (rs232)"); break;
- case 1: printf (" (v35)"); break;
- case 2: printf (" (rs530)"); break;
- case 3: printf (" (x21)"); break;
- case 4: printf (" (rs485)"); break;
- case 9: printf (" (no cable)"); break;
- }
- if (debug_valid && debug)
- printf (" debug=%d", debug);
- if (protocol_valid && *protocol)
- printf (" %.8s", protocol);
- else
- printf (" idle");
- if (cablen_valid)
- printf (" cablen=%s", cablen ? "on" : "off");
- if (keepalive_valid)
- printf (" keepalive=%s", keepalive ? "on" : "off");
-
- if (cfg_valid)
- switch (cfg) {
- case 'a' : printf (" cfg=A"); break;
- case 'b' : printf (" cfg=B"); break;
- case 'c' : printf (" cfg=C"); break;
- case 'd' : printf (" cfg=D"); break;
- default : printf (" cfg=unknown");
- }
- if (dir_valid)
- printf (" dir=%d", dir);
-
- if (baud_valid) {
- if (baud)
- printf (" %ld", baud);
- else
- printf (" extclock");
- }
- if (mtu_valid)
- printf (" mtu=%d", mtu);
-
- if (aflag && rqlen_valid)
- printf (" rqlen=%d", rqlen);
-
- if (clk_valid)
- switch (clk) {
- case E1CLK_INTERNAL: printf (" syn=int"); break;
- case E1CLK_RECEIVE: printf (" syn=rcv"); break;
- case E1CLK_RECEIVE_CHAN0: printf (" syn=rcv0"); break;
- case E1CLK_RECEIVE_CHAN1: printf (" syn=rcv1"); break;
- case E1CLK_RECEIVE_CHAN2: printf (" syn=rcv2"); break;
- case E1CLK_RECEIVE_CHAN3: printf (" syn=rcv3"); break;
- default: printf (" syn=%d", clk); break;
- }
-
- if (dpll_valid)
- printf (" dpll=%s", dpll ? "on" : "off");
- if (nrzi_valid)
- printf (" nrzi=%s", nrzi ? "on" : "off");
- if (invclk_valid)
- printf (" invclk=%s", invclk ? "on" : "off");
- if (invrclk_valid)
- printf (" invrclk=%s", invrclk ? "on" : "off");
- if (invtclk_valid)
- printf (" invtclk=%s", invtclk ? "on" : "off");
- if (unfram_valid)
- printf (" unfram=%s", unfram ? "on" : "off");
- if (use16_valid)
- printf (" use16=%s", use16 ? "on" : "off");
- if (aflag) {
- if (crc4_valid)
- printf (" crc4=%s", crc4 ? "on" : "off");
- if (higain_valid)
- printf (" higain=%s", higain ? "on" : "off");
- if (monitor_valid)
- printf (" monitor=%s", monitor ? "on" : "off");
- if (phony_valid)
- printf (" phony=%s", phony ? "on" : "off");
- if (scrambler_valid)
- printf (" scrambler=%s", scrambler ? "on" : "off");
- if (loop_valid)
- printf (" loop=%s", loop ? "on" : "off");
- if (rloop_valid)
- printf (" rloop=%s", rloop ? "on" : "off");
- if (ami_valid)
- printf (" ami=%s", ami ? "on" : "off");
- }
- if (timeslots_valid)
- printf (" ts=%s", format_timeslots (timeslots));
- if (subchan_valid)
- printf (" pass=%s", format_timeslots (subchan));
- if (level_valid)
- printf (" (level=-%.1fdB)", level / 10.0);
- printf ("\n");
-}
-
-static void
-setup_chan (int fd, int argc, char **argv)
-{
- int i, mode, loop, nrzi, dpll, invclk, phony, use16, crc4, unfram, ami;
- int higain, clk, keepalive, debug, port, dlci, invrclk, invtclk;
- int monitor, dir, scrambler, rloop, cablen;
- int mode_valid;
- long baud, timeslots, mtu, rqlen;
-
- for (i=0; i<argc; ++i) {
- if (argv[i][0] >= '0' && argv[i][0] <= '9') {
- baud = strtol (argv[i], 0, 10);
- ioctl (fd, SERIAL_SETBAUD, &baud);
- } else if (strcasecmp ("extclock", argv[i]) == 0) {
- baud = 0;
- ioctl (fd, SERIAL_SETBAUD, &baud);
- } else if (strncasecmp ("cfg=", argv[i], 4) == 0) {
- if (strncasecmp ("a", argv[i]+4, 1) == 0)
- ioctl (fd, SERIAL_SETCFG, "a");
- else if (strncasecmp ("b", argv[i]+4, 1) == 0)
- ioctl (fd, SERIAL_SETCFG, "b");
- else if (strncasecmp ("c", argv[i]+4, 1) == 0)
- ioctl (fd, SERIAL_SETCFG, "c");
- else if (strncasecmp ("d", argv[i]+4, 1) == 0)
- ioctl (fd, SERIAL_SETCFG, "d");
- else {
- fprintf (stderr, "invalid cfg\n");
- exit (-1);
- }
- } else if (strcasecmp ("idle", argv[i]) == 0)
- ioctl (fd, SERIAL_SETPROTO, "\0\0\0\0\0\0\0");
- else if (strcasecmp ("async", argv[i]) == 0) {
- mode = SERIAL_ASYNC;
- if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
- ioctl (fd, SERIAL_SETPROTO, "async\0\0");
- } else if (strcasecmp ("sync", argv[i]) == 0) {
- mode = SERIAL_HDLC;
- if (ioctl (fd, SERIAL_SETMODE, &mode) >= 0)
- ioctl (fd, SERIAL_SETPROTO, "sync\0\0\0");
- } else if (strcasecmp ("cisco", argv[i]) == 0) {
- mode = SERIAL_HDLC;
- ioctl (fd, SERIAL_SETMODE, &mode);
- ioctl (fd, SERIAL_SETPROTO, "cisco\0\0");
- } else if (strcasecmp ("rbrg", argv[i]) == 0) {
- mode = SERIAL_HDLC;
- ioctl (fd, SERIAL_SETMODE, &mode);
- ioctl (fd, SERIAL_SETPROTO, "rbrg\0\0\0");
- } else if (strcasecmp ("raw", argv[i]) == 0) {
- mode = SERIAL_HDLC;
- ioctl (fd, SERIAL_SETMODE, &mode);
- ioctl (fd, SERIAL_SETPROTO, "raw\0\0\0\0");
- } else if (strcasecmp ("packet", argv[i]) == 0) {
- mode = SERIAL_HDLC;
- ioctl (fd, SERIAL_SETMODE, &mode);
- ioctl (fd, SERIAL_SETPROTO, "packet\0");
- } else if (strcasecmp ("ppp", argv[i]) == 0) {
- /* check that ppp line discipline is present */
- if (ppp_ok ()) {
- mode = SERIAL_HDLC;
- ioctl (fd, SERIAL_SETMODE, &mode);
- ioctl (fd, SERIAL_SETPROTO, "ppp\0\0\0\0");
- }
- } else if (strncasecmp ("keepalive=", argv[i], 10) == 0) {
- keepalive = (strcasecmp ("on", argv[i] + 10) == 0);
- ioctl (fd, SERIAL_SETKEEPALIVE, &keepalive);
- } else if (strcasecmp ("fr", argv[i]) == 0) {
- mode = SERIAL_HDLC;
- ioctl (fd, SERIAL_SETMODE, &mode);
- ioctl (fd, SERIAL_SETPROTO, "fr\0\0\0\0\0");
- } else if (strcasecmp ("zaptel", argv[i]) == 0) {
- mode = SERIAL_HDLC;
- ioctl (fd, SERIAL_SETMODE, &mode);
- ioctl (fd, SERIAL_SETPROTO, "zaptel\0");
- } else if (strncasecmp ("debug=", argv[i], 6) == 0) {
- debug = strtol (argv[i]+6, 0, 10);
- mode_valid = ioctl (fd, SERIAL_GETMODE, &mode) >= 0;
- if (!mode_valid || mode != SERIAL_ASYNC) {
- if (debug == 0) {
- set_debug_ifconfig(0);
- } else {
- ioctl (fd, SERIAL_SETDEBUG, &debug);
- set_debug_ifconfig(1);
- }
- } else {
- ioctl (fd, SERIAL_SETDEBUG, &debug);
- }
- } else if (strncasecmp ("loop=", argv[i], 5) == 0) {
- loop = (strcasecmp ("on", argv[i] + 5) == 0);
- ioctl (fd, SERIAL_SETLOOP, &loop);
- } else if (strncasecmp ("rloop=", argv[i], 6) == 0) {
- rloop = (strcasecmp ("on", argv[i] + 6) == 0);
- ioctl (fd, SERIAL_SETRLOOP, &rloop);
- } else if (strncasecmp ("dpll=", argv[i], 5) == 0) {
- dpll = (strcasecmp ("on", argv[i] + 5) == 0);
- ioctl (fd, SERIAL_SETDPLL, &dpll);
- } else if (strncasecmp ("nrzi=", argv[i], 5) == 0) {
- nrzi = (strcasecmp ("on", argv[i] + 5) == 0);
- ioctl (fd, SERIAL_SETNRZI, &nrzi);
- } else if (strncasecmp ("invclk=", argv[i], 7) == 0) {
- invclk = (strcasecmp ("on", argv[i] + 7) == 0);
- ioctl (fd, SERIAL_SETINVCLK, &invclk);
- } else if (strncasecmp ("invrclk=", argv[i], 8) == 0) {
- invrclk = (strcasecmp ("on", argv[i] + 8) == 0);
- ioctl (fd, SERIAL_SETINVRCLK, &invrclk);
- } else if (strncasecmp ("invtclk=", argv[i], 8) == 0) {
- invtclk = (strcasecmp ("on", argv[i] + 8) == 0);
- ioctl (fd, SERIAL_SETINVTCLK, &invtclk);
- } else if (strncasecmp ("higain=", argv[i], 7) == 0) {
- higain = (strcasecmp ("on", argv[i] + 7) == 0);
- ioctl (fd, SERIAL_SETHIGAIN, &higain);
- } else if (strncasecmp ("phony=", argv[i], 6) == 0) {
- phony = (strcasecmp ("on", argv[i] + 6) == 0);
- ioctl (fd, SERIAL_SETPHONY, &phony);
- } else if (strncasecmp ("unfram=", argv[i], 7) == 0) {
- unfram = (strcasecmp ("on", argv[i] + 7) == 0);
- ioctl (fd, SERIAL_SETUNFRAM, &unfram);
- } else if (strncasecmp ("scrambler=", argv[i], 10) == 0) {
- scrambler = (strcasecmp ("on", argv[i] + 10) == 0);
- ioctl (fd, SERIAL_SETSCRAMBLER, &scrambler);
- } else if (strncasecmp ("monitor=", argv[i], 8) == 0) {
- monitor = (strcasecmp ("on", argv[i] + 8) == 0);
- ioctl (fd, SERIAL_SETMONITOR, &monitor);
- } else if (strncasecmp ("use16=", argv[i], 6) == 0) {
- use16 = (strcasecmp ("on", argv[i] + 6) == 0);
- ioctl (fd, SERIAL_SETUSE16, &use16);
- } else if (strncasecmp ("crc4=", argv[i], 5) == 0) {
- crc4 = (strcasecmp ("on", argv[i] + 5) == 0);
- ioctl (fd, SERIAL_SETCRC4, &crc4);
- } else if (strncasecmp ("ami=", argv[i], 4) == 0) {
- ami = (strcasecmp ("on", argv[i] + 4) == 0);
- ioctl (fd, SERIAL_SETLCODE, &ami);
- } else if (strncasecmp ("mtu=", argv[i], 4) == 0) {
- mtu = strtol (argv[i] + 4, 0, 10);
- ioctl (fd, SERIAL_SETMTU, &mtu);
- } else if (strncasecmp ("rqlen=", argv[i], 6) == 0) {
- rqlen = strtol (argv[i] + 6, 0, 10);
- ioctl (fd, SERIAL_SETRQLEN, &rqlen);
- } else if (strcasecmp ("syn=int", argv[i]) == 0) {
- clk = E1CLK_INTERNAL;
- ioctl (fd, SERIAL_SETCLK, &clk);
- } else if (strcasecmp ("syn=rcv", argv[i]) == 0) {
- clk = E1CLK_RECEIVE;
- ioctl (fd, SERIAL_SETCLK, &clk);
- } else if (strcasecmp ("syn=rcv0", argv[i]) == 0) {
- clk = E1CLK_RECEIVE_CHAN0;
- ioctl (fd, SERIAL_SETCLK, &clk);
- } else if (strcasecmp ("syn=rcv1", argv[i]) == 0) {
- clk = E1CLK_RECEIVE_CHAN1;
- ioctl (fd, SERIAL_SETCLK, &clk);
- } else if (strcasecmp ("syn=rcv2", argv[i]) == 0) {
- clk = E1CLK_RECEIVE_CHAN2;
- ioctl (fd, SERIAL_SETCLK, &clk);
- } else if (strcasecmp ("syn=rcv3", argv[i]) == 0) {
- clk = E1CLK_RECEIVE_CHAN3;
- ioctl (fd, SERIAL_SETCLK, &clk);
- } else if (strncasecmp ("ts=", argv[i], 3) == 0) {
- timeslots = scan_timeslots (argv[i] + 3);
- ioctl (fd, SERIAL_SETTIMESLOTS, &timeslots);
- } else if (strncasecmp ("pass=", argv[i], 5) == 0) {
- timeslots = scan_timeslots (argv[i] + 5);
- ioctl (fd, SERIAL_SETSUBCHAN, &timeslots);
- } else if (strncasecmp ("dlci", argv[i], 4) == 0) {
- dlci = strtol (argv[i]+4, 0, 10);
- ioctl (fd, SERIAL_ADDDLCI, &dlci);
- } else if (strncasecmp ("dir=", argv[i], 4) == 0) {
- dir = strtol (argv[i]+4, 0, 10);
- ioctl (fd, SERIAL_SETDIR, &dir);
- } else if (strncasecmp ("port=", argv[i], 5) == 0) {
- if (strncasecmp ("rs232", argv[i]+5, 5) == 0) {
- port = 0;
- ioctl (fd, SERIAL_SETPORT, &port);
- } else if (strncasecmp ("v35", argv[i]+5, 3) == 0) {
- port = 1;
- ioctl (fd, SERIAL_SETPORT, &port);
- } else if (strncasecmp ("rs449", argv[i]+5, 5) == 0) {
- port = 2;
- ioctl (fd, SERIAL_SETPORT, &port);
- } else {
- fprintf (stderr, "invalid port type\n");
- exit (-1);
- }
-#if 1
- } else if (strcasecmp ("reset", argv[i]) == 0) {
- ioctl (fd, SERIAL_RESET, 0);
- } else if (strcasecmp ("hwreset", argv[i]) == 0) {
- ioctl (fd, SERIAL_HARDRESET, 0);
-#endif
- } else if (strncasecmp ("cablen=", argv[i], 7) == 0) {
- loop = (strcasecmp ("on", argv[i] + 7) == 0);
- ioctl (fd, SERIAL_SETCABLEN, &cablen);
- }
- }
-}
-
-static void
-get_mask (void)
-{
-#ifdef __linux__
- int fd;
-
- fd = open ("/dev/serial/ctl0", 0);
- if (fd < 0) {
- perror ("/dev/serial/ctl0");
- exit (-1);
- }
- if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
- perror ("getting list of channels");
- exit (-1);
- }
- close (fd);
-#else
- int fd, fd1, fd2, fd3, i;
- char buf [80];
-
- for (i=0, fd=-1; i<12 && fd<0; i++) {
- sprintf (buf, "/dev/cx%d", i*4);
- fd = open (buf, 0);
- }
-
- for (i=0, fd1=-1; i<3 && fd1<0; i++) {
- sprintf (buf, "/dev/ct%d", i*2);
- fd1 = open (buf, 0);
- }
-
- for (i=0, fd2=-1; i<3 && fd2<0; i++) {
- sprintf (buf, "/dev/cp%d", i*4);
- fd2 = open (buf, 0);
- }
-
- /* Try only one */
- for (i=0, fd3=-1; i<1 && fd3<0; i++) {
- sprintf (buf, "/dev/ce%d", i*4);
- fd3 = open (buf, 0);
- }
-
- if ((fd < 0) && (fd1 < 0) && (fd2 < 0) && (fd3 < 0)) {
- fprintf (stderr, "No Cronyx adapters installed\n");
- exit (-1);
- }
-
- if (fd >= 0) {
- if (ioctl (fd, SERIAL_GETREGISTERED, &mask) < 0) {
- perror ("getting list of channels");
- exit (-1);
- }
- close (fd);
- }
-
- if (fd1 >= 0) {
- if (ioctl (fd1, SERIAL_GETREGISTERED, (mask+16)) < 0) {
- perror ("getting list of channels");
- exit (-1);
- }
- close (fd1);
- }
-
- if (fd2 >= 0) {
- if (ioctl (fd2, SERIAL_GETREGISTERED, (mask+32)) < 0) {
- perror ("getting list of channels");
- exit (-1);
- }
- close (fd2);
- }
-
- if (fd3 >= 0) {
- if (ioctl (fd3, SERIAL_GETREGISTERED, (mask+48)) < 0) {
- perror ("getting list of channels");
- exit (-1);
- }
- close (fd3);
- }
-#endif
-}
-
-static int
-open_chan_ctl (int num)
-{
- char device [80];
- int fd;
-
-#ifdef __linux__
- sprintf (device, "/dev/serial/ctl%d", num);
-#else
- switch (adapter_type) {
- case 0:
- sprintf (device, "/dev/cx%d", num);
- break;
- case 1:
- sprintf (device, "/dev/ct%d", num);
- break;
- case 2:
- sprintf (device, "/dev/cp%d", num);
- break;
- case 3:
- sprintf (device, "/dev/ce%d", num);
- break;
- }
-#endif
- fd = open (device, 0);
- if (fd < 0) {
- if (errno == ENODEV)
- fprintf (stderr, "chan%d: not configured\n", num);
- else
- perror (device);
- exit (-1);
- }
-#ifdef __linux__
- if (ioctl (fd, SERIAL_GETNAME, &chan_name) < 0)
- sprintf (chan_name, "chan%d", num);
-#else
- switch (adapter_type) {
- case 0: sprintf (chan_name, "cx%d", num); break;
- case 1: sprintf (chan_name, "ct%d", num); break;
- case 2: sprintf (chan_name, "cp%d", num); break;
- case 3: sprintf (chan_name, "ce%d", num); break;
- }
-#endif
- return fd;
-}
-
-int
-main (int argc, char **argv)
-{
- char *p;
- int fd, need_header, chan_num;
-
- if (argc > 1 && strcmp(argv[1], "help") == 0)
- usage();
-
- for (;;) {
- switch (getopt (argc, argv, "mseftucviax")) {
- case -1:
- break;
- case 'a':
- ++aflag;
- continue;
- case 'm':
- ++mflag;
- continue;
- case 's':
- ++sflag;
- continue;
- case 'e':
- ++eflag;
- continue;
- case 'f':
- ++eflag;
- ++fflag;
- continue;
- case 't':
- ++tflag;
- continue;
- case 'u':
- ++tflag;
- ++uflag;
- continue;
- case 'c':
- ++cflag;
- continue;
- case 'v':
- ++vflag;
- continue;
- case 'i':
- ++iflag;
- continue;
- case 'x':
- ++xflag;
- continue;
- default:
- usage();
- }
- break;
- }
- argc -= optind;
- argv += optind;
-
- if (argc <= 0) {
- get_mask ();
- need_header = 1;
- adapter_type = 0;
-#ifndef __linux__
- for (; adapter_type < 4; ++adapter_type)
-#endif
- {
- for (chan_num=0; chan_num<MAXCHAN; ++chan_num)
- if (mask[adapter_type*16+chan_num/8] & 1 << (chan_num & 7)) {
- fd = open_chan_ctl (chan_num);
- if (vflag) {
-#ifdef __linux__
- char buf[256];
- if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0) {
- printf ("Version: %s\n", buf);
- close (fd);
- return (0);
- }
-#endif
- }
- if (iflag) {
- print_chan (fd);
- print_ifconfig (fd);
- } else if (sflag||xflag)
- print_stats (fd, need_header);
- else if (mflag)
- print_modems (fd, need_header);
- else if (eflag)
- print_e1_stats (fd, need_header);
- else if (tflag)
- print_e3_stats (fd, need_header);
- else if (cflag)
- clear_stats (fd);
- else
- print_chan (fd);
- close (fd);
- need_header = 0;
- }
- }
- return (0);
- }
-
- p = argv[0] + strlen (argv[0]);
- while (p > argv[0] && p[-1] >= '0' && p[-1] <= '9')
- --p;
- chan_num = strtol (p, 0, 10);
-#ifndef __linux__
- if (strncasecmp ("cx", argv[0], 2)==0)
- adapter_type = 0;
- else if (strncasecmp ("ct", argv[0], 2)==0)
- adapter_type = 1;
- else if (strncasecmp ("cp", argv[0], 2)==0)
- adapter_type = 2;
- else if (strncasecmp ("ce", argv[0], 2)==0)
- adapter_type = 3;
- else {
- fprintf (stderr, "Wrong channel name\n");
- exit (-1);
- }
-#endif
- argc--;
- argv++;
-
- fd = open_chan_ctl (chan_num);
- if (vflag) {
-#ifdef __linux__
- char buf[256];
- if (ioctl (fd, SERIAL_GETVERSIONSTRING, &buf) >= 0)
- printf ("Version: %s\n", buf);
-#endif
- }
- if (iflag) {
- print_chan (fd);
- print_ifconfig (fd);
- close (fd);
- return (0);
- }
- if (sflag||xflag) {
- print_stats (fd, 1);
- close (fd);
- return (0);
- }
- if (mflag) {
- print_modems (fd, 1);
- close (fd);
- return (0);
- }
- if (eflag) {
- print_e1_stats (fd, 1);
- close (fd);
- return (0);
- }
- if (tflag) {
- print_e3_stats (fd, 1);
- close (fd);
- return (0);
- }
- if (cflag) {
- clear_stats (fd);
- close (fd);
- return (0);
- }
- if (argc > 0)
- setup_chan (fd, argc, argv);
- else
- print_chan (fd);
- close (fd);
- return (0);
-}
diff --git a/sbin/setkey/Makefile b/sbin/setkey/Makefile
index 47ef3d36bee4..a32fef103121 100644
--- a/sbin/setkey/Makefile
+++ b/sbin/setkey/Makefile
@@ -25,7 +25,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
.include <src.opts.mk>
diff --git a/sbin/setkey/Makefile.depend b/sbin/setkey/Makefile.depend
index ca3301c271b9..48f9c6dc2589 100644
--- a/sbin/setkey/Makefile.depend
+++ b/sbin/setkey/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/arpa \
include/xlocale \
@@ -10,8 +8,6 @@ DIRDEPS = \
lib/libc \
lib/libcompiler_rt \
lib/libipsec \
- lib/liby \
- usr.bin/lex/lib \
usr.bin/yacc.host \
diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y
index ae0859c22d2c..a7bcd2d8dafc 100644
--- a/sbin/setkey/parse.y
+++ b/sbin/setkey/parse.y
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $KAME: parse.y,v 1.83 2004/05/18 08:48:23 sakane Exp $ */
/*-
@@ -43,9 +42,11 @@
#include <netipsec/key_var.h>
#include <netipsec/ipsec.h>
#include <arpa/inet.h>
+#include <netinet/udp.h>
#include <string.h>
#include <unistd.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <netdb.h>
@@ -64,6 +65,12 @@ u_int32_t p_reqid;
u_int p_key_enc_len, p_key_auth_len;
caddr_t p_key_enc, p_key_auth;
time_t p_lt_hard, p_lt_soft;
+u_int p_natt_type;
+struct addrinfo *p_natt_oai, *p_natt_oar;
+int p_natt_sport, p_natt_dport;
+int p_natt_fraglen;
+bool esn;
+vchar_t p_hwif;
static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
@@ -110,7 +117,8 @@ extern void yyerror(const char *);
/* SPD management */
%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
%token F_POLICY PL_REQUESTS
-%token F_AIFLAGS
+%token F_AIFLAGS F_NATT F_NATT_MTU
+%token F_ESN F_HWIF
%token TAGGED
%type <num> prefix protocol_spec upper_spec
@@ -521,12 +529,35 @@ extension
}
| F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
| F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
+ | F_NATT ipaddr BLCL DECSTRING ELCL ipaddr BLCL DECSTRING ELCL
+ {
+ p_natt_type = UDP_ENCAP_ESPINUDP;
+ p_natt_oai = $2;
+ p_natt_oar = $6;
+ if (p_natt_oai == NULL || p_natt_oar == NULL)
+ return (-1);
+ p_natt_sport = $4;
+ p_natt_dport = $8;
+ }
+ | F_NATT_MTU DECSTRING
+ {
+ p_natt_fraglen = $2;
+ }
+ | F_ESN
+ {
+ esn = true;
+ p_ext |= SADB_X_SAFLAGS_ESN;
+ }
+ | F_HWIF STRING
+ {
+ p_hwif = $2;
+ }
;
/* definition about command for SPD management */
/* spdadd */
spdadd_command
- : SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
+ : SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec spd_hwif EOT
{
int status;
struct addrinfo *src, *dst;
@@ -630,6 +661,14 @@ ipaddropts
| ipaddropts ipaddropt
;
+spd_hwif
+ :
+ | F_HWIF STRING
+ {
+ p_hwif = $2;
+ }
+ ;
+
ipaddropt
: F_AIFLAGS
{
@@ -773,11 +812,7 @@ policy_requests
%%
int
-setkeymsg0(msg, type, satype, l)
- struct sadb_msg *msg;
- unsigned int type;
- unsigned int satype;
- size_t l;
+setkeymsg0(struct sadb_msg *msg, unsigned type, unsigned satype, size_t l)
{
msg->sadb_msg_version = PF_KEY_V2;
@@ -791,21 +826,33 @@ setkeymsg0(msg, type, satype, l)
return 0;
}
+static int
+setkeymsg_plen(struct addrinfo *s)
+{
+ switch (s->ai_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ return (sizeof(struct in_addr) << 3);
+#endif
+#ifdef INET6
+ case AF_INET6:
+ return (sizeof(struct in6_addr) << 3);
+#endif
+ default:
+ return (-1);
+ }
+}
+
/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
static int
-setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
- unsigned int type;
- unsigned int upper;
- vchar_t *policy;
- struct addrinfo *srcs;
- int splen;
- struct addrinfo *dsts;
- int dplen;
+setkeymsg_spdaddr(unsigned type, unsigned upper, vchar_t *policy,
+ struct addrinfo *srcs, int splen, struct addrinfo *dsts, int dplen)
{
struct sadb_msg *msg;
char buf[BUFSIZ];
int l, l0;
struct sadb_address m_addr;
+ struct sadb_x_if_hw_offl m_if_hw;
struct addrinfo *s, *d;
int n;
int plen;
@@ -824,6 +871,20 @@ setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
memcpy(buf + l, policy->buf, policy->len);
l += policy->len;
+ if (p_hwif.len != 0) {
+ l0 = sizeof(struct sadb_x_if_hw_offl);
+ m_if_hw.sadb_x_if_hw_offl_len = PFKEY_UNIT64(l0);
+ m_if_hw.sadb_x_if_hw_offl_exttype = SADB_X_EXT_IF_HW_OFFL;
+ m_if_hw.sadb_x_if_hw_offl_flags = 0;
+ memset(&m_if_hw.sadb_x_if_hw_offl_if[0], 0,
+ sizeof(m_if_hw.sadb_x_if_hw_offl_if));
+ strlcpy(&m_if_hw.sadb_x_if_hw_offl_if[0], p_hwif.buf,
+ sizeof(m_if_hw.sadb_x_if_hw_offl_if));
+
+ memcpy(buf + l, &m_if_hw, l0);
+ l += l0;
+ }
+
l0 = l;
n = 0;
@@ -835,18 +896,9 @@ setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
if (s->ai_addr->sa_family != d->ai_addr->sa_family)
continue;
- switch (s->ai_addr->sa_family) {
- case AF_INET:
- plen = sizeof(struct in_addr) << 3;
- break;
-#ifdef INET6
- case AF_INET6:
- plen = sizeof(struct in6_addr) << 3;
- break;
-#endif
- default:
+ plen = setkeymsg_plen(s);
+ if (plen == -1)
continue;
- }
/* set src */
sa = s->ai_addr;
@@ -892,12 +944,8 @@ setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
static int
-setkeymsg_addr(type, satype, srcs, dsts, no_spi)
- unsigned int type;
- unsigned int satype;
- struct addrinfo *srcs;
- struct addrinfo *dsts;
- int no_spi;
+setkeymsg_addr(unsigned type, unsigned satype, struct addrinfo *srcs,
+ struct addrinfo *dsts, int no_spi)
{
struct sadb_msg *msg;
char buf[BUFSIZ];
@@ -968,18 +1016,9 @@ setkeymsg_addr(type, satype, srcs, dsts, no_spi)
if (s->ai_addr->sa_family != d->ai_addr->sa_family)
continue;
- switch (s->ai_addr->sa_family) {
- case AF_INET:
- plen = sizeof(struct in_addr) << 3;
- break;
-#ifdef INET6
- case AF_INET6:
- plen = sizeof(struct in6_addr) << 3;
- break;
-#endif
- default:
+ plen = setkeymsg_plen(s);
+ if (plen == -1)
continue;
- }
/* set src */
sa = s->ai_addr;
@@ -1023,11 +1062,8 @@ setkeymsg_addr(type, satype, srcs, dsts, no_spi)
/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
static int
-setkeymsg_add(type, satype, srcs, dsts)
- unsigned int type;
- unsigned int satype;
- struct addrinfo *srcs;
- struct addrinfo *dsts;
+setkeymsg_add(unsigned type, unsigned satype, struct addrinfo *srcs,
+ struct addrinfo *dsts)
{
struct sadb_msg *msg;
char buf[BUFSIZ];
@@ -1037,6 +1073,10 @@ setkeymsg_add(type, satype, srcs, dsts)
struct sadb_address m_addr;
struct sadb_x_sa_replay m_replay;
struct addrinfo *s, *d;
+ struct sadb_x_nat_t_type m_natt_type;
+ struct sadb_x_nat_t_port m_natt_port;
+ struct sadb_x_nat_t_frag m_natt_frag;
+ struct sadb_x_if_hw_offl m_if_hw;
int n;
int plen;
struct sockaddr *sa;
@@ -1146,6 +1186,64 @@ setkeymsg_add(type, satype, srcs, dsts)
memcpy(buf + l, &m_replay, len);
l += len;
}
+
+ if (p_natt_type != 0) {
+ len = sizeof(m_natt_type);
+ memset(&m_natt_type, 0, sizeof(m_natt_type));
+ m_natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
+ m_natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+ m_natt_type.sadb_x_nat_t_type_type = p_natt_type;
+ memcpy(buf + l, &m_natt_type, len);
+ l += len;
+
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OAI;
+ sa = p_natt_oai->ai_addr;
+ salen = p_natt_oai->ai_addr->sa_len;
+ m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+ PFKEY_ALIGN8(salen));
+ m_addr.sadb_address_prefixlen = setkeymsg_plen(p_natt_oai);
+ setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+ sizeof(m_addr), (caddr_t)sa, salen);
+
+ len = sizeof(m_natt_port);
+ memset(&m_natt_port, 0, sizeof(m_natt_port));
+ m_natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+ m_natt_port.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
+ m_natt_port.sadb_x_nat_t_port_port = htons(p_natt_sport);
+ memcpy(buf + l, &m_natt_port, len);
+ l += len;
+
+ memset(&m_addr, 0, sizeof(m_addr));
+ m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OAR;
+ sa = p_natt_oar->ai_addr;
+ salen = p_natt_oar->ai_addr->sa_len;
+ m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+ PFKEY_ALIGN8(salen));
+ m_addr.sadb_address_prefixlen = setkeymsg_plen(p_natt_oar);
+ setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+ sizeof(m_addr), (caddr_t)sa, salen);
+
+ len = sizeof(m_natt_port);
+ memset(&m_natt_port, 0, sizeof(m_natt_port));
+ m_natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+ m_natt_port.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
+ m_natt_port.sadb_x_nat_t_port_port = htons(p_natt_dport);
+ memcpy(buf + l, &m_natt_port, len);
+ l += len;
+
+ if (p_natt_fraglen != -1) {
+ len = sizeof(m_natt_frag);
+ memset(&m_natt_port, 0, sizeof(m_natt_frag));
+ m_natt_frag.sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
+ m_natt_frag.sadb_x_nat_t_frag_exttype =
+ SADB_X_EXT_NAT_T_FRAG;
+ m_natt_frag.sadb_x_nat_t_frag_fraglen = p_natt_fraglen;
+ memcpy(buf + l, &m_natt_frag, len);
+ l += len;
+ }
+ }
+
l0 = l;
n = 0;
@@ -1157,18 +1255,9 @@ setkeymsg_add(type, satype, srcs, dsts)
if (s->ai_addr->sa_family != d->ai_addr->sa_family)
continue;
- switch (s->ai_addr->sa_family) {
- case AF_INET:
- plen = sizeof(struct in_addr) << 3;
- break;
-#ifdef INET6
- case AF_INET6:
- plen = sizeof(struct in6_addr) << 3;
- break;
-#endif
- default:
+ plen = setkeymsg_plen(s);
+ if (plen == -1)
continue;
- }
/* set src */
sa = s->ai_addr;
@@ -1204,6 +1293,20 @@ setkeymsg_add(type, satype, srcs, dsts)
}
}
+ if (p_hwif.len != 0) {
+ len = sizeof(struct sadb_x_if_hw_offl);
+ m_if_hw.sadb_x_if_hw_offl_len = PFKEY_UNIT64(len);
+ m_if_hw.sadb_x_if_hw_offl_exttype = SADB_X_EXT_IF_HW_OFFL;
+ m_if_hw.sadb_x_if_hw_offl_flags = 0;
+ memset(&m_if_hw.sadb_x_if_hw_offl_if[0], 0,
+ sizeof(m_if_hw.sadb_x_if_hw_offl_if));
+ strlcpy(&m_if_hw.sadb_x_if_hw_offl_if[0], p_hwif.buf,
+ sizeof(m_if_hw.sadb_x_if_hw_offl_if));
+
+ memcpy(buf + l, &m_if_hw, len);
+ l += len;
+ }
+
if (n == 0)
return -1;
else
@@ -1211,9 +1314,7 @@ setkeymsg_add(type, satype, srcs, dsts)
}
static struct addrinfo *
-parse_addr(host, port)
- char *host;
- char *port;
+parse_addr(char *host, char *port)
{
struct addrinfo hints, *res = NULL;
int error;
@@ -1232,8 +1333,7 @@ parse_addr(host, port)
}
static int
-fix_portstr(spec, sport, dport)
- vchar_t *spec, *sport, *dport;
+fix_portstr(vchar_t *spec, vchar_t *sport, vchar_t *dport)
{
char *p, *p2;
u_int l;
@@ -1273,13 +1373,8 @@ fix_portstr(spec, sport, dport)
}
static int
-setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
- char *buf;
- int *off;
- struct sadb_ext *ebuf;
- int elen;
- caddr_t vbuf;
- int vlen;
+setvarbuf(char *buf, int *off, struct sadb_ext *ebuf, int elen, caddr_t vbuf,
+ int vlen)
{
memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
memcpy(buf + *off, (caddr_t)ebuf, elen);
@@ -1290,7 +1385,7 @@ setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
}
void
-parse_init()
+parse_init(void)
{
p_spi = 0;
@@ -1307,13 +1402,18 @@ parse_init()
p_aiflags = 0;
p_aifamily = PF_UNSPEC;
- return;
+ p_natt_type = 0;
+ p_natt_oai = p_natt_oar = NULL;
+ p_natt_sport = p_natt_dport = 0;
+ p_natt_fraglen = -1;
+
+ esn = false;
+ p_hwif.len = 0;
+ p_hwif.buf = NULL;
}
void
-free_buffer()
+free_buffer(void)
{
/* we got tons of memory leaks in the parser anyways, leave them */
-
- return;
}
diff --git a/sbin/setkey/sample.cf b/sbin/setkey/sample.cf
index 2a3485cdcd14..796b34ce154d 100644
--- a/sbin/setkey/sample.cf
+++ b/sbin/setkey/sample.cf
@@ -25,7 +25,6 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD$
# There are sample scripts for IPsec configuration by manual keying.
# A security association is uniquely identified by a triple consisting
diff --git a/sbin/setkey/scriptdump.pl b/sbin/setkey/scriptdump.pl
index a1d8adb207bc..f5b9f254538b 100644
--- a/sbin/setkey/scriptdump.pl
+++ b/sbin/setkey/scriptdump.pl
@@ -1,5 +1,4 @@
#! @LOCALPREFIX@/bin/perl
-# $FreeBSD$
if ($< != 0) {
print STDERR "must be root to invoke this\n";
diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8
index 79e28b99f950..e3bcf10b9a9a 100644
--- a/sbin/setkey/setkey.8
+++ b/sbin/setkey/setkey.8
@@ -27,9 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd April 27, 2022
+.Dd August 25, 2024
.Dt SETKEY 8
.Os
.\"
@@ -45,6 +43,9 @@
.Op Fl v
.Fl f Ar filename
.Nm
+.Op Fl v
+.Fl e Ar script
+.Nm
.Op Fl Pgltv
.Fl D
.Nm
@@ -65,11 +66,14 @@ The
.Nm
utility takes a series of operations from the standard input
(if invoked with
-.Fl c )
-or the file named
+.Fl c ) ,
+from the file named
.Ar filename
(if invoked with
-.Fl f Ar filename ) .
+.Fl f Ar filename ) ,
+or from the command line argument following the option
+(if invoked with
+.Fl e Ar script ) .
.Bl -tag -width indent
.It Fl D
Dump the SAD entries.
@@ -226,7 +230,7 @@ IPv4/v6 address.
The
.Nm
utility
-can resolve a FQDN into numeric addresses.
+can resolve an FQDN into numeric addresses.
If the FQDN resolves into multiple addresses,
.Nm
will install multiple SAD/SPD entries into the kernel
@@ -277,7 +281,7 @@ and they cannot be used.
.Pp
.It Ar extensions
take some of the following:
-.Bl -tag -width Fl -compact
+.Bl -tag -width Fl natt_mtu -compact
.\"
.It Fl m Ar mode
Specify a security protocol mode for use.
@@ -322,6 +326,28 @@ Do not allow cyclic sequence number.
.It Fl lh Ar time
.It Fl ls Ar time
Specify hard/soft life time duration of the SA.
+.It Fl natt Ar oai \([ Ar sport \(] Ar oar \([ Ar dport \(]
+Manually configure NAT-T for the SA, by specifying initiator
+.Ar oai
+and
+requestor
+.Ar oar
+ip addresses and ports.
+Note that the
+.Sq \([
+and
+.Sq \(]
+symbols are part of the syntax for the ports specification,
+not indication of the optional components.
+.It Fl natt_mtu Ar fragsize
+Configure NAT-T fragment size.
+.It Fl esn
+Enable Extended Sequence Number extension for this SA.
+.It Fl hwif Ar ifname
+Request hardware offload to the specified interface
+.Ar ifname
+(only).
+By default offload occurs to all capable interfaces.
.El
.\"
.Pp
@@ -453,26 +479,43 @@ is expressed in one of the following three formats:
.Xc
.El
.Pp
-The direction of a policy must be specified as
-one of:
-.Li out ,
-.Li in ,
+.Bl -tag -compact -width "policy level"
+.It Ar direction
+The
+.Ar direction
+of a policy must be specified as one of:
+.Li out
+or
+.Li in .
+.It Ar policy level
+The direction is followed by one of the following policy levels:
.Li discard ,
.Li none ,
or
.Li ipsec .
+.Bl -compact -bullet
+.It
The
.Li discard
-direction
-means that packets matching the supplied indices will be discarded
-while
+policy level means that packets matching the supplied indices will
+be discarded.
+.It
+The
.Li none
-means that IPsec operations will not take place on the packet and
+policy level means that IPsec operations will not take place on
+the packet.
+.It
+The
.Li ipsec
-means that IPsec operation will take place onto the packet.
+policy level means that IPsec operation will take place onto
+the packet.
+.El
+.It Ar protocol/mode/src-dst/level
The
.Ar protocol/mode/src-dst/level
statement gives the rule for how to process the packet.
+.Bl -compact -bullet
+.It
The
.Ar protocol
is specified as
@@ -480,12 +523,15 @@ is specified as
.Li esp
or
.Li ipcomp .
+.It
The
.Ar mode
is either
.Li transport
or
.Li tunnel .
+.El
+.Pp
If
.Ar mode
is
@@ -497,6 +543,7 @@ and
with a dash,
.Sq - ,
between the addresses.
+.Pp
If
.Ar mode
is
@@ -506,6 +553,7 @@ both
and
.Ar dst
can be omitted.
+.Pp
The
.Ar level
is one of the following:
@@ -514,28 +562,35 @@ or
.Li unique .
If the SA is not available in every level, the kernel will request
the SA from the key exchange daemon.
+.Pp
+.Bl -compact -bullet
+.It
A value of
.Li default
tells the kernel to use the system wide default protocol
e.g.,\& the one from the
.Li esp_trans_deflev
sysctl variable, when the kernel processes the packet.
+.It
A value of
.Li use
means that the kernel will use an SA if it is available,
otherwise the kernel will pass the packet as it would normally.
+.It
A value of
.Li require
means that an SA is required whenever the kernel sends a packet matched
that matches the policy.
+.It
The
.Li unique
level is the same as
.Li require
but, in addition, it allows the policy to bind with the unique out-bound SA.
+.Pp
For example, if you specify the policy level
.Li unique ,
-.Xr racoon 8
+.Xr racoon 8 Pq Pa ports/security/ipsec-tools
will configure the SA for the policy.
If you configure the SA by manual keying for that policy,
you can put the decimal number as the policy identifier after
@@ -550,6 +605,8 @@ must be between 1 and 32767,
which corresponds to
.Ar extensions Fl u
of manual SA configuration.
+.El
+.El
.Pp
When you want to use an SA bundle, you can define multiple rules.
For
@@ -597,6 +654,7 @@ hmac-sha2-512 512 ah/esp: 256bit ICV (RFC4868)
aes-xcbc-mac 128 ah/esp: 96bit ICV (RFC3566)
128 ah-old/esp-old: 128bit ICV (no document)
tcp-md5 8 to 640 tcp: rfc2385
+chacha20-poly1305 256 ah/esp: 128bit ICV (RFC7634)
.Ed
.Ss Encryption Algorithms
The following encryption algorithms can be used as the
@@ -612,6 +670,7 @@ null 0 to 2048 rfc2410
aes-cbc 128/192/256 rfc3602
aes-ctr 160/224/288 rfc3686
aes-gcm-16 160/224/288 AEAD; rfc4106
+chacha20-poly1305 256 rfc7634
.Ed
.Pp
Note that the first 128/192/256 bits of a key for
@@ -688,7 +747,7 @@ add 10.1.10.36 10.1.10.34 tcp 0x1001 -A tcp-md5 "TCP-MD5 BGP secret" ;
.Sh SEE ALSO
.Xr ipsec_set_policy 3 ,
.Xr if_ipsec 4 ,
-.Xr racoon 8 ,
+.Xr racoon 8 Pq Pa ports/security/ipsec-tools ,
.Xr sysctl 8
.Rs
.%T "Changed manual key configuration for IPsec"
diff --git a/sbin/setkey/setkey.c b/sbin/setkey/setkey.c
index faf6373b312e..f7268d8f1e10 100644
--- a/sbin/setkey/setkey.c
+++ b/sbin/setkey/setkey.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $KAME: setkey.c,v 1.28 2003/06/27 07:15:45 itojun Exp $ */
/*-
@@ -99,6 +98,7 @@ usage(void)
printf("usage: setkey [-v] -c\n");
printf(" setkey [-v] -f filename\n");
+ printf(" setkey [-v] -e \"<script>\"\n");
printf(" setkey [-Pagltv] -D\n");
printf(" setkey [-Pv] -F\n");
printf(" setkey [-h] -x\n");
@@ -129,13 +129,27 @@ main(int ac, char **av)
thiszone = gmt2local(0);
- while ((c = getopt(ac, av, "acdf:ghltvxDFP")) != -1) {
+ while ((c = getopt(ac, av, "acde:f:ghltvxDFP")) != -1) {
switch (c) {
case 'c':
f_mode = MODE_SCRIPT;
fp = stdin;
break;
+ case 'e':
+ if (fp != stdin) {
+ err(-1, "only one -f/-e option is accepted");
+ }
+ f_mode = MODE_SCRIPT;
+ fp = fmemopen(optarg, strlen(optarg), "r");
+ if (fp == NULL) {
+ err(-1, "fmemopen");
+ /*NOTREACHED*/
+ }
+ break;
case 'f':
+ if (fp != stdin) {
+ err(-1, "only one -f/-e option is accepted");
+ }
f_mode = MODE_SCRIPT;
if ((fp = fopen(optarg, "r")) == NULL) {
err(-1, "fopen");
@@ -488,7 +502,7 @@ static const char *ipproto[] = {
};
#define STR_OR_ID(x, tab) \
- (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
+ (((x) < nitems(tab) && tab[(x)]) ? tab[(x)] : numstr(x))
const char *
numstr(int x)
diff --git a/sbin/setkey/test-pfkey.c b/sbin/setkey/test-pfkey.c
index ba702c80eb37..c3d2ac88e4c0 100644
--- a/sbin/setkey/test-pfkey.c
+++ b/sbin/setkey/test-pfkey.c
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $KAME: test-pfkey.c,v 1.4 2000/06/07 00:29:14 itojun Exp $ */
/*-
diff --git a/sbin/setkey/test-policy.c b/sbin/setkey/test-policy.c
index 3bf5c8975171..80021349f17c 100644
--- a/sbin/setkey/test-policy.c
+++ b/sbin/setkey/test-policy.c
@@ -27,8 +27,6 @@
* 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/types.h>
diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l
index 9a0cc9ea1915..65756f0fd12c 100644
--- a/sbin/setkey/token.l
+++ b/sbin/setkey/token.l
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $KAME: token.l,v 1.43 2003/07/25 09:35:28 itojun Exp $ */
/*-
@@ -147,6 +146,7 @@ tcp { yylval.num = 0; return(PR_TCP); }
/* authentication alogorithm */
{hyphen}A { BEGIN S_AUTHALG; return(F_AUTH); }
+<S_AUTHALG>chacha20-poly1305 { yylval.num = SADB_X_AALG_CHACHA20POLY1305; BEGIN INITIAL; return(ALG_AUTH); }
<S_AUTHALG>hmac-sha1 { yylval.num = SADB_AALG_SHA1HMAC; BEGIN INITIAL; return(ALG_AUTH); }
<S_AUTHALG>hmac-sha2-256 { yylval.num = SADB_X_AALG_SHA2_256; BEGIN INITIAL; return(ALG_AUTH); }
<S_AUTHALG>hmac-sha2-384 { yylval.num = SADB_X_AALG_SHA2_384; BEGIN INITIAL; return(ALG_AUTH); }
@@ -163,6 +163,7 @@ tcp { yylval.num = 0; return(PR_TCP); }
<S_ENCALG>aes-cbc { yylval.num = SADB_X_EALG_AESCBC; BEGIN INITIAL; return(ALG_ENC); }
<S_ENCALG>aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC_SALT); }
<S_ENCALG>aes-gcm-16 { yylval.num = SADB_X_EALG_AESGCM16; BEGIN INITIAL; return(ALG_ENC_SALT); }
+<S_ENCALG>chacha20-poly1305 { yylval.num = SADB_X_EALG_CHACHA20POLY1305; BEGIN INITIAL; return(ALG_ENC_SALT); }
/* compression algorithms */
{hyphen}C { return(F_COMP); }
@@ -184,6 +185,10 @@ nocyclic-seq { return(NOCYCLICSEQ); }
{hyphen}r { return(F_REPLAY); }
{hyphen}lh { return(F_LIFETIME_HARD); }
{hyphen}ls { return(F_LIFETIME_SOFT); }
+{hyphen}natt { return(F_NATT); }
+{hyphen}natt_mtu { return(F_NATT_MTU); }
+{hyphen}esn { return(F_ESN); }
+{hyphen}hwif { return(F_HWIF); }
/* ... */
any { return(ANY); }
@@ -251,23 +256,20 @@ any { return(ANY); }
%%
void
-yyfatal(s)
- const char *s;
+yyfatal(const char *s)
{
yyerror(s);
exit(1);
}
void
-yyerror(s)
- const char *s;
+yyerror(const char *s)
{
printf("line %d: %s at [%s]\n", lineno, s, yytext);
}
int
-parse(fp)
- FILE **fp;
+parse(FILE **fp)
{
yyin = *fp;
diff --git a/sbin/setkey/vchar.h b/sbin/setkey/vchar.h
index c7e96cb9ca1a..035bfa82e1e6 100644
--- a/sbin/setkey/vchar.h
+++ b/sbin/setkey/vchar.h
@@ -1,4 +1,3 @@
-/* $FreeBSD$ */
/* $KAME: vchar.h,v 1.2 2000/06/07 00:29:14 itojun Exp $ */
/*-
diff --git a/sbin/shutdown/Makefile b/sbin/shutdown/Makefile
index fc7e38be03cd..6c5d6e4487e2 100644
--- a/sbin/shutdown/Makefile
+++ b/sbin/shutdown/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
PACKAGE=runtime
PROG= shutdown
MAN= shutdown.8
diff --git a/sbin/shutdown/Makefile.depend b/sbin/shutdown/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/shutdown/Makefile.depend
+++ b/sbin/shutdown/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/shutdown/shutdown.8 b/sbin/shutdown/shutdown.8
index 12a7baba0de8..ed44ac36aef6 100644
--- a/sbin/shutdown/shutdown.8
+++ b/sbin/shutdown/shutdown.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)shutdown.8 8.2 (Berkeley) 4/27/95
-.\" $FreeBSD$
-.\"
-.Dd January 11, 2020
+.Dd August 4, 2024
.Dt SHUTDOWN 8
.Os
.Sh NAME
@@ -39,13 +36,14 @@
.Nm
.Op Fl
.Oo
-.Fl c | Fl h | Fl p |
+.Fl c | Fl f | Fl h | Fl p |
.Fl r | Fl k
.Oc
.Oo
.Fl o
.Op Fl n
.Oc
+.Op Fl q
.Ar time
.Op Ar warning-message ...
.Nm poweroff
@@ -56,6 +54,10 @@ utility provides an automated shutdown procedure for super-users
to nicely notify users when the system is shutting down,
saving them from system administrators, hackers, and gurus, who
would otherwise not bother with such niceties.
+In order to use the
+.Nm
+command, the user must have root privileges or be a member of the
+operator group.
.Pp
The following options are available:
.Bl -tag -width indent
@@ -69,6 +71,12 @@ At the present time, only systems with BMC supported by the
driver that implement this functionality support this flag.
The amount of time the system is off is dependent on the device
that implements this feature.
+.It Fl f
+The
+.Nm
+command ignores the presence of the
+.Pa /var/run/noshutdown
+file.
.It Fl h
The system is halted at the specified
.Ar time .
@@ -112,6 +120,12 @@ to
or
.Xr reboot 8 .
This option should probably not be used.
+.It Fl q
+Shut down quietly.
+Suppress the warning message to all logged in users about system shutdown.
+It is an error to supply a
+.Ar warning-message
+when warnings are suppressed.
.It Ar time
.Ar Time
is the time at which
@@ -198,6 +212,12 @@ file that
.Nm
created will be removed automatically.
.Pp
+If the
+.Pa /var/run/noshutdown
+file is present,
+.Nm
+exits without executing any action on the system.
+.Pp
When run without options, the
.Nm
utility will place the system into single user mode at the
@@ -211,11 +231,18 @@ is equivalent to running:
shutdown -p now
.Ed
.Sh FILES
-.Bl -tag -width /var/run/nologin -compact
+.Bl -tag -width /var/run/noshutdown -compact
.It Pa /var/run/nologin
tells
.Xr login 1
not to let anyone log in
+.It Pa /var/run/noshutdown
+prevents
+.Nm
+from initiating an action on the system.
+Can be overridden with the
+.Fl f
+option.
.El
.Sh EXAMPLES
Reboot the system in 30 minutes and display a warning message on the terminals
diff --git a/sbin/shutdown/shutdown.c b/sbin/shutdown/shutdown.c
index 76e02d1fd6b1..762b23ab6bd9 100644
--- a/sbin/shutdown/shutdown.c
+++ b/sbin/shutdown/shutdown.c
@@ -29,23 +29,10 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1988, 1990, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)shutdown.c 8.4 (Berkeley) 4/28/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/boottrace.h>
#include <sys/resource.h>
+#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/time.h>
@@ -57,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <pwd.h>
#include <setjmp.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -92,7 +80,8 @@ static struct interval {
#undef S
static time_t offset, shuttime;
-static int docycle, dohalt, dopower, doreboot, killflg, mbuflen, oflag;
+static int docycle, dohalt, dopower, doreboot, ign_noshutdown,
+ killflg, mbuflen, oflag;
static char mbuf[BUFSIZ];
static const char *nosync, *whom;
@@ -100,7 +89,7 @@ static void badtime(void);
static void die_you_gravy_sucking_pig_dog(void);
static void finish(int);
static void getoffset(char *);
-static void loop(void);
+static void loop(bool);
static void nolog(void);
static void timeout(int);
static void timewarn(int);
@@ -113,13 +102,16 @@ main(int argc, char **argv)
{
char *p, *endp;
struct passwd *pw;
+ struct stat st;
int arglen, ch, len, readstdin;
+ bool dowarn;
#ifndef DEBUG
if (geteuid())
errx(1, "NOT super-user");
#endif
+ dowarn = true;
nosync = NULL;
readstdin = 0;
@@ -144,7 +136,7 @@ main(int argc, char **argv)
goto poweroff;
}
- while ((ch = getopt(argc, argv, "-chknopr")) != -1)
+ while ((ch = getopt(argc, argv, "-cfhknopqr")) != -1)
switch (ch) {
case '-':
readstdin = 1;
@@ -152,6 +144,9 @@ main(int argc, char **argv)
case 'c':
docycle = 1;
break;
+ case 'f':
+ ign_noshutdown = 1;
+ break;
case 'h':
dohalt = 1;
break;
@@ -167,6 +162,9 @@ main(int argc, char **argv)
case 'p':
dopower = 1;
break;
+ case 'q':
+ dowarn = false;
+ break;
case 'r':
doreboot = 1;
break;
@@ -192,6 +190,8 @@ main(int argc, char **argv)
getoffset(*argv++);
poweroff:
+ if (!dowarn && *argv != NULL)
+ usage("warning-message supplied but suppressed with -q");
if (*argv) {
for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) {
arglen = strlen(*argv);
@@ -222,6 +222,12 @@ poweroff:
}
mbuflen = strlen(mbuf);
+ if (!ign_noshutdown && stat(_PATH_NOSHUTDOWN, &st) == 0) {
+ (void)printf("Shutdown cannot be done, " _PATH_NOSHUTDOWN
+ " is present\n");
+ exit(2);
+ }
+
if (offset) {
BOOTTRACE("Shutdown at %s", ctime(&shuttime));
(void)printf("Shutdown at %.24s.\n", ctime(&shuttime));
@@ -249,12 +255,12 @@ poweroff:
setsid();
#endif
openlog("shutdown", LOG_CONS, LOG_AUTH);
- loop();
+ loop(dowarn);
return(0);
}
static void
-loop(void)
+loop(bool dowarn)
{
struct interval *tp;
u_int sltime;
@@ -277,13 +283,14 @@ loop(void)
* the next wait time.
*/
if ((sltime = offset - tp->timeleft)) {
- if (sltime > (u_int)(tp->timetowait / 5))
+ if (dowarn && sltime > (u_int)(tp->timetowait / 5))
timewarn(offset);
(void)sleep(sltime);
}
}
for (;; ++tp) {
- timewarn(tp->timeleft);
+ if (dowarn)
+ timewarn(tp->timeleft);
if (!logged && tp->timeleft <= NOLOG_TIME) {
logged = 1;
nolog();
@@ -598,7 +605,7 @@ usage(const char *cp)
if (cp != NULL)
warnx("%s", cp);
(void)fprintf(stderr,
- "usage: shutdown [-] [-c | -h | -p | -r | -k] [-o [-n]] time [warning-message ...]\n"
+ "usage: shutdown [-] [-c | -f | -h | -p | -r | -k] [-o [-n]] [-q] time [warning-message ...]\n"
" poweroff\n");
exit(1);
}
diff --git a/sbin/swapon/Makefile b/sbin/swapon/Makefile
index c832be3dc96a..0c034338a533 100644
--- a/sbin/swapon/Makefile
+++ b/sbin/swapon/Makefile
@@ -1,6 +1,3 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
PACKAGE=runtime
PROG= swapon
MAN= swapon.8
@@ -11,4 +8,9 @@ MLINKS+=swapon.8 swapctl.8
LIBADD= util
+.include <src.opts.mk>
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
.include <bsd.prog.mk>
diff --git a/sbin/swapon/Makefile.depend b/sbin/swapon/Makefile.depend
index 991757ecadc0..678747db6f2c 100644
--- a/sbin/swapon/Makefile.depend
+++ b/sbin/swapon/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/swapon/swapon.8 b/sbin/swapon/swapon.8
index 0146a7750e12..f5534c06eb9f 100644
--- a/sbin/swapon/swapon.8
+++ b/sbin/swapon/swapon.8
@@ -25,9 +25,6 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)swapon.8 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
.Dd November 29, 2021
.Dt SWAPON 8
.Os
diff --git a/sbin/swapon/swapon.c b/sbin/swapon/swapon.c
index 4daa6e8b17ee..3dff4df5e63f 100644
--- a/sbin/swapon/swapon.c
+++ b/sbin/swapon/swapon.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)swapon.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/disk.h>
#include <sys/disklabel.h>
@@ -68,9 +54,10 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-static void usage(void);
+#define DOT_ELI ".eli"
+
+static void usage(void) __dead2;
static const char *swap_on_off(const char *, int, char *);
-static const char *swap_on_off_gbde(const char *, int);
static const char *swap_on_off_geli(const char *, char *, int);
static const char *swap_on_off_md(const char *, char *, int);
static const char *swap_on_off_sfile(const char *, int);
@@ -245,21 +232,18 @@ swap_on_off(const char *name, int doingall, char *mntops)
(fnmatch(_PATH_DEV MD_NAME "[0-9]*", name, 0) == 0 ||
fnmatch(MD_NAME "[0-9]*", name, 0) == 0 ||
strncmp(_PATH_DEV MD_NAME, name,
- sizeof(_PATH_DEV) + sizeof(MD_NAME)) == 0 ||
- strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0))
+ sizeof(_PATH_DEV MD_NAME)) == 0 ||
+ strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0 ||
+ strncmp(_PATH_DEV MD_NAME DOT_ELI, name,
+ sizeof(_PATH_DEV MD_NAME DOT_ELI)) == 0 ||
+ strncmp(MD_NAME DOT_ELI, name, sizeof(MD_NAME DOT_ELI)) == 0))
return (swap_on_off_md(name, mntops, doingall));
basebuf = strdup(name);
base = basename(basebuf);
- /* Swap on encrypted device by GEOM_BDE. */
- if (fnmatch("*.bde", base, 0) == 0) {
- free(basebuf);
- return (swap_on_off_gbde(name, doingall));
- }
-
/* Swap on encrypted device by GEOM_ELI. */
- if (fnmatch("*.eli", base, 0) == 0) {
+ if (fnmatch("*" DOT_ELI, base, 0) == 0) {
free(basebuf);
return (swap_on_off_geli(name, mntops, doingall));
}
@@ -283,59 +267,6 @@ swap_basename(const char *name)
return (dname);
}
-static const char *
-swap_on_off_gbde(const char *name, int doingall)
-{
- const char *ret;
- char pass[64 * 2 + 1];
- unsigned char bpass[64];
- char *dname;
- int i, error;
-
- dname = swap_basename(name);
- if (dname == NULL)
- return (NULL);
-
- if (which_prog == SWAPON) {
- arc4random_buf(bpass, sizeof(bpass));
- for (i = 0; i < (int)sizeof(bpass); i++)
- sprintf(&pass[2 * i], "%02x", bpass[i]);
- pass[sizeof(pass) - 1] = '\0';
-
- error = run_cmd(NULL, "%s init %s -P %s", _PATH_GBDE,
- dname, pass);
- if (error) {
- /* bde device found. Ignore it. */
- free(dname);
- if (qflag == 0)
- warnx("%s: Device already in use", name);
- return (NULL);
- }
- error = run_cmd(NULL, "%s attach %s -p %s", _PATH_GBDE,
- dname, pass);
- free(dname);
- if (error) {
- warnx("gbde (attach) error: %s", name);
- return (NULL);
- }
- }
-
- ret = swap_on_off_sfile(name, doingall);
-
- if (which_prog == SWAPOFF) {
- error = run_cmd(NULL, "%s detach %s", _PATH_GBDE, dname);
- free(dname);
- if (error) {
- /* bde device not found. Ignore it. */
- if (qflag == 0)
- warnx("%s: Device not found", name);
- return (NULL);
- }
- }
-
- return (ret);
-}
-
/* Build geli(8) arguments from mntops */
static char *
swap_on_geli_args(const char *mntops)
@@ -401,6 +332,8 @@ swap_on_geli_args(const char *mntops)
return (NULL);
}
Tflag = " -T ";
+ } else if ((p = strstr(token, "file=")) == token) {
+ /* ignore known option */
} else if (strcmp(token, "late") == 0) {
/* ignore known option */
} else if (strcmp(token, "noauto") == 0) {
@@ -490,24 +423,38 @@ swap_on_off_md(const char *name, char *mntops, int doingall)
char *p, *vnodefile;
size_t linelen;
u_long ul;
+ const char *suffix;
+ char *devbuf, *dname;
+ int name_len;
fd = -1;
sfd = NULL;
- if (strlen(name) == (sizeof(MD_NAME) - 1))
+ devbuf = strdup(name);
+ name_len = strlen(name) - strlen(DOT_ELI);
+ if (name_len > 0 && strcmp(suffix = &name[name_len], DOT_ELI) == 0) {
+ suffix++;
+ devbuf[name_len] = '\0';
+ } else
+ suffix = NULL;
+ /* dname will be name without /dev/ prefix and .eli suffix */
+ dname = basename(devbuf);
+ if (strlen(dname) == (sizeof(MD_NAME) - 1))
mdunit = -1;
else {
errno = 0;
- ul = strtoul(name + 2, &p, 10);
+ ul = strtoul(dname + 2, &p, 10);
if (errno == 0) {
if (*p != '\0' || ul > INT_MAX)
errno = EINVAL;
}
if (errno) {
- warn("Bad device unit: %s", name);
+ warn("Bad device unit: %s", dname);
+ free(devbuf);
return (NULL);
}
mdunit = (int)ul;
}
+ free(devbuf);
vnodefile = NULL;
if ((p = strstr(mntops, "file=")) != NULL) {
@@ -647,10 +594,19 @@ swap_on_off_md(const char *name, char *mntops, int doingall)
}
}
}
- snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV,
- MD_NAME, mdunit);
- mdpath[sizeof(mdpath) - 1] = '\0';
- ret = swap_on_off_sfile(mdpath, doingall);
+
+ if (suffix != NULL && strcmp("eli", suffix) == 0) {
+ /* Swap on encrypted device by GEOM_ELI. */
+ snprintf(mdpath, sizeof(mdpath), "%s%s%d" DOT_ELI, _PATH_DEV,
+ MD_NAME, mdunit);
+ mdpath[sizeof(mdpath) - 1] = '\0';
+ ret = swap_on_off_geli(mdpath, mntops, doingall);
+ } else {
+ snprintf(mdpath, sizeof(mdpath), "%s%s%d", _PATH_DEV,
+ MD_NAME, mdunit);
+ mdpath[sizeof(mdpath) - 1] = '\0';
+ ret = swap_on_off_sfile(mdpath, doingall);
+ }
if (which_prog == SWAPOFF) {
if (ret != NULL) {
diff --git a/sbin/swapon/tests/Makefile b/sbin/swapon/tests/Makefile
new file mode 100644
index 000000000000..aa0c9cf202d6
--- /dev/null
+++ b/sbin/swapon/tests/Makefile
@@ -0,0 +1,5 @@
+ATF_TESTS_SH= swapon_test
+
+TEST_METADATA.swapon_test+= required_user="root"
+
+.include <bsd.test.mk>
diff --git a/sbin/swapon/tests/swapon_test.sh b/sbin/swapon/tests/swapon_test.sh
new file mode 100755
index 000000000000..a04bb36cc49e
--- /dev/null
+++ b/sbin/swapon/tests/swapon_test.sh
@@ -0,0 +1,225 @@
+# Copyright (c) 2025 Ronald Klop <ronald@FreeBSD.org>
+#
+# 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.
+#
+#
+
+atf_test_case attach_mdX cleanup
+attach_mdX_head()
+{
+ atf_set "descr" "mdX device should attach"
+}
+attach_mdX_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo 'md31 none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md31 as swap device" -x "swapon -F fstab.out -a"
+}
+attach_mdX_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_mdX cleanup
+attach_dev_mdX_head()
+{
+ atf_set "descr" "/dev/mdX device should attach"
+}
+attach_dev_mdX_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md32 none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md32 as swap device" -x "swapon -F fstab.out -a"
+}
+attach_dev_mdX_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_md cleanup
+attach_md_head()
+{
+ atf_set "descr" "md device should attach"
+}
+attach_md_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo 'md none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md[0-9][0-9]* as swap device" -x "swapon -F fstab.out -a"
+}
+attach_md_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_md cleanup
+attach_dev_md_head()
+{
+ atf_set "descr" "/dev/md device should attach"
+}
+attach_dev_md_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md[0-9][0-9]* as swap device" -x "swapon -F fstab.out -a"
+}
+attach_dev_md_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_mdX_eli cleanup
+attach_mdX_eli_head()
+{
+ atf_set "descr" "mdX.eli device should attach"
+}
+attach_mdX_eli_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo 'md33.eli none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md33.eli as swap device" -x "swapon -F fstab.out -a"
+}
+attach_mdX_eli_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_mdX_eli cleanup
+attach_dev_mdX_eli_head()
+{
+ atf_set "descr" "/dev/mdX.eli device should attach"
+}
+attach_dev_mdX_eli_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md34.eli none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md34.eli as swap device" -x "swapon -F fstab.out -a"
+}
+attach_dev_mdX_eli_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_md_eli cleanup
+attach_md_eli_head()
+{
+ atf_set "descr" "md.eli device should attach"
+}
+attach_md_eli_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo 'md.eli none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md[0-9][0-9]*.eli as swap device" -x "swapon -F fstab.out -a"
+}
+attach_md_eli_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+atf_test_case attach_dev_md_eli cleanup
+attach_dev_md_eli_head()
+{
+ atf_set "descr" "/dev/md.eli device should attach"
+}
+attach_dev_md_eli_body()
+{
+ # if the swapfile is too small (like 1k) then mdconfig hangs looking up the md
+ # but need a swapfile bigger than one page kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize * 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo '/dev/md.eli none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:0 -o match:"swapon: adding /dev/md[0-9][0-9]*.eli as swap device" -x "swapon -F fstab.out -a"
+}
+attach_dev_md_eli_cleanup()
+{
+ swapoff -F fstab.out -a
+}
+
+###
+
+atf_test_case attach_too_small
+attach_too_small_head()
+{
+ atf_set "descr" "should refuse to attach if smaller than one kernel page size"
+}
+attach_too_small_body()
+{
+ # Need to use smaller than kernel page size
+ pagesize=$(sysctl -n hw.pagesize)
+ minsize=$(( pagesize / 2 ))
+ atf_check -s exit:0 -x "truncate -s $minsize swapfile"
+ atf_check -s exit:0 -o save:fstab.out -x "echo 'md35 none swap sw,file=swapfile 0 0'"
+ atf_check -s exit:1 -e match:"swapon: /dev/md35: NSWAPDEV limit reached" -x "swapon -F fstab.out -a"
+ atf_check -s exit:0 -x "mdconfig -d -u 35"
+}
+
+###
+atf_init_test_cases()
+{
+ atf_add_test_case attach_mdX
+ atf_add_test_case attach_dev_mdX
+ atf_add_test_case attach_md
+ atf_add_test_case attach_dev_md
+
+ atf_add_test_case attach_mdX_eli
+ atf_add_test_case attach_dev_mdX_eli
+ atf_add_test_case attach_md_eli
+ atf_add_test_case attach_dev_md_eli
+
+ atf_add_test_case attach_too_small
+}
diff --git a/sbin/sysctl/Makefile b/sbin/sysctl/Makefile
index 2069bd3382d2..99074e47964d 100644
--- a/sbin/sysctl/Makefile
+++ b/sbin/sysctl/Makefile
@@ -1,5 +1,4 @@
-# @(#)Makefile 8.1 (Berkeley) 6/6/93
-# $FreeBSD$
+.include <src.opts.mk>
PACKAGE=runtime
CONFS= sysctl.conf
@@ -7,4 +6,12 @@ PROG= sysctl
WARNS?= 3
MAN= sysctl.8
+.if ${MK_JAIL} != "no" && !defined(RESCUE)
+CFLAGS+= -DJAIL
+LIBADD+= jail
+.endif
+
+HAS_TESTS=
+SUBDIR.${MK_TESTS}+= tests
+
.include <bsd.prog.mk>
diff --git a/sbin/sysctl/Makefile.depend b/sbin/sysctl/Makefile.depend
index 6cfaab1c3644..6ef78fac5cbf 100644
--- a/sbin/sysctl/Makefile.depend
+++ b/sbin/sysctl/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8
index bd4000697552..e0e35f075a78 100644
--- a/sbin/sysctl/sysctl.8
+++ b/sbin/sysctl/sysctl.8
@@ -1,3 +1,6 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
.\"
@@ -25,10 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93
-.\" $FreeBSD$
-.\"
-.Dd June 30, 2022
+.Dd January 31, 2025
.Dt SYSCTL 8
.Os
.Sh NAME
@@ -36,13 +36,15 @@
.Nd get or set kernel state
.Sh SYNOPSIS
.Nm
-.Op Fl bdehiNnoTtqWx
+.Op Fl j Ar jail
+.Op Fl bdeFhiJlNnoqTtVWx
.Op Fl B Ar bufsize
.Op Fl f Ar filename
.Ar name Ns Op = Ns Ar value Ns Op , Ns Ar value
.Ar ...
.Nm
-.Op Fl bdehNnoTtqWx
+.Op Fl j Ar jail
+.Op Fl bdeFhJlNnoqTtVWx
.Op Fl B Ar bufsize
.Fl a
.Sh DESCRIPTION
@@ -53,11 +55,10 @@ privilege to set kernel state.
The state to be retrieved or set is described using a
.Dq Management Information Base
.Pq Dq MIB
-style name, described as a dotted set of
-components.
+style name, described as a dotted set of components.
.Pp
The following options are available:
-.Bl -tag -width indent
+.Bl -tag -width "-f filename"
.It Fl A
Equivalent to
.Fl o a
@@ -69,10 +70,6 @@ opaque or excluded from listing via the
flag.
This option is ignored if one or more variable names are specified on
the command line.
-.It Fl b
-Force the value of the variable(s) to be output in raw, binary format.
-No names are printed and no terminating newlines are output.
-This is mostly useful with a single variable.
.It Fl B Ar bufsize
Set the buffer size to read from the
.Nm
@@ -82,6 +79,10 @@ This is necessary for a
.Nm
that has variable length, and the probe value of 0 is a valid length, such as
.Va kern.arandom .
+.It Fl b
+Force the value of the variable(s) to be output in raw, binary format.
+No names are printed and no terminating newlines are output.
+This is mostly useful with a single variable.
.It Fl d
Print the description of the variable instead of its value.
.It Fl e
@@ -95,11 +96,19 @@ This option is ignored if either
or
.Fl n
is specified, or a variable is being set.
+.It Fl F
+Print the format of the variable.
+This is additional information to describe the type of the variable and
+most useful with struct types such as clockinfo, timeval, and loadavg.
.It Fl f Ar filename
Specify a file which contains a pair of name and value in each line.
.Nm
reads and processes the specified file first and then processes the name
and value pairs in the command line argument.
+Note that when the
+.Fl j Ar jail
+option is specified, the file will be opened before attaching to the jail and
+then be processed inside the jail.
.It Fl h
Format output for human, rather than machine, readability.
.It Fl i
@@ -108,6 +117,17 @@ The purpose is to make use of
.Nm
for collecting data from a variety of machines (not all of which
are necessarily running exactly the same software) easier.
+.It Fl J
+Display only jail prision sysctl variables (CTLFLAG_PRISON).
+.It Fl j Ar jail
+Perform the actions inside the
+.Ar jail
+(by jail id or jail name).
+.It Fl l
+Show the length of variables along with their values.
+This option cannot be combined with the
+.Fl N
+option.
.It Fl N
Show only variable names, not their values.
This is particularly useful with shells that offer programmable
@@ -145,6 +165,8 @@ to standard error.
Display only variables that are settable via loader (CTLFLAG_TUN).
.It Fl t
Print the type of the variable.
+.It Fl V
+Display only VNET sysctl variables (CTLFLAG_VNET).
.It Fl W
Display only writable variables that are not statistical.
Useful for determining the set of runtime tunable sysctls.
@@ -185,8 +207,10 @@ Please refer to
for more information on which tunables are available and how to set them.
.Pp
The string and integer information is summarized below.
-For a detailed description of these variable see
-.Xr sysctl 3 .
+For a detailed description of these variables see
+.Xr sysctl 3
+and
+.Xr security 7 .
.Pp
The changeable column indicates whether a process with appropriate
privilege can change the value.
@@ -194,75 +218,77 @@ String and integer values can be set using
.Nm .
.Bl -column security.bsd.unprivileged_read_msgbuf integerxxx
.It Sy "Name Type Changeable"
-.It "kern.ostype string no"
-.It "kern.osrelease string no"
-.It "kern.osrevision integer no"
-.It "kern.version string no"
-.It "kern.maxvnodes integer yes"
-.It "kern.maxproc integer no"
-.It "kern.maxprocperuid integer yes"
-.It "kern.maxfiles integer yes"
-.It "kern.maxfilesperproc integer yes"
-.It "kern.argmax integer no"
-.It "kern.securelevel integer raise only"
-.It "kern.hostname string yes"
-.It "kern.hostid integer yes"
-.It "kern.clockrate struct no"
-.It "kern.posix1version integer no"
-.It "kern.ngroups integer no"
-.It "kern.job_control integer no"
-.It "kern.saved_ids integer no"
-.It "kern.boottime struct no"
-.It "kern.domainname string yes"
-.It "kern.filedelay integer yes"
-.It "kern.dirdelay integer yes"
-.It "kern.metadelay integer yes"
-.It "kern.osreldate integer no"
-.It "kern.bootfile string yes"
-.It "kern.corefile string yes"
-.It "kern.logsigexit integer yes"
-.It "security.bsd.suser_enabled integer yes"
-.It "security.bsd.see_other_uids integer yes"
-.It "security.bsd.unprivileged_proc_debug integer yes"
-.It "security.bsd.unprivileged_read_msgbuf integer yes"
-.It "vm.loadavg struct no"
-.It "hw.machine string no"
-.It "hw.model string no"
-.It "hw.ncpu integer no"
-.It "hw.byteorder integer no"
-.It "hw.physmem integer no"
-.It "hw.usermem integer no"
-.It "hw.pagesize integer no"
-.It "hw.floatingpoint integer no"
-.It "hw.machine_arch string no"
-.It "hw.realmem integer no"
-.It "machdep.adjkerntz integer yes"
-.It "machdep.disable_rtc_set integer yes"
-.It "machdep.guessed_bootdev string no"
-.It "user.cs_path string no"
-.It "user.bc_base_max integer no"
-.It "user.bc_dim_max integer no"
-.It "user.bc_scale_max integer no"
-.It "user.bc_string_max integer no"
-.It "user.coll_weights_max integer no"
-.It "user.expr_nest_max integer no"
-.It "user.line_max integer no"
-.It "user.re_dup_max integer no"
-.It "user.posix2_version integer no"
-.It "user.posix2_c_bind integer no"
-.It "user.posix2_c_dev integer no"
-.It "user.posix2_char_term integer no"
-.It "user.posix2_fort_dev integer no"
-.It "user.posix2_fort_run integer no"
-.It "user.posix2_localedef integer no"
-.It "user.posix2_sw_dev integer no"
-.It "user.posix2_upe integer no"
-.It "user.stream_max integer no"
-.It "user.tzname_max integer no"
-.It "user.localbase string no"
+.It Va "kern.ostype string no"
+.It Va "kern.osrelease string no"
+.It Va "kern.osrevision integer no"
+.It Va "kern.version string no"
+.It Va "kern.maxvnodes integer yes"
+.It Va "kern.maxproc integer no"
+.It Va "kern.maxprocperuid integer yes"
+.It Va "kern.maxfiles integer yes"
+.It Va "kern.maxfilesperproc integer yes"
+.It Va "kern.argmax integer no"
+.It Va "kern.securelevel integer raise only"
+.It Va "kern.hostname string yes"
+.It Va "kern.hostid integer yes"
+.It Va "kern.clockrate struct no"
+.It Va "kern.posix1version integer no"
+.It Va "kern.ngroups integer no"
+.It Va "kern.job_control integer no"
+.It Va "kern.saved_ids integer no"
+.It Va "kern.boottime struct no"
+.It Va "kern.domainname string yes"
+.It Va "kern.filedelay integer yes"
+.It Va "kern.dirdelay integer yes"
+.It Va "kern.metadelay integer yes"
+.It Va "kern.osreldate integer no"
+.It Va "kern.bootfile string yes"
+.It Va "kern.corefile string yes"
+.It Va "kern.logsigexit integer yes"
+.It Va "security.bsd.suser_enabled integer yes"
+.It Va "security.bsd.see_other_uids integer yes"
+.It Va "security.bsd.see_other_gids integer yes"
+.It Va "security.bsd.see_jail_proc integer yes"
+.It Va "security.bsd.unprivileged_proc_debug integer yes"
+.It Va "security.bsd.unprivileged_read_msgbuf integer yes"
+.It Va "vm.loadavg struct no"
+.It Va "hw.machine string no"
+.It Va "hw.model string no"
+.It Va "hw.ncpu integer no"
+.It Va "hw.byteorder integer no"
+.It Va "hw.physmem integer no"
+.It Va "hw.usermem integer no"
+.It Va "hw.pagesize integer no"
+.It Va "hw.floatingpoint integer no"
+.It Va "hw.machine_arch string no"
+.It Va "hw.realmem integer no"
+.It Va "machdep.adjkerntz integer yes"
+.It Va "machdep.disable_rtc_set integer yes"
+.It Va "machdep.guessed_bootdev string no"
+.It Va "user.cs_path string no"
+.It Va "user.bc_base_max integer no"
+.It Va "user.bc_dim_max integer no"
+.It Va "user.bc_scale_max integer no"
+.It Va "user.bc_string_max integer no"
+.It Va "user.coll_weights_max integer no"
+.It Va "user.expr_nest_max integer no"
+.It Va "user.line_max integer no"
+.It Va "user.re_dup_max integer no"
+.It Va "user.posix2_version integer no"
+.It Va "user.posix2_c_bind integer no"
+.It Va "user.posix2_c_dev integer no"
+.It Va "user.posix2_char_term integer no"
+.It Va "user.posix2_fort_dev integer no"
+.It Va "user.posix2_fort_run integer no"
+.It Va "user.posix2_localedef integer no"
+.It Va "user.posix2_sw_dev integer no"
+.It Va "user.posix2_upe integer no"
+.It Va "user.stream_max integer no"
+.It Va "user.tzname_max integer no"
+.It Va "user.localbase string no"
.El
.Sh FILES
-.Bl -tag -width ".In netinet/icmp_var.h" -compact
+.Bl -tag -width "<netinet/icmp_var.h>" -compact
.It In sys/sysctl.h
definitions for top level identifiers, second level kernel and hardware
identifiers, and user level identifiers
@@ -286,20 +312,20 @@ definitions for fourth level UDP identifiers
For example, to retrieve the maximum number of processes allowed
in the system, one would use the following request:
.Pp
-.Dl "sysctl kern.maxproc"
+.Dl Va "sysctl kern.maxproc"
.Pp
To set the maximum number of processes allowed
per uid to 1000, one would use the following request:
.Pp
-.Dl "sysctl kern.maxprocperuid=1000"
+.Dl Va "sysctl kern.maxprocperuid=1000"
.Pp
Information about the system clock rate may be obtained with:
.Pp
-.Dl "sysctl kern.clockrate"
+.Dl Va "sysctl kern.clockrate"
.Pp
Information about the load average history may be obtained with:
.Pp
-.Dl "sysctl vm.loadavg"
+.Dl Va "sysctl vm.loadavg"
.Pp
More variables than these exist, and the best and likely only place
to search for their deeper meaning is undoubtedly the source where
@@ -312,7 +338,9 @@ option has been deprecated and is silently ignored.
.Xr sysctl 3 ,
.Xr loader.conf 5 ,
.Xr sysctl.conf 5 ,
-.Xr loader 8
+.Xr security 7 ,
+.Xr loader 8 ,
+.Xr jail 8
.Sh HISTORY
A
.Nm
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 5a090ca20fc4..302dc6865123 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -29,13 +29,13 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
+#ifdef JAIL
+#include <sys/jail.h>
+#endif
#include <sys/sysctl.h>
#include <sys/vmmeter.h>
#include <dev/evdev/input.h>
@@ -54,6 +54,9 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <inttypes.h>
+#ifdef JAIL
+#include <jail.h>
+#endif
#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
@@ -62,13 +65,18 @@ __FBSDID("$FreeBSD$");
#include <sysexits.h>
#include <unistd.h>
+#ifdef JAIL
+static const char *jailname;
+#endif
static const char *conffile;
static int aflag, bflag, Bflag, dflag, eflag, hflag, iflag;
static int Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag;
+static bool Fflag, Jflag, lflag, Vflag;
+static void attach_jail(void);
static int oidfmt(int *, int, char *, u_int *);
-static int parsefile(const char *);
+static int parsefile(FILE *);
static int parse(const char *, int);
static int show_var(int *, int, bool);
static int sysctl_all(int *, int);
@@ -123,8 +131,8 @@ usage(void)
{
(void)fprintf(stderr, "%s\n%s\n",
- "usage: sysctl [-bdehiNnoqTtWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
- " sysctl [-bdehNnoqTtWx] [ -B <bufsize> ] -a");
+ "usage: sysctl [-j jail] [-bdeFhiJlNnoqTtVWx] [ -B <bufsize> ] [-f filename] name[=value] ...",
+ " sysctl [-j jail] [-bdeFhJlNnoqTtVWx] [ -B <bufsize> ] -a");
exit(1);
}
@@ -133,12 +141,13 @@ main(int argc, char **argv)
{
int ch;
int warncount = 0;
+ FILE *file = NULL;
setlocale(LC_NUMERIC, "");
setbuf(stdout,0);
setbuf(stderr,0);
- while ((ch = getopt(argc, argv, "AabB:def:hiNnoqtTwWxX")) != -1) {
+ while ((ch = getopt(argc, argv, "AaB:bdeFf:hiJj:lNnoqTtVWwXx")) != -1) {
switch (ch) {
case 'A':
/* compatibility */
@@ -147,18 +156,21 @@ main(int argc, char **argv)
case 'a':
aflag = 1;
break;
- case 'b':
- bflag = 1;
- break;
case 'B':
Bflag = strtol(optarg, NULL, 0);
break;
+ case 'b':
+ bflag = 1;
+ break;
case 'd':
dflag = 1;
break;
case 'e':
eflag = 1;
break;
+ case 'F':
+ Fflag = true;
+ break;
case 'f':
conffile = optarg;
break;
@@ -168,6 +180,20 @@ main(int argc, char **argv)
case 'i':
iflag = 1;
break;
+ case 'J':
+ Jflag = true;
+ break;
+ case 'j':
+#ifdef JAIL
+ if ((jailname = optarg) == NULL)
+ usage();
+#else
+ errx(1, "not built with jail support");
+#endif
+ break;
+ case 'l':
+ lflag = true;
+ break;
case 'N':
Nflag = 1;
break;
@@ -180,19 +206,22 @@ main(int argc, char **argv)
case 'q':
qflag = 1;
break;
+ case 'T':
+ Tflag = 1;
+ break;
case 't':
tflag = 1;
break;
- case 'T':
- Tflag = 1;
+ case 'V':
+ Vflag = true;
+ break;
+ case 'W':
+ Wflag = 1;
break;
case 'w':
/* compatibility */
/* ignored */
break;
- case 'W':
- Wflag = 1;
- break;
case 'X':
/* compatibility */
aflag = xflag = 1;
@@ -207,16 +236,27 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
- if (Nflag && nflag)
+ /* Nflag is name only and doesn't make sense to combine with these */
+ /* TODO: few other combinations do not make sense but come back later */
+ if (Nflag && (lflag || nflag))
usage();
- if (aflag && argc == 0)
+ if (aflag && argc == 0) {
+ attach_jail();
exit(sysctl_all(NULL, 0));
+ }
if (argc == 0 && conffile == NULL)
usage();
- warncount = 0;
- if (conffile != NULL)
- warncount += parsefile(conffile);
+ if (conffile != NULL) {
+ file = fopen(conffile, "r");
+ if (file == NULL)
+ err(EX_NOINPUT, "%s", conffile);
+ }
+ attach_jail();
+ if (file != NULL) {
+ warncount += parsefile(file);
+ fclose(file);
+ }
while (argc-- > 0)
warncount += parse(*argv++, 0);
@@ -224,6 +264,23 @@ main(int argc, char **argv)
return (warncount);
}
+static void
+attach_jail(void)
+{
+#ifdef JAIL
+ int jid;
+
+ if (jailname == NULL)
+ return;
+
+ jid = jail_getid(jailname);
+ if (jid == -1)
+ errx(1, "jail not found");
+ if (jail_attach(jid) != 0)
+ errx(1, "cannot attach to jail");
+#endif
+}
+
/*
* Parse a single numeric value, append it to 'newbuf', and update
* 'newsize'. Returns true if the value was parsed and false if the
@@ -557,15 +614,11 @@ parse(const char *string, int lineno)
}
static int
-parsefile(const char *filename)
+parsefile(FILE *file)
{
- FILE *file;
char line[BUFSIZ], *p, *pq, *pdq;
int warncount = 0, lineno = 0;
- file = fopen(filename, "r");
- if (file == NULL)
- err(EX_NOINPUT, "%s", filename);
while (fgets(line, sizeof(line), file) != NULL) {
lineno++;
p = line;
@@ -601,7 +654,6 @@ parsefile(const char *filename)
else
warncount += parse(p, lineno);
}
- fclose(file);
return (warncount);
}
@@ -950,6 +1002,57 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
}
/*
+ * This displays a combination of name, type, format, and/or description.
+ *
+ * Returns zero if anything was actually output.
+ * Returns one if there is an error.
+ */
+static int
+show_info(char *name, const char *sep, int ctltype, char *fmt, int *qoid, int nlen)
+{
+ u_char buf[BUFSIZ];
+ const char *prntype;
+ int error = 0, i;
+ size_t j;
+
+ if (!nflag)
+ printf("%s%s", name, sep);
+ if (tflag) {
+ if (ctl_typename[ctltype] != NULL)
+ prntype = ctl_typename[ctltype];
+ else {
+ prntype = "unknown";
+ error++;
+ }
+ if (Fflag || dflag)
+ printf("%s%s", prntype, sep);
+ else
+ fputs(prntype, stdout);
+ }
+ if (Fflag) {
+ if (!isprint(fmt[0])) /* Few codes doesn't have formats */
+ fmt = "";
+ if (dflag)
+ printf("%s%s", fmt, sep);
+ else
+ fputs(fmt, stdout);
+ }
+ if (!dflag)
+ return (error);
+
+ qoid[1] = CTL_SYSCTL_OIDDESCR;
+ bzero(buf, BUFSIZ);
+ j = sizeof(buf);
+ i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
+ if (i < 0) {
+ putchar('\n');
+ return (1);
+ }
+ fputs(buf, stdout);
+ return (error);
+}
+
+/*
* This formats and outputs the value of one variable
*
* Returns zero if anything was actually output.
@@ -960,9 +1063,9 @@ static int
show_var(int *oid, int nlen, bool honor_skip)
{
static int skip_len = 0, skip_oid[CTL_MAXNAME];
- u_char buf[BUFSIZ], *val, *oval, *p;
+ u_char *val, *oval, *p;
char name[BUFSIZ], fmt[BUFSIZ];
- const char *sep, *sep1, *prntype;
+ const char *sep, *sep1;
int qoid[CTL_MAXNAME+2];
uintmax_t umv;
intmax_t mv;
@@ -977,7 +1080,6 @@ show_var(int *oid, int nlen, bool honor_skip)
/* Silence GCC. */
umv = mv = intlen = 0;
- bzero(buf, BUFSIZ);
bzero(fmt, BUFSIZ);
bzero(name, BUFSIZ);
qoid[0] = CTL_SYSCTL;
@@ -993,10 +1095,18 @@ show_var(int *oid, int nlen, bool honor_skip)
if (Wflag && ((kind & CTLFLAG_WR) == 0 || (kind & CTLFLAG_STATS) != 0))
return (1);
+ /* if Jflag then only list sysctls that are prison variables. */
+ if (Jflag && (kind & CTLFLAG_PRISON) == 0)
+ return (1);
+
/* if Tflag then only list sysctls that are tuneables. */
if (Tflag && (kind & CTLFLAG_TUN) == 0)
return (1);
+ /* if Vflag then only list sysctls that are vnet variables. */
+ if (Vflag && (kind & CTLFLAG_VNET) == 0)
+ return (1);
+
if (Nflag) {
printf("%s", name);
return (0);
@@ -1008,25 +1118,8 @@ show_var(int *oid, int nlen, bool honor_skip)
sep = ": ";
ctltype = (kind & CTLTYPE);
- if (tflag || dflag) {
- if (!nflag)
- printf("%s%s", name, sep);
- if (ctl_typename[ctltype] != NULL)
- prntype = ctl_typename[ctltype];
- else
- prntype = "unknown";
- if (tflag && dflag)
- printf("%s%s", prntype, sep);
- else if (tflag) {
- printf("%s", prntype);
- return (0);
- }
- qoid[1] = CTL_SYSCTL_OIDDESCR;
- j = sizeof(buf);
- i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
- printf("%s", buf);
- return (0);
- }
+ if (tflag || Fflag || dflag)
+ return show_info(name, sep, ctltype, fmt, qoid, nlen);
/* keep track of encountered skip nodes, ignoring descendants */
if ((skip_len == 0 || skip_len >= nlen * (int)sizeof(int)) &&
@@ -1109,6 +1202,8 @@ show_var(int *oid, int nlen, bool honor_skip)
case CTLTYPE_STRING:
if (!nflag)
printf("%s%s", name, sep);
+ if (lflag)
+ printf("%zd%s", len, sep);
printf("%.*s", (int)len, p);
free(oval);
return (0);
@@ -1127,6 +1222,8 @@ show_var(int *oid, int nlen, bool honor_skip)
case CTLTYPE_U64:
if (!nflag)
printf("%s%s", name, sep);
+ if (lflag)
+ printf("%zd%s", len, sep);
hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
sep1 = "";
while (len >= intlen) {
@@ -1197,6 +1294,8 @@ show_var(int *oid, int nlen, bool honor_skip)
if (func) {
if (!nflag)
printf("%s%s", name, sep);
+ if (lflag)
+ printf("%zd%s", len, sep);
i = (*func)(len, p);
free(oval);
return (i);
@@ -1209,6 +1308,8 @@ show_var(int *oid, int nlen, bool honor_skip)
}
if (!nflag)
printf("%s%s", name, sep);
+ if (lflag)
+ printf("%zd%s", len, sep);
printf("Format:%s Length:%zu Dump:0x", fmt, len);
while (len-- && (xflag || p < val + 16))
printf("%02x", *p++);
diff --git a/sbin/sysctl/sysctl.conf b/sbin/sysctl/sysctl.conf
index 0c9e796a7ac8..50243a333c23 100644
--- a/sbin/sysctl/sysctl.conf
+++ b/sbin/sysctl/sysctl.conf
@@ -1,4 +1,3 @@
-# $FreeBSD$
#
# This file is read when going to multi-user and its contents piped thru
# ``sysctl'' to adjust kernel values. ``man 5 sysctl.conf'' for details.
diff --git a/sbin/sysctl/tests/Makefile b/sbin/sysctl/tests/Makefile
new file mode 100644
index 000000000000..b209b2448241
--- /dev/null
+++ b/sbin/sysctl/tests/Makefile
@@ -0,0 +1,3 @@
+ATF_TESTS_SH= sysctl_test
+
+.include <bsd.test.mk>
diff --git a/sbin/sysctl/tests/Makefile.depend b/sbin/sysctl/tests/Makefile.depend
new file mode 100644
index 000000000000..11aba52f82cf
--- /dev/null
+++ b/sbin/sysctl/tests/Makefile.depend
@@ -0,0 +1,10 @@
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/sbin/sysctl/tests/sysctl_test.sh b/sbin/sysctl/tests/sysctl_test.sh
new file mode 100644
index 000000000000..b4cc7180a0f9
--- /dev/null
+++ b/sbin/sysctl/tests/sysctl_test.sh
@@ -0,0 +1,174 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2022 Yoshihiro Ota <ota@j.email.ne.jp>
+#
+# 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.
+#
+
+sysctl_name="kern.ostype"
+sysctl_value="FreeBSD"
+sysctl_type="string"
+sysctl_description="Operating system type"
+
+atf_test_case sysctl_aflag
+sysctl_aflag_head()
+{
+ atf_set "descr" "Exercise all sysctl handlers"
+}
+sysctl_aflag_body()
+{
+ # Avoid using atf_check here since sysctl -ao generates tons of
+ # output and it would all otherwise be saved.
+ sysctl -ao >/dev/null 2>stderr
+ if [ $? -ne 0 ]; then
+ cat stderr
+ atf_fail "sysctl -ao failed"
+ elif [ -s stderr ]; then
+ cat stderr
+ atf_fail "sysctl -ao printed to stderr"
+ fi
+}
+
+
+atf_test_case sysctl_aflag_jail
+sysctl_aflag_jail_head()
+{
+ atf_set "descr" "Exercise all sysctl handlers in a jail"
+ atf_set "require.user" "root"
+}
+sysctl_aflag_jail_body()
+{
+ local jail
+
+ jail=sysctl_test_aflag_jail
+
+ # Avoid using atf_check here since sysctl -ao generates tons of
+ # output and it would all otherwise be saved.
+ jail -c name=$jail command=sysctl -ao >/dev/null 2>stderr
+ if [ $? -ne 0 ]; then
+ atf_fail "sysctl -ao failed"
+ elif [ -s stderr ]; then
+ cat stderr
+ atf_fail "sysctl -ao printed to stderr"
+ fi
+
+ jail -c name=$jail vnet command=sysctl -ao >/dev/null 2>stderr
+ if [ $? -ne 0 ]; then
+ atf_fail "sysctl -ao failed"
+ elif [ -s stderr ]; then
+ cat stderr
+ atf_fail "sysctl -ao printed to stderr"
+ fi
+}
+
+
+atf_test_case sysctl_by_name
+sysctl_by_name_head()
+{
+ atf_set "descr" "Verify name without any arguments"
+}
+sysctl_by_name_body()
+{
+ atf_check -o "inline:${sysctl_name}: ${sysctl_value}\n" sysctl ${sysctl_name}
+}
+
+
+atf_test_case sysctl_nflag
+sysctl_nflag_head()
+{
+ atf_set "descr" "Verify -n argument"
+}
+sysctl_nflag_body()
+{
+ atf_check -o "inline:${sysctl_value}\n" sysctl -n ${sysctl_name}
+}
+
+
+atf_test_case sysctl_eflag
+sysctl_eflag_head()
+{
+ atf_set "descr" "Verify -e argument"
+}
+sysctl_eflag_body()
+{
+ atf_check -o "inline:${sysctl_name}=${sysctl_value}\n" sysctl -e ${sysctl_name}
+}
+
+
+atf_test_case sysctl_tflag
+sysctl_tflag_head()
+{
+ atf_set "descr" "Verify -t argument"
+}
+sysctl_tflag_body()
+{
+ atf_check -o "inline:${sysctl_name}: ${sysctl_type}\n" sysctl -t ${sysctl_name}
+}
+
+
+atf_test_case sysctl_dflag
+sysctl_dflag_head()
+{
+ atf_set "descr" "Verify -d argument"
+}
+sysctl_dflag_body()
+{
+ atf_check -o "inline:${sysctl_name}: ${sysctl_description}\n" sysctl -d ${sysctl_name}
+}
+
+
+atf_test_case sysctl_tflag_dflag
+sysctl_tflag_dflag_head()
+{
+ atf_set "descr" "Verify -t -d arguments"
+}
+sysctl_tflag_dflag_body()
+{
+ atf_check -o "inline:${sysctl_name}: ${sysctl_type}: ${sysctl_description}\n" sysctl -t -d ${sysctl_name}
+ atf_check -o "inline:${sysctl_name}: ${sysctl_type}: ${sysctl_description}\n" sysctl -d -t ${sysctl_name}
+}
+
+
+atf_test_case sysctl_nflag_tflag_dflag
+sysctl_nflag_tflag_dflag_head()
+{
+ atf_set "descr" "Verify -n -t -d arguments"
+}
+sysctl_nflag_tflag_dflag_body()
+{
+ atf_check -o "inline:${sysctl_type}: ${sysctl_description}\n" sysctl -n -t -d ${sysctl_name}
+}
+
+
+atf_init_test_cases()
+{
+ atf_add_test_case sysctl_aflag
+ atf_add_test_case sysctl_aflag_jail
+ atf_add_test_case sysctl_by_name
+ atf_add_test_case sysctl_nflag
+ atf_add_test_case sysctl_eflag
+ atf_add_test_case sysctl_tflag
+ atf_add_test_case sysctl_dflag
+ atf_add_test_case sysctl_tflag_dflag
+ atf_add_test_case sysctl_nflag_tflag_dflag
+}
diff --git a/sbin/tests/Makefile b/sbin/tests/Makefile
index 3b3078f8612a..29b1b564beca 100644
--- a/sbin/tests/Makefile
+++ b/sbin/tests/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
.PATH: ${SRCTOP}/tests
KYUAFILE= yes
diff --git a/sbin/tests/Makefile.depend b/sbin/tests/Makefile.depend
index f80275d86ab1..11aba52f82cf 100644
--- a/sbin/tests/Makefile.depend
+++ b/sbin/tests/Makefile.depend
@@ -1,4 +1,3 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
diff --git a/sbin/tunefs/Makefile b/sbin/tunefs/Makefile
index 9d0754edca89..4ea2219c8e03 100644
--- a/sbin/tunefs/Makefile
+++ b/sbin/tunefs/Makefile
@@ -1,16 +1,8 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
-PACKAGE=runtime
+PACKAGE=ufs
PROG= tunefs
-SRCS= tunefs.c getmntopts.c
-LIBADD= ufs
+LIBADD= ufs util
MAN= tunefs.8
-MOUNT= ${SRCTOP}/sbin/mount
-CFLAGS+= -I${MOUNT}
-.PATH: ${MOUNT}
-
WARNS?= 3
.include <bsd.prog.mk>
diff --git a/sbin/tunefs/Makefile.depend b/sbin/tunefs/Makefile.depend
index 735bf03b75b6..910688a678fa 100644
--- a/sbin/tunefs/Makefile.depend
+++ b/sbin/tunefs/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
diff --git a/sbin/tunefs/tunefs.8 b/sbin/tunefs/tunefs.8
index 065844a831cd..0fb11041d97d 100644
--- a/sbin/tunefs/tunefs.8
+++ b/sbin/tunefs/tunefs.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)tunefs.8 8.2 (Berkeley) 12/11/93
-.\" $FreeBSD$
-.\"
-.Dd January 29, 2019
+.Dd November 17, 2023
.Dt TUNEFS 8
.Os
.Sh NAME
@@ -95,6 +92,41 @@ this parameter should be set higher.
Specify the expected average file size.
.It Fl j Cm enable | disable
Turn on/off soft updates journaling.
+.Pp
+Enabling journaling reduces the time spent by
+.Xr fsck_ffs 8
+cleaning up a filesystem after a crash to a few seconds from minutes to hours.
+Without journaling, the time to recover after a crash is a function
+of the number of files in the filesystem and the size of the filesystem.
+With journaling, the time to recover after a crash is a function of the
+amount of activity in the filesystem in the minute before the crash.
+Journaled recovery time is usually only a few seconds and never
+exceeds a minute.
+.Pp
+The drawback to using journaling is that the writes to its log adds
+an extra write load to the media containing the filesystem.
+Thus a write-intensive workload will have reduced throughput on a
+filesystem running with journaling.
+.Pp
+Like all journaling filesystems, the journal recovery will only fix
+issues known to the journal.
+Specifically if a media error occurs,
+the journal will not know about it and hence will not fix it.
+Thus when using journaling, it is still necessary to run a full fsck
+every few months or after a filesystem panic to check for and fix
+any errors brought on by media failure.
+A full fsck can be done by running a background fsck on a live
+filesystem or by running with the
+.Fl f
+flag on an unmounted filesystem.
+When running
+.Xr fsck_ffs 8
+in background on a live filesystem the filesystem performance
+will be about half of normal during the time that the background
+.Xr fsck_ffs 8
+is running.
+Running a full fsck on a UFS filesystem is the equivalent of
+running a scrub on a ZFS filesystem.
.It Fl J Cm enable | disable
Turn on/off gjournal flag.
.It Fl k Ar held-for-metadata-blocks
@@ -183,7 +215,9 @@ read this to determine the device file for a
specified mount point.
.El
.Sh SEE ALSO
+.Xr ffs 4 ,
.Xr fs 5 ,
+.Xr tuning 7 ,
.Xr dumpfs 8 ,
.Xr gjournal 8 ,
.Xr growfs 8 ,
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index e59b583ea58b..6f6df8446cd9 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#if 0
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1983, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
/*
* tunefs: change layout parameters to an existing file system.
*/
@@ -80,7 +66,7 @@ static char clrbuf[MAXBSIZE];
static struct uufsd disk;
#define sblock disk.d_fs
-static void usage(void);
+static void usage(void) __dead2;
static void printfs(void);
static int journal_alloc(int64_t size);
static void journal_clear(void);
@@ -91,18 +77,14 @@ main(int argc, char *argv[])
{
const char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue;
const char *tvalue;
- const char *special, *on;
+ const char *special;
const char *name;
- int active;
+ char *diskname;
int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, kflag;
int kvalue, Lflag, lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue;
int pflag, sflag, svalue, Svalue, tflag;
int ch, found_arg, i;
- int iovlen = 0;
const char *chg[2];
- struct statfs stfs;
- struct iovec *iov = NULL;
- char errmsg[255] = {0};
if (argc < 3)
usage();
@@ -110,7 +92,6 @@ main(int argc, char *argv[])
lflag = mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0;
avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL;
evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0;
- active = 0;
found_arg = 0; /* At least one arg is required. */
while ((ch = getopt(argc, argv, "Aa:e:f:j:J:k:L:l:m:N:n:o:ps:S:t:"))
!= -1)
@@ -309,7 +290,7 @@ main(int argc, char *argv[])
if (found_arg == 0 || argc != 1)
usage();
- on = special = argv[0];
+ special = argv[0];
if (ufs_disk_fillout(&disk, special) == -1)
goto err;
/*
@@ -319,13 +300,6 @@ main(int argc, char *argv[])
(sblock.fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) != 0) &&
(found_arg > 1 || !pflag))
errx(1, "%s is not clean - run fsck.\n", special);
- if (disk.d_name != special) {
- if (statfs(special, &stfs) != 0)
- warn("Can't stat %s", special);
- if (strcmp(special, stfs.f_mntonname) == 0)
- active = 1;
- }
-
if (pflag) {
printfs();
exit(0);
@@ -570,20 +544,9 @@ main(int argc, char *argv[])
if (sbwrite(&disk, Aflag) == -1)
goto err;
+ diskname = strdup(disk.d_name);
ufs_disk_close(&disk);
- if (active) {
- build_iovec_argf(&iov, &iovlen, "fstype", "ufs");
- build_iovec_argf(&iov, &iovlen, "fspath", "%s", on);
- build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
- if (nmount(iov, iovlen,
- stfs.f_flags | MNT_UPDATE | MNT_RELOAD) < 0) {
- if (errmsg[0])
- err(9, "%s: reload: %s", special, errmsg);
- else
- err(9, "%s: reload", special);
- }
- warnx("file system reloaded");
- }
+ chkdoreload(getmntpoint(diskname), warnx);
exit(0);
err:
if (disk.d_error != NULL)
@@ -976,7 +939,6 @@ journal_alloc(int64_t size)
*/
if (size == 0) {
size = (sblock.fs_size * sblock.fs_bsize) / 1024;
- size = MIN(SUJ_MAX, size);
if (size / sblock.fs_fsize > sblock.fs_fpg)
size = sblock.fs_fpg * sblock.fs_fsize;
size = MAX(SUJ_MIN, size);
diff --git a/sbin/umbctl/Makefile b/sbin/umbctl/Makefile
new file mode 100644
index 000000000000..35afb1bcfd4b
--- /dev/null
+++ b/sbin/umbctl/Makefile
@@ -0,0 +1,8 @@
+CFLAGS+= -I${SRCTOP}/sys/dev/usb/net
+
+PROG= umbctl
+MAN= umbctl.8
+
+BINDIR= /sbin
+
+.include <bsd.prog.mk>
diff --git a/sbin/umbctl/umbctl.8 b/sbin/umbctl/umbctl.8
new file mode 100644
index 000000000000..55f8e315fabc
--- /dev/null
+++ b/sbin/umbctl/umbctl.8
@@ -0,0 +1,161 @@
+.\"-
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2018 by Pierre Pronchery <khorben@defora.org>
+.\"
+.\" 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(S) ``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(S) 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: pppoectl.8,v 1.30 2016/09/12 05:35:20 sevan Exp $
+.\"
+.\" $NetBSD: umbctl.8,v 1.3 2020/03/22 07:45:02 khorben Exp $
+.\"
+.\" last edit-date: [Fri Dec 20 18:20:00 2024]
+.\"
+.Dd December 20, 2024
+.Dt UMBCTL 8
+.Os
+.Sh NAME
+.Nm umbctl
+.Nd display or set MBIM cellular modem interface parameters (4G/LTE)
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Ar ifname
+.Op Ar parameter Op Ar value
+.Ar ...
+.Nm
+.Op Fl v
+.Fl f Ar config-file
+.Ar ifname
+.Sh DESCRIPTION
+.Nm
+supports the following options:
+.Bl -tag -width "-f config_file"
+.It Fl f Ar config-file
+Parse
+.Ar config-file
+for
+.Ar parameter Ns Op \&= Ns Ar value
+pairs, one per line, as if they had been specified on the command line.
+This allows the password or PIN codes to be not passed as command line
+arguments.
+Comments starting with # to the end of the current line are ignored.
+.It Fl v
+Enables verbose mode.
+.El
+.Pp
+The
+.Xr umb 4
+driver may require a number of additional arguments or optional
+parameters besides the settings that can be adjusted with
+.Xr ifconfig 8 .
+These may be credentials or other tunable connectivity variables.
+The
+.Nm
+utility can be used to display the current settings, or to adjust these
+parameters as required.
+.Pp
+For whatever intent
+.Nm
+is being called, at least the parameter
+.Ar ifname
+needs to be specified, naming the interface for which the settings
+are to be performed or displayed.
+Use
+.Xr ifconfig 8
+or
+.Xr netstat 1
+to see which interfaces are available.
+.Pp
+If no other parameter is given,
+.Nm
+will just list the current status for
+.Ar ifname
+and exit.
+.Pp
+If any additional parameter is supplied, superuser privileges are
+required, and the command works in
+.Ql set
+mode.
+This is normally done quietly, unless the option
+.Fl v
+is also enabled, which will cause a final printout of the status as
+described above once all other actions have been taken.
+.Pp
+The parameters currently supported include:
+.Bl -tag -width "username=username"
+.It Ar apn Ns \&= Ns Em access-point
+Set the APN to
+.Em access-point .
+.It Ar username Ns \&= Ns Em username
+Set the username to
+.Em username .
+.It Ar password Ns \&= Ns Em password
+Set the password to
+.Em password .
+.It Ar pin Ns \&= Ns Em pin-code
+Enter the PIN
+.Em pin-code .
+.It Ar puk Ns \&= Ns Em puk-code
+Enter the PUK
+.Em puk-code .
+.It Ar roaming
+Allow data connections when roaming.
+.It Ar -roaming
+Deny data connections when roaming.
+.El
+.Sh EXAMPLES
+Display the settings for umb0:
+.Bd -literal
+# umbctl umb0
+umb0: state up, mode automatic, registration home network
+ provider "BSD-Net", dataclass LTE, signal good
+ phone number "+15554242", roaming "" (denied)
+ APN "", TX 50000000, RX 100000000
+ firmware "MBIM_FW_V1.0", hardware "MBIM_HW_V1.0"
+.Ed
+.Pp
+Configure the connection parameters for umb0 from the command line:
+.Bd -literal
+# umbctl umb0 apn operator.internet username mobile password mobile
+.Ed
+.Pp
+Configure the connection parameters for umb0 from a file:
+.Bd -literal
+# umbctl -f /dev/stdin umb0 << EOF
+pin=1234
+EOF
+.Ed
+.Sh SEE ALSO
+.Xr netstat 1 ,
+.Xr umb 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Nx 9.0 ,
+and
+.Fx 15.0 .
+.Sh AUTHORS
+The program was written by
+.An Pierre Pronchery .
diff --git a/sbin/umbctl/umbctl.c b/sbin/umbctl/umbctl.c
new file mode 100644
index 000000000000..3d57b486ad80
--- /dev/null
+++ b/sbin/umbctl/umbctl.c
@@ -0,0 +1,557 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Original copyright (c) 2018 Pierre Pronchery <khorben@defora.org> (for the
+ * NetBSD Project)
+ *
+ * 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 DEVELOPERS ``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 DEVELOPERS 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) 2022 ADISTA SAS (FreeBSD updates)
+ *
+ * Updates for FreeBSD by Pierre Pronchery <pierre@defora.net>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * $NetBSD: umbctl.c,v 1.4 2020/05/13 21:44:30 khorben Exp $
+ */
+
+#include <sys/endian.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+#include "mbim.h"
+#include "if_umbreg.h"
+
+/* constants */
+static const struct umb_valdescr _umb_actstate[] =
+ MBIM_ACTIVATION_STATE_DESCRIPTIONS;
+
+static const struct umb_valdescr _umb_simstate[] =
+ MBIM_SIMSTATE_DESCRIPTIONS;
+
+static const struct umb_valdescr _umb_regstate[] =
+ MBIM_REGSTATE_DESCRIPTIONS;
+
+static const struct umb_valdescr _umb_pktstate[] =
+ MBIM_PKTSRV_STATE_DESCRIPTIONS;
+
+static const struct umb_valdescr _umb_dataclass[] =
+ MBIM_DATACLASS_DESCRIPTIONS;
+
+static const struct umb_valdescr _umb_state[] =
+ UMB_INTERNAL_STATE_DESCRIPTIONS;
+
+static const struct umb_valdescr _umb_pin_state[] =
+{
+ { UMB_PIN_REQUIRED, "PIN required"},
+ { UMB_PIN_UNLOCKED, "PIN unlocked"},
+ { UMB_PUK_REQUIRED, "PUK required"},
+ { 0, NULL }
+};
+
+static const struct umb_valdescr _umb_regmode[] =
+{
+ { MBIM_REGMODE_UNKNOWN, "unknown" },
+ { MBIM_REGMODE_AUTOMATIC, "automatic" },
+ { MBIM_REGMODE_MANUAL, "manual" },
+ { 0, NULL }
+};
+
+static const struct umb_valdescr _umb_ber[] =
+{
+ { UMB_BER_EXCELLENT, "excellent" },
+ { UMB_BER_VERYGOOD, "very good" },
+ { UMB_BER_GOOD, "good" },
+ { UMB_BER_OK, "ok" },
+ { UMB_BER_MEDIUM, "medium" },
+ { UMB_BER_BAD, "bad" },
+ { UMB_BER_VERYBAD, "very bad" },
+ { UMB_BER_EXTREMELYBAD, "extremely bad" },
+ { 0, NULL }
+};
+
+
+/* prototypes */
+static int _char_to_utf16(const char * in, uint16_t * out, size_t outlen);
+static int _error(int ret, char const * format, ...);
+static int _umbctl(char const * ifname, int verbose, int argc, char * argv[]);
+static int _umbctl_file(char const * ifname, char const * filename,
+ int verbose);
+static void _umbctl_info(char const * ifname, struct umb_info * umbi);
+static int _umbctl_ioctl(char const * ifname, int fd, unsigned long request,
+ struct ifreq * ifr);
+static int _umbctl_set(char const * ifname, struct umb_parameter * umbp,
+ int argc, char * argv[]);
+static int _umbctl_socket(void);
+static int _usage(void);
+static void _utf16_to_char(uint16_t * in, int inlen, char * out, size_t outlen);
+
+
+/* functions */
+/* char_to_utf16 */
+/* this function is from OpenBSD's ifconfig(8) */
+static int _char_to_utf16(const char * in, uint16_t * out, size_t outlen)
+{
+ int n = 0;
+ uint16_t c;
+
+ for (;;) {
+ c = *in++;
+
+ if (c == '\0') {
+ /*
+ * NUL termination is not required, but zero out the
+ * residual buffer
+ */
+ memset(out, 0, outlen);
+ return n;
+ }
+ if (outlen < sizeof(*out))
+ return -1;
+
+ *out++ = htole16(c);
+ n += sizeof(*out);
+ outlen -= sizeof(*out);
+ }
+}
+
+
+/* error */
+static int _error(int ret, char const * format, ...)
+{
+ va_list ap;
+
+ fputs("umbctl: ", stderr);
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ fputs("\n", stderr);
+ return ret;
+}
+
+
+/* umbctl */
+static int _umbctl(char const * ifname, int verbose, int argc, char * argv[])
+{
+ int fd;
+ struct ifreq ifr;
+ struct umb_info umbi;
+ struct umb_parameter umbp;
+
+ if((fd = _umbctl_socket()) < 0)
+ return 2;
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if(argc != 0)
+ {
+ memset(&umbp, 0, sizeof(umbp));
+ ifr.ifr_data = (caddr_t)&umbp;
+ if(_umbctl_ioctl(ifname, fd, SIOCGUMBPARAM, &ifr) != 0
+ || _umbctl_set(ifname, &umbp, argc, argv) != 0
+ || _umbctl_ioctl(ifname, fd, SIOCSUMBPARAM,
+ &ifr) != 0)
+ {
+ close(fd);
+ return 2;
+ }
+ }
+ if(argc == 0 || verbose > 0)
+ {
+ ifr.ifr_data = (caddr_t)&umbi;
+ if(_umbctl_ioctl(ifname, fd, SIOCGUMBINFO, &ifr) != 0)
+ {
+ close(fd);
+ return 3;
+ }
+ _umbctl_info(ifname, &umbi);
+ }
+ if(close(fd) != 0)
+ return _error(2, "%s: %s", ifname, strerror(errno));
+ return 0;
+}
+
+
+/* umbctl_file */
+static int _file_parse(char const * ifname, struct umb_parameter * umbp,
+ char const * filename);
+
+static int _umbctl_file(char const * ifname, char const * filename, int verbose)
+{
+ int fd;
+ struct ifreq ifr;
+ struct umb_parameter umbp;
+ struct umb_info umbi;
+
+ if((fd = _umbctl_socket()) < 0)
+ return 2;
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&umbp;
+ memset(&umbp, 0, sizeof(umbp));
+ if(_umbctl_ioctl(ifname, fd, SIOCGUMBPARAM, &ifr) != 0
+ || _file_parse(ifname, &umbp, filename) != 0
+ || _umbctl_ioctl(ifname, fd, SIOCSUMBPARAM, &ifr) != 0)
+ {
+ close(fd);
+ return 2;
+ }
+ if(verbose > 0)
+ {
+ ifr.ifr_data = (caddr_t)&umbi;
+ if(_umbctl_ioctl(ifname, fd, SIOCGUMBINFO, &ifr) != 0)
+ {
+ close(fd);
+ return 3;
+ }
+ _umbctl_info(ifname, &umbi);
+ }
+ if(close(fd) != 0)
+ return _error(2, "%s: %s", ifname, strerror(errno));
+ return 0;
+}
+
+static int _file_parse(char const * ifname, struct umb_parameter * umbp,
+ char const * filename)
+{
+ int ret = 0;
+ FILE * fp;
+ char buf[512];
+ size_t len;
+ int i;
+ int eof;
+ char * tokens[3] = { buf, NULL, NULL };
+ char * p;
+
+ if((fp = fopen(filename, "r")) == NULL)
+ return _error(2, "%s: %s", filename, strerror(errno));
+ while(fgets(buf, sizeof(buf), fp) != NULL)
+ {
+ if(buf[0] == '#')
+ continue;
+ buf[sizeof(buf) - 1] = '\0';
+ if((len = strlen(buf)) > 0)
+ {
+ if(buf[len - 1] != '\n')
+ {
+ ret = _error(2, "%s: %s", filename,
+ "Line too long");
+ while((i = fgetc(fp)) != EOF && i != '\n');
+ continue;
+ }
+ buf[len - 1] = '\0';
+ }
+ if((p = strchr(buf, '=')) != NULL)
+ {
+ tokens[1] = p + 1;
+ *p = '\0';
+ } else
+ tokens[1] = NULL;
+ ret |= _umbctl_set(ifname, umbp, (p != NULL) ? 2 : 1, tokens)
+ ? 2 : 0;
+ }
+ eof = feof(fp);
+ if(fclose(fp) != 0 || !eof)
+ return _error(2, "%s: %s", filename, strerror(errno));
+ return ret;
+}
+
+
+/* umbctl_info */
+static void _umbctl_info(char const * ifname, struct umb_info * umbi)
+{
+ char provider[UMB_PROVIDERNAME_MAXLEN + 1];
+ char pn[UMB_PHONENR_MAXLEN + 1];
+ char roaming[UMB_ROAMINGTEXT_MAXLEN + 1];
+ char apn[UMB_APN_MAXLEN + 1];
+ char fwinfo[UMB_FWINFO_MAXLEN + 1];
+ char hwinfo[UMB_HWINFO_MAXLEN + 1];
+
+ _utf16_to_char(umbi->provider, UMB_PROVIDERNAME_MAXLEN,
+ provider, sizeof(provider));
+ _utf16_to_char(umbi->pn, UMB_PHONENR_MAXLEN, pn, sizeof(pn));
+ _utf16_to_char(umbi->roamingtxt, UMB_ROAMINGTEXT_MAXLEN,
+ roaming, sizeof(roaming));
+ _utf16_to_char(umbi->apn, UMB_APN_MAXLEN, apn, sizeof(apn));
+ _utf16_to_char(umbi->fwinfo, UMB_FWINFO_MAXLEN, fwinfo, sizeof(fwinfo));
+ _utf16_to_char(umbi->hwinfo, UMB_HWINFO_MAXLEN, hwinfo, sizeof(hwinfo));
+ printf("%s: state %s, mode %s, registration %s\n"
+ "\tprovider \"%s\", dataclass %s, signal %s\n"
+ "\tphone number \"%s\", roaming \"%s\" (%s)\n"
+ "\tAPN \"%s\", TX %" PRIu64 ", RX %" PRIu64 "\n"
+ "\tfirmware \"%s\", hardware \"%s\"\n",
+ ifname, umb_val2descr(_umb_state, umbi->state),
+ umb_val2descr(_umb_regmode, umbi->regmode),
+ umb_val2descr(_umb_regstate, umbi->regstate), provider,
+ umb_val2descr(_umb_dataclass, umbi->cellclass),
+ umb_val2descr(_umb_ber, umbi->ber), pn, roaming,
+ umbi->enable_roaming ? "allowed" : "denied",
+ apn, umbi->uplink_speed, umbi->downlink_speed,
+ fwinfo, hwinfo);
+}
+
+
+/* umbctl_ioctl */
+static int _umbctl_ioctl(char const * ifname, int fd, unsigned long request,
+ struct ifreq * ifr)
+{
+ if(ioctl(fd, request, ifr) != 0)
+ return _error(-1, "%s: %s", ifname, strerror(errno));
+ return 0;
+}
+
+
+/* umbctl_set */
+/* callbacks */
+static int _set_apn(char const *, struct umb_parameter *, char const *);
+static int _set_username(char const *, struct umb_parameter *, char const *);
+static int _set_password(char const *, struct umb_parameter *, char const *);
+static int _set_pin(char const *, struct umb_parameter *, char const *);
+static int _set_puk(char const *, struct umb_parameter *, char const *);
+static int _set_roaming_allow(char const *, struct umb_parameter *,
+ char const *);
+static int _set_roaming_deny(char const *, struct umb_parameter *,
+ char const *);
+
+static int _umbctl_set(char const * ifname, struct umb_parameter * umbp,
+ int argc, char * argv[])
+{
+ struct
+ {
+ char const * name;
+ int (*callback)(char const *,
+ struct umb_parameter *, char const *);
+ int parameter;
+ } callbacks[] =
+ {
+ { "apn", _set_apn, 1 },
+ { "username", _set_username, 1 },
+ { "password", _set_password, 1 },
+ { "pin", _set_pin, 1 },
+ { "puk", _set_puk, 1 },
+ { "roaming", _set_roaming_allow, 0 },
+ { "-roaming", _set_roaming_deny, 0 },
+ };
+ int i;
+ size_t j;
+
+ for(i = 0; i < argc; i++)
+ {
+ for(j = 0; j < sizeof(callbacks) / sizeof(*callbacks); j++)
+ if(strcmp(argv[i], callbacks[j].name) == 0)
+ {
+ if(callbacks[j].parameter && i + 1 == argc)
+ return _error(-1, "%s: Incomplete"
+ " parameter", argv[i]);
+ if(callbacks[j].callback(ifname, umbp,
+ callbacks[j].parameter
+ ? argv[i + 1] : NULL))
+ return -1;
+ if(callbacks[j].parameter)
+ i++;
+ break;
+ }
+ if(j == sizeof(callbacks) / sizeof(*callbacks))
+ return _error(-1, "%s: Unknown parameter", argv[i]);
+ }
+ return 0;
+}
+
+static int _set_apn(char const * ifname, struct umb_parameter * umbp,
+ char const * apn)
+{
+ umbp->apnlen = _char_to_utf16(apn, umbp->apn, sizeof(umbp->apn));
+ if(umbp->apnlen < 0 || (size_t)umbp->apnlen > sizeof(umbp->apn))
+ return _error(-1, "%s: %s", ifname, "APN too long");
+ return 0;
+}
+
+static int _set_username(char const * ifname, struct umb_parameter * umbp,
+ char const * username)
+{
+ umbp->usernamelen = _char_to_utf16(username, umbp->username,
+ sizeof(umbp->username));
+ if(umbp->usernamelen < 0
+ || (size_t)umbp->usernamelen > sizeof(umbp->username))
+ return _error(-1, "%s: %s", ifname, "Username too long");
+ return 0;
+}
+
+static int _set_password(char const * ifname, struct umb_parameter * umbp,
+ char const * password)
+{
+ umbp->passwordlen = _char_to_utf16(password, umbp->password,
+ sizeof(umbp->password));
+ if(umbp->passwordlen < 0
+ || (size_t)umbp->passwordlen > sizeof(umbp->password))
+ return _error(-1, "%s: %s", ifname, "Password too long");
+ return 0;
+}
+
+static int _set_pin(char const * ifname, struct umb_parameter * umbp,
+ char const * pin)
+{
+ umbp->is_puk = 0;
+ umbp->op = MBIM_PIN_OP_ENTER;
+ umbp->pinlen = _char_to_utf16(pin, umbp->pin, sizeof(umbp->pin));
+ if(umbp->pinlen < 0 || (size_t)umbp->pinlen
+ > sizeof(umbp->pin))
+ return _error(-1, "%s: %s", ifname, "PIN code too long");
+ return 0;
+}
+
+static int _set_puk(char const * ifname, struct umb_parameter * umbp,
+ char const * puk)
+{
+ umbp->is_puk = 1;
+ umbp->op = MBIM_PIN_OP_ENTER;
+ umbp->pinlen = _char_to_utf16(puk, umbp->pin, sizeof(umbp->pin));
+ if(umbp->pinlen < 0 || (size_t)umbp->pinlen > sizeof(umbp->pin))
+ return _error(-1, "%s: %s", ifname, "PUK code too long");
+ return 0;
+}
+
+static int _set_roaming_allow(char const * ifname, struct umb_parameter * umbp,
+ char const * unused)
+{
+ (void) ifname;
+ (void) unused;
+
+ umbp->roaming = 1;
+ return 0;
+}
+
+static int _set_roaming_deny(char const * ifname, struct umb_parameter * umbp,
+ char const * unused)
+{
+ (void) ifname;
+ (void) unused;
+
+ umbp->roaming = 0;
+ return 0;
+}
+
+
+/* umbctl_socket */
+static int _umbctl_socket(void)
+{
+ int fd;
+
+ if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return _error(-1, "socket: %s", strerror(errno));
+ return fd;
+}
+
+
+/* usage */
+static int _usage(void)
+{
+ fputs("Usage: umbctl [-v] ifname [parameter [value]] [...]\n"
+" umbctl -f config-file ifname\n",
+ stderr);
+ return 1;
+}
+
+
+/* utf16_to_char */
+static void _utf16_to_char(uint16_t * in, int inlen, char * out, size_t outlen)
+{
+ uint16_t c;
+
+ while (outlen > 0) {
+ c = inlen > 0 ? htole16(*in) : 0;
+ if (c == 0 || --outlen == 0) {
+ /* always NUL terminate result */
+ *out = '\0';
+ break;
+ }
+ *out++ = isascii(c) ? (char)c : '?';
+ in++;
+ inlen--;
+ }
+}
+
+
+/* main */
+int main(int argc, char * argv[])
+{
+ int o;
+ char const * filename = NULL;
+ int verbose = 0;
+
+ while((o = getopt(argc, argv, "f:gv")) != -1)
+ switch(o)
+ {
+ case 'f':
+ filename = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ return _usage();
+ }
+ if(optind == argc)
+ return _usage();
+ if(filename != NULL)
+ {
+ if(optind + 1 != argc)
+ return _usage();
+ return _umbctl_file(argv[optind], filename, verbose);
+ }
+ return _umbctl(argv[optind], verbose, argc - optind - 1,
+ &argv[optind + 1]);
+}
diff --git a/sbin/umount/Makefile b/sbin/umount/Makefile
index 8101322cc6ef..d97283d70c21 100644
--- a/sbin/umount/Makefile
+++ b/sbin/umount/Makefile
@@ -1,7 +1,3 @@
-# @(#)Makefile 8.4 (Berkeley) 6/22/95
-#
-# $FreeBSD$
-
PACKAGE=runtime
PROG= umount
SRCS= umount.c vfslist.c mounttab.c
diff --git a/sbin/umount/Makefile.depend b/sbin/umount/Makefile.depend
index 85338ebe3beb..a2d89550fa2b 100644
--- a/sbin/umount/Makefile.depend
+++ b/sbin/umount/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/rpc \
include/rpcsvc \
diff --git a/sbin/umount/umount.8 b/sbin/umount/umount.8
index 00edb9c3599f..2c26ca868dae 100644
--- a/sbin/umount/umount.8
+++ b/sbin/umount/umount.8
@@ -25,10 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
-.\" $FreeBSD$
-.\"
-.Dd June 19, 2020
+.Dd January 16, 2024
.Dt UMOUNT 8
.Os
.Sh NAME
@@ -36,7 +33,7 @@
.Nd unmount file systems
.Sh SYNOPSIS
.Nm
-.Op Fl fNnv
+.Op Fl dfNnv
.Ar special ... | node ... | fsid ...
.Nm
.Fl a | A
@@ -74,6 +71,11 @@ except for those mounted at
.Pa /
or
.Pa /dev .
+.It Fl d
+If the filesystem is mounted on an
+.Xr md 4
+device (a memory disk), detach it after
+.Xr unmount 2 .
.It Fl F Ar fstab
Specify the
.Pa fstab
@@ -185,6 +187,7 @@ file system table
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr autounmountd 8 ,
+.Xr mdconfig 8 ,
.Xr mount 8
.Sh HISTORY
A
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index 9119c5be0da1..c15fd13d065a 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -29,20 +29,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1980, 1989, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)umount.c 8.8 (Berkeley) 5/8/95";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/socket.h>
@@ -64,10 +50,20 @@ static const char rcsid[] =
#include "mounttab.h"
+/* used by md_detach() */
+#include <sys/ioctl.h>
+#include <sys/mdioctl.h>
+#include <fcntl.h>
+#include <paths.h>
+
+#define DEV_MD _PATH_DEV MD_NAME
+#define DEV_MDCTL _PATH_DEV MDCTL_NAME
+
typedef enum { FIND, REMOVE, CHECKUNIQUE } dowhat;
static struct addrinfo *nfshost_ai = NULL;
-static int fflag, vflag;
+static int dflag, fflag, vflag;
+static int all;
static char *nfshost;
struct statfs *checkmntlist(char *);
@@ -84,17 +80,18 @@ int checkname (char *, char **);
int umountfs(struct statfs *sfs);
void usage (void);
int xdr_dir (XDR *, char *);
+int md_detach(const char *);
int
main(int argc, char *argv[])
{
- int all, errs, ch, mntsize, error, nfsforce, ret;
+ int errs, ch, mntsize, error, nfsforce, ret;
char **typelist = NULL;
struct statfs *mntbuf, *sfs;
struct addrinfo hints;
nfsforce = all = errs = 0;
- while ((ch = getopt(argc, argv, "AaF:fh:Nnt:v")) != -1)
+ while ((ch = getopt(argc, argv, "AadF:fh:Nnt:v")) != -1)
switch (ch) {
case 'A':
all = 2;
@@ -102,6 +99,9 @@ main(int argc, char *argv[])
case 'a':
all = 1;
break;
+ case 'd':
+ dflag = 1;
+ break;
case 'F':
setfstab(optarg);
break;
@@ -469,6 +469,16 @@ umountfs(struct statfs *sfs)
clnt_destroy(clp);
}
free(orignfsdirname);
+
+ if (dflag) {
+ if (md_detach(sfs->f_mntfromname) == 0) {
+ if (vflag)
+ (void)printf("%s: detached\n",
+ sfs->f_mntfromname);
+ } else if (!all)
+ return (-1);
+ }
+
return (0);
}
@@ -651,7 +661,45 @@ usage(void)
{
(void)fprintf(stderr, "%s\n%s\n",
- "usage: umount [-fNnv] special ... | node ... | fsid ...",
- " umount -a | -A [-F fstab] [-fnv] [-h host] [-t type]");
+ "usage: umount [-dfNnv] special ... | node ... | fsid ...",
+ " umount -a | -A [-F fstab] [-dfnv] [-h host] [-t type]");
exit(1);
}
+
+int
+md_detach(const char *device)
+{
+ struct md_ioctl mdio;
+ char *eptr;
+ int fd;
+
+ if (strncmp(device, DEV_MD, sizeof(DEV_MD) - 1)) {
+ if (!all)
+ warnx("invalid md device: %s", device);
+ return (-1);
+ }
+
+ memset(&mdio, 0, sizeof(mdio));
+ mdio.md_version = MDIOVERSION;
+ mdio.md_options = fflag ? MD_FORCE : 0;
+ mdio.md_unit = strtoul(device + sizeof(DEV_MD) - 1, &eptr, 0);
+ if (mdio.md_unit == (unsigned)ULONG_MAX || eptr - device == sizeof(DEV_MD) - 1) {
+ warnx("invalid md device: %s", device);
+ return (-1);
+ }
+
+ fd = open(DEV_MDCTL, O_RDWR, 0);
+ if (fd < 0) {
+ warn("%s", DEV_MDCTL);
+ return (-1);
+ }
+
+ if (ioctl(fd, MDIOCDETACH, &mdio) < 0) {
+ warn("%s", DEV_MD);
+ close(fd);
+ return (-1);
+ }
+
+ close(fd);
+ return (0);
+}
diff --git a/sbin/veriexec/Makefile b/sbin/veriexec/Makefile
index 8039a8295ccd..6b6007c4bb3d 100644
--- a/sbin/veriexec/Makefile
+++ b/sbin/veriexec/Makefile
@@ -1,5 +1,3 @@
-# $FreeBSD$
-
PROG= veriexec
MAN= veriexec.8
SRCS= \
diff --git a/sbin/veriexec/Makefile.depend b/sbin/veriexec/Makefile.depend
index 480d2d2c255e..cbe57ebe4cf8 100644
--- a/sbin/veriexec/Makefile.depend
+++ b/sbin/veriexec/Makefile.depend
@@ -1,8 +1,6 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
@@ -11,6 +9,7 @@ DIRDEPS = \
lib/libcompiler_rt \
lib/libsecureboot \
lib/libveriexec \
+ usr.bin/yacc.host \
.include <dirdeps.mk>
diff --git a/sbin/veriexec/manifest_lexer.l b/sbin/veriexec/manifest_lexer.l
index 6c9a2cf1ae9f..468532928ba0 100644
--- a/sbin/veriexec/manifest_lexer.l
+++ b/sbin/veriexec/manifest_lexer.l
@@ -22,8 +22,6 @@
* 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 <stdio.h>
diff --git a/sbin/veriexec/manifest_parser.y b/sbin/veriexec/manifest_parser.y
index 5889650f824b..e3f5d77f97ec 100644
--- a/sbin/veriexec/manifest_parser.y
+++ b/sbin/veriexec/manifest_parser.y
@@ -22,8 +22,6 @@
* 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/stat.h>
@@ -56,6 +54,7 @@ static struct verified_exec_params *params = &oparams;
# define SHA_DIGEST_LENGTH br_sha1_SIZE
# define SHA256_DIGEST_LENGTH br_sha256_SIZE
# define SHA384_DIGEST_LENGTH br_sha384_SIZE
+# define SHA512_DIGEST_LENGTH br_sha512_SIZE
#endif
static int fmode;
@@ -72,9 +71,8 @@ struct fingerprint_type {
static const struct fingerprint_type fingerprint_table[] = {
{ "sha1", SHA_DIGEST_LENGTH },
{ "sha256", SHA256_DIGEST_LENGTH },
-#if MAXFINGERPRINTLEN > 32
{ "sha384", SHA384_DIGEST_LENGTH },
-#endif
+ { "sha512", SHA512_DIGEST_LENGTH },
{ NULL, 0 }
};
diff --git a/sbin/veriexec/veriexec.8 b/sbin/veriexec/veriexec.8
index 161406ae6de2..8352dd8e5e49 100644
--- a/sbin/veriexec/veriexec.8
+++ b/sbin/veriexec/veriexec.8
@@ -1,5 +1,7 @@
.\"-
-.\" Copyright (c) 2018, Juniper Networks, Inc.
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.\" Copyright (c) 2018-2024, Juniper Networks, Inc.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -22,9 +24,7 @@
.\" (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 February 14, 2022
+.Dd April 19, 2025
.Dt VERIEXEC 8
.Os
.Sh NAME
@@ -34,12 +34,16 @@
.Nm
.Op Fl v
.Op Fl C Ar directory
+.Op Fl S
.Pa manifest
.Nm
.Fl z Ar state
.Nm
.Fl i Ar state
.Nm
+.Fl l
+.Ar file ...
+.Nm
.Fl x
.Ar file ...
.Sh DESCRIPTION
@@ -53,6 +57,11 @@ The first form is for loading a
first verifies a digital signature of the
.Ar manifest
and if successful, parses it and feeds its content to kernel.
+The
+.Fl S
+flag indicates that certificate validity should be checked.
+Without this, a valid signature with an expired certificate
+will still be accepted.
.Pp
The second form with
.Fl z
@@ -63,6 +72,14 @@ and with
to query the current
.Ar state .
.Pp
+With
+.Fl l
+.Nm
+will report any labels associated with the remaining arguments
+assumed to be files.
+If only a single file argument is given, the bare label (if any)
+will be reported, otherwise the pathname followed by label.
+.Pp
The final form with
.Fl x
is used to test whether
@@ -80,7 +97,7 @@ The possible states
are:
.Bl -tag -width enforce
.It Ar loaded
-set automatically when first
+set automatically when the first
.Pa manifest
has been loaded.
.It Ar active
@@ -92,7 +109,7 @@ state.
.It Ar enforce
.Xr mac_veriexec 4
will fail attempts to
-.Xr exec 2
+.Xr execve 2
or
.Xr open 2
files with
@@ -120,10 +137,11 @@ The manifest contains a mapping of relative pathnames to fingerprints
with optional flags.
For example:
.Bd -literal -offset indent
-sbin/veriexec sha256=f22136...c0ff71 no_ptrace
+sbin/veriexec sha256=f22136...c0ff71 no_ptrace trusted
usr/bin/python sha256=5944d9...876525 indirect
sbin/somedaemon sha256=77fc2f...63f5687 label=mod1/val1,mod2/val2
.Ed
+.Pp
The supported flags are:
.Bl -tag -width indirect
.It Ql indirect
@@ -132,16 +150,31 @@ but can be used as an interpreter for example via:
.Bd -literal -offset indent
#!/usr/bin/python
.Ed
+.It Ql no_fips
+If the system has a notion of running in FIPS mode,
+a file marked with this flag will not be allowed to
+exec.
.It Ql no_ptrace
do not allow running executable under a debugger.
Useful for any application critical to the security state of system.
+.It Ql trusted
+this flag is required for a process to use
+.Xr veriexec 4
+to interact with
+.Xr mac_veriexec 4 .
+Generally only
+.Nm
+should need this flag.
+Implies
+.Ql no_ptrace .
+
.El
.Pp
The
.Ql label
argument allows associating a
.Xr maclabel 7
-with the executable.
+with a file.
Neither
.Nm
nor
@@ -150,10 +183,60 @@ nor
pay any attention to the content of the label
they are provided for the use of other
.Xr mac 4
-modules.
+modules or indeed other applications.
+.Sh EXAMPLES
+Load the manifest for a
+.Xr tarfs 5
+package mounted on
+.Pa /mnt
+and be strict about enforcing certificate validity:
+.Bd -literal -offset indent
+# veriexec -S -C /mnt /mnt/manifest
+
+.Ed
+.Nm
+will look for a detached signature that it recognizes, such as
+.Pa manifest.asc
+(OpenPGP) or
+.Pa manifest.*sig
+(X.509).
+In the case of an X.509 signature we also need a matching certificate chain
+.Pa manifest.*certs .
+In either case there needs to be a suitable trust anchor in the trust store.
+.Pp
+We can now activate:
+.Bd -literal -offset indent
+# veriexec -z active
+
+.Ed
+Any user can check if
+.Xr mac_veriexec 4
+is
+.Ql active :
+.Bd -literal -offset indent
+$ veriexec -i active
+
+.Ed
+Any user can check that
+.Pa /mnt/bin/app
+is verified:
+.Bd -literal -offset indent
+$ veriexec -x /mnt/bin/app
+
+.Ed
+If it is not, we will get an Authentiaction error,
+but unless
+.Xr mac_veriexec 4
+is enforcing we would still be able to run it.
+.Sh NOTES
+It is only safe to set
+.Xr mac_veriexec 4
+to
+.Ql enforce
+state, if sufficient manifests have been loaded
+to cover all the applications that might need to be run.
.Sh HISTORY
The Verified Exec system first appeared in
.Nx .
-This utility derrives from the one found in Junos.
-The key difference is the requirement that manifest files
-be digitally signed.
+This utility derives from the one found in Junos,
+which requires that manifest files be digitally signed.
diff --git a/sbin/veriexec/veriexec.c b/sbin/veriexec/veriexec.c
index aff514b1cac5..0619b261665e 100644
--- a/sbin/veriexec/veriexec.c
+++ b/sbin/veriexec/veriexec.c
@@ -1,5 +1,7 @@
/*-
- * Copyright (c) 2018, Juniper Networks, Inc.
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2018-2023, Juniper Networks, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,8 +25,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <stdlib.h>
#include <sysexits.h>
#include <unistd.h>
@@ -50,10 +50,10 @@ const char *Cdir = NULL;
* @return always returns code 0
*/
static int
-veriexec_usage()
+veriexec_usage(void)
{
printf("%s",
- "Usage:\tveriexec [-h] [-i state] [-C] [-xv state|verbosity] [path]\n");
+ "Usage:\tveriexec [-C path] [-hlxv] [-[iz] state] [path]\n");
return (0);
}
@@ -135,20 +135,58 @@ veriexec_state_modify(const char *arg_text)
return (state);
}
+#ifdef HAVE_VERIEXEC_GET_PATH_LABEL
+static void
+veriexec_check_labels(int argc, char *argv[])
+{
+ char buf[BUFSIZ];
+ char *cp;
+ int n;
+
+ n = (argc - optind);
+ for (; optind < argc; optind++) {
+ cp = veriexec_get_path_label(argv[optind], buf, sizeof(buf));
+ if (cp) {
+ if (n > 1)
+ printf("%s: %s\n", argv[optind], cp);
+ else
+ printf("%s\n", cp);
+ if (cp != buf)
+ free(cp);
+ }
+ }
+ exit(EX_OK);
+}
+#endif
+
+static void
+veriexec_check_paths(int argc, char *argv[])
+{
+ int x;
+
+ x = EX_OK;
+ for (; optind < argc; optind++) {
+ if (veriexec_check_path(argv[optind])) {
+ warn("%s", argv[optind]);
+ x = 2;
+ }
+ }
+ exit(x);
+}
+
int
main(int argc, char *argv[])
{
long long converted_int;
uint32_t state;
- char c;
- int x;
+ int c, x;
if (argc < 2)
return (veriexec_usage());
dev_fd = open(_PATH_DEV_VERIEXEC, O_WRONLY, 0);
- while ((c = getopt(argc, argv, "hC:i:xvz:")) != -1) {
+ while ((c = getopt(argc, argv, "C:hi:lSxvz:")) != -1) {
switch (c) {
case 'h':
/* Print usage info */
@@ -174,6 +212,15 @@ main(int argc, char *argv[])
exit((x & state) == 0);
break;
+#ifdef HAVE_VERIEXEC_GET_PATH_LABEL
+ case 'l':
+ veriexec_check_labels(argc, argv);
+ break;
+#endif
+ case 'S':
+ /* Strictly enforce certificate validity */
+ ve_enforce_validity_set(1);
+ break;
case 'v':
/* Increase the verbosity */
@@ -185,13 +232,7 @@ main(int argc, char *argv[])
/*
* -x says all other args are paths to check.
*/
- for (x = EX_OK; optind < argc; optind++) {
- if (veriexec_check_path(argv[optind])) {
- warn("%s", argv[optind]);
- x = 2;
- }
- }
- exit(x);
+ veriexec_check_paths(argc, argv);
break;
case 'z':
/* Modify the state */
diff --git a/sbin/veriexec/veriexec.h b/sbin/veriexec/veriexec.h
index b06025f47e90..692a14859a57 100644
--- a/sbin/veriexec/veriexec.h
+++ b/sbin/veriexec/veriexec.h
@@ -1,4 +1,6 @@
/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
* Copyright (c) 2018, Juniper Networks, Inc.
*
* Redistribution and use in source and binary forms, with or without
@@ -21,8 +23,6 @@
* 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 __VERIEXEC_H__
diff --git a/sbin/zfsbootcfg/Makefile b/sbin/zfsbootcfg/Makefile
index 566ba2261705..318de8a030fa 100644
--- a/sbin/zfsbootcfg/Makefile
+++ b/sbin/zfsbootcfg/Makefile
@@ -1,21 +1,7 @@
-# @(#)Makefile 8.4 (Berkeley) 6/22/95
-# $FreeBSD$
-
+PACKAGE=zfs
PROG= zfsbootcfg
MAN= zfsbootcfg.8
LIBADD+=zfsbootenv
-CFLAGS+= -DIN_BASE
-CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include
-CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/include/os/freebsd
-CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/lib/libspl/include
-CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/lib/libspl/include/os/freebsd
-CFLAGS+= -I${SRCTOP}/sys
-CFLAGS+= -I${SRCTOP}/cddl/compat/opensolaris/include
-CFLAGS+= -I${SRCTOP}/sys/contrib/openzfs/module/icp/include
-CFLAGS+= -include ${SRCTOP}/sys/contrib/openzfs/include/os/freebsd/spl/sys/ccompile.h
-CFLAGS+= -DHAVE_ISSETUGID
-CFLAGS+= -include ${SRCTOP}/sys/modules/zfs/zfs_config.h
-
.include <bsd.prog.mk>
diff --git a/sbin/zfsbootcfg/Makefile.depend b/sbin/zfsbootcfg/Makefile.depend
index 53090da6e2fc..d4df14bcefb6 100644
--- a/sbin/zfsbootcfg/Makefile.depend
+++ b/sbin/zfsbootcfg/Makefile.depend
@@ -1,27 +1,12 @@
-# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
- cddl/lib/libavl \
- cddl/lib/libnvpair \
- cddl/lib/libumem \
- cddl/lib/libuutil \
- cddl/lib/libzfs \
- cddl/lib/libzfs_core \
- gnu/lib/csu \
+ cddl/lib/libzfsbootenv \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
- lib/libexpat \
- lib/libgeom \
- lib/libmd \
- lib/libsbuf \
- lib/libthr \
- lib/libutil \
- lib/libz \
- lib/msun \
.include <dirdeps.mk>
diff --git a/sbin/zfsbootcfg/zfsbootcfg.8 b/sbin/zfsbootcfg/zfsbootcfg.8
index 797e5d4edaaa..3831adfc81bd 100644
--- a/sbin/zfsbootcfg/zfsbootcfg.8
+++ b/sbin/zfsbootcfg/zfsbootcfg.8
@@ -22,9 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
-.\"
-.Dd July 22, 2020
+.Dd July 28, 2025
.Dt ZFSBOOTCFG 8
.Os
.Sh NAME
@@ -46,14 +44,11 @@
is used to set
.Xr boot.config 5 Ns -style
options to be used by
-.Xr zfsboot 8 ,
.Xr gptzfsboot 8
or
.Xr loader 8
the next time the machine is booted.
Once
-.Xr zfsboot 8
-or
.Xr gptzfsboot 8
or
.Xr loader 8
@@ -132,8 +127,7 @@ To clear the boot options:
.Xr boot.config 5 ,
.Xr bectl 8 ,
.Xr gptzfsboot 8 ,
-.Xr loader 8 ,
-.Xr zfsboot 8
+.Xr loader 8
.Sh HISTORY
.Nm
appeared in
diff --git a/sbin/zfsbootcfg/zfsbootcfg.c b/sbin/zfsbootcfg/zfsbootcfg.c
index f4b2eeabcc3b..03b028a9ab71 100644
--- a/sbin/zfsbootcfg/zfsbootcfg.c
+++ b/sbin/zfsbootcfg/zfsbootcfg.c
@@ -23,9 +23,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
#include <errno.h>
#include <limits.h>